Wrapping my head around eeprom

Hi there. I've been trying to edit a code to have 2 switches that when either are pulled low during startup, they toggle the state of the LED they are tied to, and update that state into eeprom for the next power up. For this Im using an attiny13/85.

The problem I'm having is I can't get the second switch to be independent from the first one. If I try to move the bits, it doesn't keep the state from last power up at all. If I use the same bits, the LEDs both turn on/off when either of the switches was held during startup.

here is the code:

#include <avr/io.h>
#include <avr/eeprom.h>

#define PIN_SW1     PB3
#define PIN_SW2     PB4

#define PIN_LED1    PB0
#define PIN_LED2    PB1

uint8_t toggled1  = 0;
uint8_t sw_state1     = HIGH;
uint8_t sw_last_loop1 = HIGH;

uint8_t toggled2  = 0;
uint8_t sw_state2     = HIGH;
uint8_t sw_last_loop2 = HIGH;

void setup() {
  // put your setup code here, to run once:

  DDRB &= ~(1 << PIN_SW1); // input
  PORTB |= (1 << PIN_SW1); // activate pull-up resistor HIGH
  DDRB &= ~(1 << PIN_SW2); // same here
  PORTB |= (1 << PIN_SW2);

  DDRB |= (1 << PIN_LED1); // output
  DDRB |= (1 << PIN_LED2); // output

  //setup variables for eeprom

  sw_last_loop1 = read_switch1();
  sw_state1 = sw_last_loop1;
  uint8_t toggle_1 = 0x0;
  bool eeprom_written_1 = false;

  sw_last_loop2 = read_switch2();
  sw_state2 = sw_last_loop2;
  uint8_t toggle_2 = 0x2;
  bool eeprom_written_2 = false;

  if (eeprom_is_ready()) {

    toggle_1 = eeprom_read_byte((uint8_t *)0x0);
    toggle_2 = eeprom_read_byte((uint8_t *)0x2);

    toggle_1 = eeprom_read_byte((uint8_t *)0x0);
    if (toggle_1 != 0x0 && toggle_1 != 0x1) {
      toggle_1 = 0x0;
    }

    toggle_2 = eeprom_read_byte((uint8_t *)0x0);
    if (toggle_2 != 0x2 && toggle_2 != 0x3) {
      toggle_2 = 0x2;
    }

    //when switch is pulled low, toggle state of LED upon each start up.

    if (sw_last_loop1 == LOW) {
      toggled1 = ! toggled1;
      toggle_1 ^= 0x1;
      eeprom_update_byte((uint8_t *)0x0, toggle_1);
      eeprom_written_1 = true;
    }
    if (sw_last_loop2 == LOW) {
      toggled2 = ! toggled2;
      toggle_2 ^= 0x2;
      eeprom_update_byte((uint8_t *)0x3, toggle_2);
      eeprom_written_2 = true;
    }
    toggled1 = toggle_1;
    toggled2 = toggle_2;
  }

  //blink when if done
  if (eeprom_written_1) {
    for (int i = 0; i < 3; i++) {
      PORTB |= (1 << PIN_LED1); //high
      delay(100);
      PORTB &= ~(1 << PIN_LED1); //low
      delay(100);
    }
  }

  if (eeprom_written_2) {
    for (int i = 0; i < 3; i++) {
      PORTB |= (1 << PIN_LED2);
      delay(100);
      PORTB &= ~(1 << PIN_LED2);
      delay(100);
    }
  }

}//end setup.

void loop() {

  if (toggled1) {
    PORTB &= ~(1 << PIN_LED1);
  } else {
    PORTB |= (1 << PIN_LED1);
  }
  if (toggled2) {
    PORTB &= ~(1 << PIN_LED2);
  } else {
    PORTB |= (1 << PIN_LED2);
  }

}

uint8_t read_switch1() {

  uint8_t rv = PINB & (1 << PIN_SW1);
  return rv;
  
}

uint8_t read_switch2() {

  uint8_t rv = PINB & (1 << PIN_SW2);
  return rv;
  
}

Can anyone point me in the right direction for a second address to be used to get them to work independently?

I'm not clear about why you are reading the same eeprom address twice into both toggle_1 and toggle_2.

    toggle_1 = eeprom_read_byte((uint8_t *)0x0);
    toggle_2 = eeprom_read_byte((uint8_t *)0x0);

    toggle_1 = eeprom_read_byte((uint8_t *)0x0);
    if (toggle_1 != 0x0 && toggle_1 != 0x1) {
      toggle_1 = 0x0;
    }

    toggle_2 = eeprom_read_byte((uint8_t *)0x0);
    if (toggle_2 != 0x2 && toggle_2 != 0x3) {
      toggle_2 = 0x2;
    }

oop. toggle_2 is supposed to be 0x2 in the start. i’ll edit it now

toggle_2 is supposed to be 0x2 in the start. i’ll edit it now

It's bad practice to edit originally posted code as it can confuse readers as to why certain posts were made. It's always better to post revised code in a new post.

That said, you still have a second reading of toggle_2 at the 0x0 address which overwrites the first reading at 0x02

toggle_1 = eeprom_read_byte((uint8_t *)0x0);
    toggle_2 = eeprom_read_byte((uint8_t *)0x2);  //corrected address

    toggle_1 = eeprom_read_byte((uint8_t *)0x0);
    if (toggle_1 != 0x0 && toggle_1 != 0x1) {
      toggle_1 = 0x0;
    }

    toggle_2 = eeprom_read_byte((uint8_t *)0x0); //uncorrected address
    if (toggle_2 != 0x2 && toggle_2 != 0x3) {
      toggle_2 = 0x2;
    }

Why are you reading twice?

ok. revised with those variables out. i’m not exactly sure why, i was wondering the same thing. doesn’t change why it doesn’t work


#include <avr/io.h>
#include <avr/eeprom.h>

#define PIN_SW1     PB3
#define PIN_SW2     PB4

#define PIN_LED1    PB0
#define PIN_LED2    PB1

uint8_t toggled1  = 0;
uint8_t sw_state1     = HIGH;
uint8_t sw_last_loop1 = HIGH;

uint8_t toggled2  = 0;
uint8_t sw_state2     = HIGH;
uint8_t sw_last_loop2 = HIGH;

void setup() {
  // put your setup code here, to run once:

  DDRB &= ~(1 << PIN_SW1); // input
  PORTB |= (1 << PIN_SW1); // activate pull-up resistor HIGH
  DDRB &= ~(1 << PIN_SW2); // same here
  PORTB |= (1 << PIN_SW2);

  DDRB |= (1 << PIN_LED1); // output
  DDRB |= (1 << PIN_LED2); // output

  //setup variables for eeprom

  sw_last_loop1 = read_switch1();
  sw_state1 = sw_last_loop1;
  uint8_t toggle_1 = 0x0;
  bool eeprom_written_1 = false;

  sw_last_loop2 = read_switch2();
  sw_state2 = sw_last_loop2;
  uint8_t toggle_2 = 0x2;
  bool eeprom_written_2 = false;

  if (eeprom_is_ready()) {

    toggle_1 = eeprom_read_byte((uint8_t *)0x0);
    if (toggle_1 != 0x0 && toggle_1 != 0x1) {
      toggle_1 = 0x0;
    }

    toggle_2 = eeprom_read_byte((uint8_t *)0x2);
    if (toggle_2 != 0x2 && toggle_2 != 0x3) {
      toggle_2 = 0x2;
    }

    //when switch is pulled low, toggle state of LED upon each start up.

    if (sw_last_loop1 == LOW) {
      toggled1 = ! toggled1;
      toggle_1 ^= 0x1;
      eeprom_update_byte((uint8_t *)0x0, toggle_1);
      eeprom_written_1 = true;
    }
    if (sw_last_loop2 == LOW) {
      toggled2 = ! toggled2;
      toggle_2 ^= 0x2;
      eeprom_update_byte((uint8_t *)0x3, toggle_2);
      eeprom_written_2 = true;
    }
    toggled1 = toggle_1;
    toggled2 = toggle_2;
  }

  //blink when if done
  if (eeprom_written_1) {
    for (int i = 0; i < 3; i++) {
      PORTB |= (1 << PIN_LED1); //high
      delay(100);
      PORTB &= ~(1 << PIN_LED1); //low
      delay(100);
    }
  }

  if (eeprom_written_2) {
    for (int i = 0; i < 3; i++) {
      PORTB |= (1 << PIN_LED2);
      delay(100);
      PORTB &= ~(1 << PIN_LED2);
      delay(100);
    }
  }

}//end setup.

void loop() {

  if (toggled1) {
    PORTB &= ~(1 << PIN_LED1);
  } else {
    PORTB |= (1 << PIN_LED1);
  }
  if (toggled2) {
    PORTB &= ~(1 << PIN_LED2);
  } else {
    PORTB |= (1 << PIN_LED2);
  }

}

uint8_t read_switch1() {

  uint8_t rv = PINB & (1 << PIN_SW1);
  return rv;
  
}

uint8_t read_switch2() {

  uint8_t rv = PINB & (1 << PIN_SW2);
  return rv;
  
}

toggle_2 = eeprom_read_byte((uint8_t *)0x2);
eeprom_update_byte((uint8_t *)0x3, toggle_2);

There seems to be some confusion as to the address holding toggle_2.

If this doesn't fix your issues, can you please describe in some detail what the code does and does not do correctly.

the current code functions like this:

when code is first uploaded, led1 is on, led2 is off (for whatever reason, both should be on).

led1 upon startup if pin_sw1 is pulled low, will toggle blink and keep whatever state upon each power on/off.

led2 upon startup if pin_sw2 is pulled low, just blinks on, stays on, and then when powered down, goes back to being off, not keeping any state besides low.

Im assuming it has something to do with toggle2 = 0, so when I put 0x2, the variables dont line up?

Let's get this sorted out first, because if there is a wiring issue for the leds, switches, or misunderstanding of the registers that needs to be fixed.

First you can try a simple setup which turns both leds on.

void setup() {
  // put your setup code here, to run once:

  DDRB &= ~(1 << PIN_SW1); // input
  PORTB |= (1 << PIN_SW1); // activate pull-up resistor HIGH
  DDRB &= ~(1 << PIN_SW2); // same here
  PORTB |= (1 << PIN_SW2);

  DDRB |= (1 << PIN_LED1); // output
  DDRB |= (1 << PIN_LED2); // output
  PORTB |= (1 << PIN_LED1); //led on
  PORTB |= (1 << PIN_LED2); //led on
}

If that goes as expected, then try this version of setup which leaves out the eeprom section, and should blink each led 3x at the end because it inverts the logic of eeprom_written. You can modify the commented lines to test if the switches are read properly.

void setup() {
  // put your setup code here, to run once:

  DDRB &= ~(1 << PIN_SW1); // input
  PORTB |= (1 << PIN_SW1); // activate pull-up resistor HIGH
  DDRB &= ~(1 << PIN_SW2); // same here
  PORTB |= (1 << PIN_SW2);

  DDRB |= (1 << PIN_LED1); // output
  DDRB |= (1 << PIN_LED2); // output

  //setup variables for eeprom

  sw_last_loop1 = read_switch1();
  sw_state1 = sw_last_loop1;
  uint8_t toggle_1 = 0x0;
  bool eeprom_written_1 = false;

  sw_last_loop2 = read_switch2();
  sw_state2 = sw_last_loop2;
  uint8_t toggle_2 = 0x2;
  bool eeprom_written_2 = false;
  
/*
  if (eeprom_is_ready()) {

    toggle_1 = eeprom_read_byte((uint8_t *)0x0);
    if (toggle_1 != 0x0 && toggle_1 != 0x1) {
      toggle_1 = 0x0;
    }

    toggle_2 = eeprom_read_byte((uint8_t *)0x2);
    if (toggle_2 != 0x2 && toggle_2 != 0x3) {
      toggle_2 = 0x2;
    }

    //when switch is pulled low, toggle state of LED upon each start up.

    if (sw_last_loop1 == LOW) {
      toggled1 = ! toggled1;
      toggle_1 ^= 0x1;
      eeprom_update_byte((uint8_t *)0x0, toggle_1);
      eeprom_written_1 = true;
    }
    if (sw_last_loop2 == LOW) {
      toggled2 = ! toggled2;
      toggle_2 ^= 0x2;
      eeprom_update_byte((uint8_t *)0x3, toggle_2);
      eeprom_written_2 = true;
    }
    toggled1 = toggle_1;
    toggled2 = toggle_2;
  }
  */

  //blink when if done
  //if(sw_last_loop1){
  if (!eeprom_written_1) {
    for (int i = 0; i < 3; i++) {
      PORTB |= (1 << PIN_LED1); //high
      delay(100);
      PORTB &= ~(1 << PIN_LED1); //low
      delay(100);
    }
  }
  //if(sw_last_loop2) {}
  if (!eeprom_written_2) {
    for (int i = 0; i < 3; i++) {
      PORTB |= (1 << PIN_LED2);
      delay(100);
      PORTB &= ~(1 << PIN_LED2);
      delay(100);
    }
  }

}//end setup.

yup this works. I know that wiring isn't an issue because in my previous code, the LEDs will blink. It's just that I cant find a separate address that works for LED2 to keep track of it's state without either impeding LED1 or just not working at all. It'll only work with 0x0/0x1, which will tie both LEDs together, which is not the goal. Im trying to have separate control.

I may be confused. Are the leds on with the outputs LOW or HIGH?

when code is first uploaded, led1 is on, led2 is off (for whatever reason, both should be on).

Why are the leds not on when you expect them to be on?

Can you write a simple test sketch to just read and write to two different eeprom addresses?

I think this is happening to led1 and led2 when you turn it on for the first time

// in setup you do
    toggle_1 = 0x00;
    toggled1 = toggle_1;
// in loop you do
  if (toggled1) { //   This is going to be false as you made it 0x00
    PORTB &= ~(1 << PIN_LED1);    //  <<<<< this is NOT happening
  } else {
    PORTB |= (1 << PIN_LED1);     //  <<<<< this IS happening, led turns on

This is happening to led2

// in setup you do 
    toggle_2 = 0x02;
    toggled2 = toggle_2;
// in loop you do 
 if (toggled2) {  // This is TRUE as you made it 0x02
    PORTB &= ~(1 << PIN_LED2);   //  <<<<<<<< this IS happening, led stays off
  } else {
    PORTB |= (1 << PIN_LED2);    //  <<<<<<< this is NOT happening

And I am confused what you try to accomplish.

Is is that when you press button 1 at startup the status of LED1 will change to the opposite to what it was at powerdown and when you press button 2 at startup the status of LED2 will change to the opposite of what it was at powerdown?
That's just it?

[EDIT] Well in case it is, below sketch does just that.

#include <EEPROM.h>

#define PIN_SW1     PB3
#define PIN_SW2     PB4
#define PIN_LED1    PB0
#define PIN_LED2    PB1

void setup() {
  PORTB = (1 << PIN_SW1) | (1 << PIN_SW2); // activate pull-up resistor HIGH
  DDRB = (1 << PIN_LED1) | (1 << PIN_LED2); // output
  if (!(PINB & (1 << PIN_SW1))) (EEPROM.write (1, (!(EEPROM.read(1)))));
  if (!(PINB & (1 << PIN_SW2))) (EEPROM.write (2, (!(EEPROM.read(2)))));
  digitalWrite(PIN_LED1, EEPROM.read(1));
  digitalWrite(PIN_LED2, EEPROM.read(2));
}

void loop() {
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.