- admin4小时前管理员1
#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); } }主楼 - admin4小时前管理员1
#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]; }完整调用系数读出温度的。
- admin2小时前管理员1
下面为 上面的简版
- admin2小时前管理员1
#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]; }