• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

NodeMCU v3 + Blynk, проблема с EEPROM

CodeNameHawk

Moderator
Команда форума
Так по нажатию кнопки-то не работает...(
Я бы описал вопрос так :
Есть такая схема..., которая питается от...
В есп залит такой скетч.
Если есть внешний сервер, то он присылает то то и то то....
При нажатии на кнопку есп в сериал выдает такую отладочную информацию, а мне кажется, что она должна быть такой...
 

CodeNameHawk

Moderator
Команда форума
В правильном устройстве такие зависимости снимают в лабораторных условиях и прописывают их во флеш
Если вас почитать, то телевизор с функцией запоминания последнего канала неправильное устройство.
Поэтому калибровку либо делаем на стадии изготовления устройства либо грузим по воздуху
Можно и по воздуху, но намного удобней посмотреть на индикаторе и внести нужную калибровку в память.
через интерфейс в процессе эксплуатации устройства
Так это он и пытается сделать.
 
Последнее редактирование:

SPAX

Member
Вроде победил, но как-то топорно мне кажется....

Если изначально чистая ЕСП, то сыпятся ошибки оно и понятно, т.к. в памяти нет значений MIN_SENS и MAX_SENS...как только пропишешь кнопкой эти значения, то всё работает, но мне кажется это не правильно как-то....

Можете посмотреть, как этот код вообще на правильность написан?

Код:
#define BLYNK_PRINT Serial


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

//датчик температуры пола DS18B20
#define DS         D6               //объявляем пин датчика температуры пола DS18B20 как GPIO 12 (D6)
OneWire  ds1(DS);
float tempPol  = 99.0;              // Текущие показания от датчика теплого пола ds18b20

// датчик влажн почвы
#define SENS_HUM A0                 //объявляем пин датчика влажн почвы как GPIO 17 (A0)
#define But_Min V9                  //Виртуальная кнопка колибровки Min значения влажности почвы
#define But_Max V10                 //Виртуальная кнопка колибровки Max значения влажности почвы

// датчик влажн почвы
int16_t humIn;                      // Читаем показания датчика влажности почвы Аналоговый вход
int16_t humOut;                     // Оброботанные показания от датчика влажности почвы 0-100%
float MIN_SENS = 480;               // Калибровка 0%
float MAX_SENS = 210;               // Калибровка 100%


BlynkTimer timer;

////////////////////////////CONNECT////////////////////////////////////////////////
#define USE_LOCAL_SERVER

#ifdef USE_LOCAL_SERVER
      #define SERVER IPAddress(192, 168, 1, 17) // Свой IP пишите
      
#endif

/*
   Wifi Credentials
*/

#define WIFI_SSID               "**"  //Имя точки доступа WIFI VVK   AndroidAP
#define WIFI_PASS               "**" //пароль точки доступа WIFI vtb24admin 1234567890

/*
     Blynk Auth Code
*/
#define AUTH                      "**"


///////////////////////////////////////////////////////
//          Функции для подключения к Blynk          //

void ConnectBlynk()
{
  //*******************************************************
  // Запускаем WiFi
    if (WiFi.status() != WL_CONNECTED)// Если нет WiFi, то коннектимся
    {
      BLYNK_LOG(WIFI_SSID);
      
      WiFi.begin(WIFI_SSID, WIFI_PASS);

      int8_t count=0;
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
        Serial.print(WiFi.status());
        count++;
        if (count >= 5){break;Serial.println("WiFi not connected");}
      }
    }
  /*  Дисконект - для справки
    WiFi.disconnect(); // отключаемся от сети
    Serial.println("Disconnect WiFi.");
  */
 
  //*******************************************************
  // Запускаем Blynk

  if (WiFi.status() == WL_CONNECTED)// Если нет WiFi, то не коннектимся
    {
          // CONNECT TO BLYNK
          #ifdef USE_LOCAL_SERVER // Если используются локальный сервер
            Blynk.config(AUTH, SERVER, 8080);
            Blynk.connect();
          #else // Иначе конектимся постаринке к блинку
            Blynk.config(AUTH);
            Blynk.connect();
          #endif
    }

 
  // До бесконечности будем оставаться в цикле while
  // пока не установим связь с сервером
  //  while (Blynk.connect() == false) {}
 
}//ConnectBlynk()


// Реконектимся если обрыв связи
void reconnectBlynk() {
  if (!Blynk.connected())
  {
    BLYNK_LOG("Disconnected now");
    ConnectBlynk();
    if (Blynk.connected())
    {
      BLYNK_LOG("Reconnected");     
    }
    else
    {
      BLYNK_LOG("Not reconnected");     
    }
  }
}
////////////////////////////CONNECT-END//////////////////////////////////////////////////

////////////////////////EEPROM//////////////////////////////////////////////////////////
#include <EEPROM.h>

void setupAddrEEPROM(){
 
    EEPROM.begin(8);
    EEPROM.get(0, MIN_SENS);
    EEPROM.get(4, MAX_SENS);
    EEPROM.end();
  }
    

////////////////////////EEPROM-END//////////////////////////////////////////////////////

void pressVButton_Min() {
    EEPROM.begin(8);
    MIN_SENS = analogRead(SENS_HUM);
    EEPROM.put(0, MIN_SENS);
    EEPROM.end();
    delay(50);
}

BLYNK_WRITE(But_Min){
  int pinValue = param.asInt();
  Serial.print("But_Min: ");
  Serial.println(pinValue); 
  if(pinValue == 1) {
    pressVButton_Min();
    }
 }
 
void pressVButton_Max() {
    EEPROM.begin(8);
    MAX_SENS = analogRead(SENS_HUM);
    EEPROM.put(4, MAX_SENS);
    EEPROM.end();
    delay(50);
}
 
BLYNK_WRITE(But_Max){
  int pinValue2 = param.asInt();
  Serial.print("But_Max: ");
  Serial.println(pinValue2); 
  if(pinValue2 == 1) {
    pressVButton_Max();
    }
 }

void sendSensor()
{
 
  byte data1[2];
 
  ds1.reset();
  ds1.write(0xCC);
  ds1.write(0x44);
      
  Blynk.virtualWrite(V5, tempPol);
  Blynk.virtualWrite(V8, humOut);
    
// Читаем данные с ds18b20
    ds1.reset();
    ds1.write(0xCC);
    ds1.write(0xBE);
    data1[0] = ds1.read();
    data1[1] = ds1.read();
    tempPol = ((data1[1] << 8) | data1[0]) * 0.0625;
// Выводим показания в монитор порта
    Serial.print("tempPol:");
    Serial.println(tempPol);

// Читаем показания датчика влажности почвы
    humIn = analogRead(SENS_HUM);
        
// Обрабатываем показания и представляем в виде от 0 до 100
   humOut = map(humIn, int16_t(MIN_SENS), int16_t(MAX_SENS), 0, 100);

// Выводим показания в монитор порта
    Serial.print("humIn:");
    Serial.println(humIn);
    Serial.print("MIN_SENS:");   
    Serial.println(MIN_SENS);
    Serial.print("MAX_SENS:");   
    Serial.println(MAX_SENS);
    Serial.print("humOut:");   
    Serial.println(humOut);

}

void setup()
{

// Debug console
  Serial.begin(9600);
    
// Загружаем данные из EEPROM
  setupAddrEEPROM();
  delay(2000); 
 
// Инициализация PIN-ов Arduino
  pinMode(SENS_HUM, INPUT);
  delay(50);
 
// Вызываем функцию подключения к Blynk
   reconnectBlynk();   

// Задаем интервальные таймеры
   timer.setInterval(30000, reconnectBlynk); // Проверяем есть ли связь с сервером

   timer.setInterval(1500L, sendSensor);
    
// Инициализация датчика OneWire для DS18B20
  Wire.begin();
  delay(50);
 
}

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

CodeNameHawk

Moderator
Команда форума
Если изначально чистая ЕСП, то сыпятся ошибки оно и понятно, т.к. в памяти нет значений MIN_SENS и MAX_SENS...как только пропишешь кнопкой эти значения, то всё работает, но мне кажется это не правильно как-то....
Ну так нужна проверка того, что считали с еепром и если MIN_SENS и MAX_SENS равны нулю или вы точно знаете, что они не правильны, заменяете на правильные значения. Это например когда MIN_SENS больше MAX_SENS.
Это вам и советовал nikolz.

Если изначально чистая ЕСП, то сыпятся ошибки оно и понятно, т.к. в памяти нет значений MIN_SENS и MAX_SENS...
Это про то, что я и говорил, если бы добавили вывод отладочной информации о том, что считали с еепром, то давно бы победили этот код.
 

SPAX

Member
Ну так нужна проверка того, что считали с еепром и если MIN_SENS и MAX_SENS равны нулю или вы точно знаете, что они не правильны, заменяете на правильные значения. Это например когда MIN_SENS больше MAX_SENS.
Получилось)
Могли бы вы весь код глянуть на наличие каких-нибудь недочётов?

Код:
#define BLYNK_PRINT Serial


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

//датчик температуры пола DS18B20
#define DS         D6               //объявляем пин датчика температуры пола DS18B20 как GPIO 12 (D6)
OneWire  ds1(DS);
float tempPol  = 99.0;              // Текущие показания от датчика теплого пола ds18b20

// датчик влажн почвы
#define SENS_HUM A0                 //объявляем пин датчика влажн почвы как GPIO 17 (A0)
#define But_Min V9                  //Виртуальная кнопка колибровки Min значения влажности почвы
#define But_Max V10                 //Виртуальная кнопка колибровки Max значения влажности почвы

// датчик влажн почвы
int16_t humIn;                      // Читаем показания датчика влажности почвы Аналоговый вход
int16_t humOut;                     // Оброботанные показания от датчика влажности почвы 0-100%
float MIN_SENS = 480;               // Калибровка 0%
float MAX_SENS = 210;               // Калибровка 100%


BlynkTimer timer;

////////////////////////////CONNECT////////////////////////////////////////////////
#define USE_LOCAL_SERVER

#ifdef USE_LOCAL_SERVER
      #define SERVER IPAddress(192, 168, 1, 17) // Свой IP пишите
      
#endif

/*
   Wifi Credentials
*/

#define WIFI_SSID               "**"  //Имя точки доступа WIFI VVK   AndroidAP
#define WIFI_PASS               "**" //пароль точки доступа WIFI vtb24admin 1234567890

/*
     Blynk Auth Code
*/
#define AUTH                      "**"


///////////////////////////////////////////////////////
//          Функции для подключения к Blynk          //

void ConnectBlynk()
{
  //*******************************************************
  // Запускаем WiFi
    if (WiFi.status() != WL_CONNECTED)// Если нет WiFi, то коннектимся
    {
      BLYNK_LOG(WIFI_SSID);
      
      WiFi.begin(WIFI_SSID, WIFI_PASS);

      int8_t count=0;
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
        Serial.print(WiFi.status());
        count++;
        if (count >= 5){break;Serial.println("WiFi not connected");}
      }
    }
  /*  Дисконект - для справки
    WiFi.disconnect(); // отключаемся от сети
    Serial.println("Disconnect WiFi.");
  */
 
  //*******************************************************
  // Запускаем Blynk

  if (WiFi.status() == WL_CONNECTED)// Если нет WiFi, то не коннектимся
    {
          // CONNECT TO BLYNK
          #ifdef USE_LOCAL_SERVER // Если используются локальный сервер
            Blynk.config(AUTH, SERVER, 8080);
            Blynk.connect();
          #else // Иначе конектимся постаринке к блинку
            Blynk.config(AUTH);
            Blynk.connect();
          #endif
    }

 
  // До бесконечности будем оставаться в цикле while
  // пока не установим связь с сервером
  //  while (Blynk.connect() == false) {}
 
}//ConnectBlynk()


// Реконектимся если обрыв связи
void reconnectBlynk() {
  if (!Blynk.connected())
  {
    BLYNK_LOG("Disconnected now");
    ConnectBlynk();
    if (Blynk.connected())
    {
      BLYNK_LOG("Reconnected");     
    }
    else
    {
      BLYNK_LOG("Not reconnected");     
    }
  }
}
////////////////////////////CONNECT-END//////////////////////////////////////////////////

////////////////////////EEPROM//////////////////////////////////////////////////////////
#include <EEPROM.h>

void setupAddrEEPROM(){
 
    EEPROM.begin(8);
    EEPROM.get(0, MIN_SENS);
    EEPROM.get(4, MAX_SENS);
    if(int16_t(MIN_SENS) == 0)
    {
      EEPROM.begin(8);
      MIN_SENS = 480;
      EEPROM.put(0, MIN_SENS);
      EEPROM.end();
    }
    if(int16_t(MAX_SENS) == 0)
    {
      EEPROM.begin(8);
      MAX_SENS = 210;
      EEPROM.put(4, MAX_SENS);
      EEPROM.end();
    }
    EEPROM.end();
  }
    

////////////////////////EEPROM-END//////////////////////////////////////////////////////

void pressVButton_Min() {
    EEPROM.begin(8);
    MIN_SENS = analogRead(SENS_HUM);
    EEPROM.put(0, MIN_SENS);
    EEPROM.end();
    delay(50);
}

BLYNK_WRITE(But_Min){
  int pinValue = param.asInt();
  Serial.print("But_Min: ");
  Serial.println(pinValue);
  if(pinValue == 1) {
    pressVButton_Min();
    }
 }
 
void pressVButton_Max() {
    EEPROM.begin(8);
    MAX_SENS = analogRead(SENS_HUM);
    EEPROM.put(4, MAX_SENS);
    EEPROM.end();
    delay(50);
}
 
BLYNK_WRITE(But_Max){
  int pinValue2 = param.asInt();
  Serial.print("But_Max: ");
  Serial.println(pinValue2);
  if(pinValue2 == 1) {
    pressVButton_Max();
    }
 }

void sendSensor()
{
 
  byte data1[2];
 
  ds1.reset();
  ds1.write(0xCC);
  ds1.write(0x44);
      
  Blynk.virtualWrite(V5, tempPol);
  Blynk.virtualWrite(V8, humOut);
    
// Читаем данные с ds18b20
    ds1.reset();
    ds1.write(0xCC);
    ds1.write(0xBE);
    data1[0] = ds1.read();
    data1[1] = ds1.read();
    tempPol = ((data1[1] << 8) | data1[0]) * 0.0625;
// Выводим показания в монитор порта
    Serial.print("tempPol:");
    Serial.println(tempPol);

// Читаем показания датчика влажности почвы
    humIn = analogRead(SENS_HUM);
        
// Обрабатываем показания и представляем в виде от 0 до 100
   humOut = map(humIn, int16_t(MIN_SENS), int16_t(MAX_SENS), 0, 100);

// Выводим показания в монитор порта
    Serial.print("humIn:");
    Serial.println(humIn);
    Serial.print("MIN_SENS:");   
    Serial.println(MIN_SENS);
    Serial.print("MAX_SENS:");   
    Serial.println(MAX_SENS);
    Serial.print("humOut:");   
    Serial.println(humOut);

}

void setup()
{

// Debug console
  Serial.begin(9600);
    
// Загружаем данные из EEPROM
  setupAddrEEPROM();
  delay(2000);
 
// Инициализация PIN-ов Arduino
  pinMode(SENS_HUM, INPUT);
  delay(50);
 
// Вызываем функцию подключения к Blynk
   reconnectBlynk();   

// Задаем интервальные таймеры
   timer.setInterval(30000, reconnectBlynk); // Проверяем есть ли связь с сервером

   timer.setInterval(1500L, sendSensor);
    
// Инициализация датчика OneWire для DS18B20
  Wire.begin();
  delay(50);
 
}

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

22:02:27.241 -> [2119]
22:02:27.275 -> ___ __ __
22:02:27.275 -> / _ )/ /_ _____ / /__
22:02:27.309 -> / _ / / // / _ \/ '_/
22:02:27.342 -> /____/_/\_, /_//_/_/\_\
22:02:27.376 -> /___/ v0.6.1 on NodeMCU
22:02:27.410 ->
22:02:27.410 -> [2168] Connecting to 192.168.1.17
22:02:27.444 -> [2256] Ready (ping: 17ms).
22:02:27.478 -> [2323] Reconnected
22:02:29.007 -> tempPol:27.38
22:02:29.007 -> humIn:442
22:02:29.007 -> MIN_SENS:476.00
22:02:29.041 -> MAX_SENS:229.00
22:02:29.041 -> humOut:14
 

nikolz

Well-known member
в качестве совета, есть параметр wifi, не знаю как он называется в ардуино потому что пишу на СИ и SDK
его установка в 1 включает автоматическое восстановление соединения в случае разрыва.
т е можно выкинуть то что вы нагородили с реконектом.
 

SPAX

Member
в качестве совета, есть параметр wifi, не знаю как он называется в ардуино потому что пишу на СИ и SDK
его установка в 1 включает автоматическое восстановление соединения в случае разрыва.
т е можно выкинуть то что вы нагородили с реконектом.
На сколько я помню, данный параметр повешает всю плату на переподключение, и будет до посинения искать коннект, пока он не найдется, тем самым повесит весь код...
Та функция, которая расписана у меня, не даёт повешаться основному коду, т.к. реконнект будет искаться только через заданные промежутки времени...(например 3 мин)
 

CodeNameHawk

Moderator
Команда форума
void setupAddrEEPROM()
{
EEPROM.begin(8);
EEPROM.get(0, MIN_SENS);
EEPROM.get(4, MAX_SENS);
if(int16_t(MIN_SENS) == 0)
{
EEPROM.begin(8);
MIN_SENS = 480;
EEPROM.put(0, MIN_SENS);
EEPROM.end();
}
if(int16_t(MAX_SENS) == 0)
{
EEPROM.begin(8); MAX_SENS = 210;
EEPROM.put(4, MAX_SENS);
EEPROM.end();
}
EEPROM.end(); }
После EEPROM.begin должно гарантированно наступить EEPROM.end , у вас же если будет ошибка, два раза подряд поступит EEPROM.begin
Попробуйте так
Код:
void setupAddrEEPROM()
{
EEPROM.begin(8);
EEPROM.get(0, MIN_SENS);
EEPROM.get(4, MAX_SENS);
EEPROM.end();
if(int16_t(MIN_SENS) == 0)
{
EEPROM.begin(8);
MIN_SENS = 480;
EEPROM.put(0, MIN_SENS);
EEPROM.end();
}
if(int16_t(MAX_SENS) == 0)
{
EEPROM.begin(8);
MAX_SENS = 210;
EEPROM.put(4, MAX_SENS);
EEPROM.end();
}
}
Есть функции WiFi.AutoConnect, WiFi.AutoReconect

И у вас MIN_SENS = 480; MAX_SENS = 210; так задумано?
 

SPAX

Member
После EEPROM.begin должно гарантированно наступить EEPROM.end , у вас же если будет ошибка, два раза подряд поступит EEPROM.begin
Понял, спасибо, исправил.
И у вас MIN_SENS = 480; MAX_SENS = 210; так задумано?
Да, это просто значения датчика на воздухе и в руке. Чтоб хоть какие-то примерные цифры записались....
 
Сверху Снизу