Go Down

Topic: LED bike light mod (Read 5275 times) previous topic - next topic

nyg78

I am trying to modify the bike light project found at the bottom of this page: http://www.ladyada.net/learn/arduino/lesson5.html

I want to do two things: 1) I want to add a second push button switch to change the direction of the currently running pattern. For example, if the lights go right to left, pushing the button would make them go from left to right, pushing the button again would set them back to the original direction. 2) I want this to remember what light pattern was displayed when it is turned off and then back on again.

I changed some of the patterns from the original code and will add more which I know how to do, but I need help with the two things above. Would I need a buttonState2 in there for the pattern reverse switch?  Any help is appreciated. Thank you. Here's where I'm at:

Code: [Select]

/*
*  Bike light with pattern reverse button
*/

int potPin = 0;                 // input pin for the pot
int timer = 50;
// you can adjust the numbers below to set the max and min for the speed adjustment
int x = 10;        // sets the max speed (0 = fast) the lower the number the faster it can go
int y = 300;      // sets the min speed (100 = slow) the higher the number the slower it can go

int switchPin = 2;              // pattern select switch is connected to pin 2
int switchPin2 = 3;              // pattern reverse switch is connected to pin 3
int led1Pin = 11;
int led2Pin = 10;
int led3Pin = 9;
int led4Pin = 8;
int led5Pin = 7;

int val;                        // variable for reading the pin status
int val2;                       // variable for reading the delayed status
int buttonState;                // variable to hold the button state

int lightMode = 0;              // What mode is the light in?

void setup() {
  pinMode(switchPin, INPUT);    // Set the switch pin as input
  pinMode(switchPin2, INPUT);   // set the 2nd switch as input
 
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(led3Pin, OUTPUT);
  pinMode(led4Pin, OUTPUT);
  pinMode(led5Pin, OUTPUT);
 
  Serial.begin(9600);           // Set up serial communication at 9600bps
  buttonState = digitalRead(switchPin);   // read the initial state
}

void loop(){
  val = digitalRead(switchPin);      // read input value and store it in val
  delay(10);                         // 10 milliseconds is a good amount of time
    timer = analogRead(0);               // reads the pot and sets the timer to the value
    timer = map(timer, 0, 1023, x, y);   // maps the timer value to the max and min values set above with x and y 
  val2 = digitalRead(switchPin);     // read the input again to check for bounces
  if (val == val2) {                 // make sure we got 2 consistant readings!
    if (val != buttonState) {          // the button state has changed!
      if (val == LOW) {                // check if the button is pressed
        if (lightMode == 0) {          // if its off
          lightMode = 1;               // alternate blinking!
        } else {
          if (lightMode == 1) {        // if its alternate blinking
            lightMode = 2;             // wave then come back!
          } else {
            if (lightMode == 2) {      // if its waving then coming back
              lightMode = 3;           // make it wave!
            } else {
               if (lightMode == 3) { //  if its waving,
                lightMode = 0;           // turn light off!
              }
}
          }
        }
      }
    }
    buttonState = val;                 // save the new state in our variable
  }

  // Now do whatever the lightMode indicates
  if (lightMode == 0) { // all-off
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, LOW);
  }
if (lightMode == 1) { // alternate blinking
    digitalWrite(led1Pin, HIGH);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, HIGH);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, HIGH);
    delay(timer);
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, HIGH);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, HIGH);
    digitalWrite(led5Pin, LOW);
    delay(timer);
  }
if (lightMode == 2)  { // "wave" then come back
    digitalWrite(led1Pin, HIGH);
    delay(timer);
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, HIGH);
    delay(timer);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, HIGH);
    delay(timer);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, HIGH);
    delay(timer);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, HIGH);
    delay(timer);
    digitalWrite(led5Pin, LOW);
    digitalWrite(led4Pin, HIGH);
    delay(timer);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led3Pin, HIGH);
    delay(timer);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led2Pin, HIGH);
    delay(timer);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led1Pin, HIGH);
  }
  if (lightMode == 3)  { // "wave"
    digitalWrite(led5Pin, LOW);
    digitalWrite(led1Pin, HIGH);
    delay(timer);
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, HIGH);
    delay(timer);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, HIGH);
    delay(timer);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, HIGH);
    delay(timer);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, HIGH);
    delay(timer);
    digitalWrite(led5Pin, LOW);
  }   
}

nyg78

Any suggestions how to do this?

nyg78

Still haven't figured this out.  Any new people around that can help?  I'm sure it can be done, just don't know how to do it!  Thank you.

Magician

Add some code to work with second button (on pin #3):
Code: [Select]
int val_rev;                        // variable for reading the pin status
int val2_rev;                       // variable for reading the delayed status
int buttonState_rev;
............................................

Then in the beginning of main loop you will have to check the status of second "reverse" button:
Code: [Select]
  val_rev = digitalRead(switchPin2);      //REVERSE read input value and store it in val
  delay(10);                         // 10 milliseconds is a good amount of time
  val2_rev = digitalRead(switchPin2);     // read the input again to check for bounces
  if (val_rev == val2_rev) {                 // make sure we got 2 consistant readings!
    buttonState_rev = val_rev;                 // save the new state in our variable
  }

And last thing is reverse lighting pattern depends on buttonState_rev, I'll show for light_mode 2 , but you can re-work others similar:

Code: [Select]

if (lightMode == 2) { // blinking
  if ( buttonState_rev == LOW ) {
    digitalWrite(led1Pin, HIGH);
    digitalWrite(led2Pin, HIGH);
    digitalWrite(led3Pin, HIGH);
    digitalWrite(led4Pin, HIGH);
    digitalWrite(led5Pin, HIGH);
    delay(100);
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, LOW);
    delay(100);
  }
  else  {
    digitalWrite(led5Pin, HIGH);
    digitalWrite(led4Pin, HIGH);
    digitalWrite(led3Pin, HIGH);
    digitalWrite(led3Pin, HIGH);
    digitalWrite(led2Pin, HIGH);
    delay(100);
    digitalWrite(led5Pin, LOW);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led1Pin, LOW);
    delay(100);
  }
}


To store status of the pattern when power is switch off, you have to study how to store variable in EEPROM . In playground, AFAIR, some example code to work with EEPROM

nyg78

I've been working at it but can't get it to work.  I changed some of the original, so from this point this is the code I will be using.  The button to change the pattern works and the pot works, just not button 2 to reverse the pattern.  In the code I only changed the first mode (lightMode 0) to do the reverse, I realize the others are unchanged but want to make sure the button works first, which right now it doesn't.  Here's where I'm at:
Code: [Select]

/*
*  bike light with pattern reverse button & pot
*/

int potPin = 0;                 // input pin for the pot
int timer = 50;      // you can adjust the numbers below to set the max and min for the speed adjustment
int x = 10;        // sets the max speed (0 = fast) the lower the number the faster it can go
int y = 300;      // sets the min speed (100 = slow) the higher the number the slower it can go

int switchPin = 2;              // switch is connected to pin 2
int switchPin2 = 13;             // switch to reverse pattern is connected to pin 13
int led1Pin = 11;
int led2Pin = 10;
int led3Pin = 9;
int led4Pin = 8;
int led5Pin = 7;
int led6Pin = 6;
int led7Pin = 5;
int led8Pin = 4;

int val;                        // variable for reading the pin status
int val2;                       // variable for reading the delayed status
int buttonState;                // variable to hold the button state
int val_rev;                        // variable for reading the pin status
int val2_rev;                       // variable for reading the delayed status
int buttonState_rev;


int lightMode = 0;              // What mode is the light in?

void setup() {
  pinMode(switchPin, INPUT);    // Set the switch pin as input

  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(led3Pin, OUTPUT);
  pinMode(led4Pin, OUTPUT);
  pinMode(led5Pin, OUTPUT);
  pinMode(led6Pin, OUTPUT);
  pinMode(led7Pin, OUTPUT);
  pinMode(led8Pin, OUTPUT);
 
  Serial.begin(9600);           // Set up serial communication at 9600bps
  buttonState = digitalRead(switchPin);   // read the initial state
}

void loop(){
  val = digitalRead(switchPin);      // read input value and store it in val
  delay(10);                         // 10 milliseconds is a good amount of time
    timer = analogRead(0);               // reads the pot and sets the timer to the value
    timer = map(timer, 0, 1023, x, y);   // maps the timer value to the max and min vaues set above with x and y 
  val2 = digitalRead(switchPin);     // read the input again to check for bounces
  val_rev = digitalRead(switchPin2);      //REVERSE read input value and store it in val
  delay(10);                         // 10 milliseconds is a good amount of time
  val2_rev = digitalRead(switchPin2);     // read the input again to check for bounces
  if (val_rev == val2_rev) {                 // make sure we got 2 consistant readings!
    buttonState_rev = val_rev;                 // save the new state in our variable
  }
  if (val == val2) {                 // make sure we got 2 consistant readings!
    if (val != buttonState) {          // the button state has changed!
      if (val == LOW) {                // check if the button is pressed
        if (lightMode == 0) {          // if its left to right
          lightMode = 1;               // chase left to right then back!
        } else {
          if (lightMode == 1) {        // if its left to right then back
            lightMode = 2;             // double left to right!
          } else {
            if (lightMode == 2) {      // if its double left to right
              lightMode = 3;           // all off
            } else {
              if (lightMode == 3) {    // if its all off
                lightMode = 0;
              }
    }
          }
        }
      }
    }
    buttonState = val;                 // save the new state in our variable
  }

  // Now do whatever the lightMode indicates
  if (lightMode == 0)  { // single left to right
    if ( buttonState_rev == LOW ) {
    digitalWrite(led1Pin, HIGH);
    delay(timer);
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, HIGH);
    delay(timer);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, HIGH);
    delay(timer);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, HIGH);
    delay(timer);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, HIGH);
    delay(timer);
    digitalWrite(led5Pin, LOW);
    digitalWrite(led6Pin, HIGH);
    delay(timer);
    digitalWrite(led6Pin, LOW);
    digitalWrite(led7Pin, HIGH);
    delay(timer);
    digitalWrite(led7Pin, LOW);
    digitalWrite(led8Pin, HIGH);
    delay(timer);
    digitalWrite(led8Pin, LOW);
  }
  else  { //single right to left
    digitalWrite(led8Pin, HIGH);
    delay(timer);
    digitalWrite(led8Pin, LOW);
    digitalWrite(led7Pin, HIGH);
    delay(timer);
    digitalWrite(led7Pin, LOW);
    digitalWrite(led6Pin, HIGH);
    delay(timer);
    digitalWrite(led6Pin, LOW);
    digitalWrite(led5Pin, HIGH);
    delay(timer);
    digitalWrite(led5Pin, LOW);
    digitalWrite(led4Pin, HIGH);
    delay(timer);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led3Pin, HIGH);
    delay(timer);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led2Pin, HIGH);
    delay(timer);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led1Pin, HIGH);
    delay(timer);
    digitalWrite(led1Pin, LOW);
  }
}
if (lightMode == 1)  { // single light left to right then back
    digitalWrite(led1Pin, HIGH);
    delay(timer);
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, HIGH);
    delay(timer);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, HIGH);
    delay(timer);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, HIGH);
    delay(timer);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, HIGH);
    delay(timer);
    digitalWrite(led5Pin, LOW);
    digitalWrite(led6Pin, HIGH);
    delay(timer);
    digitalWrite(led6Pin, LOW);
    digitalWrite(led7Pin, HIGH);
    delay(timer);
    digitalWrite(led7Pin, LOW);
    digitalWrite(led8Pin, HIGH);
    delay(timer);
    digitalWrite(led8Pin, LOW);
    digitalWrite(led7Pin, HIGH);
    delay(timer);
    digitalWrite(led7Pin, LOW);
    digitalWrite(led6Pin, HIGH);
    delay(timer);
    digitalWrite(led6Pin, LOW);
    digitalWrite(led5Pin, HIGH);
    delay(timer);
    digitalWrite(led5Pin, LOW);
    digitalWrite(led4Pin, HIGH);
    delay(timer);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led3Pin, HIGH);
    delay(timer);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led2Pin, HIGH);
    delay(timer);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led1Pin, HIGH);
  }
  if (lightMode == 2)  { // double lights left to right
    digitalWrite(led1Pin, HIGH);
    delay(timer);
    digitalWrite(led2Pin, HIGH);
    delay(timer);
    digitalWrite(led1Pin, LOW);
    digitalWrite(led3Pin, HIGH);
    delay(timer);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led4Pin, HIGH);
    delay(timer);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led5Pin, HIGH);
    delay(timer);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led6Pin, HIGH);
    delay(timer);
    digitalWrite(led5Pin, LOW);
    digitalWrite(led7Pin, HIGH);
    delay(timer);
    digitalWrite(led6Pin, LOW);
    digitalWrite(led8Pin, HIGH);
    delay(timer);
    digitalWrite(led7Pin, LOW);
    delay(timer);
    digitalWrite(led8Pin, LOW);
    delay(timer);
  }
  if (lightMode == 3) { // all off
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, LOW);
    digitalWrite(led6Pin, LOW);
    digitalWrite(led7Pin, LOW);
    digitalWrite(led8Pin, LOW);
  }
}

Magician

Why did you change pin #3 to pin #13?
I don't think pin #13 as input is a good idea, it wired to on-board led.
And, code isn't checking status of the "reverse" button if it in the middle lighting pattern. I just show  you an idea to start with. Try to test it pressing rev. button (pin #3) for long time, when lighting pattern finished it's subroutine and start again.

To make it more responsive for operator, look in:
http://arduino.cc/en/Reference/AttachInterrupt
And it's second reason to live #3 as reverse input, you can't create interrupt routine with #13.


nyg78

Thanks Magician.  I moved it to pin #3 and now it reverses the pattern if I hold it down, but when I let go, it goes back to the original.  How can I get it to "hold" the pattern until I press the button again?

nyg78

Hmmm didn't work.  I was supposed to replace this:
Code: [Select]

if (val_rev == val2_rev) {                 // make sure we got 2 consistant readings!
    buttonState_rev = val_rev;                 // save the new state in our variable
  }


With this, right?
Code: [Select]

if (val_rev == val2_rev && val_rev != buttonState_rev ) {                 
    buttonState_rev = val_rev;                 // save the new state in our variable
  }


It still won't "hold" the pattern when I let go of the button.  Any other suggestions?

Magician

Probably, it could be done easier, how you wire your buttons to ground?
If so, try this:
Code: [Select]

val_rev = digitalRead(switchPin2);
if (!val_rev) {                 // make sure we got 2 consistant readings!
   buttonState_rev = !buttonState_rev ;                 // save the new state in our variable
 }

nyg78

Wow, it works!  Thank you very much for your help!

I wire the buttons to ground just like here http://www.ladyada.net/learn/arduino/lesson5.html

Another thing.  When I originally was putting this together, instead of this which I currently have:
Code: [Select]

digitalWrite(led1Pin, HIGH);
    delay(timer);
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, HIGH);
    delay(timer);


I had used this, which seemed to not be so jerky when the pot was turned:
Code: [Select]

digitalWrite(led1Pin, HIGH);
    delay(timer);
    timer = analogRead(0);               // reads the pot and sets the timer to the value
    timer = map(timer, 0, 1023, x, y);   // maps the timer value to the max and min vaues set above with x and y 
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, HIGH);
    delay(timer);
    timer = analogRead(0);               // reads the pot and sets the timer to the value
    timer = map(timer, 0, 1023, x, y);   // maps the timer value to the max and min vaues set above with x and y 


Doing this to every pattern took up a lot of memory.  Do you know a way to make it look smoother as I turn the pot?

Also, sometimes when I push the button to change the pattern, it doesn't work, but if I turn the pot slightly and then push the button it will change the pattern.  Any way to fix this?

I appreciate all of the help you have provided.

Magician

I'd leave analogRead in the beginning, as in original version, and try to smooth out irregularities by averaging:
Code: [Select]

  timer = 0;
for ( int i = 0; i < 10; i++ ) {
    timer += analogRead(0);               // reads the pot and sets the timer to the value
}
  timer = timer / 10;
   timer = map(timer, 0, 1023, x, y);   // maps the timer value to the max and min vaues set above with x and y 

nyg78

So put that in the void loop() section under the delay(10)?

Magician

#12
Jul 30, 2011, 02:23 am Last Edit: Jul 30, 2011, 02:28 am by Magician Reason: 1
Yes, like in the post #4.
Quote
Also, sometimes when I push the button to change the pattern, it doesn't work, but if I turn the pot slightly and then push the button it will change the pattern.  Any way to fix this?

And look into attachinterrupt, I advised you earlier, it should fix it.

nyg78

That fixed the smoothing issue.  I going to work on that attachinterrupt.

nyg78

Getting nowhere with this interrupt.  I'm completely lost.

Go Up