Storing the last state of a relay in EEPROM of NodeMcu?

Basically the idea is to store the LastState of a relay in the EEPROM , incase if power failure or reboot , it will have the laststate stored in the EEPROM and acts accordingly. But the problem here is NodeMcu has certain gpio sequence to boot up properly. Will the EEPROM make any difference in the boot up process ?

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <EEPROM.h>

#define VPIN V1

char auth[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
char ssid[] = "xxxxx";
char pass[] = "xxxxxxxxx";
char server[] = "xxx.xxx.x.xxx";

void lightOn();
void lightOff();

boolean LampState = 0;
boolean SwitchReset = true;

const int TacSwitch = D4;
const int RelayPin = D0;

bool SwitchState;

BlynkTimer timer;
WidgetLED VLED(V11);

void setup() {
  Serial.begin(115200);
  EEPROM.begin(512);
  pinMode(RelayPin, OUTPUT);
  pinMode(TacSwitch, INPUT);
  SwitchState = EEPROM.read(0);
  digitalWrite(RelayPin,SwitchState);
  delay(10);
  digitalWrite(RelayPin, LOW);
  Blynk.begin(auth, ssid, pass, server, 8080);
  timer.setInterval(100, ButtonCheck);
}

void loop() {
  Blynk.run();
  timer.run();
}

void ButtonCheck() {
  boolean SwitchState = (digitalRead(TacSwitch));
  if (!SwitchState && SwitchReset == true) {
    if (LampState) {
      EEPROM.write(0, SwitchState);   // Write state to EEPROM
      EEPROM.commit();
      lightOff();
    } else {
      EEPROM.write(0, SwitchState);
      EEPROM.commit();
      lightOn();
    }
    SwitchReset = false;
    delay(50);
  }
  else if (SwitchState) {
    EEPROM.write(0, SwitchState);
      EEPROM.commit();
    SwitchReset = true;
  }
}

void ToggleRelay() {
  LampState = !LampState;
  if (LampState) {
    EEPROM.write(0, SwitchState);
      EEPROM.commit();
    lightOn();
  }
  else lightOff();
  EEPROM.write(0, SwitchState);
      EEPROM.commit();
}

void lightOn() {
  digitalWrite(RelayPin, LOW);
  LampState = 1;
  Blynk.virtualWrite(VPIN, HIGH);
  VLED.off();
}

void lightOff() {
  digitalWrite(RelayPin, HIGH);
  LampState = 0;
  Blynk.virtualWrite(VPIN, LOW);
  VLED.on();
}
BLYNK_WRITE(VPIN) {
  int SwitchStatus = param.asInt();
  if (SwitchStatus == 2) {
    ToggleRelay();
  }
  else if (SwitchStatus) {
    EEPROM.write(0, SwitchState);
      EEPROM.commit();
    lightOn();
  }
  else lightOff();
  EEPROM.write(0, SwitchState);
      EEPROM.commit();
}

added a bit of EEPROM read and write lines in the code but cannot get it working.
Can anyone tell will it affect the boot up process ?

Why would you want to do that? The Blynk Server remembers everything.

Actually NO! Once power cuts off or the device reboots , the relay comes into life even though it was in OFF condition. (For info : Am running local server). What ever the state was before the reboot will not remain the same after the reboot. So am planning to write the state to EEPROM and later read the state from it and act accordingly.
Any alternate way of getting this ?

EEPROM is initialized after boot sequence, so it still has no use because certain pins will go high/low or the other way around when the MCU boots. So it will always switch according to the state of pins during the boot.

And even if you run a local server, the state of the pin is saved on the server, you just have to use Blynk.Sync() to retrieve it.

If you want to escape all boot sequences or pin changes during that proces I think you need to look at a hardware solution. But I don’t know how to do that. I think it can be done using a transistor and a big capacitor.

So as per your saying EEPROM doesnt help in retrieving the last state ! ??

What if the Local server (RPi3) reboots ? will it still remember the last state ?

That is hell of a kind to deal . It introduces other problems and PCB needs to be modified.(Tedious Job)

Can you please provide me with a example sketch for Blynk.sync(); ? I went through the community, but i was not able to understand and inject that to my code.

I’m pretty sure it will not help. There are probably certain pins which stay low during boot and you should be able to use those with values stored in EEPROM, but I’ve always found the result to be sketchy at best (see what I did there…).

Yes, it will remember the pin state, even if it reboots. Amazing :wink:

Blynk.Sync is described in the docs. Basically it’s just Blynk.syncVirtual(pinnumber). So hence, it only syncs virtual pins, but that’s not really an issue, you want to work with vPins anyway instead of actual physical pins due to their flexibility

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#define VPIN V1

char auth[] = "xxxxxxxxxxxxxxxxxxxxxxx";
char ssid[] = "xxxxx";
char pass[] = "xxxxxxxxx";
char server[] = "xxx.xxx.x.xxx";

void lightOn();
void lightOff();

boolean LampState = 0;
boolean SwitchReset = true;

const int TacSwitch = D2;
const int RelayPin = D6;

BlynkTimer timer;
int uptimeCounter;
String someStaticData = "SomeStaticData";

BLYNK_CONNECTED() {
    Blynk.syncVirtual(V11);
}

BLYNK_WRITE(V11)
        {
    uptimeCounter = param[0].asInt();
    someStaticData = param[1].asString();
        }

void increment() {
  uptimeCounter++;

  //storing int and string in V0 pin on server
  Blynk.virtualWrite(V11, uptimeCounter, someStaticData);

  //updating value display with uptimeCounter
  Blynk.virtualWrite(V11, uptimeCounter);
}


WidgetLED VLED(V11);

void setup() {
  Serial.begin(115200);
  pinMode(RelayPin, OUTPUT);
  pinMode(TacSwitch, INPUT_PULLUP);
  delay(10);
  digitalWrite(RelayPin, LOW);
  Blynk.begin(auth, ssid, pass, server, 8080);
  timer.setInterval(100, ButtonCheck);
  timer.setInterval(1000L, increment);
}

void loop() {
  Blynk.run();
  timer.run();
}

void ButtonCheck() {
  boolean SwitchState = (digitalRead(TacSwitch));
  if (!SwitchState && SwitchReset == true) {
    if (LampState) {
      lightOff();
    } else {
      lightOn();
    }
    SwitchReset = false;
    delay(50);
  }
  else if (SwitchState) {
    SwitchReset = true;
  }
}

void ToggleRelay() {
  LampState = !LampState;
  if (LampState) {
    lightOn();
  }
  else lightOff();
}

void lightOn() {
  digitalWrite(RelayPin, LOW);
  LampState = 1;
  Blynk.virtualWrite(VPIN, HIGH);
  VLED.off();
}

void lightOff() {
  digitalWrite(RelayPin, HIGH);
  LampState = 0;
  Blynk.virtualWrite(VPIN, LOW);
  VLED.on();
}
BLYNK_WRITE(VPIN) {
  int SwitchStatus = param.asInt();
  if (SwitchStatus == 2) {
    ToggleRelay();
  }
  else if (SwitchStatus) {
    lightOn();
  }
  else lightOff();
}

will this sync with the hardware or with the app ? From the blynk.docs i came up with this.
Should i provide a new virtual pin or the existing the virtual pin used in the code ? After reading the Blynk docs i am confused (Should i give two virtual pins for sync and write ?)

So in your original sketch you chose to connect your relay to D0, which is GPIO 16.
That’s not a good choice of pin, as it’s one of those ‘special’ pins. See this post:

NdeMCU EEPROM has a limited life - the manufacturers say that each memory location should be good for around 100,000 write operations.
Your original code writes to EEPROM every 100 milliseconds (or 10 times per seconds) so after less than three hours of running this code you will have exceeded the probable life of the memory location you’re using.
As @Lichtsignaal says, the data is stored o the Blynk server anyway, so use of EEPROM in this situation gains you nothing.

I also find this a bit odd…

So, on startup you’re reading the value from EEPROM and writing the value to the relay pin, then 10 milliseconds later overriding it by forcing it LOW. Why?

When people give you pointers to possible solutions, it’s time to take those suggestions and do a bit of experimenting, rather than asking “will this work”.

Pete.

Yeah am aware of it. After so much of research am able to get it working. For boot up sequence there are some pins that have to be untouched or external resistors to pullup .

After @Lichtsignaal insisted not to use EEPROM, now am trying to use Blynk.sync .

Of course i am experimenting and trying out different options to get this working. “Will this work” doesnt mean am totally depending on others ! its just can i move on with this or any better way of getting things simpler, Here we have many Awesome brains to guide us with innovative ways. Anyways sorry for that.

Come on, not in these days! After some minute or two searching:
https://www.aliexpress.com/item/TXS0108E-Logic-Level-converter-8-Channel-Duel-Hole-bi-directional-level-converter-Module-For-Arduino-With/32867937613.html

Need to use OE pin for that purpose. As an addition we gain the 5V level compatibility
But I believe the syncing with server is all You need…

Or LVC16t245 for 16ch (this one I do own and tested)

Thank you for the link. But thats not required. As @Lichtsignaal said i used Blynk.syncvirtual and got it working well… we need to try and play with the code, because adding an external converter module will just make the product more bulkier. And if proceeding with mass production, we cannot depend on these sought of modules.

@PeteKnight True. i had not thought of that .and thanks for the link about Gpio’s .

Thank you everyone for helping me out. :raised_hands:

If you’re planning on doing that then you should sign-up to a Blynk plan and you’ll get support with producing your firmware and app.
https://www.blynk.io/plans/

The free version of Blynk isn’t meant for commercial use.

Pete.

1 Like

Yeah am totally aware of it . Am just trying to say that adding external modules will make it tough duing mass production.

Well, It depends on purpose! Sometimes it is just not allowed to trigger the pins during boot. For light controller it shouldn’t matter. Although… If it had to trigger switch for a whole street lighting, then this short pulse could ruin things…
And yes, syncing with server for non commercial purposes (or those commercial non critical) is fairly enough.

Nice example. Surely things are get messy,

With this module >
Do we have the control to delay the triggering during the boot up process ? (5 sec of delay) . Ex: If it takes the device 5-6sec to boot completely and then sync up with the server, can we have the control to adjust the delay so that after everything boots up the relays or output devices start to respond .

It’s just an example, but yes - it is possible. One of the features this chip has is the OE (output enable) pin, which controls all its outputs. It can disable the outputs (turn them into high impedance state). This input can then be controlled by either MCU (with carefully chosen GPIO) or an integrating RC circuit (preferably with Schmidt trigger on input)

That’s actually smart way. But in nodemcu we already have way too less gpoi to work with . And even that has limitations. By reserving pin for OE we will loose a pin .
But the module your are referring is best if dont want false triggers

Then there are I/O expanders :slight_smile: Or ESP32. ALSO with RC integrator we are not loosing any pin … Etc…
Electronics is an art of engineering. I was always impressed how far it allows us to reach…

1 Like

Is this problem solved?
If not I had the answer…I mean the code.

1 Like

@sourav this is a year old topic… and aside form the side trails, the general consensus seemed to simply use Blynk and its sync commands to “remember” a last known vPin state.

If you do have working code for saving and retrieving GPIO pin states from EEPROM upon boot, that can coexist with Blynk, then I recommend you great a new topic under the Projects made with Blynk category and include lots of details.

Better then reopening old topics that already have diverging subject matter.

Thank you.

1 Like