Go Down

### Topic: Adding an on/off button with an existing sketch (Read 2752 times)previous topic - next topic

#### bobmcinnis

##### Dec 14, 2012, 02:09 amLast Edit: Dec 14, 2012, 02:51 am by Coding Badly Reason: 1
I've finally gotten my 11 year-old son interested in the Arduino I bought him a few months back for his birthday because has a great application--a project in school to build a model of a nebula. We've been building one out of fuzzy stuff and inserting LED's.  We've successfully made four LED randomly flicker using the sketch below.

We also have a push button attached we've used in previous projects to turn LED's on and off after each push. Our problem is we're now trying to add  the on/off button part of the first sketch to the random flickering sketch and it's not going well. Any help would be appreciated. I'm going to post three sketches. First, the twinkle sketch, which works great:

Code: [Select]
`/* * randomly flickering LEDs */int ledPin[] = {  13, 9, 10, 11};              // pwm pins onlyint ledState[5];                 // last state of each ledlong randNumber;void setup() {  for (int i=0; i<=4; i++){      // set each led pin as an output    pinMode(ledPin[i], OUTPUT);  }  randomSeed(analogRead(0));     // seed the rnd generator with noise from unused pin  for (int i=0; i<=4; i++){      // init each led with a random value    ledState[i] = random(20, 201);  }}void loop(){  for (int i=0; i<=4; i++){                  // for each led:    analogWrite(ledPin[i], ledState[i]);     // set the pwm value of that pin determined previously    randNumber = random(-40, 41);            // generate new random number and add that to the current value    ledState[i] += randNumber;               // that range can be tweaked to change the intensity of the flickering    if (ledState[i] > 200) {                 // clamp the limits of the pwm values so it remains within      ledState[i] = 200;                     // a pleasing range as well as the pwm range    }    if (ledState[i] < 10) {      ledState[i] = 10;    }  }  delay(100);    // the delay between changes}`

Here's the button sketch we've also gotten to work:

Code: [Select]
`/* Debounce Each time the input pin goes from LOW to HIGH (e.g. because of a push-button press), the output pin is toggled from LOW to HIGH or HIGH to LOW.  There's a minimum delay between toggles to debounce the circuit (i.e. to ignore noise).   The circuit: * LED attached from pin 13 to ground * pushbutton attached from pin 2 to +5V * 10K resistor attached from pin 2 to ground * Note: On most Arduino boards, there is already an LED on the board connected to pin 13, so you don't need any extra components for this example. created 21 November 2006 by David A. Mellis modified 3 Jul 2009 by Limor Fried http://www.arduino.cc/en/Tutorial/Debounce */// constants won't change. They're used here to // set pin numbers:const int buttonPin = 2;     // the number of the pushbutton pinconst int ledPingreen =  13;      // the number of the LED pinconst int ledPinred =  9;      // the number of the LED pinconst int ledPinblue =  11;      // the number of the LED pinconst int ledPinyellow =  10;      // the number of the LED pin// Variables will change:int ledState = LOW;         // the current state of the output pinint lastButtonState = LOW;   // the previous reading from the input pinint lastReading= LOW;// the following variables are long's because the time, measured in miliseconds,// will quickly become a bigger number than can be stored in an int.long lastDebounceTime = 0;  // the last time the output pin was toggledlong debounceDelay = 50;    // the debounce time; increase if the output flickersvoid setup() {  pinMode(buttonPin, INPUT);  pinMode(ledPingreen, OUTPUT);  pinMode(ledPinred, OUTPUT);  pinMode(ledPinblue, OUTPUT);  pinMode(ledPinyellow, OUTPUT);}void loop() {  // read the state of the switch into a local variable:  int reading = digitalRead(buttonPin);  // check to see if you just pressed the button  // (i.e. the input went from LOW to HIGH),  and you've waited  // long enough since the last press to ignore any noise:    // If the switch changed, due to noise or pressing:  if (reading != lastReading) {    // reset the debouncing timer    lastDebounceTime = millis();    // save the reading.  Next time through the loop,    // it'll be lastReading:    lastReading = reading;  }    if ((millis() - lastDebounceTime) > debounceDelay) {    // whatever the reading is at, it's been there for longer    // than the debounce delay, so accept the button state change:      // toggle the LED if the state of the button changes from LOW to HIGH:    if (lastButtonState == LOW && reading == HIGH) {      if (ledState == HIGH) {        ledState = LOW;      } else {        ledState = HIGH;      }      digitalWrite(ledPingreen, ledState);      digitalWrite(ledPinred, ledState);      digitalWrite(ledPinblue, ledState);      digitalWrite(ledPinyellow, ledState);    }    lastButtonState = reading;  }}`

I seem to be exceeding the 9500 character limit, so I'll put in the next post the code after unsuccessfully trying to insert the button code and put it into the random flickering code.

Moderator edit: [code] [/code] tags added.

#### bobmcinnis

#1
##### Dec 14, 2012, 02:10 amLast Edit: Dec 14, 2012, 02:52 am by Coding Badly Reason: 1
Here's the code after unsuccessfully trying to insert the button code and put it into the random flickering code:

Code: [Select]
`/* * randomly flickering LEDs */const int buttonPin = 2;     // the number of the pushbutton pinint ledPin[] = {  13, 9, 10, 11};              // pwm pins onlyint ledState[5];                 // last state of each ledlong randNumber;// the following variables are long's because the time, measured in miliseconds,// will quickly become a bigger number than can be stored in an int.long lastDebounceTime = 0;  // the last time the output pin was toggledlong debounceDelay = 50;    // the debounce time; increase if the output flickersvoid setup() {    pinMode(buttonPin, INPUT);  for (int i=0; i<=4; i++){      // set each led pin as an output    pinMode(ledPin[i], OUTPUT);  }  randomSeed(analogRead(0));     // seed the rnd generator with noise from unused pin  for (int i=0; i<=4; i++){      // init each led with a random value    ledState[i] = random(20, 201);  }}void loop() {  // read the state of the switch into a local variable:  int reading = digitalRead(buttonPin);  // check to see if you just pressed the button  // (i.e. the input went from LOW to HIGH),  and you've waited  // long enough since the last press to ignore any noise:    // If the switch changed, due to noise or pressing:  if (reading != lastReading) {    // reset the debouncing timer    lastDebounceTime = millis();    // save the reading.  Next time through the loop,    // it'll be lastReading:    lastReading = reading;  }    if ((millis() - lastDebounceTime) > debounceDelay) {    // whatever the reading is at, it's been there for longer    // than the debounce delay, so accept the button state change:      // toggle the LED if the state of the button changes from LOW to HIGH:    if (lastButtonState == LOW && reading == HIGH) {      if (ledState == HIGH) {        ledState = LOW;      } else {        ledState = HIGH;      }      digitalWrite(ledPingreen, ledState);      digitalWrite(ledPinred, ledState);      digitalWrite(ledPinblue, ledState);      digitalWrite(ledPinyellow, ledState);    }    lastButtonState = reading;  }}void loop(){  for (int i=0; i<=4; i++){                  // for each led:    analogWrite(ledPin[i], ledState[i]);     // set the pwm value of that pin determined previously    randNumber = random(-40, 41);            // generate new random number and add that to the current value    ledState[i] += randNumber;               // that range can be tweaked to change the intensity of the flickering    if (ledState[i] > 200) {                 // clamp the limits of the pwm values so it remains within      ledState[i] = 200;                     // a pleasing range as well as the pwm range    }    if (ledState[i] < 10) {      ledState[i] = 10;    }  }  delay(100);    // the delay between changes}`

Here are the errors we're getting. My son is only 11 and I'm 51. We're both new to this so we're both struggling. I'm assuming we're not accounting for the difference between the way the button turns on the LED's from LOW to HIGH in the button sketch and the way the random flickering is handled in the other sketch. Any advice would be appreciated. Thanks.

Code: [Select]
`random_flickering_with_button.cpp: In function 'void loop()':random_flickering_with_button:35: error: 'lastReading' was not declared in this scoperandom_flickering_with_button:48: error: 'lastButtonState' was not declared in this scoperandom_flickering_with_button:49: error: ISO C++ forbids comparison between pointer and integerrandom_flickering_with_button:50: error: incompatible types in assignment of 'int' to 'int [5]'random_flickering_with_button:52: error: incompatible types in assignment of 'int' to 'int [5]'random_flickering_with_button:54: error: 'ledPingreen' was not declared in this scoperandom_flickering_with_button:55: error: 'ledPinred' was not declared in this scoperandom_flickering_with_button:56: error: 'ledPinblue' was not declared in this scoperandom_flickering_with_button:57: error: 'ledPinyellow' was not declared in this scoperandom_flickering_with_button:59: error: 'lastButtonState' was not declared in this scoperandom_flickering_with_button.cpp: In function 'void loop()':random_flickering_with_button:64: error: redefinition of 'void loop()'random_flickering_with_button:26: error: 'void loop()' previously defined here`

Moderator edit: [code] [/code] tags added.

#### fkeel

#2
##### Dec 14, 2012, 02:50 am
I did some editing

Code: [Select]
`/* * randomly flickering LEDs */const int buttonPin = 2;     // the number of the pushbutton pinint ledPin[] = {  13, 9, 10, 11};              // pwm pins onlyint ledState[5];                 // last state of each ledint lastReading = 0; // -----> added this as you forgot to initialize itint lastButtonState = LOW; // -----> added this as you forgot to initialize itlong randNumber;// the following variables are long's because the time, measured in miliseconds,// will quickly become a bigger number than can be stored in an int.long lastDebounceTime = 0;  // the last time the output pin was toggledlong debounceDelay = 50;    // the debounce time; increase if the output flickersvoid setup() {    pinMode(buttonPin, INPUT);  for (int i=0; i<=4; i++){      // set each led pin as an output    pinMode(ledPin[i], OUTPUT); // -----> changed from ledPin to ledPin[i]  }  randomSeed(analogRead(0));     // seed the rnd generator with noise from unused pin  for (int i=0; i<=4; i++){      // init each led with a random value    ledState[i] = random(20, 201); // -----> changed from ledPin to ledPin[i]  }}void loop() {  // read the state of the switch into a local variable:  int reading = digitalRead(buttonPin);  // check to see if you just pressed the button   // (i.e. the input went from LOW to HIGH),  and you've waited   // long enough since the last press to ignore any noise:    // If the switch changed, due to noise or pressing:  if (reading != lastReading) {    // reset the debouncing timer    lastDebounceTime = millis();    // save the reading.  Next time through the loop,    // it'll be lastReading:    lastReading = reading;  }     if ((millis() - lastDebounceTime) > debounceDelay) {    // whatever the reading is at, it's been there for longer    // than the debounce delay, so accept the button state change:      // toggle the LED if the state of the button changes from LOW to HIGH:    if (lastButtonState == LOW && reading == HIGH) {      if (ledState[1] == HIGH) { //which one do you mean? I just randomly chose ledState[1] ---> you probably want a for loop here        ledState[1] = LOW;      } else {        ledState[1] = HIGH;      }      //digitalWrite(ledPingreen, ledState); //declare the variables      //digitalWrite(ledPinred, ledState);      //digitalWrite(ledPinblue, ledState);      //digitalWrite(ledPinyellow, ledState);    }    lastButtonState = reading;  }// you cant have 2 "loop" functions. put everything in one  for (int i=0; i<=4; i++){                  // for each led:    analogWrite(ledPin[i], ledState[i]);     // set the pwm value of that pin determined previously -----> its an ARRAY tell it which index you need    randNumber = random(-40, 41);            // generate new random number and add that to the current value    ledState[i] += randNumber;               // that range can be tweaked to change the intensity of the flickering    if (ledState[i] > 200) {                 // clamp the limits of the pwm values so it remains within      ledState[i] = 200;                     // a pleasing range as well as the pwm range    }    if (ledState[i] < 10) {      ledState[i] = 10;    }  }  delay(100);    // the delay between changes}`

basically there are three problems

a) you need to declare each and every variable. you need to assign a value to it before you use it
b) you cant assume that the compiler knows which index of an array you are interested in. if you use a value from an array dont forget to add the index ( ... this thing: ). Make sure you understand arrays
c) arduino can only have on "loop" function. put everything there.

your code should compile fine, the way I edited it. I did not check it for functionality though.

Cheers

p.
http://embodimentlabs.tumblr.com/
http://paulstrohmeier.info/

#### fkeel

#3
##### Dec 14, 2012, 02:54 am
read this. its for java, but the principle applies to c as well.

and take a quick look at this: http://arduino.cc/en/Reference/Array
http://embodimentlabs.tumblr.com/
http://paulstrohmeier.info/

#### bobmcinnis

#4
##### Dec 14, 2012, 10:11 pm
Thanks fkeel. I appreciate you cleaning up my code and the explanations. You're right, it does compile without an error. The button still doesn't work, as I'm sure you know, so we're moving through the clues you provided trying to figure out the solution. This may be too beyond us at this point and we're running out of time.

If we can't get the code fixed in time, I'm wondering if there's an alternative way for a button to control this. Perhaps just put it between the battery and the Arduino?

Thanks for your help. If you think it should be working with the code you fixed, please let us know and we'll try to make sure all the pins are in the right places, etc.

Thanks again!

#### fkeel

#5
##### Dec 14, 2012, 10:17 pm
to be honest, I did not look at the functionality of what it does.

I think you might be better off writing code from scratch.

If you tell me what *exactly* you want the code to do I can give you some more pointers.
http://embodimentlabs.tumblr.com/
http://paulstrohmeier.info/

#### fkeel

#6
##### Dec 14, 2012, 10:29 pmLast Edit: Dec 14, 2012, 10:40 pm by fkeel Reason: 1
ok, I think I know what you want to do. I played with it for a bit. This will work, assuming the button code is still ok.

make sure you understand the code though.

Code: [Select]
`const int buttonPin = 2;     // the number of the pushbutton pinint ledPin[] = {  13, 9, 10, 11};              // pwm pins onlyint ledState[5];                 // last state of each ledint lastReading = 0; // -----> added this as you forgot to initialize itint lastButtonState = LOW; // -----> added this as you forgot to initialize it///////////////////////////// this is a variable which decides whether to blinklights or notboolean blinkLEDs = true; ///////////////////////////long randNumber;// the following variables are long's because the time, measured in miliseconds,// will quickly become a bigger number than can be stored in an int.long lastDebounceTime = 0;  // the last time the output pin was toggledlong debounceDelay = 50;    // the debounce time; increase if the output flickersvoid setup() {  pinMode(buttonPin, INPUT);  for (int i=0; i<=4; i++){      // set each led pin as an output    pinMode(ledPin[i], OUTPUT); // -----> changed from ledPin to ledPin[i]  }  randomSeed(analogRead(0));     // seed the rnd generator with noise from unused pin  for (int i=0; i<=4; i++){      // init each led with a random value    ledState[i] = random(20, 201); // -----> changed from ledPin to ledPin[i]  }}void loop() {  // read the state of the switch into a local variable:  int reading = digitalRead(buttonPin);  // check to see if you just pressed the button   // (i.e. the input went from LOW to HIGH),  and you've waited   // long enough since the last press to ignore any noise:    // If the switch changed, due to noise or pressing:  if (reading != lastReading) {    // reset the debouncing timer    lastDebounceTime = millis();    // save the reading.  Next time through the loop,    // it'll be lastReading:    lastReading = reading;  }   if ((millis() - lastDebounceTime) > debounceDelay) {    // whatever the reading is at, it's been there for longer    // than the debounce delay, so accept the button state change:    // toggle the LED if the state of the button changes from LOW to HIGH:    if (lastButtonState == LOW && reading == HIGH) {        ////////////////////////      ///// if blinkLEDs is true, the following code will set it to false      ////// if blinkLEDS is flase it will be set to true.      ////// so everytime you push the button, it will switch state      ///////////////////////      if (blinkLEDs == true){        blinkLEDS = false;      }      else {        blinkLEDs = true;      }    }    lastButtonState = reading;  }  ////////////  //if blinkLEDs is true, awesomeNebulaEffect will happen  if (blinkLEDs == true) {    doAwesomeNebulaEffect(); // this calls the function "doAwseomNebulaEffect"  }  ///////////////  // THis is where the loop ends}//////////////////////// this is a function. its called from within the loop, but the code is outside of the loop// here we declare the function which makes the nabula effectvoid doAwesomeNebulaEffect () {  for (int i=0; i<=4; i++){                  // for each led:    analogWrite(ledPin[i], ledState[i]);     // set the pwm value of that pin determined previously -----> its an ARRAY tell it which index you need    randNumber = random(-40, 41);            // generate new random number and add that to the current value    ledState[i] += randNumber;               // that range can be tweaked to change the intensity of the flickering    if (ledState[i] > 200) {                 // clamp the limits of the pwm values so it remains within      ledState[i] = 200;                     // a pleasing range as well as the pwm range    }    if (ledState[i] < 10) {      ledState[i] = 10;    }  }}`
http://embodimentlabs.tumblr.com/
http://paulstrohmeier.info/

#### bobmcinnis

#7
##### Dec 14, 2012, 10:43 pm
Thanks! My son is very excited and appreciative. We'll give it a try. I'll make sure I take him through the code.

#### bobmcinnis

#8
##### Dec 14, 2012, 10:50 pm
Hmmm. We're getting an error:

sketch_dec14b.cpp: In function 'void loop()':
sketch_dec14b:58: error: 'blinkLEDS' was not declared in this scope

If it helps, the button code was taken from the second sketch I posted and worked great with in that one. When I tried to move it over to the  twinkle one, that's where the problems seemed to start.

Sorry, I really wasn't looking for someone to write the code for us, but under the circumstances, I can't tell you how much we appreciate it!

#### Arrch

#9
##### Dec 14, 2012, 10:50 pm

sketch_dec14b:58: error: 'blinkLEDS' was not declared in this scope

Note the case difference between the error message and what's declared.

#### fkeel

#10
##### Dec 14, 2012, 10:56 pmLast Edit: Dec 14, 2012, 10:58 pm by fkeel Reason: 1
what Arrch said :-D

also: I did not test it. it *should* work in principle, but it probably wont as I am a horrible coder (I am sloppy with the details, so chances are high there are more little bugs in there.) also. I never tested it.

so the principle is correct. but you need to work on the details ... and in order to do that, you need to understand the principle... so in the end... its still down to you to write your code :-D

also, you want to understand it, so you can edit it later.

I just found it easyer to do it, than to explain how to do it.
http://embodimentlabs.tumblr.com/
http://paulstrohmeier.info/

#### bobmcinnis

#11
##### Dec 14, 2012, 11:01 pm
Aha! We noticed the uppercase "S" and it worked! THANKS SO MUCH!!!!

One more question. Upon the button press, the lights stop twinkling but still remain on. Would there happen to be an easy change to a variable to make them turn off altogether instead of stopping twinkling?

Honestly, I think he's happy the way it is, but if there's a variable we can change in the code to have the button turn the lights off, we'd love to give it a try?

Thanks!

#### fkeel

#12
##### Dec 14, 2012, 11:03 pmLast Edit: Dec 14, 2012, 11:05 pm by fkeel Reason: 1
edit: *after* the if statement where you call the nebula function, use digitalWrite to set all pins to LOW if blinkLEDs is false

post some videos :-D
http://embodimentlabs.tumblr.com/
http://paulstrohmeier.info/

#### bobmcinnis

#13
##### Dec 14, 2012, 11:04 pm
Thank you!!! This'll help us explore the code. We really appreciate all your help.

#### bobmcinnis

#14
##### Dec 14, 2012, 11:38 pm
Thanks for that last edit. It worked with

{
digitalWrite(ledPin[1] ,LOW);
digitalWrite(ledPin[2] ,LOW);
digitalWrite(ledPin[3] ,LOW);
digitalWrite(ledPin[0] ,LOW);

Yay! We'll definitely post a video

Go Up

Please enter a valid email to subscribe