Jump to content
43oh

PWM with MSP430G2231 + TLC5916


Recommended Posts

  • Replies 33
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

Here's the end result:     80 Osram PointLEDs, MSP430G2231, 2 x TLC5916. Still want to try the the 5940 to reduce components.

You can donate to Tesla Museum

Here's what I ended up with:  

Everything is on a breadboard. LEDs are powered by 3.3V from my PSU, Rext is 560ohm.

 

It works great with your original pattern or using my original (non-PWM) code. If I change the pattern to the one I posted all LEDs either on constant, on but dim, or not on at all (changes each time I reset the MSP).

 

Here's a video showing the breadboard and my original pattern:

 

http://www.youtube.com/embed/KGCC3TQcBeo

Link to post
Share on other sites

Thanks again Rob!

 

Same result, unfortunately :( With your pattern it works great but if I change lines 2,4,6 for full brightness it does not work.

 

I can get it to work with only line 2 at full brightness only using one TLC (if I connect the second, it freaks out and just starts flashing).

 

edit: I'm not using the external crystal on my breadboard. Could that have anything to do with it?

Link to post
Share on other sites

Sounds like hardware/supply problem.

Set all LEDs to 100% on both TLCs and check your 3.3V supply.

With 560ohm Rext, the output current is 33mA per LED, 16 LEDs will draw >500mA.

Switching them on and off could be affecting your supply and cause resets.

Add bypass and decoupling capacitors. One 100uF and three 0.1uF next to each chip's supply pin.

 

Also, 33mA might be a bit too much for your LEDs at 100% duty cycle.

Try changing Rext to something like 820ohm or 1k (this could also be a good way to see if the supply is the problem here, use 1k-1.8k resistor and see if that makes the difference.)

Link to post
Share on other sites

LEDs have a typical 70mA rating (Lumiled SuperFlux)

 

I have 15, drawing 390mA total.

 

I was able to get it working reliably using a pot set to ~1.7k ohms. I do not have the capacitors on my breadboard because all I have are SMT.

 

I'll desolder the M-M headers from my LP and put the M-F ones on tomorrow and then use the MSP from the LP to see if anything changes. Also pick up some through-hole capacitors

Link to post
Share on other sites

I make my boards at Seeed, but cross check with iTeadStudio, depending on color, size, you may get a better deal at one or the other.

 

BTW, my LED/shift register board will be available through 43oh store in couple of weeks. It will be sold as a full kit with 3 chips, LEDs, sockets, headers, resistors, etc., all under $10.

Link to post
Share on other sites

Next question (I just won't stop, will I?):

 

Now that I have it working on my breadboard, I've been making the pattern to how I'd like but I can't seem to figure out how to make it behave the way I had before.

 

In my original design the first five steps were executed with a for () loop "for (CurStep = 0; CurStep < 6; CurStep++)" then the remaining steps were executed repeatedly with a while (1) and a nested for () "for (CurStep = 6; CurStep < 15; CurStep++)".

 

I see in your code where the magic happens with the 'if' condition in the interrupt. How could I change this to behave the same as my original, executing the first few steps only once then moving on to the remaining steps? I've tried substituting a loop sequence similar to my original but to no avail.

 

Appreciate all the help! :thumbup:

Link to post
Share on other sites

Here it is.

Use patternCounter to count steps, patternIndex to select patterns.

Put your logic in the while loop.

 

#include "msp430G2231.h"
#include "pattern.h"

#define SDI BIT5
#define CLK BIT4
#define LE  BIT0

// 16 levels of brightness
const char lut[16] = { 0, 3, 6, 10, 20, 30, 40, 60, 80, 100, 120, 150, 180, 210,
	240, 255 };

char pwmCounter = 0;
char patternIndex = 0;
char patternCounter = 0;
int patternDelay = 0;

void main(void) {

WDTCTL = WDTPW + WDTHOLD;
DCOCTL |= DCO0 + DCO1; // DCO = 15.25MHz
BCSCTL1 |= RSEL0 + RSEL1 + RSEL2 + RSEL3; // as above

P1OUT = 0;
P1DIR |= (SDI + CLK + LE);

// setup timer
CCR0 = 1200; //
TACTL = TASSEL_2 + MC_1 + ID_0; // SMCLK, up mode, 1:1
CCTL0 = CCIE; // CCR0 interrupt enabled

_bis_SR_register(GIE);

while (1) {
	// logic goes here
	// patternIndex is used for pattern selection
	// patternCounter is used for timeline
	if(patternCounter < 6) {
		patternIndex++;
		patternCounter++;
	} else {
		patternIndex--;
		patternCounter++;
	}

               // don't change
	_bis_SR_register(LPM0_bits); // go to sleep and wait
};
}

#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0(void) {

patternIndex &= 0x0F; // mask patternCounter to get 0-15 range
pwmCounter++;
pwmCounter++; // increase again to get 128 pwm steps instead of 256

char i;
char pwm;
for (i = 0; i < 16; i++) {
	pwm = lut[pattern[patternIndex][i]];
	if (pwm > pwmCounter) {
		P1OUT |= SDI;
	} else {
		P1OUT &= ~SDI;
	}
	P1OUT |= CLK;
	P1OUT &= ~CLK;
}
P1OUT |= LE;
P1OUT &= ~LE;

patternDelay++;
if (patternDelay == 500) { // animation speed
	patternDelay = 0;
	_bic_SR_register_on_exit(LPM0_bits); // ready for next pattern, wake up after ISR
}
}

Link to post
Share on other sites

Thanks again Rob.

 

I'm still having a helluva time with the pattern though. Rather than a single while loop, I need to use a for loop that only gets executed once then a while loop for the rest of the pattern.

 

Example:

for (patternIndex = 0; patternIndex < 7;) {
            patternIndex++;
            patternCounter++;
  }

  while (1) {
   for (patternIndex = 7; patternIndex < 14;) {
  	            patternIndex++;
  	            patternCounter++;
   }
  };

 

I tried using those loops instead of the if else but it did not work. I tried quite a few things, actually. What am I doing wrong?

Link to post
Share on other sites

In your case (very simple sequence,) you could get rid of patternCounter and just use patternIndex.

 

while (1) {
     // logic goes here
     // patternIndex is used for pattern selection
     // patternCounter is used for timeline

        patternIndex++;
        patternCounter++;
   if(patternCounter == 14) {
     patternIndex = 6;
     patternCounter = 6;
   }
               // don't change
     _bis_SR_register(LPM0_bits); // go to sleep and wait
  };

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...