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.

CC2530 ADC Battery measuring

Other Parts Discussed in Thread: Z-STACK, CC2530, CC2592, CC2591, CC2531, CC2530EM

Hi,

 

I'm now using the internal cc2530 VDD/3 to measure the voltage of battery, however, I found that I cannot get the correct value according to the adc program.

Could someone help me to see what's my problem?

 

I test this program both on the smartrf05eb and bb, both the readings were wrong. Thank you.

 

 

int8 HalAdcGetVdd (void)

{

  ADCCON3 = 0x0F;

  while (!(ADCCON1 & 0x80));

  return ADCH;

}

 

 

int8 HalAdcGetTmp (void)

{

  ADCCON3 = 0x0E;

  while (!(ADCCON1 & 0x80));

 

  return ADCH;

}

 

And By the way, according to the 

 

 

Filename:       hal_adc.h

  Revised:        $Date: 2010-03-19 20:18:21 -0700 (Fri, 19 Mar 2010) $

  Revision:       $Revision: 21954 $

 

 

 

/* Reference Voltages */

#define HAL_ADC_REF_125V          0x00    /* Internal Reference (1.25V-CC2430)(1.15V-CC2530) */

 

 

The Ref 125v in cc2530 is only about 1.15v, right? I'm looking for your reply.

  • Hello -

    Please install the Z-Stack 2.3.1 release:

    http://focus.ti.com/docs/toolsw/folders/print/z-stack.html

    Refer to the battery level constants and implementation in hal_board_cfg.h (e.g. VDD_MIN_RUN), ZMain.c (e.g. zmain_vdd_check()), and hal_adc.c/h.

    Also, you can use the examples from TVSA (Temperature and Voltage Sample Application) which is attached. Note that the temperature measurement needs to be calibrated and the sample app assumes that the part is always first powered-up at room temperature (refer to use of variable 'voltageAtCalbr'). As you will see, an application-specific implementation of calibration needs to be added and the calibration should probably be stored in a new OSAL_Nv item created by the application.

    TVSA.zip
  • Thank you very much

  • You're welcome! And thank you for using TI LPRF!!

  • Hi, ,


    I'm sorry to bother you again. However, I still cannot get the battery voltage from the ADCH. NO matter how I make the program below, the reading from ADCH is always around 119 (varies from 117-120). Could you please help me to find what happened? Thank you very much.


    int8 HalAdcGetVdd (void)

    {

      ADCCON3 = 0x0F;

      while (!(ADCCON1 & 0x80));

      return ADCH;

    }

  • Hi LZH,

    I know it's been a long while since you posted this topic, I just wanted to ask you how many pins you used in your CC2530 board. I want to use the ADC to know battery level too. 

    Many thanks

  • Hi Mario,

    If you use internal ADC to read battery level, you don't have to use any ADC pin.

  • YiKai, thanks for replying. Correct me if I am wrong here: I am using an LDO converter to power the device, that means I need to read the analogue voltage directly from the battery to have a valid measure, so I need to bring the battery output to one of the ADC pins right?

    I don't like this way of measuring battery voltage, most probably I will have to place a voltage resistor, wasting current when the power budget is kind of critical...

  • Yes, you have to bring the battery output to one of ADC pins.

  • OK. I got a last question YiKai: If I use an LDO (Vout=2.5V) to power the device, I would have to place a voltage divider to bring the battery to the ADC, that means a power consumption that is unacceptable, so I may remove the LDO and power the device directly from the battery. Do you think that's a good idea?

    Thank you very much for your help

  • It should be no problem if you don't connect CC2530 with PA such as CC2591/CC2592.

  • You mean powering the device directly from the battery? (I am using the CC2531 standalone, without the extender)

    thanks

  • PA means power amplifier and is used to output large TX power. If you don't use it, it should be no problem to connect battery directly.

  • OK thanks again!

    I had no plans to use the PA

  • Hi chen ,

         case:

               I am using an LDO converter to power the device, that means I need to read the analogue voltage directly from the battery to have a valid measure, so I need to bring the battery output to one of the ADC pins right?

               i have to bring the battery output to one of ADC pins!

            1.  which ADC pins should be use?is it use internal ADC?

            2.  Does zmain_vdd_check(); always  work  when i bring the battery output to one of ADC pins (P05)

            3.  How can i set a event to check the battery everyday one times?

     

           

  • Hi  Chen, if i use , what is the difference in battery monitor?

  • 1.  which ADC pins should be use?is it use internal ADC?

    You can connect of any pin from Pin0 to Pin7 on  Port 0. All of them can serve internal ADC reading.

    2.  Does zmain_vdd_check(); always  work  when i bring the battery output to one of ADC pins (P05)

    zmain_vdd_check use API HalAdcCheckVdd() to check VDD. If you bring battery output to one of ADC pins, you should use API HalAdcRead() to do ADC reading.

    3.  How can i set a event to check the battery everyday one times?

    You can create a BATTERY_CHECK_EVT  event and make it wake-up every 24 hours like the followings:
    if ( events & BATTERY_CHECK_EVT )
    {
        // Do adc reading to Check battery here
        ....
        osal_start_timerEx( zclXXX_TaskID, BATTERY_CHECK_EVT, 86400000); //Start a timer to trigger BATTERY_CHECK_EVT in 24 hours
        return ( events ^ BATTERY_CHECK_EVT );
    }

    and start it first time in zcl_XXX_Init by calling osal_start_timerEx( zclXXX_TaskID, BATTERY_CHECK_EVT, 1000);

     

  • thanks for your quick support!

               as i ask you before, i am not family with EVENT definition

               we can find KEYCHANGE definition in  comdef.h and that seems there is a rule about how to define those EVENT,but bot clearly。

    and i have define a KEYHOLD_EVT  yesterday  as Below ,it seems good after testing。

    /*********************************************************************
     * Global Generic System Messages
     */

    #define KEY_CHANGE                0xC0    // Key EventsKeyHoldCheckByCompare
      
    #define KEYHOLD_EVT               0xC1    // Key HOLD Events,define for keyhold, it seems no problem after test 

    // OSAL System Message IDs/Events Reserved for applications (user applications)
    // 0xE0 ?0xFC

    so could i define the battery monitor event as below ??and when there is a new event need to be defined,what i do is only   adding  one base on the lastest event defintion, and that should not more than 0XE0》》?

    #define BATTERY_CHECK_EVT   0xC2

    #define XXX1_CHECK_EVT   0xC2

    #define XXX2_CHECK_EVT   0xC3

    #define XXX3_CHECK_EVT   0xC4

     

  • Application event is a bit flag on UINT16. You can refer to how  SampleTemperatureSensor implements SAMPLETEMPERATURESENSOR_TEMP_SEND_EVT in Z-Stack Home 1.2.1


  • 1. zmain_vdd_check use API HalAdcCheckVdd() to check VDD. If you bring battery output to one of ADC pins, you should use API HalAdcRead() to do ADC reading.

     is there any hardware need to be set up except that bring battery output to one ADC pins, because i curious about what is reference point?  The battery out put is 5V or more than 5V, then the Power support of  CC2530 is 3.3v,  i think there will be oxFF all the time if battery out put are higher than 3.3V

    You can create a BATTERY_CHECK_EVT  event and make it wake-up every 24 hours like the followings:
    if ( events & BATTERY_CHECK_EVT )
    {
        // Do adc reading to Check battery here
        ....
        osal_start_timerEx( zclXXX_TaskID, BATTERY_CHECK_EVT, 86400000); //Start a timer to trigger BATTERY_CHECK_EVT in 24 hours
        return ( events ^ BATTERY_CHECK_EVT );
    }

     

    how can i put out the result for UART  when // Do adc reading finish

    and start it first time in zcl_XXX_Init by calling osal_start_timerEx( zclXXX_TaskID, BATTERY_CHECK_EVT, 1000);

     

    i don't know where is the  zcl_XXX_Init ??howi just put this begin function in onboard.C file InitBoard( OB_READY ); after key config,

     

    is that OK?

  • 1. You can refer to CC253x/4x User's Guide chapter 12 for ADC details. Basically, I would suggest you using HAL_ADC_CHN_VDD3 which means 1.15V as reference voltage.

    2. You have to define HAL_UART in your project and use HalUARTWrite to output UART.

    3. If you use SampleTemperatureSensor, zcl_XXX_Init means zclSampleTemperatureSensor_Init().

  • 1. You can refer to CC253x/4x User's Guide chapter 12 for ADC details. Basically, I would suggest you using HAL_ADC_CHN_VDD3 which means 1.15V as reference voltage.

    OK, i saw there is a initial function about  HalAdcInit(void), so i just change this initial function to follow your suggestion  ,is that right?

    void HalAdcInit (void)
    {
    #if (HAL_ADC == TRUE)
      adcRef = HAL_ADC_REF_VOLT;
    #endif
    }#define HAL_ADC_REF_AVDD          0x80    /* AVDD_SOC Pin Reference */

    then ====> #define HAL_ADC_REF_VOLT    HAL_ADC_REF_AVDD

    ======> #define HAL_ADC_REF_AVDD          0x80    /* AVDD_SOC Pin Reference */

    2. You have to define HAL_UART in your project and use HalUARTWrite to output UART.

    i know the HalUARTWrite to send string ,but i didn't know how to use it to send a variable value.

     

    3. If you use SampleTemperatureSensor, zcl_XXX_Init means zclSampleTemperatureSensor_Init().

    yes, is that OK put this function after  init_board()?

  • 1. No, you should set adcRef = HAL_ADC_REF_125V

    2. To output variable value, you can use sprintf function like the followings:

    char str[8];

    int a =100;

    sprintf(str, "%d", a);

    HalUARTWrite(HAL_UART_PORT_0,  str, 8);

    3. No, this is application event and it is not recommended to put it in init_board(). You should put it in zcl_XXX_Init().

  • 1.  oh sorry, i think you make a mistake, i just show you the code which was in the 1.21 profile sample code.

         i will change the HalADCinit base on it , just like that:  adcRef =HAL_ADC_CHN_VDD3     (CC2530)

         But when i change this defintion , i think the joykey will lose function 

    2.  when i use HalAdcRead , there is a 16 bit value of the ADC in offset binary format.

         i want to  send this value to PC by use HalUARTWrite , 

         if i use the datatpye change method ,it shows me error , as i code below:

    uint16 BatteryValue;

    char str[16];sprintf(str, "%d", a);

    BatteryValue = HalAdcRead (HAL_ADC_CHANNEL_5, HAL_ADC_DEC_512);

    sprintf(str, "%d", BatteryValue);

    HalUARTWrite(0,str,16);

     

         "Error[Pe260]: explicit type is missing ("int" assumed)


    3. OK i find it  thanks !

  • 1. You can call HalAdcSetReference() to change reference voltage to VDD3 before you use HalAdcRead to do battery read. After battery reading, you can call HalAdcSetReference() to change reference voltage back.

    2. What is char str[16];sprintf(str, "%d", a);?????? You should remove sprintf(str, "%d", a); I have no problem compile the sample code.

    uint16 BatteryValue;

    char str[16];sprintf(str, "%d", a);??????

    BatteryValue = HalAdcRead (HAL_ADC_CHANNEL_5, HAL_ADC_DEC_512);

    sprintf(str, "%d", BatteryValue);

    HalUARTWrite(0,str,16);

     

  • ok, I will try it again , and thanks a lot !

    there is another question of those value  which was feed back by using the HalAdcRead

    how can i know what is the value mean for  votlatge ? i fine a file SWRA100, but it state that this was fit for other device except CC2530

    could you please tell me how to transform 16bit value to the real votlatge?

  • This application already gives you examples. You can see it use 12 bit resolution and the measured value can be adcReading*3.45/2047. I replace 3.75 to 3.45 because the VDD3 is mapped to 1.15V not 1.25V on CC2530 (3.45=1.15*3).

  • Hi Chen,

             there is always a problem in datatype change , and  no matter  i bring 3.3v or GND   to P05, there is alway showing  乱码

     

  • Your ADC reading is 8191 which is the max value of this resolution. Try to reduce the voltage from ADC input to see if reading changes.

  • Yes , I have try to reduce the voltage to GND (and i have try any other value )  from ADC input , but it is always showing 8191.

    and i remember that there is not any initial action about setting the IO,so i put those code in the BatteryChecking initial function

    void BatteryCheckinit( uint8 reference )
    {
      P0SEL &= ~0x20;                 //设置P0.5为普通IO口
      P0DIR &= ~0x20;                 //P0.5定义为输入口
      HalAdcSetReference ( reference );
    }

    but it doesn't change any thing of the result.

     

    and there is always two switch in the P0 , which was setting as interrupt toggle. does it effect?

     

  • Bit 5 of P0SEL should be set to 1 if you want to use ADC on P0.5. It should be like

    P0SEL |= 0x20;

  • does this warning matter ?

    Warning[Pe167]: argument of type "char *" is incompatible with parameter of type "unsigned char *" ?

  • No, it doesn't matter.

  • Hi chen , it doesn't work , i showing my code as below  please  correct me if i wrong 。

    初始化:

    void BatteryCheckinit( uint8 reference )
    {
      P0SEL |= 0x20;                 //设置P0.5为普通IO口
      P0DIR &= ~0x20;                 //P0.5定义为输入口
      HalAdcSetReference ( reference );
    }

    检测电量

    void BatteryCheck( uint8 channel, uint8 resolution )
    {
      
      uint16 BatteryValue;
      char str[16];
     
      BatteryValue = HalAdcRead (channel, resolution);
     
      sprintf(str,"%d",BatteryValue);
      HalUARTWrite(0,str,16);

    }

    APP初始化

    void zclIASZoneVibration_Init( byte task_id )
    {
      zclIASZoneVibration_TaskID = task_id;

      //------------------------配置串口---------------------------------
      MT_UartInit();                    //串口初始化
      MT_UartRegisterTaskID(task_id);   //注册串口任务
      HalUARTWrite(0,"UartInit OK\n", sizeof("UartInit OK\n"));
      
    //  Battery Checking 
    #ifdef  ExBatteryCheck
     
      BatteryCheckinit(HAL_ADC_CHN_VDD3);
      osal_start_timerEx( zclIASZoneVibration_TaskID, BATTERY_CHECK_EVT, 5000); //5秒后开始 触发电池检测事件
     
     #endif 
    }

    uint16 zclIASZoneVibration_event_loop( uint8 task_id, uint16 events )
    {
      afIncomingMSGPacket_t *MSGpkt;
      (void)task_id;  // Intentionally unreferenced parameter

      if ( events & SYS_EVENT_MSG )
      {
        while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclIASZoneVibration_TaskID )) )
        {
          switch ( MSGpkt->hdr.event )
          {
    ;

            case KEY_CHANGE:
              zclIASZoneVibration_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
              break;
    #ifdef KeyHoldCheckByCompare          
            case KEYHOLD_EVT:
              zclIASZoneVibration_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
              break;
    #endif          
           
            default:
              break;
          }

          // Release the memory
          osal_msg_deallocate( (uint8 *)MSGpkt );
        }

        // return unprocessed events
        return (events ^ SYS_EVENT_MSG);
      }

    /*
    */ 
     
    #ifdef  ExBatteryCheck
        if ( events & BATTERY_CHECK_EVT )
      {
        HalUARTWrite(0,"Battery checking\n", sizeof("Battery checking\n"));
       
        BatteryCheck( HAL_ADC_CHANNEL_5, HAL_ADC_RESOLUTION_14 );
       
        osal_start_timerEx( zclIASZoneVibration_TaskID, BATTERY_CHECK_EVT,3000 ); //86400000 days
        return ( events ^ BATTERY_CHECK_EVT );
         
      }
    #endif

      // Discard unknown events
      return 0;
    }

  • Try to call   BatteryCheckinit(HAL_ADC_CHN_VDD3); right before BatteryCheck( HAL_ADC_CHANNEL_5, HAL_ADC_RESOLUTION_14 );

  • Hi chen

             i fine the device will close the ADC input  when EOC flag happen,in HalADCRead function

    so i close it as below , but it doesn't work , uart  always showing 8191

      /* Disable channel after done conversion */
     // ADCCFG &= (adcChannel ^ 0xFF);

  • no, it doesn't work ,i just curious about is it matter there are some switch on the P0 ?

  • Hi  Chen ,

              i always curious about the IO initial setting, as we know the key should be set to 1 as Peripheral function

    but why the JOY_key set pin function to GPIO when key initial as below , the joy key using ADC6  :

    HAL_KEY_JOY_MOVE_SEL &= ~(HAL_KEY_JOY_MOVE_BIT); /* Set pin function to GPIO */
    HAL_KEY_JOY_MOVE_DIR &= ~(HAL_KEY_JOY_MOVE_BIT); /* Set pin direction to Input */

  • You can refer to Section 6.4 Joystick in  SmartRF05EB User's Guide.

    The two aggregated signals, JOY_MOVE and JOY_LEVEL, can be used to detect a joystick
    event. JOY_MOVE is high whenever the joystick is moved away from the centre position,
    including pushing. The other signal, JOY_LEVEL, is a voltage level signal that gives different
    values depending on the current position of the joystick.


    And also check the schematic of Joystick on page 46.

  • so ,if i use ADC5 for checking battery , should i set ADC5 as GPIO first in BatteryCheckinit????

     

     

  • No, you should set it to peripheral function directly when you use it as ADC input.

  • i have change the function as below , and bring the ADC5(P05) to 0.52v ,

     but it doesn't send any other result to PC ,it always send 8191 

    void BatteryCheckinit( uint8 reference )
    {
      P0SEL |= 0x20;                 //设置P0.5为普通IO口
      P0DIR &= ~0x20;                 //P0.5定义为输入口
      HalAdcSetReference ( reference );
    }

    #ifdef  ExBatteryCheck
        if ( events & BATTERY_CHECK_EVT )
      {
        BatteryCheckinit(HAL_ADC_CHN_VDD3);
       
        HalUARTWrite(0,"Battery checking\n", sizeof("Battery checking\n"));
       
        BatteryCheck( HAL_ADC_CHANNEL_5, HAL_ADC_RESOLUTION_14 );
       
        osal_start_timerEx( zclIASZoneVibration_TaskID, BATTERY_CHECK_EVT,3000 ); //86400000 days
        return ( events ^ BATTERY_CHECK_EVT );
         
      }
    #endif

  • Do you use SmartRF05EB to test this ADC reading? I try it with SmartRF05EB+CC2530EM and the following code.

      uint16 adc_ain5=0;

      HalAdcSetReference(HAL_ADC_REF_125V);
      adc_ain5=HalAdcRead(HAL_ADC_CHN_AIN5,HAL_ADC_RESOLUTION_10);
      sprintf(msg,"ADC:%d",adc_ain5);
      HalLcdWriteString( (char *)msg, HAL_LCD_LINE_3 );

    And everything works fine.

  • No ,i have not SmartRF05EB:

    My hardware setting :   P01  P04  ===》Key        P10  P11===>LED     P05 ADC =====> 0~ 1 V  testing 

    and UART Sending Msg to PC 

    do you have set the IO as ADC when initial setting

      P0SEL |= 0x20;                 //设置P0.5为普通IO口
      P0DIR &= ~0x20;                 //P0.5定义为输入口

    and does HAL_ADC_CHN_AIN5 same  with  HAL_ADC_CHANNEL_5 ??、

  • will  the effect data loss when we change uint16 to char ?????

    about the warning  : Warning[Pe167]: argument of type "char *" is incompatible with parameter of type "unsigned char *"

    is there any other way to monitor the HalADCread data

  • 1. No, I don't set IO as ADC. I define HAL_ADC in my project and that's enough. Do you define HAL_ADC in your project?

    2. Yes, HAL_ADC_CHN_AIN5 is the same with HAL_ADC_CHANNEL_5

  • 1. yes  i did ,  

    /* Set to TRUE enable ADC usage, FALSE disable it */
    #ifndef HAL_ADC
    #define HAL_ADC TRUE
    #endif

    so i don't need to put those code in the BatteryChecking initial function

    P0SEL |= 0x20;                 //设置P0.5为普通IO口
      P0DIR &= ~0x20;                 //P0.5定义为输入口

  • Yes, you don't have to put those codes. If it still doesn't work, I suggest you to check your HW connection first.

  • that make me so confuse

    if there is only define the HAL_ADC  and  without any other setting  (just like port input or output )

    how can the device know the port direction?

  • You would see "ADCCFG |= adcChannel;" in API HalAdcRead which enables analog peripheral I/O. You can refer to APCFG register in swru191.

  • Hi  chen ,

                 it have  change ,but i don't think that is right。

                i have take several different voltage to test as 0.19V, 0.5V, 0.7V ,1V

               there is always those value just like 2035,2037.2039

               and those value are not in order follow the  testing voltage up