Как сохранить строковую переменную в eeprom?

Тема в разделе "Arduino & Shields", создана пользователем Чайник2005, 2 фев 2022.

  1. делаю спидометр на ардуино. есть модуль часов реального времени 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++;
       }
      }
    */

     
     
  2. DetSimen

    DetSimen Гуру

    сохраняй как структуру/uint32_t типа tm/time_t. Псмотри обьявление в time.h
     
    SergeiL нравится это.
  3. parovoZZ

    parovoZZ Гуру

    Пишешь строку посимвольно, в конце пишешь символ конца строки. При чтении обратная процедура - читаешь символы, пока не наткнёшься на символ конца строки.
     
  4. User248

    User248 Гик

    Дело в том, что у переменной типа 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() {

    }
     
     
  5. b707

    b707 Гуру

    Дед правильно сказал - что за дурость сохранять строку... сохраняйте время!
     
  6. пошел немного другим путем - использовал другую библиотеку, где можно снимать дату время в виде переменной int и мутить с числами что душе угодно. всем спасибо!
     
  7. b707

    b707 Гуру

    можно было заглянуть в заголовок текущей библиотеки и убедится, что она тоже умеет возвращать время как инт, причем даже в двух разных форматах:
    Код (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()

    привыкайте читать документацию, а не одни видосики смотреть
     
    Feofan, SergeiL, Чайник2005 и ещё 1-му нравится это.