EEPROM

николай76
Offline
Зарегистрирован: 08.06.2019

Помогите с проблемой! С делал термостат для накопительного бойлера. Сам я не программист поэтому брал коды из разных скетчей. В общем проблема с EEPROM (тоесть с сохранением установленной температурой). Через примерно 2 месяца безупречной работы после выключения питания изменяется EEPROM то есть уставка температуры к примеру если было 40 то при включении становится 104 это для бойлера не приемлимо. Где ошибка?


  #include <EEPROM2.h>
#include <SPI.h> 
#include <Wire.h>
#include <OneWire.h>
#include <Adafruit_GFX.h> // Скачанная библиотека для дисплея.
#include <Adafruit_SSD1306.h> // Скачанная библиотека для дисплея. https://yadi.sk/d/9F_uW1wIZUDna
#define OLED_RESET 4 
#define POWER_MODE 1  // 0 Внешнее питание, 1- Паразитное
Adafruit_SSD1306 display(OLED_RESET); 
extern uint8_t MediumFontRus[];
unsigned int preMillis = 0;
unsigned int T_set ;
OneWire ds(4); //Подключение датчика температуры DS18B20 к выводу D4
//                                   bmp конвертер                      http://git.robotclass.ru/tools/bmptobin.html
//значёк термометр
const unsigned char PROGMEM smileBmp[] = 
{ 0x03, 0x80, 0x00, 
0x0e, 0xe0, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x23, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x23, 0xc0, 
0x08, 0x20, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x23, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa3, 0xe0, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa3, 0xe0, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa3, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa0, 0x00, 
0x1b, 0x90, 0x00, 
0x33, 0x98, 0x00, 
0x47, 0xc4, 0x00, 
0x47, 0xc4, 0x00, 
0x47, 0xc4, 0x00, 
0x47, 0xc4, 0x00, 
0x20, 0x08, 0x00, 
0x30, 0x10, 0x00, 
0x18, 0x20, 0x00, 
0x07, 0xc0, 0x00, 
0x00, 0x00, 0x00, 
0x00, 0x00, 0x00}; //                                   пример вывода изображения       https://robotclass.ru/tutorials/graphics-lcd-nokia-5110/
void setup()
{ 
  //Считаем из постоянной памяти заданную температуру
  T_set=EEPROM_read_byte(0);
   
Serial.begin(9600);
int SW_up  = 7;
int SW_dwn = 8;
int pin  = 9;   //Выход 
  pinMode(SW_up,   INPUT);          //Кнопка "+"
  pinMode(SW_dwn,  INPUT);          //Кнопка "-"
  pinMode(pin,  OUTPUT);        //Выход 
  digitalWrite(SW_up, 1);
  digitalWrite(SW_dwn,1);
    display.begin(SSD1306_SWITCHCAPVCC, 0x3c); //Инициализация дисплея
  display.cp437(true); // эта команда исправляет сдвиг русских символов на один
  }
void loop() 
{
  byte data[2];////работа с датчиком температуры DS18B20
  ds.reset(); 
  ds.write(0xCC, POWER_MODE);
  ds.write(0x44, POWER_MODE); //Конвертация температуры датчиком
  delay(900); // не меньше 750ms для паразитного питания
  ds.reset();
  ds.write(0xCC, POWER_MODE); /*Игнорировать адрес - используется для обращения к единственному устройству на шине, при этом адрес устройства
                    игнорируется (можно обращаться к неизвестному устройству)*/
  ds.write(0xBE, POWER_MODE); //Считать ОЗУ датчика
  data[0] = ds.read(); 
  data[1] = ds.read();
int T_curr = (data[1]<<8)+data[0]; //Сдвиг на 8 бит влево (<<8)
T_curr = T_curr>>4;
////Управление кнопками "+" , "-"
if (millis() - preMillis > 10) //Пауза, которая выдерживается при удержании кнопки
        {
         preMillis = millis(); 
         {
          if(digitalRead(7)==HIGH)
              {
                delay(5);
               T_set++;  //Прибавляем к переменной T_set единицу
              }
          
            if(digitalRead(8)==HIGH)
              {
                delay(5);
               T_set--;  //Убавляем от переменной T_set единицу
               }
         }
          {EEPROM_write_byte(0, T_set); // сохраняем в память последнее значение уставки
          }
        }
////Управление реле от температуры
  if (T_curr >= T_set)    //Если текущая температура больше установленной, то выключаем реле
    {
      digitalWrite (9, LOW);
       }
   if (T_set  > T_curr) //  Если установка больше текущей, то включаем реле
     {
      digitalWrite (9, HIGH);
     }
      if ( T_curr >= 70)                                            // Если температура больше или равна 70 то
      {
       display.clearDisplay();                                    // Очищаем экран и
       display.setTextColor(WHITE);                              // Цвет текста.
     display.setTextSize(2);                                    // Размер текста
       display.setCursor(0,0);                                 // Координаты текста откуда начать писать (Х,У)
    display.print(utf8rus("Критическая"));                    // Выводим предупреждение
   display.setCursor(30,0);  display.print(utf8rus("Температура"));
    display.display();
 digitalWrite (11, HIGH);   delay(25);digitalWrite (11, LOW);  // И включаем бузер на 11 вывод
       }
////Вывод показаний на дисплей
  display.clearDisplay(); // Очистить буфер.
  display.setTextColor(WHITE); // Цвет текста.
     display.setTextSize(2); // Размер текста
    display.setCursor(2,3); // Координаты текста откуда начать писать (Х,У)
        display.print(utf8rus("Уставка="));
   ////Написать текущую температуру
    display.setTextSize(5); 
    display.setCursor(40,22);
    display.print(T_curr);
    display.setTextSize(2); 
    display.setCursor(100,18);
    display.print(utf8rus("о"));
 ////Написать уставку температуры
    display.setTextSize(2); 
    display.setCursor(100,3);
    display.print(T_set);
  ////Рамка: Линия (начало Х, начало У, конец Х, конец У, цвет)
   display.drawLine(0, 18, 128, 18,WHITE); //горизонтальная линия посередине 1
    display.drawRect (0, 0, 128 , 64,  WHITE );  //прямоугольник
display.drawBitmap(5, 25, smileBmp, 22, 38, WHITE); //   отрисовка и вывод изображеня. координаты/ название/ размер/ цвет
 display.display(); // Чтобы сделать символы видимыми на дисплее
}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

В 0 адресе eeprom не храни ничего, начинай хотя бы с 0x10

николай76
Offline
Зарегистрирован: 08.06.2019

sadman41
Offline
Зарегистрирован: 19.10.2016

Неприемлемо каждые 10мс еепром насиловать.

b707
Offline
Зарегистрирован: 26.05.2017

Вы пишете в ЕЕПРОМ температуру каждые 10 миллисекунд, независимо от того. изменяется она или нет. Абсолютно неудивительно. что ЕЕПРОМ в результате выходит из строя. ведь гарантированный ресурс ее всего 100 тыс перезаписей. Удивительно скорее то. что оно так долго держится,

николай76
Offline
Зарегистрирован: 08.06.2019

В общем вот эту строку надо ставить где то в другом месте правильно?

104          {EEPROM_write_byte(0, T_set); // сохраняем в память последнее значение уставки

b707
Offline
Зарегистрирован: 26.05.2017

николай76 пишет:

В общем вот эту строку надо ставить где то в другом месте правильно?

например, внутри условий нажатия кнопок

николай76
Offline
Зарегистрирован: 08.06.2019

Чёт не идёт у меня. пробовал делать так. Но не записывается в память при включении уставка не сохраняется значение 255.

////Управление кнопками "+" , "-"

if (millis() - preMillis > 10) //Пауза, которая выдерживается при удержании кнопки
        {
         preMillis = millis(); 
         {
          if(digitalRead(7)==HIGH)
              {
                delay(5);
               T_set++;  //Прибавляем к переменной T_set единицу
              EEPROM_write_byte(0x10, T_set);
              }
          
            if(digitalRead(8)==HIGH)
              {
                delay(5);
               T_set--;  //Убавляем от переменной T_set единицу
              EEPROM_write_byte(0x10, T_set);
               }
         }
        //  {EEPROM_write_byte(0x10, T_set); // сохраняем в память последнее значение уставки
        //  }
        }
////Управление реле от температуры

 

b707
Offline
Зарегистрирован: 26.05.2017

выложите исправленный код целиком

николай76
Offline
Зарегистрирован: 08.06.2019
  #include <EEPROM2.h>
#include <SPI.h> 
#include <Wire.h>
#include <OneWire.h>
#include <Adafruit_GFX.h> // Скачанная библиотека для дисплея.
#include <Adafruit_SSD1306.h> // Скачанная библиотека для дисплея. https://yadi.sk/d/9F_uW1wIZUDna
#define OLED_RESET 4 
#define POWER_MODE 1  // 0 Внешнее питание, 1- Паразитное
Adafruit_SSD1306 display(OLED_RESET); 
extern uint8_t MediumFontRus[];
unsigned int preMillis = 0;
unsigned int T_set ;
OneWire ds(4); //Подключение датчика температуры DS18B20 к выводу D4
//                                   bmp конвертер                      http://git.robotclass.ru/tools/bmptobin.html
//значёк термометр
const unsigned char PROGMEM smileBmp[] = 
{ 0x03, 0x80, 0x00, 
0x0e, 0xe0, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x23, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x23, 0xc0, 
0x08, 0x20, 0x00, 
0x08, 0x20, 0x00, 
0x08, 0x23, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa3, 0xe0, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa3, 0xe0, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa3, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa0, 0x00, 
0x0b, 0xa0, 0x00, 
0x1b, 0x90, 0x00, 
0x33, 0x98, 0x00, 
0x47, 0xc4, 0x00, 
0x47, 0xc4, 0x00, 
0x47, 0xc4, 0x00, 
0x47, 0xc4, 0x00, 
0x20, 0x08, 0x00, 
0x30, 0x10, 0x00, 
0x18, 0x20, 0x00, 
0x07, 0xc0, 0x00, 
0x00, 0x00, 0x00, 
0x00, 0x00, 0x00}; //                                   пример вывода изображения       https://robotclass.ru/tutorials/graphics-lcd-nokia-5110/
void setup()
{ 
  //Считаем из постоянной памяти заданную температуру
  T_set=EEPROM_read_byte(0);
   
Serial.begin(9600);
int SW_up  = 7;
int SW_dwn = 8;
int pin  = 9;   //Выход 
  pinMode(SW_up,   INPUT);          //Кнопка "+"
  pinMode(SW_dwn,  INPUT);          //Кнопка "-"
  pinMode(pin,  OUTPUT);        //Выход 
  digitalWrite(SW_up, 1);
  digitalWrite(SW_dwn,1);
    display.begin(SSD1306_SWITCHCAPVCC, 0x3c); //Инициализация дисплея
  display.cp437(true); // эта команда исправляет сдвиг русских символов на один
  }
void loop() 
{
  byte data[2];////работа с датчиком температуры DS18B20
  ds.reset(); 
  ds.write(0xCC, POWER_MODE);
  ds.write(0x44, POWER_MODE); //Конвертация температуры датчиком
  delay(900); // не меньше 750ms для паразитного питания
  ds.reset();
  ds.write(0xCC, POWER_MODE); /*Игнорировать адрес - используется для обращения к единственному устройству на шине, при этом адрес устройства
                    игнорируется (можно обращаться к неизвестному устройству)*/
  ds.write(0xBE, POWER_MODE); //Считать ОЗУ датчика
  data[0] = ds.read(); 
  data[1] = ds.read();
int T_curr = (data[1]<<8)+data[0]; //Сдвиг на 8 бит влево (<<8)
T_curr = T_curr>>4;
////Управление кнопками "+" , "-"

if (millis() - preMillis > 10) //Пауза, которая выдерживается при удержании кнопки
        {
         preMillis = millis(); 
         {
          if(digitalRead(7)==HIGH)
              {
                delay(5);
               T_set++;  //Прибавляем к переменной T_set единицу
              EEPROM_write_byte(0x10, T_set);
              }
          
            if(digitalRead(8)==HIGH)
              {
                delay(5);
               T_set--;  //Убавляем от переменной T_set единицу
              EEPROM_write_byte(0x10, T_set);
               }
         }
        //  {EEPROM_write_byte(0x10, T_set); // сохраняем в память последнее значение уставки
        //  }
        }
////Управление реле от температуры
  if (T_curr >= T_set)    //Если текущая температура больше установленной, то выключаем реле
    {
      digitalWrite (9, LOW);
       }
   if (T_set  > T_curr) //  Если установка больше текущей, то включаем реле
     {
      digitalWrite (9, HIGH);
     }
      if ( T_curr >= 70)                                            // Если температура больше или равна 70 то
      {
       display.clearDisplay();                                    // Очищаем экран и
       display.setTextColor(WHITE);                              // Цвет текста.
     display.setTextSize(2);                                    // Размер текста
       display.setCursor(0,0);                                 // Координаты текста откуда начать писать (Х,У)
    display.print(utf8rus("Критическая"));                    // Выводим предупреждение
   display.setCursor(30,0);  display.print(utf8rus("Температура"));
    display.display();
 digitalWrite (11, HIGH);   delay(25);digitalWrite (11, LOW);  // И включаем бузер на 11 вывод
       }
////Вывод показаний на дисплей
  display.clearDisplay(); // Очистить буфер.
  display.setTextColor(WHITE); // Цвет текста.
     display.setTextSize(2); // Размер текста
    display.setCursor(2,3); // Координаты текста откуда начать писать (Х,У)
        display.print(utf8rus("Уставка="));
   ////Написать текущую температуру
    display.setTextSize(5); 
    display.setCursor(40,22);
    display.print(T_curr);
    display.setTextSize(2); 
    display.setCursor(100,18);
    display.print(utf8rus("о"));
 ////Написать уставку температуры
    display.setTextSize(2); 
    display.setCursor(100,3);
    display.print(T_set);
  ////Рамка: Линия (начало Х, начало У, конец Х, конец У, цвет)
   display.drawLine(0, 18, 128, 18,WHITE); //горизонтальная линия посередине 1
    display.drawRect (0, 0, 128 , 64,  WHITE );  //прямоугольник
display.drawBitmap(5, 25, smileBmp, 22, 38, WHITE); //   отрисовка и вывод изображеня. координаты/ название/ размер/ цвет
 display.display(); // Чтобы сделать символы видимыми на дисплее
}

 

b707
Offline
Зарегистрирован: 26.05.2017

так я и думал :)

Вы пишете значение температуры в ячейку 0х10, а читаете из нулевой....

николай76
Offline
Зарегистрирован: 08.06.2019

Блин разобрался забыл изменить адрес в строке 59

  T_set=EEPROM_read_byte(0x10);

 

николай76
Offline
Зарегистрирован: 08.06.2019

Спасибо подсказали. Скажите теперь всё правильно. Работать будет?. а то опять через два месяца 104 будет, Хорошо я ночью случайно проснулся а там такое. Хорошо там есть тепловой предохранитель. а тобы рванул наверно.

Чечако
Offline
Зарегистрирован: 15.06.2018

Возьмите за правило использовать EEPROM.update, а не write. Именно в данном скетче смысла особо нет, поскольку у вас нет кнопки сохранения, а только кнопки изменения, но в будущем может пригодится, imho. Ну и опять же, если вынести адрес ячейки в define или переменную const, будет проще при отладке.

sadman41
Offline
Зарегистрирован: 19.10.2016

Может и в другом месте рванет. Это же ваша программа, никто другой на неё гарантию давать не может.

b707
Offline
Зарегистрирован: 26.05.2017

николай76 пишет:

Работать будет?. а то опять через два месяца 104 будет, Хорошо я ночью случайно проснулся а там такое.

неудивительно, когда берешься не за свое дело:

"Сам я не программист поэтому брал коды из разных скетчей. "

-ответсвенные программы, которые могут "рвануть" - не пишут копипастой "из разных скетчей". Надо четко понимать. что делается в коде.

А пока не понимаете - ограничтесь миганием светодиодом или созданием чего-то вроде  "умного вкентилятора для туалета"

николай76
Offline
Зарегистрирован: 08.06.2019

Всем большое спасибо за помощь! Как раз перестраховался. Я насчёт умного вентилятора. Попробовал на нём. Так примерно такая же программа и такой же косяк с eeprom. Если проработает 2 месяца буду и бойлер подключать. 

 

николай76
Offline
Зарегистрирован: 08.06.2019

Чечако пишет:

Возьмите за правило использовать EEPROM.update, а не write. Именно в данном скетче смысла особо нет, поскольку у вас нет кнопки сохранения, а только кнопки изменения, но в будущем может пригодится, imho. Ну и опять же, если вынести адрес ячейки в define или переменную const, будет проще при отладке.

Спасибо! Очень позновательно!

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Извините, но дополню - EEPROM создано для запоминания действий оператора или критических ситуаций. Для всего остального есть внешняя память, которую легко заменить, в отличие от процессора. 

Чечако
Offline
Зарегистрирован: 15.06.2018

mykaida пишет:

Извините, но дополню - EEPROM создано для запоминания действий оператора или критических ситуаций. Для всего остального есть внешняя память, которую легко заменить, в отличие от процессора. 

Для хранения настроек, которые меняются пару раз в день максимум - она также замечательно подходит, imho.

Green
Offline
Зарегистрирован: 01.10.2015

Не обязательно. Можно сохранять хоть каждую секунду. Всё зависит от того как организуешь.