Showing posts with label LAUNCHXL-CC1352R1. Show all posts
Showing posts with label LAUNCHXL-CC1352R1. Show all posts

Tuesday, September 1, 2020

How to remove OAD feature on CC26x2/CC13x2 project_zero

 The following steps show you how to remove OAD feature on CC26x2/CC13x2 project_zero

 1. Replace C:\ti\simplelink_cc13x2_26x2_sdk_4_10_03_02_eng\examples\rtos\CC26X2R1_LAUNCHXL\ble5stack\project_zero\tirtos\ccs\cc13x2_cc26x2_app.cmd
   with C:\ti\simplelink_cc13x2_26x2_sdk_4_10_03_02_eng\examples\rtos\CC26X2R1_LAUNCHXL\ble5stack\simple_peripheral\tirtos\ccs\cc13x2_cc26x2_app.cmd
   
2. Check "Exclude from build" on project_zero OAD folder in CCS Project Explorer.

3. Remove all OAD_xxx related code from projec_zero.c and _imgHdr

4. Change project_zero_app.cfg

m3Hwi.nvicCCR.UNALIGN_TRP = 0;
//m3Hwi.nvicCCR.UNALIGN_TRP = 1;

/* Put reset vector after OAD metadata */
var compilerOpts = prog.build.target.ccOpts.prefix; // Get the target compiler options
var regex = /(?:\-\-define\=)(\w*)(?:\=*\w*\s)/g;
var compilerDefs = [];
while ((tmp = regex.exec(compilerOpts)) !== null) compilerDefs.push(tmp[1]); // Parse compiler symbols

if (compilerDefs.indexOf('SECURITY') > -1) { // Check for SECURITY compiler symbol
    m3Hwi.resetVectorAddress = 0x90; // Image B Reset Vector Address
}
else {
    m3Hwi.resetVectorAddress = 0x50; // Image A Reset Vector Address
}

/* Put interrupt vector at start of RAM so interrupts can be configured at runtime */
m3Hwi.vectorTableAddress  = 0x20000000;

To

m3Hwi.nvicCCR.UNALIGN_TRP = 0;
//m3Hwi.nvicCCR.UNALIGN_TRP = 1;

/* Put reset vector at start of Flash */
m3Hwi.resetVectorAddress  = 0x0;

/* Put interrupt vector at start of RAM so interrupts can be configured at runtime */
m3Hwi.vectorTableAddress  = 0x20000000;

Monday, May 18, 2020

SwitchBot DIY using LPSTK-CC1352R , SG90 servo motor, and ProjectZero to away from COVID-19.

Due to COVID-19, people don't want to touch anything such as light switch arbitrarily and it is any super easy to DIY light switch robot to allow you to turn on or off light through BLE of you SmartPhone instead of touching the switch directly.

The follow steps show you how to DIY SwitchBot using Texas Instruments LPSTK-CC1352R, SG90 servo motor, and ProjectZero.

1. Add CONFIG_PWM_0 and use DIO22 as PWM output pin in project_zero.syscfg



2. Add "#include < ti/drivers/PWM.h >" and the following global variables in project_zero.c to use PWM related APIs later.

/* Period and duty in microseconds */
int16_t   pwmPeriod = 20000;
int16_t   duty = 1500;
int16_t   dutyInc = 500;

int16_t i=0;

/* Sleep time in microseconds */
PWM_Handle pwm1 = NULL;
PWM_Params params;

3. Add the following PZ_SERVO_EVT, servoClock, and Servo_clockHandler to send PZ_SERVO_EVT.

#define PZ_SERVO_EVT         11
static Clock_Struct servoClock;static void Servo_clockHandler(UArg arg);

static void Servo_clockHandler(UArg arg)
{
    //PWM_setDuty(pwm1, duty);
    pzButtonState_t *pButtonState = ICall_malloc(sizeof(pzButtonState_t));
            if(pButtonState != NULL)
            {
                //*pButtonState = buttonMsg;
                if(ProjectZero_enqueueMsg(PZ_SERVO_EVT, pButtonState) != SUCCESS)
                {
                  ICall_free(pButtonState);
                }
            }
}

4. Add "case PZ_SERVO_EVT:" in ProjectZero_processApplicationMessage to put SG90 back to original position after writing ON/OFF characteristics

      case PZ_SERVO_EVT:
      {
          PWM_setDuty(pwm1, duty);
          break;
      }


5.  Init/start servoClock and PWM in ProjectZero_init.

    Util_constructClock(&servoClock, Servo_clockHandler, 300, 0, false, 0);
    Util_startClock(&servoClock);

    PWM_init();
    PWM_Params_init(&params);
    params.dutyUnits = PWM_DUTY_US;
    params.dutyValue = 0;
    params.periodUnits = PWM_PERIOD_US;
    params.periodValue = pwmPeriod;
    pwm1 = PWM_open(CONFIG_PWM_0, &params);
    if (pwm1 == NULL) {
        /* CONFIG_PWM_0 did not open */
        while (1);
    }

    PWM_start(pwm1);
    PWM_setDuty(pwm1, duty);

6. In "case LS_LED0_ID:..." section of ProjectZero_LedService_ValueChangeHandler. Add the following code to set PWM to rotate SG90 servo motor according to ON/OFF characteristics writing.

        if (pCharData->data[0]!=0){
            PWM_setDuty(pwm1, duty-500);
            Util_startClock(&servoClock);
        }
        else{
            PWM_setDuty(pwm1, duty+800);
            Util_startClock(&servoClock);
        }


7. Build and download firmware into LPSTK-CC1352R

8. Connect GND/3V3/DIO22 pins on LPSTK-CC1352R to BROWN(GND)/RED(PWR)/ORANGE(PWM) on SG90.

9. Power on LPSTK-CC1352R and use TI SimpleLink Starter App to connect to Project Zero to toggle ON/OFF.






Wednesday, December 18, 2019

How to change CC26xx/CC13xx UART baudrate dynamically in your application.

The following steps show you how to change CC26xx/CC13xx UART baudrate dynamically in your application.

1. In port pininterrupt example into your CCS.

2. Add the following header files for UART and task related stuffs.

    #include <ti/sysbios/knl/Task.h>
    #include <ti/drivers/UART.h>
    #include <stdint.h>

3. Add the following defines and global variables for UART and task related stuffs.

    #define TASKSTACKSIZE     768
    uint32_t baudrate=115200;
    bool baudrate_change=false;
    UART_Handle uart;
    UART_Params uartParams;

    Task_Struct task0Struct;
    Char task0Stack[TASKSTACKSIZE];

4. Add the following red codes into buttonCallbackFxn to change baudrate when BTN1 is pressed.

            case Board_BUTTON1:
                currVal =  PIN_getOutputValue(Board_LED1);
                PIN_setOutputValue(ledPinHandle, Board_LED1, !currVal);
                if(baudrate==115200){
                    const char echoBaudrateChange[] = "\fChange Baudrate to 9600:\r\n";
                    UART_write(uart, echoBaudrateChange, sizeof(echoBaudrateChange));
                    baudrate=9600;
                }else{
                    const char echoBaudrateChange[] = "\fChange Baudrate to 115200:\r\n";
                    UART_write(uart, echoBaudrateChange, sizeof(echoBaudrateChange));
                    baudrate=115200;
                }
                baudrate_change=true;
                break;


5. Add the following function echoFxn()

Void echoFxn(UArg arg0, UArg arg1)
{
    char input;
    const char echoPrompt[] = "\fEchoing characters:\r\n";

    /* Create a UART with data processing off. */
    UART_Params_init(&uartParams);

RESTART_UART:
    uartParams.writeDataMode = UART_DATA_BINARY;
    uartParams.readDataMode = UART_DATA_BINARY;
    uartParams.readReturnMode = UART_RETURN_FULL;
    uartParams.readEcho = UART_ECHO_OFF;
    uartParams.baudRate = baudrate;
    uart = UART_open(Board_UART0, &uartParams);

    if (uart == NULL) {
        System_abort("Error opening the UART");
    }

    UART_write(uart, echoPrompt, sizeof(echoPrompt));

    /* Loop forever echoing */
    while (1) {
        if(baudrate_change){
            UART_close(uart);
            uart=NULL;
            baudrate_change=false;
            goto RESTART_UART;
        }
        UART_read(uart, &input, 1);
        UART_write(uart, &input, 1);
    }
}


6. Add the following red codes in main function to start UART task.

int main(void)
{
    Task_Params taskParams;
    /* Call board init functions */
    Board_initGeneral();
    Board_initUART();

    /* Construct BIOS objects */
    Task_Params_init(&taskParams);
    taskParams.stackSize = TASKSTACKSIZE;
    taskParams.stack = &task0Stack;
    Task_construct(&task0Struct, (Task_FuncPtr)echoFxn, &taskParams, NULL);
...
}


7. Build and download firmware into LaunchPad to test it.

Wednesday, September 25, 2019

How to use internal temperature reading inside CC26xx/CC13xx

The following codes show you how to use internal temperature sensor reading inside CC26xx/CC13xx.

1. Add "#include DeviceFamily_constructPath(driverlib/aon_batmon.h)"

2. Use the following codes to do internal temperature sensor reading into curr_tmp.

    int32_t curr_tmp;
    AONBatMonEnable();
    curr_tmp=AONBatMonTemperatureGetDegC();
    AONBatMonDisable();

Wednesday, July 31, 2019

Use PWM_PERIOD_HZ/PWM_DUTY_FRACTION to generate PWM for TI CC26xx/CC13xx devices.


You can replace the following mainThread function call in pwmled2 example to use PWM_PERIOD_HZ/PWM_DUTY_FRACTION to generate PWM for TI CC26xx/CC13xx devices.



void *mainThread(void *arg0)
{
    /* Period and duty in microseconds */
    uint16_t   pwmPeriod = 1000; //1K Hz PWM
    uint16_t   pwmDutyRatio = 0; //Init PWM Duty Ratio
    uint16_t   pwmDutyRatioInc = 5; //PWM Duty Ratio increase every time
    uint16_t   pwmDutyRatioMax= 50; //Max PWM Duty Ratio

    pwmDutyRatio = (uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * pwmDutyRatio) / 100);

    /* Sleep time in microseconds */
    uint32_t   time = 50000;
    PWM_Handle pwm1 = NULL;
    PWM_Handle pwm2 = NULL;
    PWM_Params params;

    /* Call driver init functions. */
    PWM_init();

    PWM_Params_init(&params);
    params.dutyUnits = PWM_DUTY_FRACTION;
    params.dutyValue = (uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * pwmDutyRatio) / 100);
    params.periodUnits =  PWM_PERIOD_HZ;
    params.periodValue = pwmPeriod;
    pwm1 = PWM_open(Board_PWM0, &params);
    if (pwm1 == NULL) {
        /* Board_PWM0 did not open */
        while (1);
    }

    PWM_start(pwm1);

    pwm2 = PWM_open(Board_PWM1, &params);
    if (pwm2 == NULL) {
        /* Board_PWM0 did not open */
        while (1);
    }

    PWM_start(pwm2);

    /* Loop forever incrementing the PWM duty */
    while (1) {
        PWM_setDuty(pwm1, (uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * pwmDutyRatio) / 100));

        PWM_setDuty(pwm2, (uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * pwmDutyRatio) / 100));

        pwmDutyRatio = (pwmDutyRatio + pwmDutyRatioInc);

        if (pwmDutyRatio == pwmDutyRatioMax || (!pwmDutyRatio)) {
            pwmDutyRatioInc = - pwmDutyRatioInc;
        }

        usleep(time);
    }
}

Tuesday, December 4, 2018

How to detect button hold in CC26x2, CC13x0, CC13x2 SDK.

The following steps show you how to detect button hold in CC26x2, CC13x0, CC13x2 SDK. I use zed_switch example to add related code to detect if right button (active-low) is pressed (low status) and hold for 3 seconds.

1. In board_key.c, change Board_PIN_BUTTON1 to use PIN_IRQ_BOTHEDGES

static PIN_Config keyPinTable[] = {
      Board_PIN_BUTTON0 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
      Board_PIN_BUTTON1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES,
      PIN_TERMINATE /* Terminate list */
    };


2. Add the following red codes in board_key.c

#include <ti/sysbios/knl/Clock.h>
...
UInt32 button_pressed_time=0;
UInt32 button_released_time=0;
static void board_key_keyFxn(PIN_Handle keyPinHandle, PIN_Id keyPinId)
{
    (void)keyPinHandle;

    if(keyPinId == keyButton0)
    {
        keysPressed |= KEY_LEFT;
    }
    else if(keyPinId == keyButton1)
    {
        if(PIN_getInputValue(keyButton1) == false){
            button_pressed_time=Clock_getTicks(); //Clock_getTicks will return counts in 10us.
            return;
         } else {
            if (PIN_getInputValue(keyButton1) == true){
                button_released_time=Clock_getTicks(); //Clock_getTicks will return counts in 10us.
            }
        }
        if ( (button_released_time-button_pressed_time)>300000 )
            keysPressed |= KEY_RIGHT_HOLD_3SEC;
        else if ( (button_released_time-button_pressed_time)>0 )
            keysPressed |= KEY_RIGHT;

    }

    if(Timer_isActive(&keyChangeClock) != true)
    {
        Timer_start(&keyChangeClock);
    }
}

3. Define KEY_RIGHT_HOLD_3SEC in board_key.h

/*! Select Key ID */
#define KEY_SELECT            0x01
/*! Up Key ID */
#define KEY_UP                0x02
/*! Down Key ID */
#define KEY_DOWN              0x04
/*! Left Key ID */
#define KEY_LEFT              0x08
/*! Right Key ID */
#define KEY_RIGHT             0x10
/*! Hold 3 seconds Right Key ID */
#define KEY_RIGHT_HOLD_3SEC   0x20


4. Add "if(keysPressed == KEY_RIGHT_HOLD_3SEC){...}" in zclSampleSw_processKey of zcl_samplesw.c to process event for right button pressing and holding for 3 seconds.

static void zclSampleSw_processKey(uint8 keysPressed)
{
    //Button 1
    if(keysPressed == KEY_LEFT)
    {
        zstack_bdbStartCommissioningReq_t zstack_bdbStartCommissioningReq;

        if(ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE)
        {
            zstack_bdbStartCommissioningReq.commissioning_mode = BDB_COMMISSIONING_MODE_NWK_FORMATION | BDB_COMMISSIONING_MODE_NWK_STEERING | BDB_COMMISSIONING_MODE_FINDING_BINDING;
            Zstackapi_bdbStartCommissioningReq(zclSampleSw_Entity,&zstack_bdbStartCommissioningReq);
        }
        else if (ZG_BUILD_JOINING_TYPE && ZG_DEVICE_JOINING_TYPE)
        {
            zstack_bdbStartCommissioningReq.commissioning_mode = BDB_COMMISSIONING_MODE_NWK_STEERING | BDB_COMMISSIONING_MODE_FINDING_BINDING;
            Zstackapi_bdbStartCommissioningReq(zclSampleSw_Entity,&zstack_bdbStartCommissioningReq);
        }
    }
    //Button 2
    if(keysPressed == KEY_RIGHT)
    {
        zstack_bdbGetZCLFrameCounterRsp_t Rsp;

        Zstackapi_bdbGetZCLFrameCounterReq(zclSampleSw_Entity, &Rsp);
        zclGeneral_SendOnOff_CmdToggle( SAMPLESW_ENDPOINT, &zclSampleSw_DstAddr, FALSE, Rsp.zclFrameCounter );
    }
    if(keysPressed == KEY_RIGHT_HOLD_3SEC)
    {
        //Event for right button pressing and holding for 3 seconds.
    }


}