Sequencing counter, save count after power outage

From the description of the put() function in the same link

Note: This function uses EEPROM.update() to perform the write, so does not rewrites the value if it didn't change.

Right - that slipped my mind

So my code is fine :slight_smile:

I never doubted it !

I did for a moment :slight_smile:

OK. I want to simulate a 4017 counter IC and sequence the outputs with a push-button, 1 to 9 and back to 1 again. Whatever output pin is functioning when the power is disconnected I want to be functioning when power is resumed. I want to use the internal EEPROM for storing the this setting at this stage as not ever likely to excede 100k writes or whatever. I have put together a sketch which only has 4 outputs at present. I did find that on resuming power the next led in the sequence was lit, so I cheated this by changing the numbers in the switch case, not sure what I did wrong in the first place, this is my first attempt with eeproms!

[code]
/*
 SIMPLE BINARY COUNTER.
  
 */
#include<EEPROM.h>
const int buttonPin = 2;      // the number of the pushbutton pin
const int ledPin1 =  10;      // LED 1
const int ledPin2 =  11;      // LED 2
const int ledPin3 =  12;      // LED 3

int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {

  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  
  // initialize the LED pin as an output:
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
 
  buttonPushCounter = EEPROM[100];

  EEPROM.get(100, buttonPushCounter);
  Leds();
}

void loop() {
  // read the state of the pushbutton value:
            buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
            if (buttonState != lastButtonState) {
  
  // if the state has changed, increment the counter
            if (buttonState == HIGH) {
  
  // if the current state is HIGH then the button
  // went from off to on:
            buttonPushCounter++;
            } 
  
  // Add a delay to debounce
            delay(50);
            }
  // save the current state as the last state,
  //for next time through the loop
            lastButtonState = buttonState;

  // Lights each LED in turn one at a time turning
  // off the preceeding LED
 
    if (buttonPushCounter  == 1) {
       digitalWrite(ledPin1, HIGH);
       digitalWrite(ledPin2, LOW);
       digitalWrite(ledPin3, LOW);
       EEPROM.put(100,buttonPushCounter);
  }
    if (buttonPushCounter == 2) {
       digitalWrite(ledPin1, LOW);
       digitalWrite(ledPin2, HIGH);
       digitalWrite(ledPin3, LOW);
       EEPROM.put(100,buttonPushCounter);
  }
    if (buttonPushCounter == 3) {
       digitalWrite(ledPin1, HIGH);
       digitalWrite(ledPin2, HIGH);
       digitalWrite(ledPin3, LOW);
       EEPROM.put(100,buttonPushCounter);
  }
    if (buttonPushCounter == 4) {
       digitalWrite(ledPin1, LOW);
       digitalWrite(ledPin2, LOW);
       digitalWrite(ledPin3, HIGH);
       EEPROM.put(100,buttonPushCounter);
  }

  if (buttonPushCounter == 5){ 
      buttonPushCounter = 1;  // reset the count
  }  
}
void Leds()
{
  switch (buttonPushCounter)
  {
    case 0:
      buttonPushCounter = 0;
      digitalWrite (ledPin1, HIGH);
      digitalWrite (ledPin2, LOW);
      digitalWrite (ledPin3, LOW);
      break;
    
    case 1:
      buttonPushCounter = 1;
      digitalWrite (ledPin1, LOW);
      digitalWrite (ledPin2, HIGH);
      digitalWrite (ledPin3, LOW);
      break;
    
    case 2:
      buttonPushCounter = 2;
      digitalWrite (ledPin1, HIGH);
      digitalWrite (ledPin2, HIGH);
      digitalWrite (ledPin3, LOW);
      break;

    case 3:
      buttonPushCounter = 3;
      digitalWrite (ledPin1, LOW);
      digitalWrite (ledPin2, LOW);
      digitalWrite (ledPin3, HIGH);
      break;
  }
}
[/code]

If you put the LED pin numbers in an array and used the counter as an index to that array you could eliminate the lengthy switch/case

why would you set buttonPushCounter to 0 when you are in the case where it's already 0 (same for 1, 2, 3...) ??


you start with the counter at 0

but when you reset, you move it back to 1

➜ that's not coherent

Yes you are correct.

When I reconnect power it turns on the next led in the sequence, not the same…

/*
 SIMPLE BINARY COUNTER.
  
 */
#include<EEPROM.h>
const int buttonPin = 2;      // the number of the pushbutton pin
const int ledPin1 =  10;      // LED 1
const int ledPin2 =  11;      // LED 2
const int ledPin3 =  12;      // LED 3

int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {

  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  
  // initialize the LED pin as an output:
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
 
  buttonPushCounter = EEPROM[10];

  EEPROM.get(10, buttonPushCounter);
  Leds();
}

void loop() {
  // read the state of the pushbutton value:
            buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
            if (buttonState != lastButtonState) {
  
  // if the state has changed, increment the counter
            if (buttonState == HIGH) {
  
  // if the current state is HIGH then the button
  // went from off to on:
            buttonPushCounter++;
            } 
  
  // Add a delay to debounce
            delay(50);
            }
  // save the current state as the last state,
  //for next time through the loop
            lastButtonState = buttonState;

  // Lights each LED in turn one at a time turning
  // off the preceeding LED
 
    if (buttonPushCounter  == 0) {
       digitalWrite(ledPin1, HIGH);
       digitalWrite(ledPin2, LOW);
       digitalWrite(ledPin3, LOW);
       EEPROM.put(10,buttonPushCounter);
  }
    if (buttonPushCounter == 1) {
       digitalWrite(ledPin1, LOW);
       digitalWrite(ledPin2, HIGH);
       digitalWrite(ledPin3, LOW);
       EEPROM.put(10,buttonPushCounter);
  }
    if (buttonPushCounter == 2) {
       digitalWrite(ledPin1, HIGH);
       digitalWrite(ledPin2, HIGH);
       digitalWrite(ledPin3, LOW);
       EEPROM.put(10,buttonPushCounter);
  }
    if (buttonPushCounter == 3) {
       digitalWrite(ledPin1, LOW);
       digitalWrite(ledPin2, LOW);
       digitalWrite(ledPin3, HIGH);
       EEPROM.put(10,buttonPushCounter);
  }

  if (buttonPushCounter == 4){ 
      buttonPushCounter = 0;  // reset the count
  }  
}
void Leds()
{
  switch (buttonPushCounter)
  {
    case 0:
      
      digitalWrite (ledPin1, HIGH);
      digitalWrite (ledPin2, LOW);
      digitalWrite (ledPin3, LOW);
      break;
    
    case 1:
      
      digitalWrite (ledPin1, LOW);
      digitalWrite (ledPin2, HIGH);
      digitalWrite (ledPin3, LOW);
      break;
    
    case 2:
      
      digitalWrite (ledPin1, HIGH);
      digitalWrite (ledPin2, HIGH);
      digitalWrite (ledPin3, LOW);
      break;

    case 3:
      
      digitalWrite (ledPin1, LOW);
      digitalWrite (ledPin2, LOW);
      digitalWrite (ledPin3, HIGH);
      break;
  }
}

try something like that

#include <EEPROM.h>

const int buttonPin = 2;
const int ledPin1 = 10;
const int ledPin2 = 11;
const int ledPin3 = 12;

int buttonPushCounter = 0;
int buttonState = 0;
int lastButtonState = 0;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);

  EEPROM.get(10, buttonPushCounter);
  if (buttonPushCounter < 0 || buttonPushCounter > 3) buttonPushCounter = 0;

  Leds();
}

void loop() {
  buttonState = digitalRead(buttonPin);

  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      buttonPushCounter++;
      if (buttonPushCounter > 3) buttonPushCounter = 0;
      EEPROM.put(10, buttonPushCounter);
      Leds();
    }
    delay(50);
  }

  lastButtonState = buttonState;
}

void Leds() {
  switch (buttonPushCounter) {
    case 0:
      digitalWrite(ledPin1, HIGH);
      digitalWrite(ledPin2, LOW);
      digitalWrite(ledPin3, LOW);
      break;
    case 1:
      digitalWrite(ledPin1, LOW);
      digitalWrite(ledPin2, HIGH);
      digitalWrite(ledPin3, LOW);
      break;
    case 2:
      digitalWrite(ledPin1, HIGH);
      digitalWrite(ledPin2, HIGH);
      digitalWrite(ledPin3, LOW);
      break;
    case 3:
      digitalWrite(ledPin1, LOW);
      digitalWrite(ledPin2, LOW);
      digitalWrite(ledPin3, HIGH);
      break;
  }
}

arrays would make your life easier.

I have just tried this sketch. When power is reconnected it turns on the same LED for a fraction of a second then jumps to the next one in the sequence

cancel that last message, user error!! all working fine.

many thanks

Now write the version with arrays.! :slight_smile:

Nice to know

Hi JML,

I have now increased LEDs to 9 in total and added a reset input so I can force the output back to 9 and start the sequence over from any point of the sequence just like a real 4017, so all is now fine. Now then, Arrays, done a lot of reading and tried adding them to the sketch you uploaded but can’t get it to work, it is stuck on LED 1 and won’t sequence, what have I missed?

thanks



const int buttonPin = 2;
int ledPins[9] = {12, 11, 10, 9, 8, 7, 6, 5, 4};       // an array of pin numbers to which LEDs are attached

int buttonPushCounter = 0;
int buttonState = 0;
int lastButtonState = 0;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPins[buttonPushCounter], OUTPUT);

 

  if (buttonPushCounter < 0 || buttonPushCounter > 3) buttonPushCounter = 0;

  Leds();
}

void loop() {
  buttonState = digitalRead(buttonPin);

  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      buttonPushCounter++;
      if (buttonPushCounter > 3) buttonPushCounter = 0;
      
      Leds();
    }
    delay(50);
  }

  lastButtonState = buttonState;
}

void Leds() {
  switch (buttonPushCounter) {
    case 0:
      digitalWrite(ledPins[buttonPushCounter], HIGH);
      
      break;
    case 1:
      digitalWrite(ledPins[buttonPushCounter], HIGH);
      
      break;
    case 2:
      digitalWrite(ledPins[buttonPushCounter], HIGH);
      
      break;
    case 3:
      digitalWrite(ledPins[buttonPushCounter], HIGH);
      
      break;
  }
}

That was valid for 3 leds…


Try to think what you are doing there

All the cases have the same code… do you need a switch ? (And again the 3…)

Sorry I actually uploaded an earlier script not the final one.

This is how I thought it worked…

We select the output pins to connect to the LEDs with

int ledPins[3] = {12, 11, 10};

Power up and sequence is buttonPushCounter = 0

so in

switch (buttonPushCounter) {
    case 0:
      digitalWrite(ledPins[buttonPushCounter], HIGH);

I assumed the LED selected was the first one in the array, i.e. on pin 12. (Which is lit to start with)

When the button is pressed buttonPressCounter = 1 so we have moved to

case 1:
      digitalWrite(ledPins[buttonPushCounter], HIGH);

now LED on pin 11 is selected (2nd LED in the array).

then another button press and we have

 case 2:
      digitalWrite(ledPins[buttonPushCounter], HIGH);

pin 10 selected (3rd LED on the array)

I tried a number of examples which seemed to work this way but they looped continuously without a switch.

That is correct, but you could do away with the switch/case and just use the counter as the index to the array in order to turn on the appropriate LED. That is, in fact, what happens in each case anyway

others are obliquely asking you, what pin gets written to when you do

digitalWrite(ledPins[3], HIGH);

I’ll be more blunt - What do you think happens?

Let’s be clear

Does not exist - index starts at 0

I wanted to let the OP think about it? After all, from his case structure, he’s aware of 0, just not thinking about that implication.
But never mind, it’s your horse now. Lead it to water, just don’t drown it.