Проблема записи double

Тема в разделе "Arduino & Shields", создана пользователем sanik, 19 фев 2021.

  1. sanik

    sanik Гик

    Добрый день! Как записать коэффициенты PID в EPROM ? Записываю с запятой а считывает цельночисленное с округлением
    Код (C++):
    #include <EEPROM.h>

    double Kp = 2, Ki = 5, Kd = 1.5;

    void setup() {
      Serial.begin(9600);
      EEPROM_double_write(65, 1.5);
    }
    void loop() {
      Kd = EEPROM_double_read(65);
      Serial.print("Kd: ");
      Serial.print(Kd);
      Serial.println(" ");
      delay(100);
    }

    //запись double значения в память (четырехбайтовое значение хранится в 4 ячейках)
    void EEPROM_double_write(int addr, double num) {
      double raw[4];
      (double&)raw = num;
      for (byte i = 0; i < 4; i++) {
        EEPROM.write(addr + i, raw[i]);
      }

    int EEPROM_double_read(int addr) {
      double raw[4];
      for (byte i = 0; i < 4; i++) {
        raw[i] = EEPROM.read(addr + i);
      }
      double&num = (double&)raw;
      return num;
    }

    }
     
  2. parovoZZ

    parovoZZ Гуру

    А чем
    Код (C++):
    pgm_write_float(data);
    не подошла?
     
  3. sanik

    sanik Гик

    А как применить? Подробнее на примере можно?
     
  4. sanik

    sanik Гик

    И разве float в PID будет работать?
    Код (C++):

    float Setpoint, Input, Output;
    float Kp = 2, Ki = 5, Kd = 1.5;
    PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
     
     
  5. sanik

    sanik Гик

    создал структуру все заработало
    Код (C++):
    #include <avr/eeprom.h>
    // объявляем структуру яйчеек памяти
    float Kp = 2, Ki = 5, Kd = 1.5;
    struct EEPROM_Struct {
      uint32_t SL1, SL2, sFD, sFW; // SetupLight[0] ,SetupLight[1], setFanDown[0], setFanWork[0]
      uint8_t lim; // limit
      byte sV; // setVent
      boolean rew, FanL, SeH, fH; // Rewes, FanLIGHT, SetenableHeat, fHeat
      int  sD, sT, sH; // setDelay, setTemp, setHum
      float p, i, d; // Kp, Ki, Kd
    };
    // создаём  пустую структуру для чтения
    EEPROM_Struct Struct_read;

    void setup() {
      Serial.begin(9600);

      // создаём и заполняем структуру записываем по адресу 10, указав размер структуры и приведя к void*
      EEPROM_Struct Struct_write;
      Struct_write.SL1 = 1; //SetupLight[0]
      Struct_write.SL2 = 2; //SetupLight[1]
      Struct_write.sFD = 120; //setFanDown[0]
      Struct_write.sFW = 3; //setFanWork[0]
      Struct_write.lim = 10; //limit
      Struct_write.sV = 30; //setVent
      Struct_write.rew = 0; //Rewes
      Struct_write.FanL = 1; //FanLIGHT
      Struct_write.SeH = 0; //SetenableHeat
      Struct_write.fH = 0; //fHeat
      Struct_write.sD = 3; //setDelay
      Struct_write.sT = 29; //setTemp
      Struct_write.sH = 70; //setHum
      Struct_write.p = Kp; //
      Struct_write.i = Ki; //
      Struct_write.d = Kd; //
      eeprom_write_block((void*)&Struct_write, 10, sizeof(Struct_write));


      // читаем из адреса 10
      eeprom_read_block((void*)&Struct_read, 10, sizeof(Struct_read));
      Kp = Struct_read.p;
      Ki = Struct_read.i;
      Kd = Struct_read.d;
      // проверяем
      // выведет 10 1000 3.14
      Serial.println(Struct_read.SL1);
      Serial.println(Struct_read.SL2);
      Serial.println(Struct_read.sFD);
      Serial.println(Struct_read.sFW);
      Serial.println(Struct_read.lim);
      Serial.println(Struct_read.sV);
      Serial.println(Struct_read.rew);
      Serial.println(Struct_read.FanL);
      Serial.println(Struct_read.SeH);
      Serial.println(Struct_read.fH);
      Serial.println(Struct_read.sD);
      Serial.println(Struct_read.sT);
      Serial.println(Struct_read.sH);
      Serial.println(Struct_read.p);
      Serial.println(Struct_read.i);
      Serial.println(Struct_read.d);
    }
    void loop() {}
    Возник новый вопрос чтоб лишний раз не перезаписывать ячейки Как создать проверку изменилось ли значение или нет
    типа такой
    Код (C++):
    if (EEPROM.read(90) != limit) {
              EEPROM.write(90, limit);
            }
     
  6. AlexU

    AlexU Гуру

    eeprom_update_*
     
  7. sanik

    sanik Гик

    То есть так?
    Код (C++):
    eeprom_update_block((void*)&Struct_write, 10, sizeof(Struct_write));

    Код (C++):
    #include <avr/eeprom.h>
    // объявляем структуру яйчеек памяти
    float Kp = 2, Ki = 5, Kd = 1.5;
    struct EEPROM_Struct {
      uint32_t SL1, SL2, sFD, sFW; // SetupLight[0] ,SetupLight[1], setFanDown[0], setFanWork[0]
      uint8_t lim; // limit
      byte sV; // setVent
      boolean rew, FanL, SeH, fH; // Rewes, FanLIGHT, SetenableHeat, fHeat
      int  sD, sT, sH; // setDelay, setTemp, setHum
      float p, i, d; // Kp, Ki, Kd
    };
    // создаём  пустую структуру для чтения
    EEPROM_Struct Struct_read;

    void setup() {
      Serial.begin(9600);

      // создаём и заполняем структуру записываем по адресу 10, указав размер структуры и приведя к void*
      EEPROM_Struct Struct_write;
      Struct_write.SL1 = 1; //SetupLight[0]
      Struct_write.SL2 = 2; //SetupLight[1]
      Struct_write.sFD = 120; //setFanDown[0]
      Struct_write.sFW = 3; //setFanWork[0]
      Struct_write.lim = 10; //limit
      Struct_write.sV = 30; //setVent
      Struct_write.rew = 0; //Rewes
      Struct_write.FanL = 1; //FanLIGHT
      Struct_write.SeH = 0; //SetenableHeat
      Struct_write.fH = 0; //fHeat
      Struct_write.sD = 3; //setDelay
      Struct_write.sT = 29; //setTemp
      Struct_write.sH = 70; //setHum
      Struct_write.p = Kp; //
      Struct_write.i = Ki; //
      Struct_write.d = Kd; //
      eeprom_update_block((void*)&Struct_write, 10, sizeof(Struct_write));


      // читаем из адреса 10
      eeprom_read_block((void*)&Struct_read, 10, sizeof(Struct_read));
      Kp = Struct_read.p;
      Ki = Struct_read.i;
      Kd = Struct_read.d;
      // проверяем
      // выведет 10 1000 3.14
      Serial.println(Struct_read.SL1);
      Serial.println(Struct_read.SL2);
      Serial.println(Struct_read.sFD);
      Serial.println(Struct_read.sFW);
      Serial.println(Struct_read.lim);
      Serial.println(Struct_read.sV);
      Serial.println(Struct_read.rew);
      Serial.println(Struct_read.FanL);
      Serial.println(Struct_read.SeH);
      Serial.println(Struct_read.fH);
      Serial.println(Struct_read.sD);
      Serial.println(Struct_read.sT);
      Serial.println(Struct_read.sH);
      Serial.println(Struct_read.p);
      Serial.println(Struct_read.i);
      Serial.println(Struct_read.d);
    }
    void loop() {}
     
  8. akl

    akl Гуру

    raw[4]; должно быть byte
     
  9. AlexU

    AlexU Гуру

    Да.
     
  10. sanik

    sanik Гик

    Да я по разному пробовал все равно не сохраняет.
     
  11. sanik

    sanik Гик

    Спасибо!
     
  12. parovoZZ

    parovoZZ Гуру

    float и double в avr-gcc одно и тоже, если не использовать специальные параметры.
     
  13. sanik

    sanik Гик

    :) Поздновато конечно но все равно спасибо! Проверил уже вчера, дописал свой код полностью)