Hi,
is there an example showing the PWM on CC2650 running in the background without the CPU?
Is there any CC2650 RTOS PWM drivers available?
Thanks,
Michael
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.
can you post your Board.c file? I'm having trouble with this. It would be nice to see a working example.
Michael,
Many thanks for posting that. I looked through it and have a question about the CC2650_PWM0 parameter: (as in your original question)
Here we have the configuration
// PWM configuration, one per PWM output
PWMCC26XX_HwAttrs pwmCC26xxHWAttrs[CC2650_PWMCOUNT] = {
{ .pwmPin = Board_PWMPIN0, .gpTimerUnit = CC2650_GPTIMER0A } ,
{ .pwmPin = Board_PWMPIN1, .gpTimerUnit = CC2650_GPTIMER0B } ,
};
I'm assuming this is where the PWM Pins are initialized.
However, in the sample code for main, I don't see any reference to these pins?
I also don't see any other reference to CC2650_PWM0 so its not clear how this maps to Board_PWMPIN0 if that is what is supposed to be happening.
void SimpleBLEPeripheralPWM_init(void)
{
PWM_Params pwmParams;
// Initialize the PWM driver.
PWM_init();
PWM_Params_init(&pwmParams);
pwmParams.idleLevel = PWM_IDLE_LOW; // Output low when PWM is not running
/* PWM in US with fractional duty cycle */
pwmParams.periodUnit = PWM_PERIOD_US;
pwmParams.periodValue = PERIOD_US;
pwmParams.dutyUnit = PWM_DUTY_FRACTION;
pwmParams.dutyValue = PWM_DUTY_FRACTION_MAX/2;
//handle = PWM_open(IOID_6, ¶ms);
PWM_Handle hPWM0 = PWM_open(CC2650_PWM0, &pwmParams);
if(hPWM0 == NULL) {
while(1);
}
PWM_start(hPWM0);
}
this is the example that I've seen in reference to this problem. However, I can't find the line of code that actually references the output pin.
There is this line:
PWM_Handle hPWM0 = PWM_open(CC2650_PWM0, &pwmParams);
However, CC2650_PWM0 is initialized , but never referenced in any of the files.
am I to assume that CC2650_PWM0 is simply supposed to be the first initialized PWM pin in the initialization list?
i.e does CC2650_PWM0 actually refer to
{ .pwmPin = Board_PWMPIN0, .gpTimerUnit = CC2650_GPTIMER0A } ,
which is the first line in the PWMCC26XX_HwAttrs structure
// PWM configuration, one per PWM output
PWMCC26XX_HwAttrs pwmCC26xxHWAttrs[CC2650_PWMCOUNT] = {
{ .pwmPin = Board_PWMPIN0, .gpTimerUnit = CC2650_GPTIMER0A } ,
{ .pwmPin = Board_PWMPIN1, .gpTimerUnit = CC2650_GPTIMER0B } ,
};
also, if I want to vary the period or duty while its running, where do I do that?
shouldn't there be a callback for that? I can't see where that would be set up in this example.
Hi Bruce,
in my project i didt the same but i open the PIN i want for the PWM.
First you have to declare "Board_PWMPIN1" in your Board.h file which GPIO it should be used:
#define Board_PWMPIN0 IOID_24
On Board.c you add it to the "BoardGpioInitTable[]":
Board_PWMPIN0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL ,
In main it will initiate the "BoardGpioInitTable":
PIN_init(BoardGpioInitTable);
By initialising your sensortag task or init function you add this:
hGpioPin = PIN_open(&pinGpioState, SensortagAppPinTable);
PWM_Params pwmParams;
PWM_Params_init(&pwmParams);
pwmParams.periodUnit = PWM_PERIOD_HZ;
pwmParams.periodValue = 614400;//100e3; <----------Here is the frequency you want
pwmParams.dutyUnit = PWM_DUTY_FRACTION; // Fractional duty cycle
pwmParams.dutyValue = PWM_DUTY_FRACTION_MAX/2; //50% duty
pwmParams.idleLevel = PWM_IDLE_LOW;
hPWM = PWM_open(CC2650_PWM0, &pwmParams);
if(hPWM == NULL ) { }
else PWM _start(hPWM);
If you want to change the Dulty Cycle or anything on the PWM you will have to do this on a semaphore with an event on your task function.
Something like this:
if (events & PWM_Dulty_Change_EVT){
PWM_stop(hPWM);
PWM_Params pwmParams;
PWM_Params_init(&pwmParams);
pwmParams.periodUnit = PWM_PERIOD_HZ;
pwmParams.periodValue = 614400;//100e3;
pwmParams.dutyUnit = PWM_DUTY_FRACTION; // Fractional duty cycle
pwmParams.dutyValue = PWM_DUTY_FRACTION_MAX/2; //50% duty<-------------------------Change Dulty
pwmParams.idleLevel = PWM_IDLE_LOW;
hPWM = PWM_open(CC2650_PWM0, &pwmParams);
if(hPWM == NULL ) {}e
else
PWM_start(hPWM);}
Use it as reference i dont know if it will work. But any change you do, use a smeaphore to wake up the task function and set an event to change your dulty.
Regards,
Michael
Thanks again for your help Michael.
can you point out in this code where the link is made between Board_PWMPIN0 and CC2650_PMW0 Is that done here:
// PWM configuration, one per PWM output
PWMCC26XX_HwAttrs pwmCC26xxHWAttrs[CC2650_PWMCOUNT] = {
{ .pwmPin = Board_SENS_LED1_EN, .gpTimerUnit = CC2650_GPTIMER0A } ,
{ .pwmPin = Board_SENS_LED2_EN, .gpTimerUnit = CC2650_GPTIMER0B } ,
// { .pwmPin = Board_PWMPIN2, .gpTimerUnit = CC2650_GPTIMER1A } ,
// { .pwmPin = Board_PWMPIN3, .gpTimerUnit = CC2650_GPTIMER1B } ,
// { .pwmPin = Board_PWMPIN4, .gpTimerUnit = CC2650_GPTIMER2A } ,
// { .pwmPin = Board_PWMPIN5, .gpTimerUnit = CC2650_GPTIMER2B } ,
// { .pwmPin = Board_PWMPIN6, .gpTimerUnit = CC2650_GPTIMER3A } ,
// { .pwmPin = Board_PWMPIN7, .gpTimerUnit = CC2650_GPTIMER3B } ,
};
If this is true then, where is CC2650_GPTIMER0A associated with CC2650_PMW0?
Or with the value 0 (which is the enumeration value)?
I need to known how to associate more then one LED
I am also confused about how the PWM actually works. Does it toggle the PIN for me?
I've run this example as is and I can't see any change in the LED output.
In other examples I've seen a function like this
/* * ======== heartBeatFxn ======== * Toggle the Board_LED0. The Task_sleep is determined by arg0 which * is configured for the heartBeat Task instance. */
Void heartBeatFxn(UArg arg0, UArg arg1)
{ while (1) { Task_sleep((UInt)arg0);
PIN_setOutputValue(ledPinHandle, Board_LED1, !PIN_getOutputValue(Board_LED1)); }
}
But in this particular example at e2e.ti.com/.../1729748 It does not show how to use the heartbeat function. Is this old code and no longer required with the new PWM driver?
This example seems to indicate that I have to toggle the LED myself. Yet there is no code in the example that actually calls this function.
Hi Bruce,
in the Board.c file you see at the bottom this:
/*
* ========================== PWM =========================================
*/
// GPTimer hardware attributes, one per timer unit (Timer 0A, 0B, 1A, 1B..)
const GPTimerCC26XX_HWAttrs gptimerCC26xxHWAttrs[CC2650_GPTIMERUNITSCOUNT] = {
{.baseAddr = GPT0_BASE, .intNum = INT_TIMER0A, .intPriority = (~0), .powerMngrId = PERIPH_GPT0, .pinMux = GPT_PIN_0A, },
{.baseAddr = GPT0_BASE, .intNum = INT_TIMER0B, .intPriority = (~0), .powerMngrId = PERIPH_GPT0, .pinMux = GPT_PIN_0B, },
};
// GPTimer objects, one per full-width timer (A+B) (Timer 0, Timer 1..)
GPTimerCC26XX_Object gptimerCC26XXObjects[CC2650_GPTIMERCOUNT];
// GPTimer configuration (used as GPTimer_Handle by driver and application)
const GPTimerCC26XX_Config GPTimerCC26XX_config[CC2650_GPTIMERUNITSCOUNT] = {
{ &gptimerCC26XXObjects[0], &gptimerCC26xxHWAttrs[0], GPT_A},
{ &gptimerCC26XXObjects[0], &gptimerCC26xxHWAttrs[1], GPT_B},
};
// PWM configuration, one per PWM output
PWMCC26XX_HwAttrs pwmCC26xxHWAttrs[CC2650_PWMCOUNT] = {
{ .pwmPin = Board_PWMPIN0, .gpTimerUnit = CC2650_GPTIMER0A } , <---------------------------------------Here is where the GPIO gets to the peripheral PWM Timer
{ .pwmPin = Board_PWMPIN1, .gpTimerUnit = CC2650_GPTIMER0B } ,
};
// PWM object, one per PWM output
PWMCC26XX_Object pwmCC26xxObjects[CC2650_PWMCOUNT];
extern const PWM_FxnTable PWMCC26XX_fxnTable;
//PWM configuration (used as PWM_Handle by driver and application)
const PWM_Config PWM_config[CC2650_PWMCOUNT+1] = {
{ &PWMCC26XX_fxnTable, &pwmCC26xxObjects[0], &pwmCC26xxHWAttrs[0] },
{ &PWMCC26XX_fxnTable, &pwmCC26xxObjects[1], &pwmCC26xxHWAttrs[1] },
{ NULL, NULL, NULL }
};
You dont have to do anything except on init() start the PWM with the parameters. If you want to see a LED blink you will have to have a very low frequency like 1 Hz or so.
If you are using high frequencies your eyes wont notice the change.
I will recommend you to get a project example like Sensortag or SimpleBLEPeripheral and change/add the Board.c and Board.h according to the PWM.
Add the PWM files to the project as well.
On Sensortag.c file where it init all GPIOs relays/leds and so on you add the PWM parameter stuff and start the PWM.
Once that is up and running you could use an osciloscope or your LED with 1Hz Frequency and 50% dulty on the port you are using to see if it is something there.
Notice that the LED has to be in the right polrity and make sure you have like 680OHm resistor so that the current limit at 2-4mA.
Its not complicated, first chane Board Files, add the Stuff into the project and add PWM Files inside "Application" Folder.
Build and check for errors and when not flash your device. PWM is easy and runs on the background so that the processor doesnt have to deal with toogling the GPIO output.
Regards,
Michael
Hi Bruce,
looks like the PIN board files are not right.
Make sure to use the board.c and board.h that is declaired under project propreties.
If you use sensortag project for example, this is on the folder c;/ti/simplelink/src/boards/cc2650stk/
The project link those on the configuration and if you declaire any GPIO to use make sure you write it in those ones.
Go ahead and add this to where you are trying to open the PWM:
PIN_Config pwmPin[] = { Board_PWMPIN1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_TERMINATE };
Change "Board_PWMPIN1" here to what you declaired.
Now if it gives you an error than you didnt write on the correct board files. If no errors than look if you have any warning about pwm or double check board.c PWM part if you wrote the write name.