-->
Page 1 of 2

Zero Cross Dimmer EEPROM Problem

PostPosted: Sat Apr 06, 2019 5:02 am
by mazeem
Hi I am working on MQTT Dimmer using NODEMCU. Normally the project is working flawlessly but when I try to save the change the state of dimmer i.e (Switch State and Brightness Value) the light glows fully and then return to new set state . My Code for the mqtt dimmer is
Code: Select all#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#include "hw_timer.h"
/************************* Pin Definition *********************************/
//Dimmer Pins
#define zcPin             D6
#define pwmPin            D7
#define led               D0

byte fade = 1;
byte state = 0;
byte tarBrightness = 255;
byte curBrightness = 0;
int val;
int dimstate;
byte zcState = 0; // 0 = ready; 1 = processing;
void zcDetectISR();
void dimTimerISR();
IPAddress ip(192, 168, 1, 80);           
IPAddress gateway(192,168,1,1);           
IPAddress subnet(255,255,255,0);       

/************************* WiFi Access Point *********************************/
#define WLAN_SSID       "xxxxx"
#define WLAN_PASS       "xxxxxx"
/************************* Adafruit.io Setup *********************************/

#define AIO_SERVER      "xxxxxx" //IP address of RPi
#define AIO_SERVERPORT  1883                   // use 8883 for SSL
#define AIO_USERNAME    ""
#define AIO_KEY         ""

/************ Global State (you don't need to change this!) ******************/

// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient esp8client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;
const char MQTT_CLIENTID[] PROGMEM  = "Test Dimmer";
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&esp8client, AIO_SERVER, AIO_SERVERPORT,MQTT_CLIENTID, AIO_USERNAME, AIO_KEY);

/****************************** Feeds ***************************************/

// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
// Setup a feed called 'onoff' for subscribing to changes.
Adafruit_MQTT_Subscribe testspeed = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/testspeed");
Adafruit_MQTT_Subscribe testswitch = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/testswitch");
/*************************** Sketch Code ************************************/

// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
// for some reason (only affects ESP8266, likely an arduino-builder bug).
void MQTT_connect();
//Servo myservo;
void ICACHE_RAM_ATTR setup() {
  Serial.begin(115200);
  EEPROM.begin(4);
  delay(10);
  pinMode(zcPin, INPUT_PULLUP);
  pinMode(pwmPin, OUTPUT);
  pinMode(led, OUTPUT);
  attachInterrupt(zcPin, zcDetectISR, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  hw_timer_init(NMI_SOURCE, 0);
  hw_timer_set_func(dimTimerISR); 
  digitalWrite(led, 1);
  Serial.print("Fan/Light MQTT Dimmer");
  tarBrightness = EEPROM.read(0);
  Serial.println(tarBrightness);
  state = EEPROM.read(1);
  Serial.println(state);
  // Connect to WiFi access point.
  Serial.println(); Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);
  WiFi.config(ip, gateway, subnet);      // forces to use the fix IP
  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
 
  // Setup MQTT subscription for onoff feed.
  mqtt.subscribe(&testswitch);
  mqtt.subscribe(&testspeed);
}
uint32_t x = 0;
void ICACHE_RAM_ATTR loop() {
  // Ensure the connection to the MQTT server is alive (this will make the first
  // connection and automatically reconnect when disconnected).  See the MQTT_connect
  // function definition further below.
  MQTT_connect();
  // this is our 'wait for incoming subscription packets' busy subloop
  // try to spend your time here

  Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(20000))) {
   
   if (subscription == &testswitch) {
      Serial.print(F("On-Off button: "));
      Serial.println((char *)testswitch.lastread);
     
      if (strcmp((char *)testswitch.lastread, "0") == 0) {
         digitalWrite(led, 0);
         state = 1;
         EEPROM.write(1, state);
         EEPROM.commit();     
        }
      if (strcmp((char *)testswitch.lastread, "1") == 0) {
        digitalWrite(led, 1);
        state = 0;
        EEPROM.write(1, state);
        EEPROM.commit();
       }
    }
   
   
   
    if (subscription == &testspeed) {
      Serial.print(F("Slider 2: "));
      Serial.println((char *)testspeed.lastread);
      val = atoi((char *)testspeed.lastread);  // convert to a number
       if ((val>0) && (state == 1)){
          tarBrightness =val;
          EEPROM.write(0, tarBrightness);
          EEPROM.commit();
          Serial.println(tarBrightness);
           }
           else{
            state = 0;
            }
    }
 
 }     
  // ping the server to keep the mqtt connection alive
  // NOT required if you are publishing once every KEEPALIVE seconds
 
    if(! mqtt.ping()) {
    mqtt.disconnect();
    }
}

void ICACHE_RAM_ATTR dimTimerISR() {
    if (fade == 1) {
      if (curBrightness > tarBrightness || (state == 0 && curBrightness > 0)) {
        --curBrightness;
      }
      else if (curBrightness < tarBrightness && state == 1 && curBrightness < 255) {
        ++curBrightness;
      }
    }
    else {
      if (state == 1) {
        curBrightness = tarBrightness;
      }
      else {
        curBrightness = 0;
      }
    }
   
    if (curBrightness == 0) {
      state = 0;
      digitalWrite(pwmPin, 0);
    }
    else if (curBrightness == 255) {
      state = 1;
      digitalWrite(pwmPin, 1);
    }
    else {
      digitalWrite(pwmPin, 1);
    }   
    zcState = 0;
}

void ICACHE_RAM_ATTR zcDetectISR() {
  if (zcState == 0) {
    zcState = 1;
    if (curBrightness < 255 && curBrightness > 0) {
      digitalWrite(pwmPin, 0);
      int dimDelay = 30 * (255 - curBrightness) + 400;//400
      hw_timer_arm(dimDelay);
     Serial.println(dimDelay);
    }
  }
}

// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
 
  int8_t ret;

  // Stop if already connected.
  if (mqtt.connected()) {
    return;
  }
 
  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
    Serial.println(mqtt.connectErrorString(ret));
    Serial.println("Retrying MQTT connection in 5 seconds...");
    mqtt.disconnect();
    delay(5000);  // wait 5 seconds
    retries--;
    if (retries == 0) {
      // basically die and wait for WDT to reset me
      while (1);
    }
  }
  Serial.println("MQTT Connected!");
}

I think when it tries to call EEPROM.Commit function light glows and when I remove this function light behaves normally but state does not save.

EEPROM.Commit funtion is like...

Code: Select allbool EEPROMClass::commit() {
  bool ret = false;
  if (!_size)
    return false;
  if(!_dirty)
    return true;
  if(!_data)
    return false;

  noInterrupts();
  if(spi_flash_erase_sector(_sector) == SPI_FLASH_RESULT_OK) {
    if(spi_flash_write(_sector * SPI_FLASH_SEC_SIZE, reinterpret_cast<uint32_t*>(_data), _size) == SPI_FLASH_RESULT_OK) {
      _dirty = false;
      ret = true;
    }
  }
  interrupts();

  return ret;
}



Please guide me the proper way to save the last state and Last Brightness of MQTT Dimmer.

Re: Zero Cross Dimmer EEPROM Problem

PostPosted: Sat Apr 06, 2019 1:43 pm
by RichardS
Turning off interrupts before writing the EEPROM, and then the EEPROM must take a while to program before interrupts are turned on again is the issue.... now the question is more why is writing one byte taking so long... because if it wrote the value in 1uS you would never notice the light staying on...

RichardS

Re: Zero Cross Dimmer EEPROM Problem

PostPosted: Sun Apr 07, 2019 2:21 am
by mazeem
so what is the proper way to turnoff interrupts while writing to eeprom??
is it like??
Code: Select alldetach interrpt(zcpin, zc isr, Rising)
eeprom.write(add, value)
eepromcomit();

or you suggest something else?

Re: Zero Cross Dimmer EEPROM Problem

PostPosted: Mon Apr 08, 2019 1:25 pm
by RichardS
I am not sure why they turn them off, you can try removing the interrupt off and interrupt on functions and see what happens, I would test a lot as it may cause issues on now and again.

I am sure someone else may know better, this is how I would approach it and see.

Code: Select all 
 //noInterrupts();
  if(spi_flash_erase_sector(_sector) == SPI_FLASH_RESULT_OK) {
    if(spi_flash_write(_sector * SPI_FLASH_SEC_SIZE, reinterpret_cast<uint32_t*>(_data), _size) == SPI_FLASH_RESULT_OK) {
      _dirty = false;
      ret = true;
    }
  }
  //interrupts();


RichardS