I have a project that uses a single momentary button to toggle between different modes. I have the change/state working well thanks to some ingenious code posted by That1guy99 (thank you). Now I'm trying to store the current mode's value in the Arduino's eeprom (so when Arduino powers down then up again it will be in the same mode). When I run the program, I get double digits of the same mode value - i.e. instead of 3, I get 33 using the serial monitor. I can figure out why? is there something that I'm missing? Following is my current sketch:
/* mark biasotti - adapted from That1guy99 example on Forum
* how to use a single momentary to toggle sequentially between different
* states. A tricolor led with common anode is switched from off to 4 different colors
* depending on how many button depresses. Then current led color mode (Mode) is stored
* and when ardruino is powered down and then up again, current mode and Led color illuminates
*/
#include <EEPROM.h>
int switchPin = 2; // switch is connected to pin 2
int greenled = 3; // green led pin
int redled = 4; // red led pin
int blueled = 5; // blue led pin
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 Mode = 0; // What mode is the light in?
void setup() {
pinMode(switchPin, INPUT); // Set the switch pin as input
pinMode(greenled, OUTPUT);
pinMode(redled, OUTPUT);
pinMode(blueled, OUTPUT);
buttonState = digitalRead(switchPin); // read the initial state
Serial.begin(9600); // for debug
}
void loop() {
Serial.print(Mode);
val = digitalRead(switchPin); // read input value and store it in val
delay(10); // 10 milliseconds is a good amount of time
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 (Mode == 0) {
Mode = 1;
EEPROM.write(100, Mode); // store mode to eeprom
digitalWrite(greenled, LOW); // green led on (common anode + tri-led so pin low means led is on)
digitalWrite(redled, HIGH);
digitalWrite(blueled, HIGH);
} else {
if (Mode == 1) {
Mode = 2;
EEPROM.write(100, Mode);
digitalWrite(greenled, HIGH);
digitalWrite(redled, LOW);
digitalWrite(blueled, HIGH);
} else {
if (Mode == 2) {
Mode =3;
EEPROM.write(100, Mode);
} else {
if (Mode == 3) {
Mode = 4;
EEPROM.write(100, Mode);
digitalWrite(greenled, HIGH);
digitalWrite(redled, HIGH);
digitalWrite(blueled, LOW);
} else {
if (Mode == 4) {
Mode = 0;
EEPROM.write(100, Mode);
digitalWrite(greenled, HIGH);
digitalWrite(redled, HIGH);
digitalWrite(blueled, HIGH);
}
}
}
}
}
}
}
buttonState = val; // save the new state in our variable
}
EEPROM.update(100, Mode); // while looping store current mode ONLY if different that currently stored address.
Serial.println(Mode);
}
void loop()
{
Serial.print(Mode);
.
.
.
EEPROM.update(100, Mode); // while looping store current mode ONLY if different that currently stored address.
Serial.println(Mode);
You print '3' and then print '3\n'; will show up as '33' on screen.
Okay I see. Thanks for that. Forgot to take that out. I'm still left with the problem of where do I put my Mode = EEPROM.read(100);? I'm thinking at the beginning of the loop? :
/* mark biasotti - adapted from That1guy99 example on Forum
* how to use a single momentary to toggle sequentially between different
* states. A tricolor led with common anode is switched from off to 4 different colors
* depending on how many button depresses. Then current led color mode (Mode) is stored
* and when ardruino is powered down and then up again, current mode and Led color illuminates
*/
#include <EEPROM.h>
int switchPin = 2; // switch is connected to pin 2
int greenled = 3; // green led pin
int redled = 4; // red led pin
int blueled = 5; // blue led pin
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 Mode = 0; // What mode is the light in?
void setup() {
pinMode(switchPin, INPUT); // Set the switch pin as input
pinMode(greenled, OUTPUT);
pinMode(redled, OUTPUT);
pinMode(blueled, OUTPUT);
buttonState = digitalRead(switchPin); // read the initial state
Serial.begin(9600); // for debug
}
void loop() {
Mode = EEPROM.read(100);
val = digitalRead(switchPin); // read input value and store it in val
delay(10); // 10 milliseconds is a good amount of time
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 (Mode == 0) {
Mode = 1;
EEPROM.write(100, Mode); // store mode to eeprom
digitalWrite(greenled, LOW); // green led on (common anode + tri-led so pin low means led is on)
digitalWrite(redled, HIGH);
digitalWrite(blueled, HIGH);
} else {
if (Mode == 1) {
Mode = 2;
EEPROM.write(100, Mode);
digitalWrite(greenled, HIGH);
digitalWrite(redled, LOW);
digitalWrite(blueled, HIGH);
} else {
if (Mode == 2) {
Mode =3;
EEPROM.write(100, Mode);
} else {
if (Mode == 3) {
Mode = 4;
EEPROM.write(100, Mode);
digitalWrite(greenled, HIGH);
digitalWrite(redled, HIGH);
digitalWrite(blueled, LOW);
} else {
if (Mode == 4) {
Mode = 0;
EEPROM.write(100, Mode);
digitalWrite(greenled, HIGH);
digitalWrite(redled, HIGH);
digitalWrite(blueled, HIGH);
}
}
}
}
}
}
}
buttonState = val; // save the new state in our variable
}
EEPROM.update(100, Mode); // while looping store current mode ONLY if different that currently stored address.
Serial.println(Mode);
}
Think I got it solved. I did a little cleanup and correction and moved the digital writes to the LEDs out of the button press loop. Seems to work now. Now I know it could be written more efficiently. Any ideas?
/* mark biasotti - adapted from That1guy99 example on Forum
how to use a single momentary to toggle sequentially between different
states. A tricolor led with common anode is switched from off to 4 different colors
depending on how many button depresses. Then current led color mode (Mode) is stored
and when ardruino is powered down and then up again, current mode and Led color illuminates
*/
#include <EEPROM.h>
int switchPin = 2; // switch is connected to pin 2
int greenled = 3; // green led pin
int redled = 4; // red led pin
int blueled = 5; // blue led pin
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 Mode = 0; // What mode is the light in?
void setup() {
pinMode(switchPin, INPUT); // Set the switch pin as input
pinMode(greenled, OUTPUT);
pinMode(redled, OUTPUT);
pinMode(blueled, OUTPUT);
buttonState = digitalRead(switchPin); // read the initial state
Serial.begin(9600); // for debug
}
void loop() {
int address = EEPROM.read(100);
Serial.println(address);
Mode = address;
val = digitalRead(switchPin); // read input value and store it in val
delay(10); // 10 milliseconds is a good amount of time
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 (Mode == 0) {
Mode = 1;
EEPROM.write(100, Mode); // store mode to eeprom
} else {
if (Mode == 1) {
Mode = 2;
} else {
if (Mode == 2) {
Mode = 3;
EEPROM.write(100, Mode);
} else {
if (Mode == 3) {
Mode = 4;
EEPROM.write(100, Mode);
} else {
if (Mode == 4) {
Mode = 0;
EEPROM.write(100, Mode);
}
}
}
}
}
}
}
buttonState = val; // save the new state in our variable
EEPROM.update(100, Mode); // while looping store current mode ONLY if different that currently stored address.
}
if (Mode == 0) { // all leds off
digitalWrite(greenled, HIGH);
digitalWrite(redled, HIGH);
digitalWrite(blueled, HIGH);
}
if (Mode == 1) {
digitalWrite(greenled, LOW); // green led on (common anode + tri-led so pin low means led is on)
digitalWrite(redled, HIGH);
digitalWrite(blueled, HIGH);
}
if (Mode == 2) { // red led on
digitalWrite(greenled, HIGH);
digitalWrite(redled, LOW);
digitalWrite(blueled, HIGH);
}
if (Mode == 4) {
digitalWrite(greenled, HIGH); // Blue led on
digitalWrite(redled, HIGH);
digitalWrite(blueled, LOW);
}
}
/code]
The reason the eprom read is not in void setup is that the arduino never goes dead but is planned to go into low-power mode. Actually this will be eventually be an ATTiny in a consumer product.
@Willpatel_Kendmirez
Yeah, I agree with you and I might do that. The button depress will be very infrequent and because of that, the if statements will be run only occasionally. I want to figure this part of my sketch out first then write the main routine.
It looks a bit cleaner. Does it work? I used your logic but have to say that the Serial.println() of mode at each loop is going to slow stuff down. Might want to move it inside the switch loop...
/* mark biasotti - adapted from That1guy99 example on Forum
* how to use a single momentary to toggle sequentially between different
* states. A tricolor led with common anode is switched from off to 4 different colors
* depending on how many button depresses. Then current led color mode (Mode) is stored
* and when ardruino is powered down and then up again, current mode and Led color illuminates
*/
#include <EEPROM.h>
const int switchPin = 2; // switch is connected to pin 2
const int greenled = 3; // green led pin
const int redled = 4; // red led pin
const int blueled = 5; // blue led pin
#define INVALID -1
#define BTN_READ_INTVL 10
#define PASS_1 0
#define PASS_2 1
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 Mode = 0; // What mode is the light in?
#define LEDS_OFF 0x00
#define GREEN_LED 0x01
#define RED_LED 0x02
#define BLUE_LED 0x04
void setup()
{
pinMode(switchPin, INPUT); // Set the switch pin as input
pinMode(greenled, OUTPUT);
pinMode(redled, OUTPUT);
pinMode(blueled, OUTPUT);
buttonState = digitalRead(switchPin); // read the initial state
Serial.begin(9600); // for debug
}
int ReadButton( void )
{
unsigned long
timeNow;
static unsigned long
timeButton = millis();
static byte
statePass = 0;
static int
lastButton;
int
nowButton;
timeNow = millis();
if( (timeNow - timeButton) < BTN_READ_INTVL )
return INVALID;
timeButton = timeNow;
switch( statePass )
{
case PASS_1:
lastButton = digitalRead(switchPin);
statePass = PASS_2;
break;
case PASS_2:
statePass = PASS_1;
nowButton = digitalRead(switchPin);
//if same on successive reads we see a difference, return the level we just saw
//otherwise return "invalid" (-1)
if( nowButton != lastButton )
return( nowButton );
else
return INVALID;
break;
}//switch
}//ReadButton
void WriteLEDs( byte Lights )
{
//low means led is on
digitalWrite(greenled, (Lights & GREEN_LED)?LOW:HIGH);
digitalWrite(redled, (Lights & RED_LED)?LOW:HIGH);
digitalWrite(blueled, (Lights & BLUE_LED)?LOW:HIGH);
}//WriteLEDs
void loop()
{
if( ReadButton() == LOW )
{
switch( Mode )
{
case 0:
Mode = 1;
EEPROM.write(100, Mode); // store mode to eeprom
WriteLEDs( GREEN_LED );
break;
case 1:
Mode = 2;
EEPROM.write(100, Mode);
WriteLEDs( RED_LED );
break;
case 2:
Mode = 3;
EEPROM.write(100, Mode);
break;
case 3:
Mode = 4;
EEPROM.write(100, Mode);
WriteLEDs( BLUE_LED );
break;
case 4:
Mode = 0;
EEPROM.write(100, Mode);
WriteLEDs( LEDS_OFF );
break;
}//switch
}//if
EEPROM.update(100, Mode); // while looping store current mode ONLY if different that currently stored address.
Serial.println(Mode);
}//loop
The reason the eprom read is not in void setup is that the arduino never goes dead but is planned to go into low-power mode. Actually this will be eventually be an ATTiny in a consumer product.
....
If you do not power down the Arduino (or ATtiny) there is no need so save to EEPROM. All RAM content (i. e. all your global and local variables) is preserved in all sleep modes.