Как записать переменную типа float в EEPROM
- Войдите на сайт для отправки комментариев
Пнд, 29/04/2013 - 19:38
Не получается записать и прочитать переменную типа float - например 3.5. Пытаюсь через промежуточную переменную типа int умножая переменную типа float на 10, но причтении и делении на 10 теряются знаки после запятой. В библиотеке EEPROM с записью float не могу разобраться. Как правильно сделать?
int val; float VAL; val = VAL*10; EEPROM.write(31, val); delay(50); /////////////// val = EEPROM.read(31); VAL = val/10;
попробуйте так
изучите как храниться тип float в памяти, и записывайте его в явном виде.
Всё равно теряются десятки, например записываю val = 2.8*10 получаю val/10( или 10.0) =2.7
изучили?
Почитал. нашёл статейку http://dvo.sut.ru/libr/cvti/i618buz/2.htm
Но для чайника это больше ознакомительно, т.к. применить знаний не хватает.
Нашел пример maksima
float val_1 = 30.12345;
float val_2 = 0;
// запись в ЕЕПРОМ
byte *x = (byte *)&val_1;
for(int i = 0; i < 4; i++) EEPROM.write(i, x[i]);
// чтение из ЕЕПРОМ
byte xx[4];
for(int i = 0; i < 4; i++) xx[i] = EEPROM.read(i);
float *y = (float*)&xx;
val_2 = y[0];
Но и здесь не знаю как правильно адресс записать
upd: не успел, опередили ) , только вынесено для удобства в функции и учитывайте что в памяти float занимает 4 байта , то есть если одну переменную записали по адресу 0, то следующая должна быть записана по адресу 4 иначе затрете предыдущую.
о! vvadim это вы нашли правильный пример.
float занимает в памяти 4 байта. Итого берем указатель на него, и пишем в память четыре раза по байту. Назад в обратном порядке.
адрес как и у любого типа EEPROM.write(i, x[i]);
тут первая i это адрес.
можно и так записать
разместится float по адресам 100-103
Дежавю. Вопрос пора в базу знаний :)
http://playground.arduino.cc/Code/EEPROMWriteAnything
Я уже смотрел и EEPROMEx , но как в код всё увязать - трудновато. Мне нужно сохранить четыре разных параметра ну и потом прочитать их. Можно пример для наглядности как записать val_1 по адрессу например 10 и прочитать val_2
float val_1 = 30.12345;
float val_2 = 0;
// запись в ЕЕПРОМ
byte *x = (byte *)&val_1;
for(int i = 0; i < 4; i++) EEPROM.write(i, x[i]);
// чтение из ЕЕПРОМ
byte xx[4];
for(int i = 0; i < 4; i++) xx[i] = EEPROM.read(i);
float *y = (float*)&xx;
val_2 = y[0];
вам же maksim даже функции дал. что сложного?
EEPROM_float_write(10, val_1) // тут пишем по адресу 10
val_2 = EEPROM_float_read(10) // тут читаем
только запомнить, что записывая по адресу 10, флоат будет лежать с 10 по 13. т.е. в 11 писать другую переменную нельзя.
Это хорошо, функции я видел. Их нужно использовать для каждой записи (адреса)?
И в примере первом maksima функций нет, мне как бы проще.
ниче не понимаю. ну да ладно. ))
Всем СПАСИБО, вроде разобрался, буду топать дальше.
Вы лучше напишите что хотите сделать в итоге.
Делаю себе меню и хочу параметры настраивать кнопками на дисплее (раньше крутил потенциометр). Несколько переменных визуально удобнее использовать в виде десятичной дроби, вот и возникла тема на форуме. Спасибо за помощь - немного разобрался.
вам же maksim даже функции дал. что сложного?
EEPROM_float_write(10, val_1) // тут пишем по адресу 10
val_2 = EEPROM_float_read(10) // тут читаем
только запомнить, что записывая по адресу 10, флоат будет лежать с 10 по 13. т.е. в 11 писать другую переменную нельзя.
Подскажите пожалуйста почему компилятор не пропускает вот такую строчку
Неужели вышел за пределы памяти?
Ошибка: redefinition of int addr
error: 'int addr' previously defined here
UPD: Разобрался. addr уже было определено!! Не внимательность)))))
Число́ одина́рной то́чности (англ. Single precision, Single) — широко распространенный компьютерный формат представления вещественных чисел, занимающий в памяти 32 бита (4 байта). Как правило, под ним понимают формат числа с плавающей запятой стандарта IEEE 754.
Для извлечения данных
Сталкивался с этим в протоколах Modbus RTU.
зачем так извращаться?
вот тут нормальные (а главное стандартные) функции описаны http://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html
к тому же можно не назначать самому адреса в EEPROM, а использовать атрибут EEMEM, тогда линкер автоматом распределит память
А работает EEMEM также как и PROGMEM и какие есть грабли?
Ну не совсем так же. С одной стороны и там и там линкер выделяет адреса под данные автоматически. И там и там для получения адреса переменной используется стандартный для Си оператор &. Но в отличии от PROGMEM EEMEM не програмирует автоматически данные в eeprom при прошивке. Данные в EEPROM все равно програмировать самому, для этого есть два способа. 1. Самый простой - при старте программы считывать eeprom и если там значения отдельных байт 0xff то это пустая ячейка и ее надо инициализировать. В случае если нормальные данные тоже могут иметь значения 0xff надо решать отдельно. Универсальное решение - разместить в eeprom специальную переменную типа uint8_t значение которой 255 если eeprom еще не инициализирован и 0 если уже инициализирован. 2. При использовании eemem линкер генерит файл .eep который содержит данные для прямого програмирования в eeprom програматором, но для ардуины это не поддерживается
граблей две: 1. Не возможно совмещать ручное размещение данных и автоматическое, либо так либо так 2. При добавлении новых переменных с атрибутом eemem не гарантируется, что адреса расположения в eeprom старых переменных останутся те же. Поэтому если делается заливка новой версии скетча с новыми eemem переменными надо специально позаботиться об инициализации и новых и старых переменных в eeprom
Подскажите, что необходимо изменить в коде выше чтобы он подходил под сохранение и чтение переменных типа unsigned long, ведь он тоже занимает 4 байта?
И прочтите мне пожалуйста строчку float *y = (float *)&x; человеческим языком.
Ответ: ну собственно, ничего особо менять и не надо, только float везда в unsigned long. Вроде все рабртает.
Запись и чтение EEPROM переменных типа float, unsigned long, long, unsigned int, int
Попробуйте использовать библиотеку VEduino (версии 0.20 и выше).
Пример использования:
Подключите потенциометр к выводу A0 платы Arduino UNO (или MEGA). При вращении потенциометра в Мониторе порта можно будет наблюдать текущее напряжение на входе A0.
Текущее значение можно записать в EEPROM по адресу 0x000 командой R. Командой W можно прочитать записанное значение.