Go Down

Topic: LED Chasing Lights Progamming (Read 2550 times) previous topic - next topic

Fennel Rye

May 24, 2012, 02:19 am Last Edit: May 24, 2012, 02:24 am by Fennel Rye Reason: 1
Hey guys,

So I have a code for a ring of LEDs to make them chase faster and faster.  I have the LEDs connected into the PWM pins arranged so that they are symmetrical, which is why the pins switching on and off in my code jump around a little. Here's the code:

Code: [Select]
void setup() {               
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT); 
}

void loop() {
  digitalWrite(1, HIGH);
  delay(500);             
  digitalWrite(1, LOW);
  digitalWrite(2, HIGH);
  delay(500);
  digitalWrite(2, LOW);
  digitalWrite(3, HIGH);
  delay(500);
  digitalWrite(3, LOW);
  digitalWrite(4, HIGH);
  delay(500);
  digitalWrite(4, LOW);
  digitalWrite(5, HIGH);
  delay(500);
  digitalWrite(5, LOW);
  digitalWrite(7, HIGH);
  delay(500);
  digitalWrite(7, LOW);
  digitalWrite(6, HIGH);
  delay(500);
  digitalWrite(6, LOW);
  digitalWrite(8, HIGH);
  delay(500);
  digitalWrite(8, LOW);
  digitalWrite(12, HIGH);
  delay(500);
  digitalWrite(12, LOW);
  digitalWrite(9, HIGH);
  delay(500);
  digitalWrite(9, LOW);
  digitalWrite(13, HIGH);
  delay(500);
  digitalWrite(13, LOW);
  digitalWrite(10, HIGH);
  delay(500);
  digitalWrite(10, LOW);
  digitalWrite(0, HIGH);
  delay(500);
  digitalWrite(0, LOW);
  digitalWrite(11, HIGH);
  delay(500);
  digitalWrite(11, LOW);
  digitalWrite(1, HIGH);
  delay(400);             
  digitalWrite(1, LOW);
  digitalWrite(2, HIGH);
  delay(400);
  digitalWrite(2, LOW);
  digitalWrite(3, HIGH);
  delay(400);
  digitalWrite(3, LOW);
  digitalWrite(4, HIGH);
  delay(400);
  digitalWrite(4, LOW);
  digitalWrite(5, HIGH);
  delay(400);
  digitalWrite(5, LOW);
  digitalWrite(7, HIGH);
  delay(400);
  digitalWrite(7, LOW);
  digitalWrite(6, HIGH);
  delay(400);
  digitalWrite(6, LOW);
  digitalWrite(8, HIGH);
  delay(400);
  digitalWrite(8, LOW);
  digitalWrite(12, HIGH);
  delay(400);
  digitalWrite(12, LOW);
  digitalWrite(9, HIGH);
  delay(400);
  digitalWrite(9, LOW);
  digitalWrite(13, HIGH);
  delay(400);
  digitalWrite(13, LOW);
  digitalWrite(10, HIGH);
  delay(400);
  digitalWrite(10, LOW);
  digitalWrite(0, HIGH);
  delay(400);
  digitalWrite(0, LOW);
  digitalWrite(11, HIGH);
  delay(400);
  digitalWrite(11, LOW);
  digitalWrite(1, HIGH);
  delay(300);             
  digitalWrite(1, LOW);
  digitalWrite(2, HIGH);
  delay(300);
  digitalWrite(2, LOW);
  digitalWrite(3, HIGH);
  delay(300);
  digitalWrite(3, LOW);
  digitalWrite(4, HIGH);
  delay(300);
  digitalWrite(4, LOW);
  digitalWrite(5, HIGH);
  delay(300);
  digitalWrite(5, LOW);
  digitalWrite(7, HIGH);
  delay(300);
  digitalWrite(7, LOW);
  digitalWrite(6, HIGH);
  delay(300);
  digitalWrite(6, LOW);
  digitalWrite(8, HIGH);
  delay(300);
  digitalWrite(8, LOW);
  digitalWrite(12, HIGH);
  delay(300);
  digitalWrite(12, LOW);
  digitalWrite(9, HIGH);
  delay(300);
  digitalWrite(9, LOW);
  digitalWrite(13, HIGH);
  delay(300);
  digitalWrite(13, LOW);
  digitalWrite(10, HIGH);
  delay(300);
  digitalWrite(10, LOW);
  digitalWrite(0, HIGH);
  delay(300);
  digitalWrite(0, LOW);
  digitalWrite(11, HIGH);
  delay(300);
  digitalWrite(11, LOW);
  digitalWrite(1, HIGH);
  delay(200);             
  digitalWrite(1, LOW);
  digitalWrite(2, HIGH);
  delay(200);
  digitalWrite(2, LOW);
  digitalWrite(3, HIGH);
  delay(200);
  digitalWrite(3, LOW);
  digitalWrite(4, HIGH);
  delay(200);
  digitalWrite(4, LOW);
  digitalWrite(5, HIGH);
  delay(200);
  digitalWrite(5, LOW);
  digitalWrite(7, HIGH);
  delay(200);
  digitalWrite(7, LOW);
  digitalWrite(6, HIGH);
  delay(200);
  digitalWrite(6, LOW);
  digitalWrite(8, HIGH);
  delay(200);
  digitalWrite(8, LOW);
  digitalWrite(12, HIGH);
  delay(200);
  digitalWrite(12, LOW);
  digitalWrite(9, HIGH);
  delay(200);
  digitalWrite(9, LOW);
  digitalWrite(13, HIGH);
  delay(200);
  digitalWrite(13, LOW);
  digitalWrite(10, HIGH);
  delay(200);
  digitalWrite(10, LOW);
  digitalWrite(0, HIGH);
  delay(200);
  digitalWrite(0, LOW);
  digitalWrite(11, HIGH);
  delay(200);
  digitalWrite(11, LOW);
  digitalWrite(1, HIGH);
  delay(100);             
  digitalWrite(1, LOW);
  digitalWrite(2, HIGH);
  delay(100);
  digitalWrite(2, LOW);
  digitalWrite(3, HIGH);
  delay(100);
  digitalWrite(3, LOW);
  digitalWrite(4, HIGH);
  delay(100);
  digitalWrite(4, LOW);
  digitalWrite(5, HIGH);
  delay(100);
  digitalWrite(5, LOW);
  digitalWrite(7, HIGH);
  delay(100);
  digitalWrite(7, LOW);
  digitalWrite(6, HIGH);
  delay(100);
  digitalWrite(6, LOW);
  digitalWrite(8, HIGH);
  delay(100);
  digitalWrite(8, LOW);
  digitalWrite(12, HIGH);
  delay(100);
  digitalWrite(12, LOW);
  digitalWrite(9, HIGH);
  delay(100);
  digitalWrite(9, LOW);
  digitalWrite(13, HIGH);
  delay(100);
  digitalWrite(13, LOW);
  digitalWrite(10, HIGH);
  delay(100);
  digitalWrite(10, LOW);
  digitalWrite(0, HIGH);
  delay(100);
  digitalWrite(0, LOW);
  digitalWrite(11, HIGH);
  delay(100);
  digitalWrite(11, LOW);
  digitalWrite(1, HIGH);
 
}


Now, at the end of this code, I want the 6 PWM LEDs to begin pulsing (fading in and out) in an endless loop. I tried using this code:

Code: [Select]

analogWrite(9, brightness);   

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
  }     
  // wait for 30 milliseconds to see the dimming effect   
  delay(30);                           
}


at the end of it (I also set int brightness = 0 and int fadeAmount= 5 before the setup), but it did not work correctly. What's the best way to go about this? I've searched around but am having trouble finding the answer.  Thanks, guys!
Fennel Rye

marco_c

#1
May 24, 2012, 03:33 am Last Edit: May 24, 2012, 03:37 am by marco_c Reason: 1
(brightness == 0 || brightness == 255)

The problem here is that if fadeamount does not make it get to exactly 255 or exactly 0, then it won't work. Try

(brightness <= 0 || brightness >= 255)

Also, what did not work?
Arduino libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com

Nick Gammon

Code: [Select]

  digitalWrite(1, HIGH);
  delay(500);             
  digitalWrite(1, LOW);
  digitalWrite(2, HIGH);
  delay(500);
  digitalWrite(2, LOW);
  digitalWrite(3, HIGH);
  delay(500);
  digitalWrite(3, LOW);
  digitalWrite(4, HIGH);
  delay(500);


blah blah...

If I may suggest a fairly big simplification:

Code: [Select]
const int numberOfLEDs = 14;

const byte LEDorder [numberOfLEDs] = { 1, 2, 3, 4, 5, 7, 6, 8, 12, 9, 13, 10, 0, 11 };

void setup() {               
  for (byte i = 0; i < numberOfLEDs; i++) 
    pinMode(LEDorder [i], OUTPUT);
}  // end of setup

void doCircle (const unsigned long delayAmount)
  {
  for (byte i = 0; i < numberOfLEDs; i++)
    {
    byte pin = LEDorder [i];
    digitalWrite(pin, HIGH);
    delay(delayAmount);             
    digitalWrite(pin, LOW);
    }   // end of for
  }  // end of doCircle
 
void loop()
  {
  for (unsigned long n = 500; n > 0; n -= 100)
    doCircle (n);
  } // end of loop


Then we can look at the problem with the pulsing.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Fennel Rye

#3
May 24, 2012, 10:34 pm Last Edit: May 24, 2012, 11:01 pm by Fennel Rye Reason: 1
Ahhhh. :smiley-roll-sweat: That is much better. Thank you, Nick. The one thing I understood how to do with the old cumbersome code that I do not with your new, nice and clean code is that once it reaches it's fastest spinning speed (which I would like to be a delay of 10 between lights) I'd like it to spin around at that speed ten times and then begin the pulsing.

My LEDs are very, very bright and I've been getting a bit of a headache working on this. It's too hard for me to not stare at the pretty, blinky LEDs.  If I wanted to set them all at a lower brightness, would I just change digitalWrite(pin, HIGH) into digitalWrite(pin, 100) or something like this? Thanks so much.
Fennel Rye

jraskell


My LEDs are very, very bright and I've been getting a bit of a headache working on this. It's too hard for me to not stare at the pretty, blinky LEDs.  If I wanted to set them all at a lower brightness, would I just change digitalWrite(pin, HIGH) into digitalWrite(pin, 100) or something like this? Thanks so much.


Something like, but not that.  digitalWrite is as it's name says, digital.  On or off.

You have to use analogWrite to vary the brightness.  Only a select number of the pins on the Arduino support analogWrite though.

Nick Gammon

To answer your first question, you could change:

Code: [Select]
for (unsigned long n = 500; n > 0; n -= 100)
   doCircle (n);


to something like:

Code: [Select]

doCircle (500);
doCircle (400);
doCircle (300);
doCircle (200);
doCircle (200);
doCircle (100);
doCircle (100);


Or even use a table of delays (like the table of pins further up).

Quote
If I wanted to set them all at a lower brightness, would I just change digitalWrite(pin, HIGH) into digitalWrite(pin, 100) or something like this?


No that won't work. digitalWrite is either on or off.

I did something along those lines a while back, but can't find it. Maybe someone else can. Basically it used a timer to establish a "PWM frequency" and then detect that in an interrupt to make all the pins into PWM pins.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

Here:

http://arduino.cc/forum/index.php?topic=103572.0
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

This is how you can do it:

Code: [Select]
volatile byte wantedPin;   // which pin to pulse on and off

const byte PWMiterations = 40;
const byte PWMdutyCycle = 2;   // <-- should be less than PWMiterations

volatile byte pwmCount;

ISR(TIMER1_COMPA_vect)
{

  // if in "on" cycle turn the LED on
 if (pwmCount > PWMdutyCycle)
   digitalWrite(wantedPin, LOW);      
 else
   digitalWrite(wantedPin, HIGH);      
 
if (++pwmCount >= PWMiterations)
  pwmCount = 0;
}  // end of TIMER1_COMPA_vect

const int numberOfLEDs = 14;

const byte LEDorder [numberOfLEDs] = { 1, 2, 3, 4, 5, 7, 6, 8, 12, 9, 13, 10, 0, 11 };

void setup()
 {                
 for (byte i = 0; i < numberOfLEDs; i++)  
   pinMode(LEDorder [i], OUTPUT);
   
 // set up Timer 1
 TCCR1A = 0;          // normal operation
 TCNT1 = 0;           // make sure we start at zero
 TCCR1B = _BV(WGM12) | _BV(CS10) | _BV (CS12);   // CTC, scale to clock / 1024
 OCR1A =  5;       // compare A register value (1000 * clock speed / 1024)
 TIMSK1 = _BV (OCIE1A);             // interrupt on Compare A Match
   
 }  // end of setup

void doCircle (const unsigned long delayAmount)
 {
 for (byte i = 0; i < numberOfLEDs; i++)
   {
   noInterrupts ();
   byte pin = LEDorder [i];
   wantedPin = pin;
   pwmCount = 0;
   interrupts ();
   delay(delayAmount);              
   digitalWrite(pin, LOW);
   }   // end of for
 }  // end of doCircle
 
void loop()
 {
 for (unsigned long n = 500; n > 0; n -= 100)
   doCircle (n);
 } // end of loop


Change the constant PWMdutyCycle to get it brighter or less bright. Right now it is fairly dull (2 / 40 cycles on, the rest off).
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Fennel Rye

#8
May 25, 2012, 02:06 am Last Edit: May 25, 2012, 02:08 am by Fennel Rye Reason: 1
Now we're getting somewhere! Here's the code I have now:

Code: [Select]
const int numberOfLEDs = 14;

const byte LEDorder [numberOfLEDs] = { 1, 2, 3, 4, 5, 7, 6, 8, 12, 9, 13, 10, 0, 11 };

void setup() {               
  for (byte i = 0; i < numberOfLEDs; i++) 
    pinMode(LEDorder [i], OUTPUT);
}  // end of setup

void doCircle (const unsigned long delayAmount)
  {
  for (byte i = 0; i < numberOfLEDs; i++)
    {
    byte pin = LEDorder [i];
    digitalWrite(pin, HIGH);
    delay(delayAmount);             
    digitalWrite(pin, LOW);
    }   // end of for
  }  // end of doCircle
 
void loop()
  {
doCircle (500);
  doCircle (450);
  doCircle (400);
  doCircle (350);
  doCircle (300);
  doCircle (250);
  doCircle (200);
  doCircle (150);
  doCircle (100);
  doCircle (90);
  doCircle (80);
  doCircle (70);
  doCircle (60);
  doCircle (50);
  doCircle (40);
  doCircle (30);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);
  doCircle (20);

 
  } // end of loop


And it's doing it's speed up and then stay at a 20 delay perfectly.  Now I'm trying to implement the pulsing after it does it's cycle of doCircle (20)'s by using a modified version of your 'fading 20 LEDs' code, but I'm running into problems. I tried this on it's own as an experiment:

Code: [Select]
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

const byte pwmPin = 3;
const byte maxPin = 11;

ISR (PCINT0_vect)
{
static byte val = 0;

val = !val;
for (byte i = 0; i <= maxPin; i++)
   if (i != pwmPin)
     digitalWrite (i, val);
}

void setup()
  {
  for (byte i = 0; i <= maxPin; i++)
    pinMode (i, OUTPUT);

  // pin change interrupt
  PCMSK0 = _BV (PCINT1);  // only want pin 9
  PCIFR  = _BV (PCIF0);   // clear any outstanding interrupts
  PCICR |= _BV (PCIE0);   // enable pin change interrupts for PCINT7..0
  }   // end of setup

void loop() 
  {
  // set the brightness of pin 9:
  analogWrite(pwmPin, brightness);   

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness == 0 || brightness == 255)
    fadeAmount = -fadeAmount ;

  // wait for 30 milliseconds to see the dimming effect   
  delay(30);                           
}  // end of loop


I changed the 'maxPin' to 11, because I didn't want all the LEDs to fade in and out at once (I don't have sufficient power so I only want pins 3, 5, 6, 9, 10, and 11 pulsing) but I only got the pin 3 LED fading.  I'm assuming I'm not understanding the maxPin.  Just tried your brightness limiting code and it worked perfectly. You're helping so much, Nick.  I really aprecciate it.  I apologize for the neverending questions, but it's exciting to be learning this stuff, however slow that process may be.  You've gotten me to the point where this thing is almost finished!  Now I just need it to end with the pulsing loop and have it all activated by a button push.  Hehe.  :smiley-roll-blue:
Fennel Rye

Nick Gammon

Code: [Select]

  doCircle (20);
 doCircle (20);
 doCircle (20);
 doCircle (20);
 doCircle (20);
 doCircle (20);
 doCircle (20);
 doCircle (20);
 doCircle (20);
 doCircle (20);
 doCircle (20);
 doCircle (20);
 doCircle (20);
 doCircle (20);
 doCircle (20);


Think "loops".

Code: [Select]
for (byte j = 0; j < 14; j++)
 doCircle (20);
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Fennel Rye

Quote
for (byte j = 0; j < 14; j++)
  doCircle (20);


Little confused about bytes.  Where are you getting the names 'i' and 'j' from for these bytes?  I understand that they are there to store a number, but I'm getting confused on where the letters are coming from.
Fennel Rye

Nick Gammon

Try this, it fades a group of LEDs on and off. After that do a bit of experimenting. :)

Code: [Select]
const int numberOfLEDs = 14;

volatile byte wantedPins [numberOfLEDs] =  { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 };   // which pin to pulse on and off

const byte PWMiterations = 40;
byte PWMdutyCycle;   // <-- should be less than PWMiterations

volatile byte pwmCount;

ISR(TIMER1_COMPA_vect)
{
byte i;

  if (pwmCount > PWMdutyCycle)
    {
    // turn all off
    for (i = 0; i < numberOfLEDs; i++)
      digitalWrite(i, LOW);     
    }
  else
    {
    // turn wanted ones on
    for (i = 0; i < numberOfLEDs; i++)
      if (wantedPins [i])
        digitalWrite(i, HIGH);     
    }
   
   
if (++pwmCount >= PWMiterations)
   pwmCount = 0;
}

void setup()
  {               
  for (byte i = 0; i < numberOfLEDs; i++) 
    pinMode(i, OUTPUT);
   
  // set up Timer 1
  TCCR1A = 0;          // normal operation
  TCNT1 = 0;           // make sure we start at zero
  TCCR1B = _BV(WGM12) | _BV(CS10) | _BV (CS12);   // CTC, scale to clock / 1024
  OCR1A =  5;       // compare A register value (1000 * clock speed / 1024)
  TIMSK1 = _BV (OCIE1A);             // interrupt on Compare A Match
   
  }  // end of setup


void loop()
  {
  for (PWMdutyCycle = 0; PWMdutyCycle < PWMiterations; PWMdutyCycle++)
    delay (100);

  for (PWMdutyCycle = PWMiterations; PWMdutyCycle > 0; PWMdutyCycle--)
    delay (100);
   
  } // end of loop


Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

Quote
Where are you getting the names 'i' and 'j' from for these bytes?



Code: [Select]
for (byte j = 0; j < 14; j++)

That declares "j" as in:

Code: [Select]
byte j
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Fennel Rye

But what is byte j? Are you creating and naming a byte with that declaration or is byte j something that already exists that you are calling upon? 
Fennel Rye

Nick Gammon

It is created at that point as a loop variable.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Go Up