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.

LAUNCHXL-CC2640R2: Waveform Generation

Part Number: LAUNCHXL-CC2640R2

What is the best way to generate a waveform using the LAUNCHXL-CC2640R2 (and possibly other tools such as Sensor Controller Studio)?

Specifically, I would like to generate a burst of square or sinusoidal pulses at a frequency of 40kHz and voltage of 5V for about 1ms. Then wait (stay idle) for 100ms. Then repeat the 1ms bursts. This loop should continue infinitely or until the program is terminated.

The time durations of 100ms and 1ms are flexible, these are just to provide an idea of the functionality. The basic goal is for the microcontroller to emit 40kHz pulses intermittently.

I am new to embedded programming, so I am wondering what is the best method. I read the Sensor Controller Studio can be used for waveform generation. I could also maybe use the AUX Timer 0 since it counts up to a specified delay value and then pulses an event output signal? But I am unsure of how I would set the frequency of this and make the pulse repeat for 1ms and then stay idle for 100ms.

Thank you in advance for the help.

  • Hi Namya,

    This depends a lot on the type of pulses you aim to generate. There is no way to generate an actual sinusoidal wave, the best you can do is to use the PWM (and some period/dutycycle trickery) to output a signal you could filter into a sinus wave. Square pulses is simpler, if the frequency is fixed, just use PWM. 

    As for the 5V level part, you would have to have some level transition in HW here as the device cannot output 5V (it can also not tolerate 5V on the input).  

  • Thank you for the response!

    A fixed-frequency 40kHz square pulse will work just fine, so I can go with that. Would you be able to guide me to some resources on how to implement this through PWM? Would I have to use Sensor Controller Studio or any other module?

    Thanks!

  • Hi Namya,

    i recommend you have a look at the pwmled example in the SDK. It is also recommended to have a look at the TI Drivers documentation for more information on ho to use the PWM driver: 

    http://dev.ti.com/tirex/explore/node?node=ADfS7ixpgUmHy56H6NON4Q__krol.2c__LATEST

  • The solution proposed by M-W will work, another option to generate a square pulse in Sensor Controller is to use the gpioSetOutput function and wait for timer0 in a loop. You must write this solution in sensor Controller Studio and start stop the task from the main application processor (CM3). General training found here:

    http://dev.ti.com/tirex/explore/node?node=ACM1I4m9AXxcH-booxaNDg__krol.2c__LATEST

  • Thank you very much for the help.

    I am now trying to modify the pwmled2 example project to fit my specifications. Below is my modified code so far in the main thread of pwmled2.c. Everything else is in the example project is the same as how I downloaded it.

    I am trying to generate a burst of pulses at 50% duty cycle for a short amount of time (time_fast) and then have it stay idle at a duty cycle of 0 for a longer period of time (time_slow). However, the duty cycle never changes from 0 to anything else in my while loop even though I am using  PWM_setDuty(). I tried different values but it always stays at 0 (or whatever value it is initialized to outside the while loop). How can I fix this?

    void *mainThread(void *arg0)

    {

        /* Period and duty in microseconds */

        uint16_t   pwmPeriod = 25;

        uint16_t   duty = 0;

        /* Sleep time in microseconds */

        uint32_t   time_slow = 100000; // delay between stages of LED

        uint32_t   time_fast = 1000;

        PWM_Handle pwm1 = NULL;

        PWM_Params params;

        /* Call driver init functions. */

        PWM_init();

        PWM_Params_init(&params);

        params.dutyUnits = PWM_DUTY_FRACTION;

        params.dutyValue = 0;

        params.periodUnits = PWM_PERIOD_US;

        params.periodValue = pwmPeriod;

        pwm1 = PWM_open(Board_PWM0, &params);

        if (pwm1 == NULL) {

            /* Board_PWM0 did not open */

            while (1);

        }

        PWM_start(pwm1);

        /* Loop forever incrementing the PWM duty */

        while (1) {

            printf("duty first %d\n", duty);

            if (duty == 0) {

                printf("duty slow %d\n", duty);

                usleep(time_slow);

                PWM_setDuty(pwm1, 0.5);

            }

            else if (duty != 0) {

                printf("duty fast %d\n", duty);

                usleep(time_fast);

                PWM_setDuty(pwm1, 0);

                printf("DUTY SET %d\n", duty);

            }

            else {

                printf("wrong duty %d\n", duty);

            }

        }

    }

  • Hi Namya,

    i would recommend you to look closer at the PWM documentation, it is not very intuitive how to use "fractions" in this driver. From the documentation:

    dutyValue = (uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 37) / 100);
    PWM_setDuty(pwm, dutyValue);  // set duty cycle to 37%

  • Thank you!

    I am able to generate a signal that turns on and off intermittently. However, I am not yet able to control the time duration the signal is on and off for. Using usleep() (commented out below) does not seem to have any effect on the time duration. Is there another way to control the time duration the pulse stays on and off? For example, outputting burst for 1ms and staying idle for 100ms.

    Additionally, would it be possible to control the number of pulses? For example, generate 5 40kHz square pulses every 100ms. I realize I can use a counter to just increment the number of pulses to 5, but I do not know how to generate just one single pulse. Currently, the signal produces bunch of square waves for the amount of time it is on.

    void *mainThread(void *arg0)

    {

        /* Period and duty */

        uint16_t   pwmPeriod = 40000; // in Hz

        uint32_t   duty;

        /* Sleep time in microseconds */

    //    uint32_t   time_slow = 10000000; // idle duration

    //    uint32_t   time_fast = 1000; // burst duration

        PWM_Handle pwm1 = NULL;

        PWM_Params params;

        /* Call driver init functions. */

        PWM_init();

        PWM_Params_init(&params);

        params.dutyUnits = PWM_DUTY_FRACTION;

        params.dutyValue = 0;

        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);

        /* Loop forever incrementing the PWM duty */

        while (1) {

            printf("duty first %d\n", duty);

            if (duty == 0) {

                duty = (uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 50) / 100);

    //            usleep(time_slow);

            }

            else if (duty != 0) {

                duty = (uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 0));

    //            usleep(time_fast);

                PWM_setDuty(pwm1, duty);

                printf("DUTY SET %d\n", duty);

            }

            else {

                printf("wrong duty %d\n", duty);

            }

        }

    }

  • Hi Namya,

    In this case, I think you should look closer at the Sensor Controller as suggested by Eirik above. For normal "Digital Output Pins" you have the option to use the "gpioGenPulseTrain" which basically lets you generate a given number of pulses in a single shot. 

  • Thank you. I will take a look. Is there an example project I could look at that incorporates this?

    What about just controlling the time duration? Not the number of pulses. Like I mentioned, usleep() did not have any effect on the time duration of how long the LED stayed on/off. Is there another way that I am missing?

  • usleep() is simply a task delay, The code above seemed to really only set the duty to 0. In theory, you could something along the lines what you were doing:

    Set duty to X

    sleep(short)

    Set duty to Y

    sleep(long)

    repeat

    As for the pulse train in SC, you specify the exact number of pulses you want, so you could do something like:

    sendPulses()

    wait()

    sendPulses()

    ...