• admin
    #include <Wire.h>
    
    // ============================================================
    // Quartzdyne 32 位压力/温度读取
    // Arduino Nano, A1/T 悬空, A2/P 悬空
    //
    // I2C 扫描结果(7 位地址):
    //   0x4E -> 压力计数器(8位读地址 0x9D)
    //   0x4F -> 温度计数器(8位读地址 0x9F)
    //   0x56 -> EEPROM(8位读地址 0xAC)
    // ============================================================
    
    const uint8_t ADDR_PRESS  = 0x4E;  // 7 位地址
    const uint8_t ADDR_TEMP   = 0x4F;  // 7 位地址
    const uint8_t ADDR_EEPROM = 0x56;  // 7 位地址
    
    const uint16_t GATE_TIME_MS = 1000;  // 必须 < 2300
    uint32_t lastRead = 0;
    
    void setup() {
      Serial.begin(115200);
      while (!Serial) { ; }
    
      Serial.println(F("Quartzdyne 32-bit P/T Data Read"));
      Serial.println(F("=========================================="));
    
      // 启用内部弱上拉(临时补救,正式版请外接 4.7kΩ)
      pinMode(A4, INPUT_PULLUP);
      pinMode(A5, INPUT_PULLUP);
      delay(10);
    
      Wire.begin();
      Wire.setClock(100000);
    
      Serial.print(F("Press  addr: 0x")); Serial.println(ADDR_PRESS, HEX);
      Serial.print(F("Temp   addr: 0x")); Serial.println(ADDR_TEMP, HEX);
      Serial.print(F("EEPROM addr: 0x")); Serial.println(ADDR_EEPROM, HEX);
      Serial.println();
    
      delay(1000);
    
      // 先发 EEPROM 当前地址读,避免旧版锁死
      uint8_t dummy;
      if (eepromReadCurrent(ADDR_EEPROM, &dummy, 1)) {
        Serial.println(F("EEPROM current read OK (bus alive)"));
      } else {
        Serial.println(F("EEPROM current read FAILED"));
      }
      Serial.println();
    
      // 首次触发
      triggerCounter(ADDR_TEMP);
      triggerCounter(ADDR_PRESS);
      lastRead = millis();
    }
    
    void loop() {
      if (millis() - lastRead < GATE_TIME_MS) return;
      lastRead = millis();
    
      uint32_t pData = 0, tData = 0;
      uint8_t  pCsum = 0, tCsum = 0;
    
      bool pOK = readCounterData(ADDR_PRESS, pData, pCsum, true);
      bool tOK = readCounterData(ADDR_TEMP,  tData, tCsum, true);
    
      if (!pOK || !tOK) {
        Serial.print(F("Read FAILED  (P="));
        Serial.print(pOK ? F("OK") : F("NACK"));
        Serial.print(F(", T="));
        Serial.print(tOK ? F("OK") : F("NACK"));
        Serial.println(F(")"));
        return;
      }
    
      bool pCsumOK = verifyChecksum(pData, pCsum);
      bool tCsumOK = verifyChecksum(tData, tCsum);
    
      Serial.print(F("P32=0x"));
      printHex32(pData);
      Serial.print(F("  P32_dec="));
      Serial.print(pData);
    
      Serial.print(F("  T32=0x"));
      printHex32(tData);
      Serial.print(F("  T32_dec="));
      Serial.print(tData);
    
      Serial.print(F("  Xp="));
      Serial.print((float)pData / 16777216.0f, 8);
      Serial.print(F("  Xt="));
      Serial.print((float)tData / 16777216.0f, 8);
    
      Serial.print(F("  csum="));
      Serial.print(pCsumOK && tCsumOK ? F("OK") : F("FAIL"));
    
      Serial.println();
    }
    
    // ============================================================
    // 辅助函数
    // ============================================================
    
    bool triggerCounter(uint8_t addr) {
      if (Wire.requestFrom(addr, (uint8_t)1) != 1) return false;
      Wire.read();
      return true;
    }
    
    bool readCounterData(uint8_t addr, uint32_t &value, uint8_t &checksum, bool readChecksum) {
      uint8_t n = readChecksum ? 5 : 4;
      if (Wire.requestFrom(addr, n) != n) return false;
    
      uint8_t b[5];
      for (uint8_t i = 0; i < n; i++) b[i] = Wire.read();
    
      value = ((uint32_t)b[0] << 24) |
              ((uint32_t)b[1] << 16) |
              ((uint32_t)b[2] << 8)  |
              ((uint32_t)b[3]);
    
      if (readChecksum) checksum = b[4];
      return true;
    }
    
    bool verifyChecksum(uint32_t value, uint8_t checksum) {
      uint8_t s = 0;
      s += (value >> 24) & 0xFF;
      s += (value >> 16) & 0xFF;
      s += (value >> 8)  & 0xFF;
      s += value & 0xFF;
      s += checksum;
      return (s == 0);
    }
    
    bool eepromReadCurrent(uint8_t addr, uint8_t *data, uint16_t len) {
      if (Wire.requestFrom(addr, (uint8_t)len) != len) return false;
      for (uint16_t i = 0; i < len; i++) data[i] = Wire.read();
      return true;
    }
    
    void printHex32(uint32_t v) {
      for (int8_t i = 3; i >= 0; i--) {
        uint8_t b = (v >> (i * 8)) & 0xFF;
        if (b < 0x10) Serial.print('0');
        Serial.print(b, HEX);
      }
    }
    主楼
  • admin
    #include <Wire.h>
    
    const uint8_t ADDR_PRESS  = 0x4E;
    const uint8_t ADDR_TEMP   = 0x4F;
    const uint8_t ADDR_EEPROM = 0x56;
    
    // 系数结构
    struct Cal1 {
      uint8_t type, prescale, n1, n2;
      float S1, S2;
      int32_t OFS2;
      int32_t C[5][5];  // 最多 5x5
    } cal1;
    
    struct Cal2 {
      uint8_t type, prescale, n1, n2;
      float S1, S2;
      int32_t OFS2;
      int32_t C[4];  // N1=0, N2=3
    } cal2;
    
    const uint16_t GATE_TIME_MS = 1000;
    uint32_t lastRead = 0;
    
    void setup() {
      Serial.begin(115200);
      pinMode(A4, INPUT_PULLUP);
      pinMode(A5, INPUT_PULLUP);
      Wire.begin();
      Wire.setClock(100000);
      delay(1000);
    
      // 读 EEPROM 系数
      uint8_t buf[256];
      if (!eepromReadSpecific(ADDR_EEPROM, 0x0000, buf, 256)) {
        Serial.println(F("EEPROM read FAILED"));
        while (1);
      }
    
      // 解析 Cal1
      cal1.type = buf[0x18];
      cal1.prescale = buf[0x19];
      cal1.n1 = buf[0x1A];
      cal1.n2 = buf[0x1B];
      cal1.S1 = bytesToFloat(&buf[0x1C]);
      cal1.S2 = bytesToFloat(&buf[0x20]);
      cal1.OFS2 = bytesToInt32(&buf[0x24]);
    
      // Cal1.C 系数按行排列:C(0,0), C(0,1), ..., C(0,N2), C(1,0), ...
      int idx = 0x28;
      for (int i = 0; i <= cal1.n1; i++) {
        for (int j = 0; j <= cal1.n2; j++) {
          cal1.C[i][j] = bytesToInt32(&buf[idx]);
          idx += 4;
        }
      }
    
      // 解析 Cal2
      cal2.type = buf[0x8C];
      cal2.prescale = buf[0x8D];
      cal2.n1 = buf[0x8E];
      cal2.n2 = buf[0x8F];
      cal2.S1 = bytesToFloat(&buf[0x90]);
      cal2.S2 = bytesToFloat(&buf[0x94]);
      cal2.OFS2 = bytesToInt32(&buf[0x98]);
    
      idx = 0x9C;
      for (int i = 0; i <= cal2.n1; i++) {
        for (int j = 0; j <= cal2.n2; j++) {
          if (i == 0) cal2.C[j] = bytesToInt32(&buf[idx]);
          idx += 4;
        }
      }
    
      Serial.println(F("Coefficients loaded"));
      Serial.print(F("Cal1 N1=")); Serial.print(cal1.n1);
      Serial.print(F(" N2=")); Serial.println(cal1.n2);
      Serial.print(F("Cal2 N1=")); Serial.print(cal2.n1);
      Serial.print(F(" N2=")); Serial.println(cal2.n2);
      Serial.println();
    
      // 触发
      triggerCounter(ADDR_TEMP);
      triggerCounter(ADDR_PRESS);
      lastRead = millis();
    }
    
    void loop() {
      if (millis() - lastRead < GATE_TIME_MS) return;
      lastRead = millis();
    
      uint32_t pData = 0, tData = 0;
      uint8_t  pCsum = 0, tCsum = 0;
    
      if (!readCounterData(ADDR_PRESS, pData, pCsum, true) ||
          !readCounterData(ADDR_TEMP,  tData, tCsum, true)) {
        Serial.println(F("Read FAILED"));
        return;
      }
    
      float pressure = calcPressure(pData, tData);
      float tempF = calcTemperature(tData);
      float tempC = (tempF - 32.0) / 1.8;
    
      Serial.print(F("P="));
      Serial.print(pressure, 3);
      Serial.print(F(" psi   T="));
      Serial.print(tempC, 3);
      Serial.print(F(" C  ("));
      Serial.print(tempF, 3);
      Serial.println(F(" F)"));
    }
    
    // ============================================================
    // 压力计算:N1=3, N2=4
    // ============================================================
    
    float calcPressure(uint32_t Xp, uint32_t Xt) {
      float xpp = (float)Xp / 16777216.0f;  // 2^24
      float xtp = (float)Xt / 16777216.0f;
    
      float z = 0;
      for (int i = 0; i <= cal1.n1; i++) {
        z *= xpp;
        float temp = 0;
        for (int j = cal1.n2; j >= 0; j--) {
          temp *= xtp;
          temp += (float)cal1.C[i][j];
        }
        z += temp;
      }
      return z * cal1.S1;
    }
    
    // ============================================================
    // 温度计算:N1=0, N2=3
    // ============================================================
    
    float calcTemperature(uint32_t Xt) {
      float xtp = (float)Xt / 16777216.0f;
    
      float z = 0;
      for (int j = cal2.n2; j >= 0; j--) {
        z *= xtp;
        z += (float)cal2.C[j];
      }
    
      // 温度 °F = S2 * (OFS2 + Z)
      return cal2.S2 * (cal2.OFS2 + z);
    }
    
    // ============================================================
    // I2C 辅助函数
    // ============================================================
    
    bool triggerCounter(uint8_t addr) {
      if (Wire.requestFrom(addr, (uint8_t)1) != 1) return false;
      Wire.read();
      return true;
    }
    
    bool readCounterData(uint8_t addr, uint32_t &value, uint8_t &checksum, bool readChecksum) {
      uint8_t n = readChecksum ? 5 : 4;
      if (Wire.requestFrom(addr, n) != n) return false;
      uint8_t b[5];
      for (uint8_t i = 0; i < n; i++) b[i] = Wire.read();
      value = ((uint32_t)b[0] << 24) | ((uint32_t)b[1] << 16) |
              ((uint32_t)b[2] << 8)  | b[3];
      if (readChecksum) checksum = b[4];
      return true;
    }
    
    bool eepromReadSpecific(uint8_t addr, uint16_t memAddr, uint8_t *data, uint16_t len) {
      uint16_t offset = 0;
      while (offset < len) {
        uint16_t chunk = len - offset;
        if (chunk > 16) chunk = 16;
    
        Wire.beginTransmission(addr);
        Wire.write(((memAddr + offset) >> 8) & 0xFF);
        Wire.write((memAddr + offset) & 0xFF);
        if (Wire.endTransmission(false) != 0) return false;
    
        uint8_t n = Wire.requestFrom(addr, (uint8_t)chunk);
        if (n != chunk) return false;
    
        for (uint16_t i = 0; i < chunk; i++) data[offset + i] = Wire.read();
        offset += chunk;
      }
      return true;
    }
    
    float bytesToFloat(const uint8_t *p) {
      uint32_t v = ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) |
                   ((uint32_t)p[2] << 8)  | p[3];
      float f;
      memcpy(&f, &v, 4);
      return f;
    }
    
    int32_t bytesToInt32(const uint8_t *p) {
      return ((int32_t)p[0] << 24) | ((int32_t)p[1] << 16) |
             ((int32_t)p[2] << 8)  | p[3];
    }

    完整调用系数读出温度的。

    #1
  • admin

    下面为 上面的简版

    #2
  • admin
    #include <Wire.h>
    
    const uint8_t ADDR_PRESS  = 0x4E;
    const uint8_t ADDR_TEMP   = 0x4F;
    const uint8_t ADDR_EEPROM = 0x56;
    
    const uint16_t GATE_TIME_MS = 1000;
    
    // 压力:N1=3, N2=4
    float pressS1;
    int32_t pressC[4][5];
    
    // 温度:N1=0, N2=3
    float tempS2;
    int32_t tempOFS2;
    int32_t tempC[4];
    
    uint32_t lastRead = 0;
    
    void setup() {
      Serial.begin(115200);
      Wire.begin();
      Wire.setClock(100000);
      delay(1000);
    
      uint8_t buf[256];
      if (!eepromRead(ADDR_EEPROM, 0x0000, buf, 256)) {
        Serial.println(F("EEPROM read FAILED"));
        while (1);
      }
    
      // ---- 压力系数 ----
      pressS1 = bytesToFloat(&buf[0x1C]);
    
      int idx = 0x28;
      for (int i = 0; i <= 3; i++) {
        for (int j = 0; j <= 4; j++) {
          pressC[i][j] = bytesToInt32(&buf[idx]);
          idx += 4;
        }
      }
    
      // ---- 温度系数 ----
      tempS2   = bytesToFloat(&buf[0x94]);
      tempOFS2 = bytesToInt32(&buf[0x98]);
    
      idx = 0x9C;
      for (int j = 0; j <= 3; j++) {
        tempC[j] = bytesToInt32(&buf[idx]);
        idx += 4;
      }
    
      Serial.println(F("Coefficients loaded"));
    
      triggerCounter(ADDR_TEMP);
      triggerCounter(ADDR_PRESS);
      lastRead = millis();
    }
    
    void loop() {
      if (millis() - lastRead < GATE_TIME_MS) return;
      lastRead = millis();
    
      uint32_t pData, tData;
    
      if (!readCounter(ADDR_PRESS, pData) ||
          !readCounter(ADDR_TEMP,  tData)) {
        Serial.println(F("Read FAILED"));
        return;
      }
    
      float pressure = calcPressure(pData, tData);
      float tempF    = calcTemperature(tData);
      float tempC    = (tempF - 32.0f) / 1.8f;
    
      Serial.print(F("P="));
      Serial.print(pressure, 3);
      Serial.print(F(" psi   T="));
      Serial.print(tempC, 3);
      Serial.print(F(" C  ("));
      Serial.print(tempF, 3);
      Serial.println(F(" F)"));
    }
    
    // 压力:N1=3, N2=4
    float calcPressure(uint32_t Xp, uint32_t Xt) {
      float xpp = (float)Xp / 16777216.0f;
      float xtp = (float)Xt / 16777216.0f;
    
      float z = 0;
      for (int i = 0; i <= 3; i++) {
        z *= xpp;
        float temp = 0;
        for (int j = 4; j >= 0; j--) {
          temp *= xtp;
          temp += (float)pressC[i][j];
        }
        z += temp;
      }
      return z * pressS1;
    }
    
    // 温度:N1=0, N2=3
    float calcTemperature(uint32_t Xt) {
      float xtp = (float)Xt / 16777216.0f;
    
      float z = 0;
      for (int j = 3; j >= 0; j--) {
        z *= xtp;
        z += (float)tempC[j];
      }
    
      return tempS2 * (tempOFS2 + z);
    }
    
    // ---- I2C ----
    
    void triggerCounter(uint8_t addr) {
      Wire.requestFrom(addr, (uint8_t)1);
      Wire.read();
    }
    
    bool readCounter(uint8_t addr, uint32_t &value) {
      if (Wire.requestFrom(addr, (uint8_t)4) != 4) return false;
    
      uint8_t b[4];
      for (uint8_t i = 0; i < 4; i++) b[i] = Wire.read();
    
      value = ((uint32_t)b[0] << 24) |
              ((uint32_t)b[1] << 16) |
              ((uint32_t)b[2] << 8)  |
               (uint32_t)b[3];
      return true;
    }
    
    bool eepromRead(uint8_t addr, uint16_t memAddr, uint8_t *data, uint16_t len) {
      uint16_t offset = 0;
      while (offset < len) {
        uint16_t chunk = len - offset;
        if (chunk > 16) chunk = 16;
    
        Wire.beginTransmission(addr);
        Wire.write(((memAddr + offset) >> 8) & 0xFF);
        Wire.write((memAddr + offset) & 0xFF);
        if (Wire.endTransmission(false) != 0) return false;
    
        if (Wire.requestFrom(addr, (uint8_t)chunk) != chunk) return false;
    
        for (uint16_t i = 0; i < chunk; i++)
          data[offset + i] = Wire.read();
    
        offset += chunk;
      }
      return true;
    }
    
    float bytesToFloat(const uint8_t *p) {
      uint32_t v = ((uint32_t)p[0] << 24) |
                   ((uint32_t)p[1] << 16) |
                   ((uint32_t)p[2] << 8)  |
                    (uint32_t)p[3];
      float f;
      memcpy(&f, &v, 4);
      return f;
    }
    
    int32_t bytesToInt32(const uint8_t *p) {
      return ((int32_t)p[0] << 24) |
             ((int32_t)p[1] << 16) |
             ((int32_t)p[2] << 8)  |
              (int32_t)p[3];
    }
    #3

发表回复

登录后回复