Jump to content
TechIO

Add more LEDs with Fading

Recommended Posts

Hello Community,

 

I found this really amazing Code from oPossoum in the Code Vault for fading a LED. The problem is, I would like to make both LED on the launchPad fading.

I am really new to MSP430G2553 and played a lot with the Code, tried to understand Clocks, Interrupts, etc. , but I am not able to get it :/

 

Can anybody help me how to or give me a good advice? Thanks!

#include <msp430.h>
#include <stdint.h>

void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;
    DCOCTL = 0; BCSCTL1 = CALBC1_16MHZ; DCOCTL  = CALDCO_16MHZ;
    P1DIR = P1SEL = BIT6;
    TACCTL1 = OUTMOD_7; TACTL = TASSEL_2 | MC_2 | TAIE;
    _EINT();
}
#pragma vector = TIMER0_A1_VECTOR
__interrupt void timer_a1_isr(void)
{
    static uint32_t x = 0x00100000L;
    static unsigned d = 1;
    TACCR1 = x >> 16;
    volatile unsigned z = TAIV;
    if(d) {
        x += (x >> 7); if(x > 0xF8000000L) d = 0;
    } else {
        x -= (x >> 7); if(x < 0x00200000L) d = 1;
    }
}

Share this post


Link to post
Share on other sites

On the G2553LP only the green LED is connected to a pin capable of PWM.

 

Here is an example of fading the green LED (but it's in Energia, not CCS):

void setup()
{
P1DIR |= BIT6;                                   
P1SEL |= BIT6;
P1OUT&=~BIT6;

CCR0 = 1000-1; // PWM Period frequency is determined by 
//clk freq divided by CCR
CCTL1 = OUTMOD_7; // CCR1 reset/set
CCR1 = 0; // CCR1 PWM duty cycle 
TACTL = TASSEL_2 + MC_1;// SMCLK, up mode
//SMCLK runns at main clock speed in this micro it's 16 Mhz
}

void loop()
{
 if(CCR1==0){ 
while(CCR1<500){
 CCR1=CCR1+1; 
delay(1);
}
 }
 else{
  while(CCR1>0){
   CCR1=CCR1-1;
  delay(1);
  } 
   
 }
}

If I have time I'll do one in CCS

Share this post


Link to post
Share on other sites

The code posted uses PWM, as well as the RED LED connected by default to P1.0; that pin doesn't support PWM.

The GREEN LED connected to P1.6 does however, which is what the code uses "BIT6".

 

So you need to find another pin that supports PWM, which on the G2553 LP means P1.2, and connect the LED to that, easily done by removing the jumper above the LED and running a jumper from the pin closest the LED to the LP pin next to the label "P1.2 (UART1)". Now, by adding BIT6 to BIT2, you can have both fading, albeit both do so in parallel.

 

@@oPossum is a wizard and often makes things which do not make sense somehow work.

 

Then,

#include <msp430.h>
#include <stdint.h>

void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;
    DCOCTL = 0; BCSCTL1 = CALBC1_16MHZ; DCOCTL  = CALDCO_16MHZ;
    P1DIR = P1SEL = BIT2 + BIT6; // BIT2 = P1.2 / BIT6 = P1.6
    TACCTL1 = OUTMOD_7; TACTL = TASSEL_2 | MC_2 | TAIE;
    _EINT();
}
#pragma vector = TIMER0_A1_VECTOR
__interrupt void timer_a1_isr(void)
{
    static uint32_t x = 0x00100000L;
    static unsigned d = 1;
    TACCR1 = x >> 16;
    volatile unsigned z = TAIV;
    if(d) {
        x += (x >> 7); if(x > 0xF8000000L) d = 0;
    } else {
        x -= (x >> 7); if(x < 0x00200000L) d = 1;
    }
}
Edited by abecedarian

Share this post


Link to post
Share on other sites

Ok here is the one that I did in CCS (fairly new to using CCS myself):

#include <msp430.h> 


void main(void) {
    WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    P1DIR |= BIT6;
    P1SEL |= BIT6;
    P1OUT&=~BIT6;

    CCR0 = 1000-1; // PWM Period frequency is determined by
    //clk freq divided by CCR
    CCTL1 = OUTMOD_7; // CCR1 reset/set
    CCR1 = 0; // CCR1 PWM duty cycle
    TACTL = TASSEL_2 + MC_1;// SMCLK, up mode
    //SMCLK runns at main clock speed in this micro it's 16 Mhz
	
    while(1){
    	if(CCR1 == 0){
    	while(CCR1<500){
    	 CCR1= CCR1+1;
    	 __delay_cycles(2000);
    	}
    	 }
    	 else{
    	  while( CCR1 > 0){
    	   CCR1= CCR1-1;
    	   __delay_cycles(2000);
    	  }
    }
    }


}

Share this post


Link to post
Share on other sites

Next aim is to let both LED fade alternating.

Is it a good idea to go on with oPossums Code (because you said he is a wizard  :biggrin: ) and try to get it or change code?

Share this post


Link to post
Share on other sites

What is your end goal? You don't need to use timers to do PWM. The fact that you are running LEDs continuously indicates you aren't worried about low power. How you decide to approach this really depends on your end goal.

 

Of course it would be smart to understand the Timer peripheral. They are extremely useful and a key to being successful at using the msp430 to its fullest.

Share this post


Link to post
Share on other sites

@Rickta69 You've confused me. It's easy to do, but you can brag about it if you'd like.

How would you do PWM without timers since the timer module(s) are what does PWM?

Here is some code that uses PWM to toggle the 2 leds on and off. It just uses delays to control the period and duty cycles.

 

#include <msp430.h>
#include <stdint.h>

struct pwm_struct {
	const unsigned period;
	unsigned duty[2];
	const uint8_t leds_bitmask[2];
};

struct pwm_struct PWM = { 100, { 0, 0 }, { BIT6, BIT0 }};

unsigned incr(unsigned ctr, unsigned amt)
{
	ctr += amt;
	return ( ctr > PWM.period ) ? 0 : ctr;
}

/*
 * main.c
 */
int main(void) {
	WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer

	P1DIR |= (PWM.leds_bitmask[0] | PWM.leds_bitmask[1]);
	P1OUT &= ~(PWM.leds_bitmask[0] | PWM.leds_bitmask[1]);

	static const unsigned leds = sizeof(PWM.duty)/sizeof(PWM.duty[0]);
	unsigned counter = 0;
	int indx;

	while (1) {
		__delay_cycles(50);
		counter = incr(counter, 1);

		for(indx=0; indx < leds; ++indx) {
			if ( counter == 0 && PWM.duty[indx] ) {
				P1OUT |= PWM.leds_bitmask[indx];
			}

			if ( PWM.duty[indx] == counter) {
				P1OUT &= ~(PWM.leds_bitmask[indx]);
			}
		}

		if ( counter == 0 ) {
			PWM.duty[0] = incr(PWM.duty[0],2); // vary green led duty cycle
		}

		if ( PWM.duty[0] > 75 ) {
			PWM.duty[1] = 10;
		}
		else {
			PWM.duty[1] = 0;
		}
	}

	return 0;
}

Share this post


Link to post
Share on other sites

Aim is to fade 3 LEDs alternating very slowly in a lamp powered by batteries.

I think oPossums solution there is a good one, isn't it ?

But I am new to MSP430 so it is quite confusing...

Share this post


Link to post
Share on other sites

There's a middle ground. Timers are a key part of working with the MSP430 and worth getting to know your way around. However, using OUTMOD_7 to directly toggle a pin in hardware is not the only way.

 

Try using the timer to fire an interrupt. Then your interrupt handler code can switch whatever LEDs you like on or off. You've let the timer do the core of the work (and left you in a position to use low power modes) but done the detail yourself. Sorry I can't give you any example code as I'm at work at the moment.

Share this post


Link to post
Share on other sites

Here is some code that uses PWM to toggle the 2 leds on and off. It just uses delays to control the period and duty cycles.

 

#include <msp430.h>
#include <stdint.h>

struct pwm_struct {
	const unsigned period;
	unsigned duty[2];
	const uint8_t leds_bitmask[2];
};

struct pwm_struct PWM = { 100, { 0, 0 }, { BIT6, BIT0 }};

unsigned incr(unsigned ctr, unsigned amt)
{
	ctr += amt;
	return ( ctr > PWM.period ) ? 0 : ctr;
}

/*
 * main.c
 */
int main(void) {
	WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer

	P1DIR |= (PWM.leds_bitmask[0] | PWM.leds_bitmask[1]);
	P1OUT &= ~(PWM.leds_bitmask[0] | PWM.leds_bitmask[1]);

	static const unsigned leds = sizeof(PWM.duty)/sizeof(PWM.duty[0]);
	unsigned counter = 0;
	int indx;

	while (1) {
		__delay_cycles(50);
		counter = incr(counter, 1);

		for(indx=0; indx < leds; ++indx) {
			if ( counter == 0 && PWM.duty[indx] ) {
				P1OUT |= PWM.leds_bitmask[indx];
			}

			if ( PWM.duty[indx] == counter) {
				P1OUT &= ~(PWM.leds_bitmask[indx]);
			}
		}

		if ( counter == 0 ) {
			PWM.duty[0] = incr(PWM.duty[0],2); // vary green led duty cycle
		}

		if ( PWM.duty[0] > 75 ) {
			PWM.duty[1] = 10;
		}
		else {
			PWM.duty[1] = 0;
		}
	}

	return 0;
}

 

__delay_cycles(50); is just some assembly instructions? like SysCtlDelay in Tiva that is simply 3 instructions?

Share this post


Link to post
Share on other sites

Aim is to fade 3 LEDs alternating very slowly in a lamp powered by batteries.

I think oPossums solution there is a good one, isn't it ?

But I am new to MSP430 so it is quite confusing...

Using a peripheral that can do the job is usually the best solution. I wouldn't use the code I wrote above to accomplish your task. I'd use the timer.

Share this post


Link to post
Share on other sites

You might want to watch the timer section of this workshop. The workshop is geared towards the msp430f5529 but the TimerA peripheral is the same on the g2553.

http://processors.wiki.ti.com/index.php/Getting_Started_with_the_MSP430_LaunchPad_Workshop

 

[EDIT: hmm .. this used to describe how to use the registers, this workshop seems geared to using the driverlib which is a higher level api. Concepts are still useful though]

Share this post


Link to post
Share on other sites

@@Rickta59 - You got me with that code. :)  I hadn't considered the old fashioned way of hard coding the signals. And my apologies if my post sounded rude- it wasn't meant to.

 

 

@L.R.A __delay_cycles("x") is a function provided by the compiler and inserts "x" no-operation instructions into the code, causing a delay amounting to "x" many processor cycles. As such, the actual delay will vary with the processor speed, i.e. an MSP430 operating at 1MHz with 50 'no-op' instruction will have an apparent delay that is 16 times longer than and MSP430 operating at 16MHz.

Share this post


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...