I2C Bus mit Arduino Nano und MCP3428 realisieren

Hi,

ich verzweifle zur Zeit an einem Uniprojekt...
Ich soll einen Lichtsensor und einen Temperatursensor mit einem MCP3428 verbinden und die Werte mit dem Nano als Master auslesen, nur leider wird mir im seriellen Monitor nichts angezeigt. Für das Register ist vorgegeben, dass die Verstärkung auf 1 und die Auflösung auf 16 Bit gesetzt wird und dass der MCP permament wandelt. Beim Aufbau bin ich mir zu 90% sicher, dass er richtig ist...beim Quellcode eher weniger :confused:
Vielleicht habt ihr ja eine Idee, wie ich das ganze doch noch zum Laufen bekomme :slight_smile:
(Die Funktionen ser_print_lux, stp() und luxmeter() wurden vom Prof erstellt)

VG
Kai

VersuchI2C_test.ino (1.51 KB)

Hast du einen I2C Scanner ausprobiert ob das IC überhaupt mal gefunden wird?

Das kann schon mal nicht stimmen:

  Wire.requestFrom(Addr, 3, stop);
  lx1 = Wire.read();
  lx2 = Wire.read();

Du empfängst 3 Bytes und liest nur 2 aus

Setze Deinen Code bitte direkt ins Forum. Benutze dazu Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

Hi,

  1. Hab gerade mal nen Scanner laufen lassen und er findet tatsächlich schon mal nichts...wobei ich nicht verstehe warum...den hab ich benutzt: A I2C Scanner for Arduino · GitHub

  2. Datenblatt ist hier nun verlinkt

  3. Ich bin grob nach diesem vorgegangen MCP3428/MCP3428.ino at master · ControlEverythingCommunity/MCP3428 · GitHub

Allerdings hab ich auch eine "Versuchsdurchführung" von der Uni, wo alles wieder anders erklärt ist...
Mich wundert es z.B. auch, dass wir 3 Bytes übertragen lassen sollen und dann in 2 Variablen speichern sollen.

Hab auch noch den Ausschnitt zur Durchführung aus meinen Projektunterlagen verlinkt.

ADC Datasheet.pdf (945 KB)

versuchsdurchfuhrung.pdf (55.5 KB)

Hier nochmal der Code:

#include <Wire.h>

// Die Adresse des MCP3428 sollte hier eingetragen werden.
const int Addr = 0x68;
const int lightReg = 0x2E;
const int tempReg = 0x2C;
boolean stop = true;
int lx1 = A4;
int lx2 = A4;

/*
  @fn setup(): hier werden Einmale Initialisierungen vorgenommen
*/
void setup() {
  Wire.begin();
  Serial.begin(9600);
 
  stp();
  Wire.beginTransmission(Addr);
  Wire.write(tempReg);
  Wire.endTransmission();
 
}

/*
  @fn loop():
    Die Inhalte dieser Funktion werden als Endlosschleife dauerhaft wiederholt
*/
void loop() {
  /* http://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf */
  Wire.beginTransmission(Addr);
  Wire.write(tempReg);
  Wire.endTransmission();
  Wire.requestFrom(Addr, 3, stop);
  lx1 = Wire.read();
  lx2 = Wire.read();
 
  Serial.println(lx1);
  Serial.println(lx2);
  ser_print_luxmeter(lx1, lx2);

  delay(1000);
}

void ser_print_luxmeter(int lx1,int lx2){
  lx1=lx1<<8;
  lx2=lx1+lx2;
  Serial.println(lx2);
}

void luxmeter(int lx1,int lx2){
  lx1=lx1<<8;
  lx2=lx1+lx2;
  //Serial.println(lx2);
  for(int i=0;i<8;i++){
    if(lx2<32767 - 4500*i){
      digitalWrite(5+i,1);
    }else{
      digitalWrite(5+i,0);
    }
  }
}

void stp(){
  long l=113000;
  Wire.begin(); //Keine Adresse, da Master
  //Wire.setClock(l);
  Serial.begin(9600);
  for(int i=5;i<13;i++){
    pinMode(i,OUTPUT);
    digitalWrite(i,HIGH);
    delay(100);
  }
  for(int i=5;i<13;i++){
 
    digitalWrite(i,LOW);
    delay(100);
  }
}

kaibarduno:

  1. Hab gerade mal nen Scanner laufen lassen und er findet tatsächlich schon mal nichts...wobei ich nicht verstehe warum...den hab ich benutzt: A I2C Scanner for Arduino · GitHub

Bei mir funktioniert der Scanner. Wenn der also bei Dir kein Ergebnis liefert, mußt Du zunächst den zugehörigen Fehler beseitigen. Da ich nicht auf Deinen Schreibtisch schauen kann, könnte ein Foto helfen.

Die Anleitung ist nicht ganz deutlich wie das abläuft.

Einerseits steht klar dort dass die Anzahl von read() mit der Nummer in requestFrom() übereinstimmen muss.

Andererseits steht da auch dass an Ende des Lesens endTransmission() kommt. Das ist falsch! Und ist im Code auch nicht vorhanden. endTransmission() sendet die Daten im Ausgangspuffer. requestFrom() ist nicht nur eine Anforderung wie man vielleicht denkt, sondern überträgt schon die Daten. read() entfernt diese lediglich aus dem Eingangspuffer

Wenn das IC gar nicht gefunden wird liegt aber vielleicht erst mal ein Hardware Problem vor. Hast du mal die Address-Pins auf Masse gelegt? Laut Datenblatt kann man die zwar glaube ich offen lassen, aber ein definierter Pegel schadet nichts.

Update: Der Scanner läuft jetzt und er gibt die Adresse 0x68 aus, die ja auch richtig wäre :slight_smile:
Daran kann es dann wohl schon mal nicht mehr liegen...

@noiasca das kann ich dir leider nicht sagen...hab es genau so gemacht wie beim ersten mal und nichts umgesteckt...

Erst einmal vielen Dank für die ganzen hilfreichen Antworten die schon kamen :slight_smile:
Habe nun noch ein kleines Update...

Ich habe den Quellcode etwas geändert und nun auch tatsächlich ein paar Werte im seriellen Monitor.
Allerdings kommt es mir sehr komisch vor, dass die Werte für den Lichtsensor bzw. den Tempsensor sich nicht ändern, wenn ich bspw. mit der Taschenlampe draufleuchte oder mal anhauche...

Außerdem weiß ich noch nicht wie ich im Quellcode hinterlege, dass er erst die Werte des Lichtsensors und dann die Werte des Tempsensors ausliest und printet. Im Moment mache ich immer entweder Temp oder Licht. Vielleicht habt ihr da ja noch eine Idee?

Im Anhang zwei Screenshots vom seriellen Monitor und hier der Quellcode:

#include <Wire.h>

// Die Adresse des MCP3428 sollte hier eingetragen werden.
const int Addr = 0x68;
const int lightReg = 0x78;
const int tempReg = 0x58;
boolean stop = true;
int lx1 = A4;
int lx2 = A4;

/*
  @fn setup(): hier werden Einmale Initialisierungen vorgenommen
*/
void setup() {
  Wire.begin();
  Serial.begin(9600);
  
  stp();
  Wire.beginTransmission(Addr);
  Wire.write(tempReg);
  Wire.endTransmission();
  
}

/*
  @fn loop():
    Die Inhalte dieser Funktion werden als Endlosschleife dauerhaft wiederholt
*/
void loop() {
  /* http://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf */
  Wire.beginTransmission(Addr);
  Wire.write(tempReg);
  Wire.requestFrom(Addr, 2, stop);
  lx1 = Wire.read();
  lx2 = Wire.read();
  
  Serial.print("lx1: ");
  Serial.println(lx1);
  Serial.print("lx2: ");
  Serial.println(lx2);
  Serial.print("ser_print_luxmeter: ");
  ser_print_luxmeter(lx1, lx2);

  delay(1000);
}

void ser_print_luxmeter(int lx1,int lx2){
  lx1=lx1<<8;
  lx2=lx1+lx2;
  Serial.println(lx2);
}

void luxmeter(int lx1,int lx2){
  lx1=lx1<<8;
  lx2=lx1+lx2;
  //Serial.println(lx2);
  for(int i=0;i<8;i++){
    if(lx2<32767 - 4500*i){
      digitalWrite(5+i,1);
    }else{
      digitalWrite(5+i,0);
    }
  }
}

void stp(){
  long l=113000;
  Wire.begin(); //Keine Adresse, da Master
  //Wire.setClock(l);
  Serial.begin(9600);
  for(int i=5;i<13;i++){
    pinMode(i,OUTPUT);
    digitalWrite(i,HIGH);
    delay(100);
  }
  for(int i=5;i<13;i++){
  
    digitalWrite(i,LOW);
    delay(100);
  }
}

  Wire.beginTransmission(Addr);
  Wire.write(tempReg);
  Wire.requestFrom(Addr, 2, stop);

Da hast du mich falsch verstanden. Nach dem write() muss ein endTransmission() stehen. Sonst wird da nichts gesendet. Es gehört nur nicht nach requestFrom().
Das Problem ist hier einfach das die Methoden leicht falsche und verwirrende Namen haben

So ist es richtig:

  Wire.beginTransmission(Addr);
  Wire.write(tempReg);
  Wire.endTransmission();
  Wire.requestFrom(Addr, 2, stop);
  lx1 = Wire.read();
  lx2 = Wire.read();

Dein Code war da schon anfangs richtig. Lediglich im Handout war es falsch beschrieben

Um unterschiedliche Register auszulesen musst du halt vor dem Empfangen eine andere Register-Nummer senden

@Serenify Wieso muss ich denn im Setup anfangs schon das Register festlegen, wenn ich das dann in der Loop nochmal mit Wire.write bestimme? Und meinst du mit deinem letzten Satz, dass ich in der Loop einfach noch die Transmission beginne und dann aber Wire.write(lightReg) nehme?

Hi,

wo ist Dein CH3+ abhanden gekommen?

Gruß André

Hi André,

was müsste da denn ran? Dachte, da der Tempsensor nur einen Output hat reicht es, wenn ich den an 3- stecke.

LG

Naja, den CH3- auf GND legen, und den CH3+ an den Sensor würde ich sagen.
Im Datenblatt gibt es doch schöne Beispiele ...

Gruß André