Auslesen SI7210 via I²C

Hallo zusammen,

ich habe Schwierigkeiten den Magnetsensor SI7210 mit dem ESP32 via I²C auszulesen.
Es scheint zu funktionieren das Register der ChipID auszulesen, allerdings erhalte ich bei den Registern für die mag. Feldstärke immer nur eine 0 als Ergebnis.

Es handelt sich bei dem IC um den SI7210. Das Datenblatt ist hier zu finden:
https://www.mouser.de/datasheet/2/368/si7210_datasheet-1128712.pdf

Hat evtl. jemand eine Idee woran es liegen könnte?

#include <Wire.h>

#define SI7210_REG_ADDR_HREVID 0xC0
#define SI7210_REG_ADDR_DSPSIGM 0xC1
#define SI7210_REG_ADDR_DSPSIGL 0xC2
#define SI7210_REG_ADDR_DSPSIGSEL 0xC3
#define SI7210_REG_ADDR_POWER_CTRL 0xC4
#define SI7210_REG_ADDR_ARAUTOINC 0xC5
#define SI7210_REG_ADDR_CTRL1 0xC6
#define SI7210_REG_ADDR_CTRL2 0xC7
#define SI7210_REG_ADDR_SLTIME 0xC8
#define SI7210_REG_ADDR_CTRL3 0xC9
#define SI7210_REG_ADDR_A0 0xCA
#define SI7210_REG_ADDR_A1 0xCB
#define SI7210_REG_ADDR_A2 0xCC
#define SI7210_REG_ADDR_CTRL4 0xCD
#define SI7210_REG_ADDR_A3 0xCE
#define SI7210_REG_ADDR_A4 0xCF
#define SI7210_REG_ADDR_A5 0xD0
#define SI7210_REG_ADDR_OTP_ADDR 0xE1
#define SI7210_REG_ADDR_OTP_DATA 0xE2
#define SI7210_REG_ADDR_OTP_CTRL 0xE3
#define SI7210_REG_ADDR_TM_FG 0xE4

#define SLAVEWRT 0x33

void setup() {
  Wire.begin();
  Serial.begin(115200);

  byte error, address;
  for (address = 1; address < 127; address++) {  //I2C Scanner, IC gefunden auf 0x33
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.print(address, HEX);
      Serial.println("  !");
    }
  }

  Wire.beginTransmission(SLAVEWRT);
  Wire.write((byte)SI7210_REG_ADDR_HREVID);  // ChipID auslesen
  Wire.endTransmission();

  byte data;
  Wire.requestFrom(SLAVEWRT, 1);  // 1 byte von 0x33 lesen
  for (int i = 0; Wire.available(); i++) {
    data = Wire.read() >> 4;
  }
  Serial.print("ChipID: ");  //ChipID ist 1
  Serial.println(data, DEC);
  delay(4);
}


void loop() {
  int32_t field;
  float result;
  float scale = 204.7f;
  uint8_t data[1];


  Wire.beginTransmission(SLAVEWRT);
  Wire.write((byte)SI7210_REG_ADDR_DSPSIGM);  // DSPSIGM REGISTER
  Wire.endTransmission();

  byte daten;
  Wire.requestFrom(SLAVEWRT, 1);  // 1 byte von 0x33 lesen
  for (int i = 0; Wire.available(); i++) {
    //data[i] = Wire.read();
    daten = Wire.read();
  }
  //Serial.println(daten);

  delay(4);
  //field = (((uint16_t)data[0]) & 0x7F) << 8;


  Wire.beginTransmission(SLAVEWRT);
  Wire.write((byte)SI7210_REG_ADDR_DSPSIGL);  // DSPSIGL REGISTER
  Wire.endTransmission();

  Wire.requestFrom(SLAVEWRT, 1);  // 1 byte von 0x33 lesen
  for (int i = 0; Wire.available(); i++) {
    //data[i] = Wire.read();
    daten = Wire.read();
  }

  //Serial.println(daten);

  //field |= data;
  //field -= 16384;

  //result = ((float)field) * scale / 16384;

  //Serial.println(result);
  delay(4);
}

Laut Datenblatt wird eine "Repeated Start Condition" erwartet.
Bzw. "restart" in der Arduino Wire Doku
Das tust du nicht, du sendest STOP!

Danke schonmal für den Tipp!
Leider werde ich nicht ganz schlau daraus, ich hatte bei

Wire.endTransmission(false)
Wire.requestFrom(SLAVEWRT, 1, false); 

false schonmal als Parameter genutzt um einen restart zu senden, aber ohne Erfolg.

Oder meinst du etwas anderes?

Ja, wenn du danach lesen möchtest, ist das richtig.

Das dürfte falsch sein, wenn du nur 1 Register auslesen willst.

Beispiel: (gilt natülich für alle diese Vorgänge)


  Wire.beginTransmission(SLAVEWRT);
  Wire.write((byte)SI7210_REG_ADDR_DSPSIGM);  // DSPSIGM REGISTER
  Wire.endTransmission(false);

  byte daten;
  Wire.requestFrom(SLAVEWRT, 1,true);  // 1 byte von 0x33 lesen
  for (int i = 0; Wire.available(); i++) {
    //data[i] = Wire.read();
    daten = Wire.read();
  }
  //Serial.println(daten);

Sind deine Pullup OK?

Wird das Ding gefunden?

Ich gebe Dir mal einen Auszug aus meinem SerialMonitor:

I2C device found at address 0x33  !
ChipID: 1
0
0
0
0

Meine Pull-ups (4k7) sind in Ordnung, gerade nochmal durchgemessen.

Mit Deinem Code erhalte ich auch eine "0" als Ergebnis.

Wire.beginTransmission(SLAVEWRT);
  Wire.write((byte)SI7210_REG_ADDR_DSPSIGM);  // DSPSIGM REGISTER
  Wire.endTransmission(false);

  byte daten;
  Wire.requestFrom(SLAVEWRT, 1,true);  // 1 byte von 0x33 lesen
  for (int i = 0; Wire.available(); i++) {
    //data[i] = Wire.read();
    daten = Wire.read();
  }
  Serial.println(daten);

  delay(4);

Tja....
Was würde ich jetzt tun?

  1. Die Rückgabe von Wire.endTransmission prüfen
  2. Die Rückgabe von Wire.requestFrom prüfen
  3. Mit einem Oszi die Pegel prüfen
  4. Mit einem Logik Analyser die Daten prüfen
  5. Einen anderen Sensor
  1. "0" dürfte ja korrekt sein
  2. "1" ebenso

Joa, mit einem Oszi kann ich nochmal dran.. weiß nur nicht wie viel Erkenntnis mir das bringen wird. Da der Sensor recht günstig ist, hatte ich gehofft diesen verwenden zu können, aber im Notfall müsste ein anderer her, ja..

Danke dir für deine Hilfe. Vielleicht gibt es ja noch jemand anderen der uns erleuchtet.

Wenn die Signalform "Scheiße" ist, kommt nicht das an, was der Sensor dir sagen will.

Ok, ich habe mir die Signale angesehen (Gelb Clock, Blau SDA)

Die Flanken sind zwar nicht supersteil, aber das Signal sah recht sauber aus. Es sollte reichen denke ich.. meine Erfahrung ist da aber auch recht gering. Was sagst Du?

Sieht mehr als ausreichend aus.
Ist also OK.

Wenn der Sensor OK ist, kann nur noch was mit dem sleep, wakeup, und starten der Messung sein.
Also ein logischer Fehler im Protokoll.
Ein Bedienerfehler.

Vielleicht solltest du mal alle Register auslesen, um zu schauen, was da so drin steht.

Beispiel:

The most significant bit is a “fresh” bit indicating the
register has been updated since last read

Wenn das nicht gesetzt ist, sind auch keine frischen Daten zu erwarten.

ich bin durch Zufall auf eine erstellte Library gestoßen mit der es möglich ist den si7210 auszulesen und zu parametrieren.
Zu finden hier:

http://www.harald-sattler.de/html/quickmill_saver.htm

Ist getestet und funktioniert.

Danke für die Hilfe!

Hier der direkte Link innerhalb der länglichen Seite

Harry