делаю спидометр на ардуино. есть модуль часов реального времени ds3231. при помощи библиотеки несложно вывести на экран дату и время, НО не получается сохранить время в EEPROM. после чтения выдает билиберду (⸮k߾⸮߮s⸮⸮H). почему так и как можно исправить? не имеющие отношение к проблеме строки закомментировал Код (C++): #include <DS3231.h> #include <EEPROM.h> #include <UTFT.h> #define PIN_POT A3 DS3231 rtc(SDA, SCL); UTFT myGLCD(TFT01_22SP, 9, 8, 12, 11, 10); extern uint8_t BigFont[]; extern uint8_t SevenSegNumFontPCMDS[]; extern uint8_t battery_24x48[]; unsigned long tmr1; unsigned long tmr0 = -20000; float veloSpeed, veloSpeed2, timeob, odom, dm, maxVeloSpeed, nowDayKm, todayOd; float Drcm; int Ddm = 12; //диаметр колеса в дюймах int lvl; float battery; float massbattery[]{7.0, 7.25, 7.5, 7.75, 8, 10}; String myString2; String myString; static char maxMassVeloSpeed[5]; static char massVeloSpeed[4]; static char odometr[9]; static char nowDayKmodometr[9]; static char battery1[2]; bool flag; void setup() { pinMode(13, OUTPUT); digitalWrite(13, HIGH); pinMode(3, INPUT_PULLUP); pinMode(PIN_POT, INPUT); attachInterrupt(0, PINGERCON, FALLING); attachInterrupt(1, PULLUP, FALLING); myGLCD.InitLCD(); myGLCD.clrScr(); Serial.begin(9600); rtc.begin(); pinMode(4, OUTPUT); digitalWrite(4, HIGH); EEPROM.get(0, odom); EEPROM.get(4, todayOd); EEPROM.get(8, maxVeloSpeed); EEPROM.get(20, myString2); flag = 0; /* dm = Ddm*2.54*3.14; //диаметр колеса в дюймах*сантиметры в дюйме*число пи Drcm = 1000*dm/100*3.6; //миллисекунд в секунде*переменная dm/сантиметры в метры*число перевода из м/с в км/ч dtostrf(maxVeloSpeed, 4, 1, maxMassVeloSpeed); nowDayKm = odom-todayOd; myGLCD.setColor(VGA_BLUE); myGLCD.setFont(BigFont); myGLCD.print(rtc.getDateStr(FORMAT_SHORT), 190, 220); myGLCD.print("max", 254 , 170); myGLCD.print("km", 132 , 200); myGLCD.print("km", 132 , 220); */ myString = rtc.getDateStr(FORMAT_SHORT); Serial.println(rtc.getDayStr()); Serial.println(myString); Serial.println(myString2); if(myString != myString2){ myString2 = rtc.getDateStr(FORMAT_SHORT); todayOd = odom; } } void loop() { /* if (millis() - tmr1 > 2500) { veloSpeed = 0; if (millis() - tmr1 > 120000){ PULLUP(); } } dtostrf(veloSpeed, 2, 1, massVeloSpeed); //перевод в строку с плавающей точкой dtostrf(odom, 7, 2, odometr); dtostrf(nowDayKm, 7, 2, nowDayKmodometr); if(veloSpeed > maxVeloSpeed){ //максимальная скорость maxVeloSpeed = veloSpeed; EEPROM.put(8, veloSpeed); //сохраняем в eeprom dtostrf(veloSpeed, 4, 1, maxMassVeloSpeed); } if (millis() - tmr0 > 20000){ tmr0 = millis(); lvl = 0; BATTERY(); myGLCD.setFont(battery_24x48); myGLCD.print(battery1, 20 , 10); } myGLCD.setColor(VGA_BLUE); myGLCD.setFont(SevenSegNumFontPCMDS); if(veloSpeed < 10){ //костыль myGLCD.print(massVeloSpeed, 120, 50); myGLCD.print("/", 88, 50); } else { myGLCD.print(massVeloSpeed, 88, 50); } myGLCD.setFont(BigFont); myGLCD.print(maxMassVeloSpeed, 190, 170); myGLCD.print(nowDayKmodometr, 20 , 200); myGLCD.print(odometr, 20 , 220); myGLCD.print(rtc.getTimeStr(), 190, 200); */ if(flag == 1){ myGLCD.setColor(VGA_LIME); myGLCD.setFont(BigFont); myGLCD.print("SAVING", CENTER, 125); EEPROM.put(0, odom); EEPROM.put(4, todayOd); EEPROM.put(20, myString2); delay(750); digitalWrite(13, LOW); while(flag == 1){} //бесконечный цикл } } /* void PINGERCON() { timeob = (millis() - tmr1); if(timeob > 100){ veloSpeed = 1/timeob*Drcm; if(veloSpeed - veloSpeed2 > 10){ //костыль защита от помех veloSpeed = veloSpeed2; } else{ odom = odom+dm/100000; nowDayKm = odom-todayOd; } tmr1 = millis(); veloSpeed2 = veloSpeed; } } */ void PULLUP(){ flag = 1; } /* void BATTERY(){ analogReference(INTERNAL); battery = analogRead(PIN_POT)*1.1/1024/0.117+0.49; analogReference(DEFAULT); while (battery >= massbattery[lvl-1]){ if (battery <= massbattery[lvl]) { dtostrf(lvl, 1, 0, battery1); } lvl++; } } */
Пишешь строку посимвольно, в конце пишешь символ конца строки. При чтении обратная процедура - читаешь символы, пока не наткнёшься на символ конца строки.
Дело в том, что у переменной типа String нет фиксированного размера. Можно переводить String в массив char и потом запоминать. Вот пример: Код (C++): #include <EEPROM.h> int addr = 100; // адрес ячейки для записи char lineBuf[20]; void setup() { Serial.begin(9600); // включаем порт для отладки String line = "Test String"; line.toCharArray(lineBuf, line.length()+1); EEPROM.put(addr, lineBuf); // записываем строку в память EEPROM.get(addr, lineBuf); // считываем строку из памяти String line2 = lineBuf; Serial.println(line2); // выводим считанное в COM-порт } void loop() { }
пошел немного другим путем - использовал другую библиотеку, где можно снимать дату время в виде переменной int и мутить с числами что душе угодно. всем спасибо!
можно было заглянуть в заголовок текущей библиотеки и убедится, что она тоже умеет возвращать время как инт, причем даже в двух разных форматах: Код (C++): class DateTime { public: DateTime (uint32_t t =0); DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour =0, uint8_t min =0, uint8_t sec =0); DateTime (const char* date, const char* time); uint16_t year() const { return 2000 + yOff; } uint8_t month() const { return m; } uint8_t day() const { return d; } uint8_t hour() const { return hh; } uint8_t minute() const { return mm; } uint8_t second() const { return ss; } uint8_t dayOfTheWeek() const; // 32-bit times as seconds since 1/1/2000 long secondstime() const; // 32-bit times as seconds since 1/1/1970 // THE ABOVE COMMENT IS CORRECT FOR LOCAL TIME; TO USE THIS COMMAND TO // OBTAIN TRUE UNIX TIME SINCE EPOCH, YOU MUST CALL THIS COMMAND AFTER // SETTING YOUR CLOCK TO UTC uint32_t unixtime(void) const; см два последних метода - secondstime() и unixtime() привыкайте читать документацию, а не одни видосики смотреть