Запись числа Float в eeprom через массив

Sanchos07
Offline
Зарегистрирован: 15.10.2016
#include <Wire.h>

#include <Eeprom24C01_02.h>

#define EEPROM_ADDRESS  0x50 

static Eeprom24C01_02 eeprom(EEPROM_ADDRESS);
byte           REG_Massive[2];
int            tmp= -32334; // любое число
byte           REG_MassiveR[2];
int t;
int a0=10;
int a1=20;
void setup()
{
    // Initialize serial communication.
    Serial.begin(9600);
        
    // Initialize EEPROM library.
    eeprom.initialize();

}

void loop()
{
   REG_Massive[0] = tmp>>8;    // разбиваю число на байты и записываю в массив
   REG_Massive[1] = tmp;
    Serial.print("REG_Massive[0]=======");
    Serial.println(REG_Massive[0]);
    Serial.print("REG_Massive[1]=======");
    Serial.println(REG_Massive[1]);
    // Write a byte at address 0 in EEPROM memory.
    Serial.println("Write byte to EEPROM memory...");
    eeprom.writeByte(a0, REG_Massive[0]); //запись 1-го байта 
    delay(50);
    eeprom.writeByte(a1,REG_Massive[1]); //запись 2-го байта
    // Write cycle time (tWR). See EEPROM memory datasheet for more details.
    delay(10);
    
    // Read a byte at address 0 in EEPROM memory.
    Serial.println("Read byte from EEPROM memory...");
     REG_MassiveR[0]= eeprom.readByte(a0); // считываю байты и записываю в массив
     REG_MassiveR[1]= eeprom.readByte(a1);
    t   = REG_MassiveR[0]<<8;
    t  += REG_MassiveR[1]; // преобразую байты из массива в число.
    // Print read byte.
    
    Serial.print("REG_MassiveR[0]=======");
    Serial.println(REG_MassiveR[0]);
    Serial.print("REG_MassiveR[1]=======");
    Serial.println(REG_MassiveR[1]);
    Serial.println(t);
   
    delay(4000);
}

  

Доброго времени суток помогите пожалуйста разбить число типа Float на байты и потом считать их. Возможно ли это сделать на подобии этого примера с Числом int пример рабочий. Но вот с float уже не выходит. Пытался разбить на 4 байта и записать в массив. 

REG_Massive[0] = tmp>>24; 
REG_Massive[1] = tmp>>16;
REG_Massive[2] = tmp>>8; 
REG_Massive[3] = tmp;

Но что то не выходит уже при объявлении tmp во float вместо int выдает ошибку.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Определите указатель на массив байт.  А потом присвойте ему адрес float

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

нахрена такие сложности?

float pi = 3.1415926;

EEPROM.put(Адрес, pi);

float pi2;

EEPROM.get(Адрес, pi2);

Serial.print(pi2);

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

ну или через массив

template<typename T>
size_t SaveToRom(const size_t AAddress, T &AValue) {
	uint8_t *valueptr = (uint8_t *)(&AValue);
	for (uint8_t i = 0; i < sizeof(T); i++) EEPROM.put(AAddress, *valueptr++);  // старшим байтом вперёд
	return sizeof(T);
}

 

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

чтение оналогична. 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

DetSimen пишет:

нахрена такие сложности?

float pi = 3.1415926;

EEPROM.put(Адрес, pi);

float pi2;

EEPROM.get(Адрес, pi2);

Serial.print(pi2);

 

Это внешний EEPROM. И  в библиотеке Eeprom24C01_02 нету методов put и get 

astwo
Offline
Зарегистрирован: 10.07.2019

Тогда зачем эта помойнаябиблиотеке нужна

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

asam пишет:

Это внешний EEPROM. И  в библиотеке Eeprom24C01_02 нету методов put и get 

Да, я невнимательная пьянь. :( 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

asam пишет:

Это внешний EEPROM. И  в библиотеке Eeprom24C01_02 нету методов put и get 

Добавить методы и сделать также.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DetSimen пишет:

ну или через массив

Ну, это тоже лишние сложности. Всё делается также, как и раньше

float massiv [] = { 2.87, 3.62, 4.12 };

EEPROM.put(Адрес, massiv);

 

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

ЕвгенийП пишет:

DetSimen пишет:

ну или через массив

Ну, это тоже лишние сложности. Всё делается также, как и раньше

float massiv [] = { 2.87, 3.62, 4.12 };

EEPROM.put(Адрес, massiv);

А put рази не запишет в ROM, в этом случае, не сам massiv, а адрес его начала в ОЗУ?

ему же float * передается, без длины.  Или я тупой навовсе?  

SLKH
Offline
Зарегистрирован: 17.08.2015

ЕвгенийП пишет:

DetSimen пишет:

ну или через массив

Ну, это тоже лишние сложности. Всё делается также, как и раньше

float massiv [] = { 2.87, 3.62, 4.12 };

EEPROM.put(Адрес, massiv);

 

правильнее { 2.87, 3.07, 4.12 }

3.62 - из другого массива.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Еще небольшой комментарий. Логичнее начинать использование EEPRAM так

byte M1[2]; // некий массив 1
byte* M1_adr = 0; // адресс в eepram  массива 1 где значения можно скачать
int M2[2]; // некий массив 2
int* M2_adr =(int*)&M1_adr[2]; // адресс в eepram  массива 2 где значения можно скачать
/*ну и так даллее*/
void setup() {
}

void loop() {

}

Но кривые библиотеки на это не рассчитаны .

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DetSimen пишет:

ему же float * передается, без длины.  

Ему передаётся float massiv [], у которого вполне правильный sizeof. Точняк, спроси у Рабиновича :-)

Давай таки проверим. Вот оригинальная put из библиотеки EEPROM

    template< typename T > const T &put( int idx, const T &t ){
        EEPtr e = idx;
        const uint8_t *ptr = (const uint8_t*) &t;
        for( int count = sizeof(T) ; count ; --count, ++e )  (*e).update( *ptr++ );
        return t;
    }

давай напишем точно такую же, но не будем ничего никуда пхать, а просто параметры напечатаем:

#include <Printing.h>

 template< typename T > const T &kaka( int idx, const T &t ){
	const uint8_t *ptr = (const uint8_t*) &t;
	printf("idx=%d; ptr=%p; sizeof=%u\r\n", idx, ptr, sizeof(T));
	return t;
 }

float massiv [] = { 2.87, 3.62, 4.12 };

void setup(void) {
	Serial.begin(57600);
	printf("massiv=%p\r\n", massiv);
	kaka(0, massiv);
}

void loop(void){}

//////////////////
//
// 	Результат
// massiv=0x100
// idx=0; ptr=0x100; sizeof=12
//

Как видишь, и адрес начала, и sizeof - всё на месте. Так с чего ему не работать?

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

ЕвгенийП пишет:

 

// 	Результат
// massiv=0x100
// idx=0; ptr=0x100; sizeof=12
//

Как видишь, и адрес начала, и sizeof - всё на месте. Так с чего ему не работать?

Нихрена не понимаю.  :(   Нада, какабычно, напицца. 

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

DetSimen пишет:

 

Нихрена не понимаю.  :(   Нада, какабычно, напицца. 

Из темплейта компилятором будет создана функция для обработки float[3] (а не float*) , таким образом - внутри неё уже будет известен размер структуры данных.

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

понятно. А для float[5]  создасца совсем другой шаблон?  

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

Из этого же шаблона создастся вторая функция, но для float[5]. И третья для float[9]... Поэтому, честно говоря, бездумное применение функции put() мне представляется разбазариванием ресурсов МК.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

sadman41 пишет:

Из этого же шаблона создастся вторая функция, но для float[5]. И третья для float[9]... Поэтому, честно говоря, бездумное применение функции put() мне представляется разбазариванием ресурсов МК.

Правильно. Но для разумного использования уже разума не хватит. Я бы сказал шаблон put сделан для лентяев. Правильнее нарисовать шаблон реферального класса на эту переменную. Но как сказал ранее разума не хватит.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

qwone пишет:
Правильнее нарисовать шаблон реферального класса на эту переменную.
А можно примерчик того, о чём Вы здесь говорите?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ЕвгенийП пишет:

qwone пишет:
Правильнее нарисовать шаблон реферального класса на эту переменную.
А можно примерчик того, о чём Вы здесь говорите?

Класс EERef из EEPROM.h  или #252  qwonelib.h  EERef  Кривоватая. Но если поймете как и почему , то где-то получите неплохой инструмент.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А что более простого примера для еепром, который бы не тащил за собой и меню, и кнопку, и lcd нету?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

А что выдернуть Вы не сможете. Там же все прозрачно.

#include <EEPROM.h>
const byte* adr = 0;
void setup() {
  Serial.begin(9600);
  EERef aaa((int)adr);
  aaa = 5;
  Serial.println(aaa);// выведено 5
  aaa += 5;
  Serial.println(aaa);// выведено 10

}

void loop() {


}

У шаблона похожее будет

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Выдернул, посмотрел. К сожалению, даже на даже на беглый взгляд, количество ошибок зашкаливает. Я даже не говорю про идейные странности - только про простые программные ляпы. Но, как Вы неоднократно писали мне и другим в той теме, баг-репорты Вас не интересуют, и учить Вас не надо. Это в силе? Или Вы передумали, и Вам интересен баг-репорт?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Зачем. Что бы править надо понимать зачем и почему. Как вы можете править мои баги, если я смутно понимаю как и почему.

Но похоже и автор EEPROM тоже в этом плавал. Иначе того шаблона не существовало. Он лишний.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, как хотите. Если Вам нравится публиковать коды с большим количеством ошибок, и не нравится узнавать об этих ошибках, не могу Вам запретить этого :)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Мне не хочется исправлять не только свои ошибки, но и чужие. Так что обойдусь.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, и ладненько.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

qwone пишет:

Еще небольшой комментарий. Логичнее начинать использование EEPRAM так

byte M1[2]; // некий массив 1
byte* M1_adr = 0; // адресс в eepram  массива 1 где значения можно скачать
int M2[2]; // некий массив 2
int* M2_adr =(int*)&M1_adr[2]; // адресс в eepram  массива 2 где значения можно скачать
/*ну и так даллее*/
void setup() {
}

void loop() {

}

Но кривые библиотеки на это не рассчитаны .

Пух, ты чё курил?

Sanchos07
Offline
Зарегистрирован: 15.10.2016

Спасибо вам всем большое, но я еле еле разобрался с это библиотекой так как самая простая для меня, то что вы написали думаю конечно правильно, но я не фига не вдупляю))) и коньяк и водка мне не помогут).

В моем примере запись и чтение работают хорошо косяк идет при получении числа из массива. Хотя может и при разбивке уже фигня идет. 

Если не сложно тыкните носом в коде где косяк.

#include <Wire.h>

#include <Eeprom24C01_02.h>

#define EEPROM_ADDRESS  0x50 

static Eeprom24C01_02 eeprom(EEPROM_ADDRESS);
byte            REG_Massive[4];
long            tmp =2147483647;
byte            REG_MassiveR[4];
long t;
int a0=1;
int a1=2;
int a2=3;
int a3=4;
void setup()
{
    // Initialize serial communication.
    Serial.begin(9600);
        
    // Initialize EEPROM library.
    eeprom.initialize();

}

void loop()
{
 
   REG_Massive[0] = tmp>>24;
   REG_Massive[1] = tmp>>16;
   REG_Massive[2] = tmp>>8;    // разбиваю число на байты и записываю в массив
   REG_Massive[3] = tmp;
   Serial.println("Write byte to EEPROM memory...");
   Serial.println(tmp);
    Serial.print("REG_Massive[0]=======");
    Serial.println(REG_Massive[0],BIN);
    Serial.print("REG_Massive[1]=======");
    Serial.println(REG_Massive[1],BIN);
    Serial.print("REG_Massive[2]=======");
    Serial.println(REG_Massive[2],BIN);
    Serial.print("REG_Massive[3]=======");
    Serial.println(REG_Massive[3],BIN);
    
    // Write a byte at address 0 in EEPROM memory.
    
    eeprom.writeByte(a0, REG_Massive[0]); //запись 1-го байта 
    delay(50);
    eeprom.writeByte(a1, REG_Massive[1]); //запись 2-го байта 
    delay(50);
    eeprom.writeByte(a2, REG_Massive[2]); //запись 3-го байта 
    delay(50);
    eeprom.writeByte(a3, REG_Massive[3]); //запись 4-го байта
    // Write cycle time (tWR). See EEPROM memory datasheet for more details.
    delay(10);
    
    // Read a byte at address 0 in EEPROM memory.
    Serial.println("Read byte from EEPROM memory...");
     REG_MassiveR[0]= eeprom.readByte(a0); // считываю байты и записываю в массив
     REG_MassiveR[1]= eeprom.readByte(a1);
     REG_MassiveR[2]= eeprom.readByte(a2); // считываю байты и записываю в массив
     REG_MassiveR[3]= eeprom.readByte(a3);
    t   = REG_MassiveR[0]<<24;
    t  += REG_MassiveR[1]<<16;
    t  += REG_MassiveR[2]<<8;
    t  += REG_MassiveR[3]; // преобразую байты из массва в число.
    // Print read byte.
    
    Serial.print("REG_MassiveR[0]=======");
    Serial.println(REG_MassiveR[0],BIN);
    Serial.print("REG_MassiveR[1]=======");
    Serial.println(REG_MassiveR[1],BIN);
    Serial.print("REG_MassiveR[2]=======");
    Serial.println(REG_MassiveR[2],BIN);
    Serial.print("REG_MassiveR[3]=======");
    Serial.println(REG_MassiveR[3],BIN);
    Serial.println(t);
   
    delay(4000);
}

монитор выдает

Write byte to EEPROM memory...
2147483647
REG_Massive[0]=======1111111
REG_Massive[1]=======11111111
REG_Massive[2]=======11111111
REG_Massive[3]=======11111111
Read byte from EEPROM memory...
REG_MassiveR[0]=======1111111
REG_MassiveR[1]=======11111111
REG_MassiveR[2]=======11111111
REG_MassiveR[3]=======11111111
-1
Ввожу 2147483647
Получаю -1 ((((
sadman41
Offline
Зарегистрирован: 19.10.2016
long  toEeprom = 2147483647;
long  fromEeprom = 0;
byte  address = 1;
...
eeprom.writeBytes(address, sizeof(toEeprom), (byte*) &toEeprom);
Serial.println(toEeprom);
...
eeprom.writeBytes(address, sizeof(fromEeprom), (byte*) &fromEeprom);
Serial.println(fromEeprom);
...

 

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

Век живи - век учись, дураком помрешь. А я, дурак, вписывал (температура*10-константа) в байт.

Но все равно - Учится, учится и еще раз учится!

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

mykaida пишет:
Век живи - век учись, дураком помрешь.
Разумеется.Пройдет очередная реформа образования и все что знаешь устарело. В программировании реформы идут еще быстрее.

Sanchos07
Offline
Зарегистрирован: 15.10.2016

к сожалению не понимаю как, но  работает ток  8 строчка readBytes  )) Спасибо большое.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Я так понял, ответа на #28 не будет? Ну, да, и хрен с ним. Только, я тебя прошу, будь другом, не превращайся в Великого. Вот этого не надо:

qwone пишет:

кривые библиотеки на это не рассчитаны .

Кривизна wiring, это его тема, а не твоя.

SLKH
Offline
Зарегистрирован: 17.08.2015

mykaida пишет:

Век живи - век учись, дураком помрешь. А я, дурак, вписывал (температура*10-константа) в байт.

Но все равно - Учится, учится и еще раз учится!

В том числе написанию "тся - ться".

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

Sanchos07 пишет:

к сожалению не понимаю как, но  работает ток  8 строчка readBytes  )) Спасибо большое.

Да, копипастнул я лихо.

Работает так:

1) Функции writeBytes()/readBytes() требуют адрес байтового массива и его размер;
2) Байтовый массив есть последовательность ячеек, а имя его - алиас адреса нулевой (начальной ячейки), т.е. указатель на него;
3) Тип данных long (а так же float) есть байтовый массив, при вычислениях интерпретируемый особый образом;
4) sizeof() возвращает размер заданной переменной в байтах;

Итого: берём адрес (через операцию &) переменной типа long (фактически - байтового массива), затем обманываем функцию  (через byte*), заставляя рассматривать данный адрес как указатель на байтовый массив. Таким образом, функция получает адрес начала байтового массива и его размер, а с ними она уже умеет работать. Внутри себя функция бежит по этому массиву и пишет (или читает) его последовательно.

asam дал наводку на это в #1.

 

Kakmyc
Offline
Зарегистрирован: 15.01.2018

В первых версиях библиотеки EEPROM.h методов put()/get() не было использовал такие функции.

Для float все точно так же, только тип данных другой

long EEPROM_long_read(int addr) { //передаем в функцию адрес ячейки из которой читать
byte raw[4]; for(byte i = 0; i < 4; i++) raw[i] = EEPROM.read(addr+i); long &num = (long&)raw; 
return num; } //возвращает считанное значение

//====================

//функция записи в EEPROM переменной типа long
  void EEPROM_long_write(int addr, long num){//передаем в функцию адрес куда писать и данные что писать
 byte raw[4]; (long&)raw = num; for(byte i = 0; i < 4; i++) EEPROM.write(addr+i, raw[i]); }//ничего не возвращает

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Kakmyc,

если уж делать без шаблонов, то лучше всё-таки везде писать не 4, а sizeof(long).

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Тогда уж sizeof(num).

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

Может сразу типа этого:

inline uint16_t EEPROM_write(uint16_t _address, uint32_t _number) {
  return EEPROM_write(_address, (uint8_t*) &_number, sizeof(_number));
}

inline uint16_t EEPROM_write(uint16_t _address, float _number) {
  return EEPROM_write(_address, (uint8_t*) &_number, sizeof(_number));
}

inline uint16_t EEPROM_write(uint16_t _address, uint64_t _number) {
  return EEPROM_write(_address, (uint8_t*) &_number, sizeof(_number));
}

uint16_t EEPROM_write(uint16_t _address, uint8_t* _ptrData, uint16_t _sizeData) {
  for (uint16_t i = 0x00; i < _sizeData; i++) {
    EEPROM.update(_address, *_ptrData);
    _address++;
    _ptrData++;
  }
  return _sizeData;
}

...

  uint16_t eepromAddress = 0x00;
  float nFloat = 1.236;
  uint64_t n64bit = 135467ULL;
  eepromAddress += EEPROM_write(eepromAddress, nFloat);
  eepromAddress += EEPROM_write(eepromAddress, n64bit);

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Kakmyc пишет:
Тогда уж sizeof(num).
В read нет никакого num :(

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

Может сразу типа этого:

Тогда уж сразу шаблон

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

Можно и шаблон, но с этим, как я вижу, пока проблемы когнитивного характера наблюдаются.