Задача: управлять температурой в пределах 37-39 градусов. Условия: питание устройства может иногда теряться. Решаю. При изменении управляемой температуры пишу ее в EEPROM, если питание пропадает - при включении считываю из EEPROM. Код. Код (C++): // на входе есть double переменная setTemp = 37.7 double tsetTemp = ((setTemp - 30.0)*10.0); Serial.print("tsetTemp = "); Serial.println(tsetTemp); byte ttsetTemp = (byte)tsetTemp; Serial.print("ttsetTemp = "); Serial.println(ttsetTemp); EEPROM.update(1,ttsetTemp); // раньше был вот этот код, но я его "разложил" на тот что сверху // EEPROM.update(1,(byte)((setTemp - 30.0)*10.0)); А теперь картинка как это работает: При старте EEPROM читается: Код (C++): setpoint = ((double)(EEPROM.read(1)))/10.0+30.0; и в нем, естественно, температура на 0.1 градус меньше. Видно, что единица теряется при преобразовании: Код (C++): byte ttsetTemp = (byte)tsetTemp; Почему?????????
Особенности работы с плавающей точкой. Скорее всего в tsetTemp оказывается что-то вроде 76.99999999 (точнее 0.7699999999E2, ибо точка плавающая). При выводе с помощью println оно корректно округляется. При присваивании переменной типа byte просто отбрасывается дробная часть. Чтобы было однозначно правильно, в таком случае лучше преобразовывать не простым присваиванием, а функцией round(). byte ttsetTemp = round(tsetTemp);
Пишите в память байты исходного double, тогда точно ничего теряться не будет. Код (C++): void EEPROM_writeDouble(int ee, double value) { byte* p = (byte*)(void*)&value; for (int i = 0; i < sizeof(value); i++) EEPROM.write(ee++, *p++); } double EEPROM_readDouble(int ee) { double value = 0.0; byte* p = (byte*)(void*)&value; for (int i = 0; i < sizeof(value); i++) *p++ = EEPROM.read(ee++); return value; } Будет занимать 4 или 8 байт в зависимости от платы, см. sizeof(value).
Ясно. Лучше всего обойтись без плавающей точки. Она нужна только при отправке температуры в PID, поскольку библиотека так написана. А до этого буду работать с int: не 37.7, а 377.