Запись первоначальных данных в EEPROM
- Войдите на сайт для отправки комментариев
Здравствуте.
Хочу сделать счетчик импульсов с выводом на двухстрочный дисплей на Arduino UNO.
У водосчетчика, с которого получаю и считаю импульсы есть начальные показания. Эти показания необходимо при загрузки скетча прописать в EEPROM для дальнейшего использования и сохренения при отключении питания.
Самый простой способ, который нашел это сделать две загрузки скетча:
1. В Setup прописать команду записи в ячейку памати первоначальных значений и загрузить скетч;
2. Закоментировать строку с выше указанной записью и снова загрузить скетч.
При первой загрузке у меня все получается на дисплее выводится первоначальные данные счетчика, но после того как я удаляю из Setup строку с записью и загружаю скетч в контроллер, при чтении из EEPROM на дисплее получается нуль. Как-будто в прошлый раз данные не записались или стерлись при повторной загрузке.
#include <EEPROM.h>
#include <Wire.h> // библиотека для управления устройствами по I2C
#include <LiquidCrystal_I2C.h> // подключаем библиотеку для LCD 1602
LiquidCrystal_I2C lcd(0x27,16,2); // присваиваем имя lcd для дисплея 16х2
volatile boolean lcdOnFlg = HIGH; //флаг включеного монитора
volatile long lcdOnTime = 0; //время включения монитора
int litrs = 110;
int address = 0;
void setup()
{
lcd.init(); // инициализация LCD дисплея
lcd.backlight(); // включение подсветки дисплея
lcd.setCursor(0,0);
lcd.print("Litrs:");
attachInterrupt(1, lcdOn, FALLING);
Serial.begin(9600);
<strong>//EEPROM.put(address,litrs); // Записать первоначального значения счетчика 110 в ячейку с адресом 0
//delay(100);</strong>
//EEPROM.get(0, litrs);
}
//прерывание от кнопки включения дисплея
void lcdOn()
{
if ((millis()-lcdOnTime) >200)
{
if(lcdOnFlg == LOW) //если экран выключен, то поднимаем флаг и запоминаем время включения
{
lcdOnTime = millis(); //запоминаем время сработки прерывания
lcdOnFlg = !lcdOnFlg ; //поднимаем флаг
}
}
lcdOnTime = millis();
}
void loop()
{
// Получаем данные из EEPROM
litrs = EEPROM.read(address);
lcd.setCursor(0,1); // ставим курсор на 1 символ второй строки
lcd.print(litrs);
if(lcdOnFlg == HIGH) //если флаг поднят - экран горит
{
if ((millis()-lcdOnTime) >10000) //проверяем время которое горит экран не более 10 секунд
{
lcd.noBacklight(); //через 10 секнд гасим экран
lcdOnFlg = !lcdOnFlg; //опускаем флаг
}
else
{
lcd.backlight();
}
}
Serial.println(litrs);
}
Подскажите где ошибка в записи или в чтении и есть ли какой-то другой не сложный алгоритм записи первоначальных данных. Спасибо.
Подскажите, а где в Вашей программе идет запись в EEPROM?
У avrdude, которым заливается UNO есть параметр -е - стирать EEPROM. Надо его (-е) удалить из platform.txt который находится в Arduino\hardware\arduino\avr
tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -У avrdude, которым заливается UNO есть параметр -е - стирать EEPROM. Надо его (-е) удалить из platform.txt который находится в Arduino\hardware\arduino\avr
tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Да это я понимаю - а где записывают? Стереть каждый может...
Да это я понимаю - а где записывают? Стереть каждый может...
см строку N20
Лично я бы не парился с двойной загрузкой скетча, а сделал бы считывание данных для записи из сериал.
То есть при запуске программа проверяет не были ли данные записаны в EEPROM (сигнатуру,так какую придумать) и если нет, то ждать их ввода из сериал. Тогда при первой загрузке сразу можно и нужные данные ввести без перекомпиляции.
#20 не прописывает для сохренения при отключении питания...
#20 не прописывает для сохренения при отключении питания...
А что же, по вашему, EEPROM.put() делает?
Записывает какие-то первоначальные показания, но не производит сохренение при отключении питания.
Записывает какие-то первоначальные показания, но не производит сохренение при отключении питания.
То есть, опять же по-вашему, EEPROM не сохраняет данные при отключении питания?
Сохраняет, конечно. Но, полагаю, что ценность прибора, который при случайной перезагрузке не сохраняет текущие показание водомера, а начинает считать каждый раз со 110 - стремится к нулю.
Сохраняет, конечно. Но, полагаю, что ценность прибора, который при случайной перезагрузке не сохраняет текущие показание водомера, а начинает считать каждый раз со 110 - стремится к нулю.
Я пока не дописал код, который записывает изменённые показания, я застрял с начальными :)
Ем слона по частям.
Спасибо всем за советы буду пробовать.
В СЕТАП()
если в ячейке № значение не равно контрольному (например 85 или другое кроме 255)
1) записать стартовые значения счетчика
2) записать в ячейку № контрольное число
В СЕТАП()
если в ячейке № значение не равно контрольному (например 85 или другое кроме 255)
1) записать стартовые значения счетчика
2) записать в ячейку № контрольное число
Не получится - сработает 1 раз. Тут надо привязаться к чему-то конкретному, например ко времени, но это потребует аппаратных доработок.
В СЕТАП()
если в ячейке № значение не равно контрольному (например 85 или другое кроме 255)
1) записать стартовые значения счетчика
2) записать в ячейку № контрольное число
Не получится - сработает 1 раз. Тут надо привязаться к чему-то конкретному, например ко времени, но это потребует аппаратных доработок.
Всё получится, оно и должно сработать один раз, а в другое место eeprom уже пишется счётчик из loop, а выводится уже сумма начального значения и счетчикал
Да, логично, ступил. Но тогда это значение и надо писать 2 раза в EEPROM и сравнивать их.
Мой вариант работает. Скажу больше - после загрузки скетча нужен один старт программы (он происходит без нашего участия). Дальше коментируем условие и снова загружаем скетч. При этом в фузах должен быть установлен бит EESAVE. При больших объемах данных исключение функции начальной записи еепром позволит уменьшить размер скетча. ТС-у это конечно не нужно.
Вот пример для записи массива
#include <avr/eeprom.h> uint8_t EEMEM ee_write;//по этому адресу (0) лежит контрольное uint16_t EEMEM ee_val_w[22];//с адреса "1" лежит массив из 22 значений типа word void writeEEPROM(){ word val[22] = {/*.......*/};//заполнить массив eeprom_write_block ((const void*) &val, (void*) &ee_val_w, sizeof(val)); } void setup() { if(eeprom_read_byte(&ee_write) != 85){ writeEEPROM(); eeprom_write_byte ((uint8_t *) &ee_write, 85); } } void loop() { word temp = eeprom_read_word(&ee_val_w[3]); //читаем четвертый элемент массива }Мой вариант работает. Скажу больше - после загрузки скетча нужен один старт программы (он происходит без нашего участия). Дальше коментируем условие и снова загружаем скетч. При этом в фузах должен быть установлен бит EESAVE. При больших объемах данных исключение функции начальной записи еепром позволит уменьшить размер скетча. ТС-у это конечно не нужно.
Поздравляю, уважаемый, но в изначальном ТЗ этого не озвучивалось. Короче - Вы сами не знали, чего хотели.
Что конкретно нужно удалить просто два символа -e?
Мой вариант работает. Скажу больше - после загрузки скетча нужен один старт программы (он происходит без нашего участия). Дальше коментируем условие и снова загружаем скетч. При этом в фузах должен быть установлен бит EESAVE. При больших объемах данных исключение функции начальной записи еепром позволит уменьшить размер скетча. ТС-у это конечно не нужно.
Как установить бит EESAVE?
Поменял я платы, была у меня такая:
Перепрошил в такую
И все заработало!
Знатоки в чем может быть отличие?
Отличие в том, что Вы неверно выставили тип платы в настройках.