Hi!
I wanted to make my little PWM program a bit more scalable, and so I wrote a quick C++ program which is below.
For the longest time I thought I'd got my logic wrong - because the LED's weren't behaving themselves, but when I tried stepping into the program right from the start, I found that the line of code causing them to illuminate was nothing to do with P1OUT!
The program is below, and I'm very bemused - could it be the compiler doesn't support objects for the F2013? From what I know, the object data is just stored in a contiguous section of ram, of which there's 128 bytes. So I lowered the 8 objects for my 8 outputs down to 2 objects, and it still goes wrong... so I don't think the object data is writing over the P1OUT port....
If you have any ideas, or suggestions to try to help debug the program, please let me know!
Thanks! =D
#include <msp430x20x3.h>class dimmableLED { public: unsigned short int dutyCycles; unsigned short int onCycles; unsigned short int currentCycle; unsigned char bitNumber; dimmableLED(void); void cycle(); };dimmableLED::dimmableLED(void) { dutyCycles=10; onCycles=5; currentCycle=0; bitNumber=2^6; }void dimmableLED::cycle(void) { bool output=0; if(++currentCycle<onCycles) output=1; if(currentCycle==dutyCycles) currentCycle=0; if(output) P1OUT |= bitNumber; else P1OUT &= bitNumber; }int main(void){unsigned short int index;WDTCTL = WDTPW + WDTHOLD;P1DIR = 255; // All outdimmableLED* LED = new dimmableLED[2]; <<<<<<< THIS MAKES MY OUTPUTS HIGH! in binary they look like this: LSB>HSB = 01101000for(index=0;index<1;index++) { LED[index].bitNumber=2^(index+3); // Position the lit LED's a little way down the full 8 LED's. }for(;;) { for(index=0;index<1;index++) { LED[index].cycle(); } } }
PxOUT is unchanged after PUC, POR, or BOR. Thus when you start executing code, They may have any bit patten in them. However, PxDIR, PxSEL, etc. are cleared by PUC, POR or BOR. Thus the corresponding pins are in digital input mode and PxOUT has no effect. If your code sets any PxDIR bit, the corresponding pin becomes an digital output pin and will go actively high or low according to PxOUT,
Thanks, I'll try doing a P1OUT=0;
I'm worried that object data is getting written into places it shouldn't...
Not sure if this is the cause of the problem, but the following lines look strange:
bitNumber=2^6; LED[index].bitNumber=2^(index+3); // Position the lit LED's a little way down the full 8 LED's.
The ^ operator in C++ is a bit-wise exclusive or, yet the lines are written as if a 2 to the power operation is wanted.
Should these lines be:
bitNumber = 1 << 6; LED[index].bitNumber = 1 << (index+3)
LED[index].bitNumber = 1 << (index+3)
Also
[code]if(output) P1OUT |= bitNumber; else P1OUT &= bitNumber;[/code]
looks like it should be
[code]if(output) P1OUT |= bitNumber; else P1OUT &= ~bitNumber;[/code]
to clear a bit
Regards
Roger.
Ooops! Thanks! I was using the wrong language.
With the little fixes, and also moving to C, as well as stepping through the C++ code - I can confirm that the C++ one gets crazy figures in the counters.
The following C program works fine, and is 402 bytes long.
The equivalent C++ program below it doesn't work correctly, and is 972 bytes long! I don't think the compiler is cut out to make C++ into assembly code for this MPU.
--------------- --------------- --------------- --------------- --------------- --------------- ---------------
Working AOK!
#include <msp430x20x3.h>const unsigned short int LEDCount=8;unsigned int dutyCycles[LEDCount];unsigned int onCycles[LEDCount];unsigned int currentCycle[LEDCount];unsigned int bitNumber[LEDCount];void cycle(unsigned short int LED) { bool theOut=false; if(++currentCycle[LED]<=onCycles[LED]) theOut=true; if(currentCycle[LED]>=dutyCycles[LED]) currentCycle[LED]=0; if(theOut) P1OUT |= bitNumber[LED]; else P1OUT &= ~bitNumber[LED]; }int main(void){unsigned short int index;int anim=0;WDTCTL = WDTPW + WDTHOLD;DCOCTL=CALDCO_16MHZ;BCSCTL1=CALBC1_16MHZ;P1OUT=0;P1DIR = 255; // All outdutyCycles[0]=200;onCycles[0] =1;dutyCycles[1]=200;onCycles[1] =6;dutyCycles[2]=200;onCycles[2] =23;dutyCycles[3]=200;onCycles[3] =110;dutyCycles[4]=200;onCycles[4] =199;dutyCycles[5]=200;onCycles[5] =110;dutyCycles[6]=200;onCycles[6] =23;dutyCycles[7]=200;onCycles[7] =6;for(index=0;index<LEDCount;index++) {// dutyCycles[index]=450;// onCycles[index]=index*50+50; currentCycle[index]=0; bitNumber[index]=1<<index; }for(;;) { for(index=0;index<LEDCount;index++) { cycle(index); } if(++anim>5000) { int i,a,b; a=dutyCycles[0]; b=onCycles[0]; for(i=0;i<LEDCount-1;i++) { dutyCycles[i]=dutyCycles[i+1]; onCycles[i] =onCycles[i+1]; } dutyCycles[LEDCount-1]=a; onCycles[LEDCount-1] =b; anim=0; } }}--------------- --------------- --------------- --------------- --------------- C++ Fails:class dimmableLED { public: unsigned short int dutyCycles; unsigned short int onCycles; unsigned short int currentCycle; unsigned char bitNumber; dimmableLED(void); void cycle(); };dimmableLED::dimmableLED(void) { dutyCycles=10; onCycles=5; currentCycle=0; bitNumber=2<<6; }void dimmableLED::cycle(void) { bool output=0; if(++currentCycle<onCycles) output=1; if(currentCycle==dutyCycles) currentCycle=0; if(output) P1OUT |= bitNumber; else P1OUT &= ~bitNumber; }int main(void){unsigned short int index;WDTCTL = WDTPW + WDTHOLD;
P1OUT=0;P1DIR = 255; // All outdimmableLED* LED = new dimmableLED[8];for(index=0;index<8;index++) { LED[index].bitNumber=1<<index; }for(;;) { for(index=0;index<8;index++) { LED[index].cycle(); } } }
After stepping through the code, and discovering all the random values, I thought that perhaps the constructors weren't getting called.
Figuring that the array of objects wasn't being initialised properly - and only vaguely remembering that a pointer to the start of memory was what an array name was. I re-wrote the code with some other definition for an array of objects that I found online - I NEED to find out why the constructors weren't called with my original code, but they were with the new code. Coming from C, and Java - the behaviour seems a bit odd.
Anyway - thanks for all the work : HERE is the working version!class dimmableLED { public: unsigned short int dutyCycles; unsigned short int onCycles; unsigned short int currentCycle; unsigned char bitNumber; dimmableLED(void); void cycle(); };dimmableLED::dimmableLED(void) { dutyCycles=200; onCycles=5; currentCycle=0; bitNumber=1; }void dimmableLED::cycle(void) { bool output=0; if(++currentCycle<onCycles) output=1; if(currentCycle==dutyCycles) currentCycle=0; if(output) P1OUT |= bitNumber; else P1OUT &= ~bitNumber; }int main(void){unsigned short int index;WDTCTL = WDTPW + WDTHOLD;DCOCTL=CALDCO_16MHZ;BCSCTL1=CALBC1_16MHZ;P1OUT=0; P1DIR = 255; // All out//dimmableLED* LED = new dimmableLED[8];//dimmableLED* LED[8] = new dimmableLED();dimmableLED LED[8]; << WORKS!LED[0].onCycles = 1;LED[1].onCycles = 2;LED[2].onCycles = 4;LED[3].onCycles = 11;LED[4].onCycles = 23;LED[5].onCycles = 50;LED[6].onCycles = 110;LED[7].onCycles = 190;for(index=0;index<8;index++) LED[index].bitNumber=1<<index;for(;;) for(index=0;index<8;index++) LED[index].cycle(); }
Hi Sarah,
I'm not exactly a C++ guru myself, but I believe
dimmableLED* LED = new dimmableLED[8];
tries to allocate a pointer to a newly initialized heap space containing an array of 8 dimmableLED's. Hence using the "dot" notation to access the objects would result in undefined behaviour.
You should try
LED[i]->onCycles = n;
to access the members of the objects. Or you can use the third line, which initializes the objects in the stack (but that comes with its own problems if used unwisely).
BTW, dynamic memory allocation is inherently more expensive than any "static" version, C++ or otherwise, since the constructor is called for each of the object instances of your class. If you look at the linker produced memory map file, you'd see that half of the code is spent on run-time allocation and initialization of the objects.
A better way would be to remove your custom constructor and treat the class as a POD ("Plain Old Data"); you can then initialize it using
dimmableLED LED[8] = {200, 5, 0, 1};
as if you're treating the object's data members collectively as an array of members (which is actually how it's represented in memory). This dramatically reduces the code size to 274 bytes (in CCS 5.1) and retains all the OOP niceties of C++, sans dynamic allocation.
Not that this will not work if you have a user-declared constructor, virtual functions, or non-static data members with different access control. See http://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/4178176
Tony
Thank you!
You've explained it very well.
I was impressed with the size you got the code down to, and so I had a go. But I'm having a bit of trouble with the instructions about removing the constructor. =(
I've removed the constructor, and want to initialise the timers in the objects, but I don't understand where the following line puts the numbers without a constructor!:
dimmableLED LED[8] = {1, 2, 4, 11, 23, 50, 110, 190};
I'm also at a loss how to assign the other values to the objects,. such as duty cycles, I don't think this would work?
LED[].dutyCycles = {200, 200, 200, 200, 200, 200, 200, 200};
Have you got any time to point me in the right direction, or even the code itself - I've been programming in Java, and C and stuff for years, so I should be able to understand what's going on with my reference manual, and a bit of time. Finding the syntax is very hard though!
Sorry for the confusing, I should've been more clear about the initialization (I blame my insomniac posting at 4am). To initialize the dimmableLED array to the values in your original code, do
dimmableLED LED[8] = { //dutyCycles onCycles currentCycles bitNumber {200, 1, 0, 1}, // array element 0 {200, 2, 0, 1}, {200, 4, 0, 1}, {200, 11, 0, 1}, {200, 23, 0, 1}, {200, 50, 0, 1}, {200, 110, 0, 1}, {200, 190, 0 1}};
which is the same syntax as initializing a 2d array or an array of structures. Of course what you end up with is more than just vanilla C arrays or structures.
And yes C++ can be appear quite opaque esp. if you come from C or Java (as I do), since it appears to share the same syntax, yet it's almost a completely different language with its own models and paradigms. However, once I (sort of) got the hang of it, I was shocked at how powerful and efficient the language can be; some things you can easily do in C++ are just painful or near impossible in plain C.
FYI, highly recommend articles by Dan Saks, who is probably the best C++ "evangelist" in embedded programming: http://www.eetimes.com/electronics-blogs/27/Programming-Pointers
Thank you! Brilliant!
I'll check out the book by Dan - it sounds a good way for me to learn good programming patterns for C++ in embedded systems.
I've amended my prototype board so there's 4 switches (I know I could have used a matrix, but this was quicker) - and 4 LED's.
I'm going to write it so that the first 2 buttons select the delay being edited... LED 1 - On time, LED 1 - Off time, LED 2 - On time, etc........
Then the other 2 buttons will increase and decrease the time. Using debouncing and 'single press' code so it doesn't cycle through values too rapidly.
Then I realised the line: if(output) P1OUT &= ................. is a BAD idea!
If I'm using this for PWM tests on several channels, I need the values to change at once - so I'm taking the P1OUT code out of the loop, and putting it after the loop reading the buttons, and amending the PWM timers... so it changes all outputs AT ONCE:
P1OUT= (LED[0].bitNumber)&(LED[1].bitNumber)&(LED[2].bitNumber)&(LED[0].bitNumber);
I don't think there's anything that will throw this off.....
Next step : The Raspberry Pi Inputs!
Thanks for all your help - it's really appreciated, and you've got no points or awards to show for it either! There should be some sort of ranking table!
Glad to know I'd been of help.
It occurred to me however that you're trying to do PWM via software. Have you looked into Timer_A generated hardware PWM? They are much more accurate and do not require any CPU intervention aside from the initial setup and optional interrupt servicing; moreover they can continue to operate in low-power modes meaning you can turn the CPU off. They can also source clock from other than MCLK, allowing for async operation.
You can still use C++ classes to map and program the Timer peripherals; in fact it can be more elegant/efficient than the C equivalent. I have a basic class model for accessing the Timer_A registers using memory-mapped objects, if you're interested I can clean the code up and post it.
Hi Tony!
>Have you looked into Timer_A generated hardware PWM?
I haven't yet! That sounds ideal, and it would give accurate timings. (as far as oscillating circuits can). =)
> in fact it can be more elegant/efficient than the C equivalent. I have a basic class model for accessing the Timer_A registers using memory-mapped objects, if you're interested I can clean the code up and post it.
Ohhh, would you? That would be brilliant. =D
------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- -------
I extended the C++ program to enable a user to control the PWM - but found that accessing the on-cycles, and duty-cycles values was much easier when I'm using a cursor, by putting them all in one big array. I'd have had to write more code in the C++ to access the right object and value (On time/Duty cycle) based on the cursor position!
So what I did was drop down to C, and combine the two values for each LED into one homogenous array. That way a simple "cursor" that is simply indexing the array can control all the timers of all the LED's without any code-bloat.
The code's here: http://sarahs-muse.livejournal.com/1343114.html
Now, I'd LOVE to write it in C++, but with the streamlined data access of the single array. I'm sure it's possible due to the way the objects are stored in order...
I'm going to run through the book you recommended - there must be some good design patterns to optimise the C++ in this kind of situation.
I have to pause my little projects now - the little Pi computer's plugged into the board. =)