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.

RTOS/CC1310: RTOS/CC1310

Part Number: CC1310
Other Parts Discussed in Thread: TMP116, SYSBIOS

Tool/software: TI-RTOS

How to reduce power consumption in standby mode of my personalized PCB, this board interfaced with the sensor tmp116, also I used a CC130 4x4 mm and communication RF, please?

  • Hello,

    In standby mode many peripherals and PD can still be active. I recommend you power down the domains in use before going into standby mode.

    Regards,
    AB
  • Hi and thank you for your reply,

    Can you expalain, how to do it, please ?

  • Hello,

    We provide power management APIs that will allow you to control the parent power domains of each peripheral. Our techncial reference manaual has a very good and descriptive section on how our power management works and diagrams that show you where each peripheral lies()

    As for the APIs we have a specific power management document that walks you through it: 

    We also provide a Pin shutdown example and a pin standby example, you can use this to understand the drivers better.

    Regards,

    AB

  • thank you for your reply,
    Here is my code, thank you for explaining me how to add the part of power management, I tried with semaphore and constraints but the current is always the same.

    ----------------------------------------Main---------------------------------------------------------------------------------------------------------------------------------
    * POSIX Header files */
    #include <pthread.h>
    #include <stdlib.h>
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Error.h>
    #include <stdint.h>
    #include <stddef.h>
    #include <unistd.h>
    #include <semaphore.h>


    /* BIOS Header files */
    #include <ti/drivers/rf/RF.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/I2C.h>


    /* TI-RTOS Header files */
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/Power.h>

    #include <ti/devices/cc13x0/driverlib/aon_batmon.h>
    #include <ti/devices/cc13x0/driverlib/aux_adc.h>
    #include <ti/devices/cc13x0/driverlib/chipinfo.h>
    #include <ti/devices/cc13x0/driverlib/sys_ctrl.h>
    #include <semaphore.h>
    #include <ti/sail/tmp116/tmp116.h>

    /* Board Header files */
    #include "Board.h"

    /* EasyLink API Header files */
    #include "easylink/EasyLink.h"



    #include "version.h"
    #include "../sonde_gw_fw/sys_intf.h"

    #include <string.h>
    #include <math.h>

    #define RFEASYLINKTX_TASK_STACK_SIZE 1024
    #define RFEASYLINKTX_TASK_PRIORITY 2

    #define RFEASYLINKTX_BURST_SIZE 1
    #define THREADSTACKSIZE 768

    #define SAMPLE_TIME 1 /*In seconds*/
    #define TMP_TASK_STACK_SIZE 768

    TMP116_Handle tmp116Handle = NULL;
    I2C_Handle i2cHandle = NULL;
    sem_t tmp116Sem;

    uint8_t SavedBattery;


    /* Global sample rate which may be accessed and set from GUI Composer App */
    volatile uint16_t sampleTime;

    /*
    * ======== tmp116Callback ========
    * When an ALERTing condition is met on the TMP116 hardware, the ALERT pin
    * is asserted generating an interrupt. This callback function serves as
    * an ISR for a single TMP116 sensor.
    */
    void tmp116Callback(uint_least8_t index)
    {
    sem_post(&tmp116Sem);
    }

    /*
    * ======== tmp116AlertTask ========
    * This task is unblocked when the ALERT pin is asserted and generates an
    * interrupt. When the TMP116 is in INTERRUPT mode, the status register must
    * be read to clear the ALERT pin.
    */

    void *tmp116AlertTask(void *arg0)
    {
    uint16_t data;

    while(1) {

    /* Pend on semaphore, tmp116Sem */
    if (0 == sem_wait(&tmp116Sem)) {

    /* Reads status register, resetting the ALERT pin */
    TMP116_readStatus(tmp116Handle, &data);

    /* Check Object Temperature High Flag */
    if (data & TMP116_STAT_ALR_HI) {
    }

    /* Check Object Temperature Low Flag */
    if (data & TMP116_STAT_ALR_LO) {
    }

    }
    }
    }


    Task_Struct txTask; /* not static so you can see in ROV */
    static Task_Params txTaskParams;
    static uint8_t txTaskStack[RFEASYLINKTX_TASK_STACK_SIZE];

    Task_Struct sensorTask; /* not static so you can see in ROV */
    static Task_Params sensorTaskParams;
    static uint8_t sensorTaskStack[RFEASYLINKTX_TASK_STACK_SIZE];

    typedef struct {
    uint8_t reason;
    int8_t temp_deg_frac_8;
    uint8_t temp_deg_frac_8_vir;
    uint8_t bat_20mV;
    } opto_sonde_data_t;

    typedef struct {
    int8_t temp_MSB;
    uint8_t temp_LSB;
    }data_t;

    void sleepAndReset(uint32_t sleep_time_secs) {

    uint32_t secs = sleep_time_secs;
    while (secs > 0)
    {
    uint32_t sleep_s = secs > 2000 ? 2000 : secs;
    Task_sleep((sleep_s * 1000u * 1000) / Clock_tickPeriod);
    secs -= sleep_s;
    }

    SysCtrlSystemReset();
    }

    static void rfEasyLinkTxFnx(UArg arg0, UArg arg1)
    {

    opto_sonde_data_t* optosonde_data = (opto_sonde_data_t*) arg0;

    EasyLink_init(EasyLink_Phy_Custom);

    /*
    * If you wish to use a frequency other than the default, use
    * the following API:
    * EasyLink_setFrequency(868000000);
    */

    /* Set output power to 12dBm */
    // EasyLink_setRfPwr(12);
    EasyLink_setRfPwr(10);

    EasyLink_TxPacket txPacket;

    // Fill packet data
    uint8_t payload_ptr = 0;
    // Payload version
    txPacket.payload[payload_ptr++] = (uint8_t) (0x0);
    // Src MAC
    EasyLink_getIeeeAddr(&txPacket.payload[payload_ptr]);
    payload_ptr += 8;

    // Copy data
    txPacket.payload[payload_ptr++] = (uint8_t) (optosonde_data->reason);
    txPacket.payload[payload_ptr++] = (uint8_t) (optosonde_data->temp_deg_frac_8 );
    txPacket.payload[payload_ptr++] = (uint8_t) (optosonde_data->temp_deg_frac_8_vir);
    txPacket.payload[payload_ptr++] = (uint8_t) (optosonde_data->bat_20mV);
    // Firmware version
    memcpy(&txPacket.payload[payload_ptr], &VERSION_HASH, sizeof(VERSION_HASH));
    payload_ptr += sizeof(VERSION_HASH);

    txPacket.len = payload_ptr;
    txPacket.absTime = 0;
    txPacket.dstAddr[0] = OPTOSONDE_ADDR;

    EasyLink_Status result = EasyLink_transmit(&txPacket);

    if (result == EasyLink_Status_Success)
    {
    /* Toggle LED1 to indicate TX */
    // PIN_setOutputValue(pinHandle, Board_PIN_LED1,!PIN_getOutputValue(Board_PIN_LED1));
    }
    else
    {
    /* Toggle LED1 and LED2 to indicate error */
    // PIN_setOutputValue(pinHandle, Board_PIN_LED1,!PIN_getOutputValue(Board_PIN_LED1));
    // PIN_setOutputValue(pinHandle, Board_PIN_LED2,!PIN_getOutputValue(Board_PIN_LED2));
    }

    Task_sleep(5);
    }

    void sendorTask_AlertCB(UArg arg0, UArg arg1)
    {
    static opto_sonde_data_t optosonde_data;
    optosonde_data.reason = optosonde_reason_periodic;
    data_t* temptread =(data_t* )arg0;

    optosonde_data.temp_deg_frac_8 = (temptread->temp_MSB);
    optosonde_data.temp_deg_frac_8_vir = (temptread->temp_LSB);
    if (!AONBatMonNewBatteryMeasureReady())
    {
    // Wait
    optosonde_data.bat_20mV =SavedBattery;
    }
    else{
    SavedBattery = (AONBatMonBatteryVoltageGet() * 390625) / 2000000;
    optosonde_data.bat_20mV = SavedBattery;
    AONBatMonDisable();

    }

    // Init Tx task
    Task_Params_init(&txTaskParams);
    txTaskParams.stackSize = RFEASYLINKTX_TASK_STACK_SIZE;
    txTaskParams.priority = RFEASYLINKTX_TASK_PRIORITY + 1;
    txTaskParams.stack = &txTaskStack;
    txTaskParams.arg0 = (xdc_UArg) &optosonde_data;

    Task_construct(&txTask, rfEasyLinkTxFnx, &txTaskParams, NULL);

    }


    /*
    * ======== mainThread ========
    */
    void *mainThread(void *argc)
    {

    static data_t temptread;
    int8_t MSB;
    uint8_t LSB;
    float tempToread;
    I2C_Handle i2cHandle;
    I2C_Params i2cParams;
    int retc;
    pthread_t alertTask;
    pthread_attr_t pAttrs;
    sampleTime = SAMPLE_TIME;
    TMP116_Params tmp116Params;

    /* Call driver init functions */
    //GPIO_init();
    I2C_init();
    TMP116_init();


    /* Create I2C for usage */
    I2C_Params_init(&i2cParams);

    i2cParams.bitRate = I2C_400kHz;

    i2cHandle = I2C_open(Board_I2C_TMP, &i2cParams);
    if (i2cHandle == NULL) {
    while (1);
    }
    else {
    }

    if(0 != sem_init(&tmp116Sem,0,0))
    {
    /* sem_init() failed */
    while (1);
    }

    pthread_attr_init(&pAttrs);
    pthread_attr_setstacksize(&pAttrs, TMP_TASK_STACK_SIZE);
    retc = pthread_create(&alertTask, &pAttrs, tmp116AlertTask, NULL);
    if (retc != 0) {
    /* pthread_create() failed */
    while (1);
    }

    /* Initialize tmp116Params structure to defaults */
    TMP116_Params_init(&tmp116Params);

    /* Callback for ALERT event */
    tmp116Params.callback = &tmp116Callback;

    /* Open TMP116 sensor with custom Params */
    tmp116Handle = TMP116_open(Board_TMP007_ROOMTEMP, i2cHandle, &tmp116Params);

    /* Check if the open is successful */
    if (tmp116Handle == NULL) {
    while(1);
    }

    /* Allow the sensor hardware to complete its first conversion */
    sleep(2);


    /* Get Die Temperature in Celsius */
    if (!TMP116_getTemp(tmp116Handle, TMP116_CELSIUS,&tempToread)) {

    }

    /* Begin infinite task loop */
    while (1) {

    TMP116_getTemp(tmp116Handle, TMP116_CELSIUS, &tempToread);
    /* Get Die and Object Temperatures */
    MSB = (int8_t )tempToread;
    LSB = (uint8_t )((tempToread-MSB) * 100);
    temptread.temp_MSB=MSB;
    temptread.temp_LSB=LSB;

    // Sensor task
    Task_Params_init(&sensorTaskParams);
    sensorTaskParams.stackSize = RFEASYLINKTX_TASK_STACK_SIZE;
    sensorTaskParams.priority = RFEASYLINKTX_TASK_PRIORITY;
    sensorTaskParams.stack = &sensorTaskStack;
    sensorTaskParams.arg0 = (xdc_UArg) &temptread;

    Task_construct(&sensorTask, sendorTask_AlertCB, &sensorTaskParams, NULL);

    // Tell RTC to sleep
    #ifdef OPTOSONDE_DEMO_MODE
    uint32_t sleep_time_s = 30;
    #elif OPTOSONDE_VITICODE
    uint32_t sleep_time_s = 10 * 60;
    #else
    uint32_t sleep_time_s = 1 *60;
    #endif

    sleepAndReset(sleep_time_s);

    }
    }

    /*
    * ======== main ========
    */

    void maini2c(void)
    {
    pthread_t thread;
    pthread_attr_t pAttrs;
    struct sched_param priParam;
    int retc;
    int detachState;

    /* Set priority and stack size attributes */
    pthread_attr_init(&pAttrs);
    priParam.sched_priority = 1;

    detachState = PTHREAD_CREATE_DETACHED;
    retc = pthread_attr_setdetachstate(&pAttrs, detachState);
    if (retc != 0) {
    // /* pthread_attr_setdetachstate() failed */
    while (1);
    }

    pthread_attr_setschedparam(&pAttrs, &priParam);

    retc |= pthread_attr_setstacksize(&pAttrs, THREADSTACKSIZE);
    if (retc != 0) {
    /* pthread_attr_setstacksize() failed */
    while (1);
    }

    retc = pthread_create(&thread, &pAttrs, mainThread, NULL);
    if (retc != 0) {
    /* pthread_create() failed */
    while (1);
    }

    /* destroy pthread attribute */
    pthread_attr_destroy(&pAttrs);
    }


    int opto_main(void)
    {

    /* Call driver init functions. */
    maini2c();
    Board_initGeneral();

    /* Start BIOS */
    BIOS_start();

    return (0);
    }
  • Hello,

    I do not see how you making the MCU sleep. I do see that you are calling a task sleep, but this just blocks the task where you called this from. You still have the sensor task running and then the easylink task running. Also you need to take into consideration that if you do not power off the sensor the current is not going to come down. I suggest having tasks that run on while loops (forever) and pend on semaphores instead of reseting the MCU and restarting everything again.

    Regards,
    AB
  • Hello and thank you for your answer,
    very good explanation, is it the threads that makes the sensor still work?
    can you help me to correct my code? because I do not know how to implement the task you talked about.
  • A number of the examples here: dev.ti.com/.../ show how to use tasks etc.

    To get the fundamentals, see the videos linked to from:
    processors.wiki.ti.com/.../TI-RTOS
  • Hello and thank you for your answer,
    very good explanation, is it the threads that makes the sensor still work?
    can you help me to correct my code? because I do not know how to implement the task you talked about.
  • We only write code as examples. You have to use the examples as a starting point for your code.
  • Thank you for repley
    So why the forum ?