Здраствуйте. Такой вопрос касаемо записи/чтения EEPROM. Есть один проект в котором будет происходить частая запись и чтение в EEPROM память Arduino (Nano Atmega168). При включенной Ардуинке запись происходит последовательно в каждую ячейку начиная с 0 и до 512, после заполнения EEPROM переходит вначало и перезапись/чтение начинается с нулевой ячейки... Но при выкл. и вкл. питания запись начнётся опять с нулевой ячейки не пройдя всю память, а откл. питания может быть частенько. Хочу реализовать, что бы при Откл. и Вкл. питания чтение началось не с нулевой ячейки памяти, а с последней ячейки куда была произведена запись и продолжила далее записываться / читаться, тем самым получится продлить жизнь микросхеме EEPROM памяти и сделать износ более равномерным. Часть кода для визуального понимания: Код (C++): byte E_1; // переменная для экономии ресурсов ОЗУ EEPROM int addr = 0; // Начальный адрес памяти EEPROM int L; // переменная для преобразования ручных поворотов через map() //другой код... void setup() { //другой код... L = EEPROM.read(addr) * 118; //умножаем значение из памяти на 118 } void finction() { //другой код... if (Right_Pin_1 == true || Left_Pin_1 == true) E_1 = 1; //если истина хотя бы 1 переменная, присваиваем E_1 единицу if (Right_Pin_1 == false && Left_Pin_1 == false && E_1 == 1) { //если все переменные лож и E_1 равна 1, тогда... EEPROM.update(addr, L / 118); //делим на 118 и записываем обновлённые значения в EEPROM в ячейку addr addr = addr + 1; //переходим на следующую ячейку памяти для записи if (addr == 512) { //если дошли до последней ячейки (для Arduino NANO Atmega168) addr = 0; //переходим обратно в первую ячейку и по кругу... } E_1 = 0; //меняем значение переменной E_1 на 0 } } void loop() { //другой код... //другой код... //другой код... }
Поскольку у вас используются не все значения байта, выберите одно для значения - маркера и записывайте его в следующую ячейку после данных. Точнее, (maddr=addr+1)%512. При старте программы ищите это значение в EEPROM и начинайте записывать новые данные с его адреса. Сначала записывайте новый маркер, потом новые данные.
Код (C++): int maddr; byte E_1; // переменная для экономии ресурсов ОЗУ EEPROM int addr = 0; // Начальный адрес памяти EEPROM int L; // переменная для преобразования ручных поворотов через map() //другой код... void setup() { //другой код... maddr = EEPROM.read(addr); L = EEPROM.read(addr) * 118; //умножаем значение из памяти на 118 } void finction() { //другой код... if (Right_Pin_1 == true || Left_Pin_1 == true) E_1 = 1; //если истина хотя бы 1 переменная, присваиваем E_1 единицу if (Right_Pin_1 == false && Left_Pin_1 == false && E_1 == 1) { //если все переменные лож и E_1 равна 1, тогда... EEPROM.update(addr, L / 118); //делим на 118 и записываем обновлённые значения в EEPROM в ячейку addr (maddr=addr+1)%512; if (addr == 512) { //если дошли до последней ячейки (для Arduino NANO Atmega168) addr = 0; //переходим обратно в первую ячейку и по кругу... } E_1 = 0; //меняем значение переменной E_1 на 0 } } void loop() { //другой код... //другой код... //другой код... }
Код (C++): #define EEPROM_SIZE 512 #define EEPROM_EMPTY 0xFF #define EEPROM_MARKER 0xFE int E_1 = 0; int addr = 0; int L; void setup() { bool init = true; for (int i=0; i<EEPROM_SIZE; i++) { if (EEPROM.read(i)==EEPROM_MARKER) { addr = (i-1+EEPROM_SIZE)%EEPROM_SIZE; init = false; break; } } if (init) L = 0; else L = EEPROM.read(addr) * 118; //умножаем значение из памяти на 118 } void finction() { //другой код... if (Right_Pin_1 == true || Left_Pin_1 == true) E_1 = 1; //если истина хотя бы 1 переменная, присваиваем E_1 единицу if (Right_Pin_1 == false && Left_Pin_1 == false && E_1 == 1) { //если все переменные лож и E_1 равна 1, тогда... int maddr = (addr+1)%EEPROM_SIZE; EEPROM.write(maddr,EEPROM_MARKER); EEPROM.update(addr, L / 118); //делим на 118 и записываем обновлённые значения в EEPROM в ячейку addr addr++; if (addr>=EEPROM_SIZE) { //если дошли до последней ячейки (для Arduino NANO Atmega168) addr = 0; //переходим обратно в первую ячейку и по кругу... } E_1 = 0; //меняем значение переменной E_1 на 0 } } void loop() { //другой код... //другой код... //другой код... }
Сложнее, чем думал. Спасибо! Сначала сам поразбираюсь в вашем коде, что бы понять его принцип для себя.
Вот я не понимаю зачем городить огород. Проще отвести 2 ячейки памяти . Вот вам и будет адрес. Ну не будет 512, будет 510. Опять же при заливке скетча ЕЕПРОМ перешивается.Знаю что 1 ячейка 0xFF . Так что если 1 ячейка 0xFF, то ЕЕПРОМ пуста. Вот отведите первые ячейки под адресс след своб ячейки. А дальше алгоритм простой. Записали данные и изменили адресс. Дошли до конца, и начали с 0х02 заново. Ведь 0х00 и 0х01 у вас адресс. Простой алгоритм без наворотов.
Для выравнивания количества циклов перезаписи по ячейкам. https://en.wikipedia.org/wiki/Wear_leveling
И у вас часто портится? Вот подсчитай-те сколько раз надо переписать, что бы испортилось окончательно. http://arduino.ru/forum/apparatnye-voprosy/resurs-eeprom-atmega-bolee-milliona-perezapisei более миллиона. А это в самоделках дохрена.
Не думаю, что все Микросхемы памяти EEPROM выдерживают такое кол-во перезаписи, риск брака всегда возможен, да и тем более если брать в расчёт, что делается проект не на год, а лет на 5, возможно и более - более качественная продумка защиты кодом лишней не будет)
Многие проекты нацеленные на века не доживают простой реализации, Но случайные небольшие проекты , могут прожить дольше. Или по простому, не надо хвататься за сложные задачи. Ну что вы собираетесть туда писать? шпоры. Флешки из той памяти не получится.
Если есть возможность как физически, так и по объёму памяти добавить код и сделать более долгую службу микроконтроллера - почему бы и нет??? Для меня в данном проекте важна долгая и стабильная работа! Тема закрыта!