Other Parts Discussed in Thread: CC2533
Hello,
How can I use the CC2530 to detect when a 3v battery has dropped to <2.5v with the indication of a LED? What would the wiring diagram look like and how can I program it starting from scratch?
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
I meant that if you could provide the entire project including all build files, workspaces, c files (start to finish, including init) , etc? Can you provide the entire project in which I can just download and test on my CC2530?
Do you know how to rework the code from the site: https://e2e.ti.com/support/wireless_connectivity/zigbee_6lowpan_802-15-4_mac/f/158/t/68930 to do battery monitoring instead of temperature monitoring?
So I've got the code from the site sunmaysky.blogspot.tw/.../cc2530-adc-howto-in-ti-z-stack.html inside of hal_adc.c in the HalAdcRead function. Below is the file of hal_adc.c. There's no warning or errors. So I wanted to know if I placed the code in the correct function and if this is the correct code to use to light an LED once the voltage is below 2.5v?
P.S. Also below is a picture of my wiring. Is it correct?
/************************************************************************************************** * INCLUDES **************************************************************************************************/ #include "hal_adc.h" #include "hal_defs.h" #include "hal_mcu.h" #include "hal_types.h" /************************************************************************************************** * CONSTANTS **************************************************************************************************/ #define HAL_ADC_EOC 0x80 /* End of Conversion bit */ #define HAL_ADC_START 0x40 /* Starts Conversion */ #define HAL_ADC_STSEL_EXT 0x00 /* External Trigger */ #define HAL_ADC_STSEL_FULL 0x10 /* Full Speed, No Trigger */ #define HAL_ADC_STSEL_T1C0 0x20 /* Timer1, Channel 0 Compare Event Trigger */ #define HAL_ADC_STSEL_ST 0x30 /* ADCCON1.ST =1 Trigger */ #define HAL_ADC_RAND_NORM 0x00 /* Normal Operation */ #define HAL_ADC_RAND_LFSR 0x04 /* Clock LFSR */ #define HAL_ADC_RAND_SEED 0x08 /* Seed Modulator */ #define HAL_ADC_RAND_STOP 0x0c /* Stop Random Generator */ #define HAL_ADC_RAND_BITS 0x0c /* Bits [3:2] */ #define HAL_ADC_DEC_064 0x00 /* Decimate by 64 : 8-bit resolution */ #define HAL_ADC_DEC_128 0x10 /* Decimate by 128 : 10-bit resolution */ #define HAL_ADC_DEC_256 0x20 /* Decimate by 256 : 12-bit resolution */ #define HAL_ADC_DEC_512 0x30 /* Decimate by 512 : 14-bit resolution */ #define HAL_ADC_DEC_BITS 0x30 /* Bits [5:4] */ #define HAL_ADC_STSEL HAL_ADC_STSEL_ST #define HAL_ADC_RAND_GEN HAL_ADC_RAND_STOP #define HAL_ADC_REF_VOLT HAL_ADC_REF_AVDD #define HAL_ADC_DEC_RATE HAL_ADC_DEC_064 #define HAL_ADC_SCHN HAL_ADC_CHN_VDD3 #define HAL_ADC_ECHN HAL_ADC_CHN_GND /* ------------------------------------------------------------------------------------------------ * Local Variables * ------------------------------------------------------------------------------------------------ */ #if (HAL_ADC == TRUE) static uint8 adcRef; #endif /************************************************************************************************** * @fn HalAdcInit * * @brief Initialize ADC Service * * @param None * * @return None **************************************************************************************************/ void HalAdcInit (void) { #if (HAL_ADC == TRUE) adcRef = HAL_ADC_REF_VOLT; #endif } /************************************************************************************************** * @fn HalAdcRead * * @brief Read the ADC based on given channel and resolution * * @param channel - channel where ADC will be read * @param resolution - the resolution of the value * * @return 16 bit value of the ADC in offset binary format. * * Note that the ADC is "bipolar", which means the GND (0V) level is mid-scale. * Note2: This function assumes that ADCCON3 contains the voltage reference. **************************************************************************************************/ #include "onboard.h" uint16 HalAdcRead (uint8 channel, uint8 resolution) { int16 reading = 0; #if (HAL_ADC == TRUE) uint8 i, resbits; uint8 adcChannel = 1; /* * If Analog input channel is AIN0..AIN7, make sure corresponing P0 I/O pin is enabled. The code * does NOT disable the pin at the end of this function. I think it is better to leave the pin * enabled because the results will be more accurate. Because of the inherent capacitance on the * pin, it takes time for the voltage on the pin to charge up to its steady-state level. If * HalAdcRead() has to turn on the pin for every conversion, the results may show a lower voltage * than actuality because the pin did not have time to fully charge. */ if (channel < 8) { for (i=0; i < channel; i++) { adcChannel <<= 1; } } uint16 adc_ain2=0; HalAdcSetReference(HAL_ADC_REF_125V); adc_ain2=HalAdcRead(HAL_ADC_CHN_AIN2,HAL_ADC_RESOLUTION_10); uint16 holder = (1.15*adc_ain2)/511; //3v in with voltage divider if (holder < 1.01){ //2.8v in with voltage divider P1_5 = 1; for(int i=0; i<50; i++){ Onboard_wait(10000); } P1_5 = 0; for(int i=0; i<1000; i++){ Onboard_wait(10000); } } /* Enable channel */ ADCCFG |= adcChannel; /* Convert resolution to decimation rate */ switch (resolution) { case HAL_ADC_RESOLUTION_8: resbits = HAL_ADC_DEC_064; break; case HAL_ADC_RESOLUTION_10: resbits = HAL_ADC_DEC_128; break; case HAL_ADC_RESOLUTION_12: resbits = HAL_ADC_DEC_256; break; case HAL_ADC_RESOLUTION_14: default: resbits = HAL_ADC_DEC_512; break; } /* writing to this register starts the extra conversion */ ADCCON3 = channel | resbits | adcRef; /* Wait for the conversion to be done */ while (!(ADCCON1 & HAL_ADC_EOC)); /* Disable channel after done conversion */ ADCCFG &= (adcChannel ^ 0xFF); /* Read the result */ reading = (int16) (ADCL); reading |= (int16) (ADCH << 8); /* Treat small negative as 0 */ if (reading < 0) reading = 0; switch (resolution) { case HAL_ADC_RESOLUTION_8: reading >>= 8; break; case HAL_ADC_RESOLUTION_10: reading >>= 6; break; case HAL_ADC_RESOLUTION_12: reading >>= 4; break; case HAL_ADC_RESOLUTION_14: default: reading >>= 2; break; } #else // unused arguments (void) channel; (void) resolution; #endif return ((uint16)reading); } /************************************************************************************************** * @fn HalAdcSetReference * * @brief Sets the reference voltage for the ADC and initializes the service * * @param reference - the reference voltage to be used by the ADC * * @return none * **************************************************************************************************/ void HalAdcSetReference ( uint8 reference ) { #if (HAL_ADC == TRUE) adcRef = reference; #endif } /********************************************************************* * @fn HalAdcCheckVdd * * @brief Check for minimum Vdd specified. * * @param vdd - The board-specific Vdd reading to check for. * * @return TRUE if the Vdd measured is greater than the 'vdd' minimum parameter; * FALSE if not. * *********************************************************************/ bool HalAdcCheckVdd(uint8 vdd) { ADCCON3 = 0x0F; while (!(ADCCON1 & 0x80)); return (ADCH > vdd); } /************************************************************************************************** **************************************************************************************************/
I will type in the periodic function later, but for now, I moved the code into the event loop:
#include <hal_adc.h>
uint16 zclSampleLight_event_loop( uint8 task_id, uint16 events )
{
//////////////////////////////////////////////////////////
uint16 adc_ain2=0;
HalAdcSetReference(HAL_ADC_REF_125V);
adc_ain2=HalAdcRead(HAL_ADC_CHN_AIN2,HAL_ADC_RESOLUTION_10);
uint16 holder = (1.15*adc_ain2)/511;
if (holder < 1.01){
P1_5 = 1;
}
Right now the code says the LED should light up once the voltage drops below 1.01 volts, but when it does, the LED doesn't light up. How can I fix this?
I've been testing the code from the site: e2e.ti.com/.../130649. It appears to be working, but my interpretations of the value g could be wrong. I got a value of 29 (2.9v) for g and that's the voltage I get off my multimeter. Does the code form the site work for ADC battery monitoring?
I've been testing the periodic event code more thoroughly and I have found it isn't working the way it is supposed to. The CC2530 checks the battery every second or so. I used an LED to verify this. If the LED keeps on turning on and off instantaneously, that means the periodic event is not working right. Why isn't it waiting for every 10 seconds to check the battery (10 sec for testing)?
#include <hal_adc.h> #define KEYHOLD_EVT 0x0100 //define event for key hold int KeyPressCnt=0; uint16 adc_ain2=0; #define HAL_ADC_REF_125V 0x00 /* Internal 1.25V Reference */ #define HAL_ADC_DEC_064 0x00 /* Decimate by 64 : 8-bit resolution */ #define HAL_ADC_DEC_128 0x10 /* Decimate by 128 : 10-bit resolution */ #define HAL_ADC_DEC_512 0x30 /* Decimate by 512 : 14-bit resolution */ #define HAL_ADC_CHN_VDD3 0x0f /* Input channel: VDD/3 */ #define HAL_ADC_CHN_TEMP 0x0e /* Temperature sensor */ uint16 value_bat; uint16 g; char k; int i=0; #define PERIODIC_EVT 0x0001 uint16 zclSampleLight_event_loop( uint8 task_id, uint16 events ) { ////////////////////////////////////////////////////////// osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 10 ); if( events & PERIODIC_EVT ) { //Do things that need periodic processing here! /* Clear ADC interrupt flag */ ADCIF = 0; ADCCON3 = (HAL_ADC_REF_125V| HAL_ADC_DEC_128 | HAL_ADC_CHN_VDD3); /* Wait for the conversion to finish */ while ( !ADCIF ); /* Get the result */ value_bat = ADCL; value_bat |= ((uint16) ADCH) << 8; /* * value now contains measurement of Vdd/3 * 0 indicates 0V and 32767 indicates 1.25V * voltage = (value*3*1.25)/32767 volts * we will multiply by this by 10 to allow units of 0.1 volts */ value_bat = value_bat >> 6; // divide first by 2^6 value_bat = (uint16)(value_bat * 37.5); value_bat = value_bat >> 9; // ...and later by 2^9...to prevent overflow during multiplication g=value_bat; P0SEL &= ~BV(4); P0DIR |= BV(4); P0_4=0; //Set P1.5 to low //////////////////////////////IF the following code keeps on turning the LED on and off every second, that means //////////////////////////////the periodic event isn't working correctly if(i==0){ //if comes here, LED will turn on P0_4=1; i=1; } else if(i==1){ //if comes here, LED will turn off P0_4=0; i=0; } /*if(g<=25){ k='b'; P0_4=1; } else if(g>25){ k='g'; P0_4=0; }*/ osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 100000 ); //supposed to be every 10 seconds return (events ^ PERIODIC_EVT); }