Files
Dual-PID/I2C-Drucksensor Anleitung.txt
T
raw-designs 453644816f Initiale Bereitstellung
Initiale Bereitstellung der aktuellen Version auf Gitea
2026-07-10 18:13:43 +02:00

237 lines
7.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Deutsche Anleitung: I²C-Drucksensor an ESP32 (Arduino)
Basierend auf der Herstelleranleitung (siehe mitgeliefertes PDF).
============================================================
1) Überblick
============================================================
Der Sensor liefert kalibrierte digitale Messwerte über I²C:
- Druck als 24Bit ADC-Wert (signed) aus den Registern 0x06, 0x07, 0x08
- Temperatur als 16Bit Wert (signed) aus den Registern 0x09, 0x0A
- Messung wird über Register 0x30 gestartet; Fertig-Status über SCO-Bit (Bit 3) in 0x30
============================================================
2) Verdrahtung an ESP32 (WICHTIG: 3,3 V!)
============================================================
Kabelfarben → ESP32:
- Braun → 3V3 (Versorgung +)
- Blau → GND
- Weiß → SDA
- Schwarz→ SCL
Pull-Ups:
- Im Hersteller-Schaltbild sind 4,7 kΩ Pull-Ups eingezeichnet.
- Laut Text sind Pull-Ups bereits integriert → normalerweise keine zusätzlichen Pull-Ups nötig.
ESP32-Pins (Beispiel):
- SDA = GPIO 21
- SCL = GPIO 22
Du kannst andere I²C-fähige GPIOs nehmen und im Code Wire.begin(SDA, SCL) setzen.
============================================================
3) I²C-Adresse
============================================================
In der Hersteller-Bit-Tabelle ist A7..A1 = 1, danach W/R.
Das ergibt eine 7BitAdresse von 0x7F.
Hinweis:
0x7F ist im I²C-Standard „speziell“/reserviert. Manche I²CScanner finden ihn nicht.
Im Zweifel den Sensor trotzdem direkt mit 0x7F ansprechen (siehe Beispielcode).
============================================================
4) Messablauf (Register-Protokoll)
============================================================
1) Messung starten:
Schreibe 0x0A in Register 0x30 (Temp + Pressure acquisition)
2) Warten bis fertig:
Lies Register 0x30. Wenn SCO (Bit 3) = 0, ist die Messung fertig.
Alternativ kann man (laut Beispiel) ~50 ms warten.
3) Daten lesen:
Lies 0x06..0x0A in einem Rutsch (5 Bytes):
- 0x06,0x07,0x08: Druck (24-bit)
- 0x09,0x0A: Temperatur (16-bit)
============================================================
5) Umrechnung in Druck und Temperatur
============================================================
5.1 Druck (24Bit signed, Fullscale nötig)
Aus den drei Bytes:
- m = (x << 16) + (y << 8) + z (x=0x06, y=0x07, z=0x08)
Vorzeichenbehandlung:
- Wenn m > 2^23:
pressure = (m - 2^24) / 2^23 * Fullscale
- sonst:
pressure = m / 2^23 * Fullscale
WICHTIG:
Fullscale = Messbereich deines Sensors (z. B. 10 bar, 16 bar, 1.2 MPa, …)
Den musst du im Code passend setzen.
5.2 Temperatur (16Bit signed, Skalierung /256)
- n = (a << 8) + b (a=0x09, b=0x0A)
Vorzeichen & Skalierung:
- Wenn n > 2^15:
tempC = (n - 2^16) / 256
- sonst:
tempC = n / 256
============================================================
6) ESP32 Arduino-Beispielcode (Wire)
============================================================
WICHTIG: Setze FULLSCALE_BAR passend zu deinem Sensor!
```cpp
#include <Wire.h>
// --- I2C-Konfiguration ---
static constexpr uint8_t I2C_ADDR = 0x7F; // laut Hersteller-Tabelle (A7..A1 = 1)
static constexpr uint8_t REG_CMD = 0x30; // Command/Status Register
static constexpr uint8_t CMD_START = 0x0A; // Start: Temp + Pressure acquisition
// Datenregister
static constexpr uint8_t REG_DATA_START = 0x06; // 0x06..0x0A (5 Bytes)
// ESP32 Pins (anpassen falls nötig)
static constexpr int PIN_SDA = 21;
static constexpr int PIN_SCL = 22;
// --- Sensor-Messbereich (WICHTIG anpassen!) ---
static constexpr float FULLSCALE_BAR = 16.0f; // Beispiel: 16 bar Fullscale
// I2C: 1 Byte in Register schreiben
bool i2cWriteReg(uint8_t addr, uint8_t reg, uint8_t value) {
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.write(value);
return (Wire.endTransmission() == 0);
}
// I2C: 1 Byte aus Register lesen
bool i2cReadReg(uint8_t addr, uint8_t reg, uint8_t &value) {
Wire.beginTransmission(addr);
Wire.write(reg);
if (Wire.endTransmission(false) != 0) return false; // Repeated start
if (Wire.requestFrom((int)addr, 1) != 1) return false;
value = Wire.read();
return true;
}
// I2C: mehrere Bytes ab Startregister lesen
bool i2cReadBytes(uint8_t addr, uint8_t startReg, uint8_t *buf, size_t len) {
Wire.beginTransmission(addr);
Wire.write(startReg);
if (Wire.endTransmission(false) != 0) return false; // Repeated start
int got = Wire.requestFrom((int)addr, (int)len);
if (got != (int)len) return false;
for (size_t i = 0; i < len; i++) buf[i] = Wire.read();
return true;
}
// Umrechnung nach Herstellerformeln
float convertPressureBar(uint8_t b0, uint8_t b1, uint8_t b2) {
uint32_t m = ((uint32_t)b0 << 16) | ((uint32_t)b1 << 8) | (uint32_t)b2;
// Hersteller: wenn m > 2^23 => negativ, sonst positiv
// 2^23 = 8388608, 2^24 = 16777216
float ratio;
if (m > 8388608UL) {
ratio = ((int32_t)m - 16777216.0f) / 8388608.0f;
} else {
ratio = (float)m / 8388608.0f;
}
return ratio * FULLSCALE_BAR;
}
float convertTempC(uint8_t b0, uint8_t b1) {
uint16_t n = ((uint16_t)b0 << 8) | (uint16_t)b1;
// Hersteller: wenn n > 2^15 => negativ
// 2^15 = 32768, 2^16 = 65536, Skalierung /256
float t;
if (n > 32768U) {
t = ((int32_t)n - 65536.0f) / 256.0f;
} else {
t = (float)n / 256.0f;
}
return t;
}
bool readPressureAndTemp(float &pressureBar, float &tempC) {
// 1) Messung starten (0x0A nach 0x30)
if (!i2cWriteReg(I2C_ADDR, REG_CMD, CMD_START)) return false;
// 2) Fertig abfragen (SCO = Bit3). Alternativ könnte man fix 50ms warten.
// Wir machen: kurze Warte + Polling mit Timeout.
const uint32_t t0 = millis();
while (true) {
uint8_t st = 0;
if (!i2cReadReg(I2C_ADDR, REG_CMD, st)) return false;
bool scoBusy = (st & (1 << 3)) != 0; // SCO bit3
if (!scoBusy) break;
if (millis() - t0 > 100) return false; // Timeout 100ms
delay(5);
}
// 3) 5 Bytes lesen: 0x06..0x0A
uint8_t data[5];
if (!i2cReadBytes(I2C_ADDR, REG_DATA_START, data, sizeof(data))) return false;
pressureBar = convertPressureBar(data[0], data[1], data[2]);
tempC = convertTempC(data[3], data[4]);
return true;
}
void setup() {
Serial.begin(115200);
delay(200);
Wire.begin(PIN_SDA, PIN_SCL);
Wire.setClock(100000); // 100 kHz als solider Start
Serial.println("I2C Drucksensor Start");
}
void loop() {
float pBar, tC;
if (readPressureAndTemp(pBar, tC)) {
Serial.print("Druck [bar]: ");
Serial.print(pBar, 3);
Serial.print(" | Temp [C]: ");
Serial.println(tC, 2);
} else {
Serial.println("Sensor-Lesefehler (I2C/Timeout).");
}
delay(200);
}
```
============================================================
7) Typische Stolpersteine & Debug
============================================================
1) Spannung wirklich 3,3 V?
Der Hersteller zeigt 3,3 V im Wiring-Bild. 5 V können je nach Sensor/Board problematisch sein.
2) I²C-Adresse 0x7F „ungewöhnlich“
Wenn dein I²C-Scanner nichts findet: trotzdem den Sensor direkt mit 0x7F testen.
3) Kabelfarben prüfen
Braun=V+, Blau=GND, Weiß=SDA, Schwarz=SCL.
4) Messbereich (Fullscale) falsch → Druckwerte falsch skaliert
Beispiel: 16 bar statt 10 bar führt zu Faktor 1,6.
5) Lange Leitungen in der Maschine
Bei Aussetzern:
- I²C-Clock reduzieren (z. B. 50 kHz oder 10 kHz)
- SDA/GND und SCL/GND verdrillen
- saubere Masseführung
Ende.