Для начала огласите какую именно библиотеку используете или только собираетесь использовать. Далее, для Еепром пофиг с чего вы записываете. Размер ячейки 8 бит, ячеек как гавна за сараем. Указываем номер и записываем байт, указываем номер и читаем байт. Если тип более 8 бит, в посте 48 достаточно неплохая биба, которая сама разлаживает и слаживеат данные и распределяет по ячейкам. Главное помните что в отличии от оперативки, память Еепром имеет ограниченное кол-во чтения записи (ок. 100 000 раз). Учитывайте это при написании кода (чтоб не заганять в цикл).
Здравствуйте Имеется простой скетч для управления влажностью, для удобства хотелось бы реализовать изменение значения порога влажности #define humLowTrigger 55.
Чтоб с ик пульта двумя кнопками прибавлять и убавлять, но что бы оно сохранялось в eeproom.
и на дисплее во время нажатия просматривалось, то что устанавливается.
Подскажите как такую задачу решить? искал на форуме но данного примера не нашел, опыта в программировании ноль.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//#include <DFR_Key.h>
#include "DHT.h"
#define temLowTrigger 27 //Setting the trigger value for the temperture, once the temperture lower than this trigger value, the heater band will start heating
#define humLowTrigger 55 //Setting the trigger value for the humidity, once the humidity lower than this value, start humidification
#define DHTPIN 13 // what pin we're connected to
// Uncomment whatever type you're using!
#define DHTTYPE DHT22 // DHT 22 (AM2302)
const int relay1 = 2; // the number of the relay 1 pin
const int relay2 = 4; // the number of the relay 2 pin
DHT dht(DHTPIN, DHTTYPE);
//Pin assignments for DFRobot LCD Keypad Shield
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
//---------------------------------------------
//DFR_Key keypad;
//int localKey = 0;
//String keyString = "";
void setup()
{
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
lcd.begin();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("initializing....");
lcd.setCursor(0, 1);
delay(1000);
Serial.begin(9600);
dht.begin();
delay(1000);
lcd.clear();
/*
OPTIONAL
keypad.setRate(x);
Sets the sample rate at once every x milliseconds.
Default: 10ms
*/
// keypad.setRate(10);
digitalWrite(relay1, HIGH);
digitalWrite(relay2, HIGH);
}
void loop()
{
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
float t = dht.readTemperature();
// check if returns are valid, if they are NaN (not a number) then something went wrong!
if (isnan(t) || isnan(h)) {
Serial.println("Failed to read from DHT");
} else {
//Display
lcd.home();
lcd.print("Hum: ");
lcd.print(h);
lcd.print(" %");
lcd.setCursor(0, 1);
lcd.print("Tem: ");
lcd.print(t);
lcd.print(" *C");
if(h < humLowTrigger) //if the humidity lower than the trigger value
digitalWrite(relay1, LOW); //start humidification
else
digitalWrite(relay1, HIGH);
if(t < temLowTrigger)
digitalWrite(relay2, LOW);//start heating
else
digitalWrite(relay2, HIGH);
}
}
если данные всегда имеют одинаковую структуру я-бы рекомендовал использовать, что-то подобное (сразу видна вся карта памяти и шибится намного сложнее):
//*************************************************************************************************
// процедуры, для записи и получении всех данных EEPROM
// собраны здесь для единообразного адресного хранения и визуализации карты использования EEPROM,
// адреса в двух байтовом виде (1 - это два байта с физическим адресом 2 и 3)
//*************************************************************************************************
// ------------------- чтение -------------------
int Get_signature() { return ReadInt(0); } // 0 - сигнатура
int Get_term_set() { return ReadInt(1); } // 1 - установленая температура
// 2...9 - резерв
int Get_temp(int Num) { return ReadInt(Num+10); } // 10..19 - массив калибровочных температур
int Get_pow(int Num) { return ReadInt(Num+20); } // 20..29 - массив мощности поддержания температуры
int Get_tep(int Num) { return ReadInt(Num+30); } // 30..39 - массив температур инерционности
int Get_dt(int Num) { return ReadInt(Num+40); } // 40..49 - массив времени цикла on/off
int Get_step(int Num) { return ReadInt(Num+50); } // 50..59 - массив времени инерционности
int Get_setup(int Num){ return ReadInt(Num+60); } // 60..69 - массив флагов калибровки
// 70..99 - резерв
// 100..511 - свободно
// ------------------- запись -------------------
int Set_signature(int value) { WriteInt(0, value); } // 0 - сигнатура
int Set_term_set(int value) { WriteInt(1, value); } // 1 - установленая температура
// 2...9 - резерв
void Set_temp(int Num, int value) { WriteInt(Num+10, value); } // 10..19 - массив калибровочных температур
void Set_pow(int Num, int value) { WriteInt(Num+20, value); } // 20..29 - массив мощности поддержания температуры
void Set_tep(int Num, int value) { WriteInt(Num+30, value); } // 30..39 - массив температур инерционности
void Set_dt(int Num, int value) { WriteInt(Num+40, value); } // 40..49 - массив времени цикла on/off
void Set_step(int Num, int value) { WriteInt(Num+50, value); } // 50..59 - массив времени инерционности
void Set_setup(int Num, int value) { WriteInt(Num+60, value); } // 60..69 - массив флагов калибровки
// 70..99 - резерв
// 100..511 - свободно
//*************************************************************************************************
// процедура читает из энерго независимой памяти двухбйтовое число
// num - идентификатор памяти (номер двухбайтного слова)
//*************************************************************************************************
int ReadInt(int num)
{
byte a;
byte b;
int result;
a = int(EEPROM.read(num * 2));
b = int(EEPROM.read(num * 2 + 1));
result = a * 255 + b;
return result;
}
//*************************************************************************************************
// процедура записывает в энерго независимую память двухбйтовое число
// num - идентификатор памяти (номер двухбайтного слова)
// value - записываемое значение
//*************************************************************************************************
void WriteInt(int num, int value)
{
byte a;
byte b;
b = value % 255;
a = (value - b) / 255;
EEPROM.write(num * 2, a);
EEPROM.write(num * 2 + 1, b);
Beep(4); // сделано для выявления безконтрольной записи и снижения ресурса EEPROM
}
Вообще то в avg-gcc есть встроенный механизм распределения памяти eeprom
Ардеина его почему то не использует, хотя он очень удобный на мой взгляд
#include <avr/eeprom.h>
....
int a EEMEM:
int b[10] EEMEM;
int c;
...
int* ptr_a = &a:
int** ptr_b = &b;
Int* ptr_c = &c;
В этом примере ptr_a равно 0, ptr_b равно 2, ptr_c равно 22, т.е автоматически выделились адреса для данных в eeprom. Эти адреса можно использовать как с ардуиновской библиотекой EEPROM так и с Си-шной avr/eeprom.h
Кроме того если при обявлении переменным EEMEM присвоить значения линкер сформирует файл .eep который можно напрямую залить в eeprom. Правда на ардуине я это не проверял, только в студии
Вообще то в avg-gcc есть встроенный механизм распределения памяти eeprom
Ардеина его почему то не использует, хотя он очень удобный на мой взгляд
#include <avr/eeprom.h>
....
int a EEMEM:
int b[10] EEMEM;
int c;
...
int* ptr_a = &a:
int** ptr_b = &b;
Int* ptr_c = &c;
В этом примере ptr_a равно 0, ptr_b равно 2, ptr_c равно 22, т.е автоматически выделились адреса для данных в eeprom. Эти адреса можно использовать как с ардуиновской библиотекой EEPROM так и с Си-шной avr/eeprom.h
Кроме того если при обявлении переменным EEMEM присвоить значения линкер сформирует файл .eep который можно напрямую залить в eeprom. Правда на ардуине я это не проверял, только в студии
хороший вариант для хорошо продуманных (архитектурно) проектов!
но на мой взгляд поиск ошибки вылезания за границу выделеной памяти сложный, да и риск велик (много переменных, и при смене типизации не факт, что компилятор выдаст ошибку),
кроме того ЛЮБОЙ вариант с авто выделением памяти чреват тем, что при смене формата (или количества данных), новые данные разместятся по иному, и станут не валидными. Мой вариант с явным резервированием места в коде позволяет вдумчиво относится к смене местоположения старых и новых данных
Недавно сталкнулся с проблемой того что во время записи/чтения из EEPROM одно значение потерялось (запись ведется примерно 1-2 раз в сутки). Пришлось задуматься о том что память несовешенна и требуется резервные копии этих значений.
Поискав на форумах узнал что некоторые не рекомендуют записывать данные в первые 8-16 ячеек, но про резервное копирование данных ни чего небыло. Ничего подобного ни кто не реализовывал.
По образованию я связист, а в связи (если это позволяет канал, и скорость передачи высокая а данных мало) то передаваемое значение типа "1234" передается как "111222333444", принимается и сравниваются последовательности из 3-х символов "111" - "1" и т.д. И если вносимые помехи или искажения приносят что то вреде "11хх223334х4" значение на выходе принимающего устройства будет "1234" так как "11х" - "1" "х22" - "2" "333" - "3" "4х4" - "4".
Так вот в реализуемом мной проекте значений вносимых в EEPROM не много, по этому написал код, где при чтении из EEPROM читаются 3 значения сравниваются, если все значения верны то прочитанное ИСТИНА, если одно отличается то исправляем по значениям из двух других, исли все значения разные то записываем значение по умолчанию.
#include <EEPROM.h> // подключаем библиотеку EEPROM
char PASS[5]; // переменная для хранения пароля считанного из EEPROM
String PASS2 = PASS; // переменная для хранения пароля
int modeWork = 0; // Режим работы 0=Free 1=Start
int addr0 = 20; // переменная адреса режима работы
int addr1 = 22; // переменная адреса пароля
int addr0a = 220; // переменная адреса режима работы
int addr1a = 222; // переменная адреса пароля
int addr0b = 420; // переменная адреса режима работы
int addr1b = 422; // переменная адреса пароля
int p1; // переменная для хнанения считанных значений из EEPROM
int p2; // переменная для хнанения считанных значений из EEPROM
int p3; // переменная для хнанения считанных значений из EEPROM
char P1a[5]; // переменная для хранения пароля считанного из EEPROM
char P2a[5]; // переменная для хранения пароля считанного из EEPROM
char P3a[5]; // переменная для хранения пароля считанного из EEPROM
String P1 = P1a; // переменная для хранения пароля
String P2 = P2a; // переменная для хранения пароля
String P3 = P3a; // переменная для хранения пароля
void setup() {
// пример записи в EEPROM переменной типа int
EEPROM.update(addr0, modeWork); // обновляем значение в EEPROM
EEPROM.update(addr0a, modeWork); // обновляем значение в EEPROM
EEPROM.update(addr0b, modeWork); // обновляем значение в EEPROM
// пример записи в EEPROM переменной типа char
EEPROM.put(addr1, PASS); // записываем массив в EEPROM
EEPROM.put(addr1a, PASS); // записываем массив в EEPROM
EEPROM.put(addr1b, PASS); // записываем массив в EEPROM
}
void loop() {
modeWorkREAD(); // чтение режима работы устройства
PASSREAD(); // чтение пароля работы устройства
}
void modeWorkREAD()
{
p1 = EEPROM.read(addr0); //читаем переменные из EEPROM
p2 = EEPROM.read(addr0a); //читаем переменные из EEPROM
p3 = EEPROM.read(addr0b); //читаем переменные из EEPROM
if (p1 == p2 == p3) // проверяем все значения на равенство
modeWork = p1;
// далее проверяем если одно значение не верно
else if (p2 == p3) // проверяем все значения на равенство кроме p1
{
modeWork = p2;
EEPROM.update(addr0, p2); // записываем значение в EEPROM
}
else if (p1 == p3) // проверяем все значения на равенство кроме p2
{
modeWork = p1;
EEPROM.update(addr0a, p1); // записываем значение в EEPROM
}
else if (p1 == p2) // проверяем все значения на равенство кроме p3
{
modeWork = p1;
EEPROM.update(addr0b, p1); // записываем значение в EEPROM
}
else if (p1 != p2 != p3) // если все значения разные то записываем значение по умолчанию
{
modeWork = 1;
EEPROM.update(addr0, modeWork);
EEPROM.update(addr0a, modeWork);
EEPROM.update(addr0b, modeWork);
}
}
void PASSREAD()
{
EEPROM.get(addr1, P1a); // считываем массив символов по адресу addr1 в переменную
EEPROM.get(addr1a, P2a); // считываем массив символов по адресу addr1 в переменную
EEPROM.get(addr1b, P3a); // считываем массив символов по адресу addr1 в переменную
P1 = P1a;
P2 = P2a;
P3 = P3a;
if (P1 == P2 && P1 == P2 && P2 == P3) // проверяем все значения на равенство
PASS2 = P1;
// далее проверяем если одно значение не верно
else if (P2 == P3) // проверяем все значения на равенство кроме P1
{
PASS2 = P2;
PASS2.toCharArray(P2a, 5); //перевод из char в String
EEPROM.put(addr1, P2a); // записываем значение в EEPROM
}
else if (P1 == P3) // проверяем все значения на равенство кроме P2
{
PASS2 = P1;
PASS2.toCharArray(P1a, 5); //перевод из char в String
EEPROM.put(addr1a, P1a); // записываем значение в EEPROM
}
else if (P1 == P2) // проверяем все значения на равенство кроме P3
{
PASS2 = P1;
PASS2.toCharArray(P1a, 5); //перевод из char в String
EEPROM.put(addr1b, P1a); // записываем значение в EEPROM
}
else // если все значения разные то записываем значение по умолчанию
{
PASS2 = "1234";
EEPROM.put(addr1, PASS2);
EEPROM.put(addr1a, PASS2);
EEPROM.put(addr1b, PASS2);
}
}
PS изначально хотел записывать и считывать по 5-ть значений, но код получился на 26 сравнениях, потом остановился на 3-х значениях где используется 4-е сравнения.
Перепроверять значения записанные в eeprom совершенно лишнее. Это борьба с последствиями, а не с причиной.
причин порчи данных в eeprom две - софт и железо. Софт - кривой скетч, который может сам портить данные например делая ошибки в адресах. Железо - у AVR известная есть болезнь по хаотичному исполнению кода со случайным затиранием ячеек памяти при неконтролируемом сбросе. Это может случаться если источник питания может создавать пограничные условия когда МК уже как бы запустился, но не так, чтобы стабильно работать. Это или кривые источники питания от сети или плохо продуманные источники автономного питания. Как правило включение BOD эту проблему решает
А если запишется случайным образом скажем в 1 и 3 ячейку одинаковые значения (вероятность практически 0, но все таки) и в 4 например другое. То по вашему алгоритму будет все совсем плохо. Нет смысла сравнивать менее 50% одинаковых значений, это будет уже означать что данные запороты полностью.
Задача. Из EEPROM, где находятся 1024 ячеек с информацией, среди которых 2 ячейки с испорченной информацией, случайно считаны 5 ячеек. Какова вероятность того, что среди них будет 2 ячейки с испорченной информацией.
Всего ячеек: 1024-2 = 1022
Общее число возможных элементарных исходов для данных испытаний равно числу способов, которыми можно считать 5 ячеек из 1024:
2. Найдем вероятность того, что среди выбранных 5 ячеек 2 с испорченной информацией.
Количество вариантов выбора из 2 ячеек с испорченной информацией:
Количество вариантов выбора из 1022 ячеек остальные 3 ячейки исправны:
Код писал под свои нужды, его можно написать компактнее.
BOD из коробки (со штатными fuses) включено же. Хотя таки да, будет полезен электролит мкФ так на 3300.
Конденсаторы в цепях питания как раз растягивают время падения напряжения, оставляя микроконтроллеру больше возможностей запороть EEPROM. Именно для противодействия этому BOD и нужен.
BOD из коробки (со штатными fuses) включено же. Хотя таки да, будет полезен электролит мкФ так на 3300.
iliya555, мне любопытно, хочу поглядеть код с 26 условиями (на длину 5 байт), мож как-нибудь ужму.
у голого МК выключен. Вы про ардуину? Это не проверял, но у голого выключен
не путайте для атмега 8 два отдельных фьюза, один включает BOD, а второй определяет уровень срабатывания. Второй запрограмирован на одно из значений с завода, но не активен пока не включен первый
Sindbad, к нему проверка на АЦП/компараторе полагается же.
Если опустилось - срочно записать и не трогать (поставить флаг, не прикасаться к памяти), пока конденсатор ещё не разрядился. Не?
Не совсем.
Если скетч не пишет в EEPROM вообще, то и проблемы при включении/выключении не возникает, т.к. в памяти нет команд записи в EEPROM.
Если же скетч пишет в EEPROM, то такие команды в памяти МК присутствуют. При уменьшении напряжения питания, МК начинает выполнять случайные команды из памяти, тогда он может выполнить и команду, которая перепишет EEPROM. И никакие флаги не помогут.
Задача BOD - остановка работы МК при падении напряжения ниже заданного уровня.
Или, если использовать внешний контроль питания, нужно прижать выход RESET к земле при падении напряжения ниже заданного.
Для начала огласите какую именно библиотеку используете или только собираетесь использовать. Далее, для Еепром пофиг с чего вы записываете. Размер ячейки 8 бит, ячеек как гавна за сараем. Указываем номер и записываем байт, указываем номер и читаем байт. Если тип более 8 бит, в посте 48 достаточно неплохая биба, которая сама разлаживает и слаживеат данные и распределяет по ячейкам. Главное помните что в отличии от оперативки, память Еепром имеет ограниченное кол-во чтения записи (ок. 100 000 раз). Учитывайте это при написании кода (чтоб не заганять в цикл).
Стардартную библиотеку eeprom
Я включаю библиотеку вот такой строкой как памятка.
Вроде должно быть понятно.
Если честно, то не доконца, вот допустим я считую ключ ibuton
В массив:
Byte addr[8];
И куда мне эт подставить в вашем коде.
Теперь понятней спасибо большое
только это уже не та стандартная биллиотека, а как раз та о которую я и рекомендовал.
спасибо всем за помощь, с записью и чтением в EEPROM разобрался, если можно еще помогите как сравнить масив:
и то что записанно в EEPROM
http://www.cplusplus.com/reference/cstring/memcmp/
если честно ничего не понял что там написанно, можно на пальцах объяснить, если не сложно
Сливаешь данные из EEPROM в другой массив и в цикле сравниваешь элементы массивов
если можно пример кода, как это делается
Зачем весь массив считывать? Считывайте элемент и тут же сравнивайте, после следующий. А так вам памяти никакой не хватит.
да я не собирался считывать весь масив, только по 8 байт,
У меня первый ключь хранится в EEprom с 0-7 адресс,
второй с 8-15 адресс,и т.д.
мне нужно как то считать эти ключь с EEPROMA и положить допустм в этот масив:
и потом этот масив нужно сравнить с этим:
но как это сделать я чет не понимаю
http://www.cplusplus.com/reference/cstring/memcmp/
как сравнить массивы я понял, а как считать этих 8 байт из EEPROM и поместить их в этот массив:
сообщение #55 строка 6
пробовал не выходит
ниче не получается
я разобрался, всем большое спасибо за помощь.
так в чём дело?
я просто все вывел в отдельную функцию, и не указал ссылку на функцию.
Смотрите библиотеку https://www.arduino.cc/en/Reference/EEPROM
если данные всегда имеют одинаковую структуру я-бы рекомендовал использовать, что-то подобное (сразу видна вся карта памяти и шибится намного сложнее):
Вообще то в avg-gcc есть встроенный механизм распределения памяти eeprom
Ардеина его почему то не использует, хотя он очень удобный на мой взгляд
В этом примере ptr_a равно 0, ptr_b равно 2, ptr_c равно 22, т.е автоматически выделились адреса для данных в eeprom. Эти адреса можно использовать как с ардуиновской библиотекой EEPROM так и с Си-шной avr/eeprom.h
Кроме того если при обявлении переменным EEMEM присвоить значения линкер сформирует файл .eep который можно напрямую залить в eeprom. Правда на ардуине я это не проверял, только в студии
Вообще то в avg-gcc есть встроенный механизм распределения памяти eeprom
Ардеина его почему то не использует, хотя он очень удобный на мой взгляд
В этом примере ptr_a равно 0, ptr_b равно 2, ptr_c равно 22, т.е автоматически выделились адреса для данных в eeprom. Эти адреса можно использовать как с ардуиновской библиотекой EEPROM так и с Си-шной avr/eeprom.h
Кроме того если при обявлении переменным EEMEM присвоить значения линкер сформирует файл .eep который можно напрямую залить в eeprom. Правда на ардуине я это не проверял, только в студии
хороший вариант для хорошо продуманных (архитектурно) проектов!
но на мой взгляд поиск ошибки вылезания за границу выделеной памяти сложный, да и риск велик (много переменных, и при смене типизации не факт, что компилятор выдаст ошибку),
кроме того ЛЮБОЙ вариант с авто выделением памяти чреват тем, что при смене формата (или количества данных), новые данные разместятся по иному, и станут не валидными. Мой вариант с явным резервированием места в коде позволяет вдумчиво относится к смене местоположения старых и новых данных
абсолютно правильного варианта здесь нет, каждый сам для себя выбирает оптимальный
я делаю просто - если структура данных в eeprom меняется, то я перезаливаю содержимое eeprom кроме того, что перезаливаю прошивку.
Недавно сталкнулся с проблемой того что во время записи/чтения из EEPROM одно значение потерялось (запись ведется примерно 1-2 раз в сутки). Пришлось задуматься о том что память несовешенна и требуется резервные копии этих значений.
Поискав на форумах узнал что некоторые не рекомендуют записывать данные в первые 8-16 ячеек, но про резервное копирование данных ни чего небыло. Ничего подобного ни кто не реализовывал.
По образованию я связист, а в связи (если это позволяет канал, и скорость передачи высокая а данных мало) то передаваемое значение типа "1234" передается как "111222333444", принимается и сравниваются последовательности из 3-х символов "111" - "1" и т.д. И если вносимые помехи или искажения приносят что то вреде "11хх223334х4" значение на выходе принимающего устройства будет "1234" так как "11х" - "1" "х22" - "2" "333" - "3" "4х4" - "4".
Так вот в реализуемом мной проекте значений вносимых в EEPROM не много, по этому написал код, где при чтении из EEPROM читаются 3 значения сравниваются, если все значения верны то прочитанное ИСТИНА, если одно отличается то исправляем по значениям из двух других, исли все значения разные то записываем значение по умолчанию.
PS изначально хотел записывать и считывать по 5-ть значений, но код получился на 26 сравнениях, потом остановился на 3-х значениях где используется 4-е сравнения.
Перепроверять значения записанные в eeprom совершенно лишнее. Это борьба с последствиями, а не с причиной.
причин порчи данных в eeprom две - софт и железо. Софт - кривой скетч, который может сам портить данные например делая ошибки в адресах. Железо - у AVR известная есть болезнь по хаотичному исполнению кода со случайным затиранием ячеек памяти при неконтролируемом сбросе. Это может случаться если источник питания может создавать пограничные условия когда МК уже как бы запустился, но не так, чтобы стабильно работать. Это или кривые источники питания от сети или плохо продуманные источники автономного питания. Как правило включение BOD эту проблему решает
C проблемой потеренной информации встретился впервые, и чтобы исключить ее в дальнейшем решил ее именно так.
А насчет BOD почитаю. Спасибо.
BOD из коробки (со штатными fuses) включено же. Хотя таки да, будет полезен электролит мкФ так на 3300.
iliya555, мне любопытно, хочу поглядеть код с 26 условиями (на длину 5 байт), мож как-нибудь ужму.
Код с 26 сравнениями писать сразу не стал, он аналогичен написанному вверху но с 5-ю значениями вместо 3-х.
Сравнения:
А если запишется случайным образом скажем в 1 и 3 ячейку одинаковые значения (вероятность практически 0, но все таки) и в 4 например другое. То по вашему алгоритму будет все совсем плохо. Нет смысла сравнивать менее 50% одинаковых значений, это будет уже означать что данные запороты полностью.
Вероятность такого варианта есть.
Задача. Из EEPROM, где находятся 1024 ячеек с информацией, среди которых 2 ячейки с испорченной информацией, случайно считаны 5 ячеек. Какова вероятность того, что среди них будет 2 ячейки с испорченной информацией.
Всего ячеек: 1024-2 = 1022
Общее число возможных элементарных исходов для данных испытаний равно числу способов, которыми можно считать 5 ячеек из 1024:
2. Найдем вероятность того, что среди выбранных 5 ячеек 2 с испорченной информацией.
Количество вариантов выбора из 2 ячеек с испорченной информацией:
Количество вариантов выбора из 1022 ячеек остальные 3 ячейки исправны:
Код писал под свои нужды, его можно написать компактнее.
BOD из коробки (со штатными fuses) включено же. Хотя таки да, будет полезен электролит мкФ так на 3300.
Конденсаторы в цепях питания как раз растягивают время падения напряжения, оставляя микроконтроллеру больше возможностей запороть EEPROM. Именно для противодействия этому BOD и нужен.
Sindbad, к нему проверка на АЦП/компараторе полагается же.
Если опустилось - срочно записать и не трогать (поставить флаг, не прикасаться к памяти), пока конденсатор ещё не разрядился. Не?
BOD из коробки (со штатными fuses) включено же. Хотя таки да, будет полезен электролит мкФ так на 3300.
iliya555, мне любопытно, хочу поглядеть код с 26 условиями (на длину 5 байт), мож как-нибудь ужму.
у голого МК выключен. Вы про ардуину? Это не проверял, но у голого выключен
не путайте для атмега 8 два отдельных фьюза, один включает BOD, а второй определяет уровень срабатывания. Второй запрограмирован на одно из значений с завода, но не активен пока не включен первый
Sindbad, к нему проверка на АЦП/компараторе полагается же.
Если опустилось - срочно записать и не трогать (поставить флаг, не прикасаться к памяти), пока конденсатор ещё не разрядился. Не?
Не совсем.
Если скетч не пишет в EEPROM вообще, то и проблемы при включении/выключении не возникает, т.к. в памяти нет команд записи в EEPROM.
Если же скетч пишет в EEPROM, то такие команды в памяти МК присутствуют. При уменьшении напряжения питания, МК начинает выполнять случайные команды из памяти, тогда он может выполнить и команду, которая перепишет EEPROM. И никакие флаги не помогут.
Задача BOD - остановка работы МК при падении напряжения ниже заданного уровня.
Или, если использовать внешний контроль питания, нужно прижать выход RESET к земле при падении напряжения ниже заданного.