Erbitte Hilfe, i2C-Code für andere Lib übersetzen bitte ...

Kann mir bitte jemand den folgenden Code, der mit Wire ein Kompass-Chip ausliest, von der Syntax von "wire" zu "SlowSoftI2CMaster" übertragen? Start, Stop, Write ist kein Problem, aber das Auslesen der 6 Register im unteren Teil der Methode (s. Kommentar) get_hmc() will mir nicht gelingen ... Danke für Hinweise!

#include <Wire.h>

int  hmc_adr = 0x1E;
byte hmc_mode = 0x02;
byte hmc_cont = 0x00;
byte hmc_regb = 0x01;
byte hmc_gain = 0xE0;
byte hmc_out = 0x03;

float res = 0;

void setup()
{
  Serial.begin(9600); //start Serial mit 9600 bis/s
}

void loop()
{
  res = get_hmc(A4,A5);
  Serial.print("HMC:"); Serial.println(res);
  delay(500);
}

int get_hmc(int dat, int clk)
{
  int  hmc_addr = 0x1E;
  byte hmc_mode = 0x02;
  byte hmc_cont = 0x00;
  byte hmc_regb = 0x01;
  byte hmc_gain = 0xE0;
  byte hmc_out =  0x03; 

  int x,y,z; // 3 Achsen

  Wire.begin();
  Wire.beginTransmission(hmc_addr); // Verbindung öffnen mit dem HMC5883
  Wire.write(hmc_mode); // Mode Register
  Wire.write(hmc_cont);   // Kontinuierliche Messung
  Wire.endTransmission();
  Wire.beginTransmission(hmc_addr); // Verbindung öffnen mit dem HMC5883
  Wire.write(hmc_regb); // Mode Register
  Wire.write(hmc_gain);   // Empfindlichkeit auf 8 Gauss
  Wire.endTransmission();
  Wire.beginTransmission(hmc_addr);
  Wire.write(hmc_out); // Register 3, X MSB Register, Lesemodus
  Wire.endTransmission();
  Wire.requestFrom(hmc_addr, 6);

  //====================== ab hier komme ich mit SlowSofti2c nichtmehr weiter ...
  x = Wire.read()<<8;  x |= Wire.read();
  z = Wire.read()<<8;  z |= Wire.read();
  y = Wire.read()<<8;  y |= Wire.read();
  
  Wire.endTransmission();
  
  float w = atan2(-y , x) / M_PI * 180.0; if(w < 0){w = w + 360.0;}
  return w; 
}

SlowSoftI2CMaster.zip (15.7 KB)

Hallo,

ich habe das einmal mit meiner RTC DS3231 probiert und es klappt soweit.

#include <SlowSoftI2CMaster.h>

SlowSoftI2CMaster rtc = SlowSoftI2CMaster(20, 21, true);
const byte I2C_7BITADDR {0x68}; // I2C Adresse der RTC ist 0x68 für DS1307 und DS3231
const byte startAddr {0x00};

void setup(void)
{
  Serial.begin(250000); 
  Serial.println(F("Intializing ..."));
  if (!rtc.i2c_init()) 
    Serial.println(F("Initialization error. SDA or SCL are low"));
  else
    Serial.println(F("...done"));
}

void loop(void)
{
  if (!rtc.i2c_start((I2C_7BITADDR<<1)|I2C_WRITE))
  {
    Serial.println("I2C device busy");
    return;
  }
 
  rtc.i2c_write(startAddr);
  rtc.i2c_rep_start((I2C_7BITADDR<<1)|I2C_READ);
  byte ss = bcdToDec(rtc.i2c_read(false) & 0x7F);    // Maske für die ersten 7 Bits alleine
  byte mm = bcdToDec(rtc.i2c_read(false) );
  byte hh = bcdToDec(rtc.i2c_read(true) & 0x3F);    // Umschaltung auf 24h statt 12h (AM/PM)
  rtc.i2c_stop();
  Serial.print(hh); Serial.print(':');
  Serial.print(mm); Serial.print(':');
  Serial.println(ss);
  delay(2000);
}

byte bcdToDec(byte val)  // convert binary coded decimal to decimal number
{
  return ( (val/16*10) + (val%16) );
}

Du benötigst eine Startadresse ab der das auslesen beginnt.

Die Reihenfolge ist immer.
Device ansprechen damit es weiß das man etwas von ihm will.
Startadresse des Registers übertragen ab der man in dem Fall auslesen möchte.
Hintereinander die Register auslesen.
Übertragung beenden.

Bei der Lib darfste demnach, laut Test, nur beim letzten read 'true' mitgeben.
Das könnte bei dir so funktionieren.
Ggf. Startaddresse und Pinnummern ändern!

#include <SlowSoftI2CMaster.h>

SlowSoftI2CMaster kompass = SlowSoftI2CMaster(20, 21, true);

const byte startAddr {0x03};

struct KompassDaten
{
  const byte addr {0x1E}; // I2C Adresse 
  int x; // 3 Achsen
  int y; 
  int z; 
};
KompassDaten hmc;


void setup(void)
{
  Serial.begin(250000); 
  Serial.println(F("Intializing ..."));
  if (!kompass.i2c_init()) 
    Serial.println(F("Initialization error. SDA or SCL are low"));
  else
    Serial.println(F("...done"));
}

void loop(void)
{
  if (!kompass.i2c_start((hmc.addr<<1)|I2C_WRITE))
  {
    Serial.println("I2C device busy");
    return;
  }
 
  kompass.i2c_write(startAddr);
  kompass.i2c_rep_start((hmc.addr<<1)|I2C_READ);
  hmc.x  = kompass.i2c_read(false) << 8;
  hmc.x |= kompass.i2c_read(false);
  hmc.z  = kompass.i2c_read(false) << 8;
  hmc.z |= kompass.i2c_read(false);
  hmc.y  = kompass.i2c_read(false) << 8;
  hmc.y |= kompass.i2c_read(true);
  kompass.i2c_stop();
  Serial.print(hmc.x); Serial.print('\t');
  Serial.print(hmc.z); Serial.print('\t');
  Serial.println(hmc.y);
  delay(2000);
}

Nach requestFrom() kommt übrigens in der Wire Bibliothek kein endTransmission(). Das ist leider schlecht benannt, aber es sendet die Daten die im Ausgangspuffer stehen

Hallo,

versuch mal, hatte gerade Lust ...
Adressen und Pins ggf. abändern.

// https://forum.arduino.cc/index.php?topic=734225.0

#include <SlowSoftI2CMaster.h>

SlowSoftI2CMaster kompass = SlowSoftI2CMaster(20, 21, true);

const byte startAddr {0x03};

struct KompassDaten
{
  const byte addrDevice   {0x1E}; // I2C Adresse 
  const byte addrRegMode  {0x02};
  const byte modeContinue {0x00};
  const byte addrRegB     {0x01};
  const byte setGain      {0xE0};
  const byte addrRegOut   {0x03};
  int x; // 3 Achsen
  int y; 
  int z; 
};
KompassDaten hmc;


void setup(void)
{
  Serial.begin(9600); 
  Serial.println(F("Intializing ..."));
  if (!kompass.i2c_init()) 
    Serial.println(F("Initialization error. SDA or SCL are low"));
  else
    Serial.println(F("...done"));

  initKompass();  
}

void loop(void)
{
  leseAchsen();
  delay(2000);
}

void initKompass (void)
{
  bool error {true};
  if (!kompass.i2c_start((hmc.addrDevice<<1)|I2C_WRITE)) { error = false; }
  if (!kompass.i2c_write( hmc.addrRegMode))  { error = false; } // Registeradresse
  if (!kompass.i2c_write( hmc.modeContinue)) { error = false; } // Wert in diese Adresse
  kompass.i2c_stop(); // ob hier notwendig weiß ich nicht genau
  
  if (!kompass.i2c_start((hmc.addrDevice<<1)|I2C_WRITE)) { error = false; }
  if (!kompass.i2c_write( hmc.addrRegB)) { error = false; } // Registeradresse
  if (!kompass.i2c_write( hmc.setGain))  { error = false; } // Wert in diese Adresse
  kompass.i2c_stop();
  
  Serial.println(F("stop done"));
  if (!error) Serial.println(F("init Error!"));
}

void leseAchsen (void)
{
  if (!kompass.i2c_start((hmc.addrDevice<<1)|I2C_WRITE))
  {
    Serial.println("I2C device busy");
  }
  else
  {
    kompass.i2c_write(hmc.addrRegOut);  // Addresse korrekt?
    kompass.i2c_rep_start((hmc.addrDevice<<1)|I2C_READ);
    hmc.x  = kompass.i2c_read(false) << 8;
    hmc.x |= kompass.i2c_read(false);
    hmc.z  = kompass.i2c_read(false) << 8;
    hmc.z |= kompass.i2c_read(false);
    hmc.y  = kompass.i2c_read(false) << 8;
    hmc.y |= kompass.i2c_read(true);
    kompass.i2c_stop();
    Serial.print(hmc.x); Serial.print('\t');
    Serial.print(hmc.z); Serial.print('\t');
    Serial.println(hmc.y);  
  }
}

Erstmal herzlichen Dank, ich komme aber erst am Montag dazu, den Code zu testen. Dass mich niemand für undankbar hält ... :slight_smile: :slight_smile: :slight_smile:

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.