bobmcinnis

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:

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}

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

* 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 flickers

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:

// 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 flickers

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:

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.

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

// 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 flickers

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:

// 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 itb) 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 arraysc) 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.

bobmcinnis

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.

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 flickers

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; } }

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

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?