Mehrere Melexis 90614 IR Thermosensoren an Arduino betreiben

Hallo Community,

ich habe aktuell mehrere Melexis 90614 IR Sensoren "hier rum liegen". Ich muss für ein Projekt > 4 Stück auf einmal auslesen. Es gibt dabei mehrere Probleme aber der Reihe nach:

1) Wenn ich mir im Internet sämtliche Schaltpläne angucke, verwenden alle zwei Pullup-Widerstände zwischen V+ und SDA & SCL. (http://bildr.org/2011/02/mlx90614-arduino/). Wenn ich dies so betreibe, dann erhalte ich einen fehlerhaften Wert von 1037°C. Entferne ich den Pullup am SCL, so erhalte ich den korrekten Temperaturwert. Warum ist dies so, bzw warum kann so ein Phänomen auftreten? Ich verstehe nicht, warum sämtliche Tutorials diesen zweiten Pullup (wohl auch mit Erfolg) einsetzen, dies aber bei mir absolut nicht funktioniert.

2) Wenn ich mehrere IR-Sensoren anschließe und verdrahte, muss man zunächst die I2C-adresse von jedem Sensor ändern, dies habe ich auch erfolgreich geschafft, sodass ich nun die Sensoren parallel auslesen kann. Jedoch stürzt der Arduino nach einer Zeit X ab. Mal kann ich 1000+ Datensätze auslesen, mal nur 14 oder weniger.

Meine Frage ist nun, hat hier jemand Erfahrung mit dem Betreiben meherer Melexis IR-Sensoren und hatte die gleichen oder ähnlichen Probleme? Verdrahtet wurde das ganze u.A. nach diesem Tutorial http://www.chrisramsay.co.uk/posts/2014/09/arduino-and-multiple-mlx90614-sensors/

Besten Gruß und vielen Dank!

napster1989:
ich habe aktuell mehrere Melexis 90614 IR Sensoren “hier rum liegen”. Ich muss für ein Projekt > 4 Stück auf einmal auslesen.

Verwendest du die Sensoren “nackt” oder auf einer fertigen Platine?

  1. Wenn ich mir im Internet sämtliche Schaltpläne angucke, verwenden alle zwei Pullup-Widerstände zwischen V+ und SDA & SCL. (bildr Is it hot? Arduino + MLX90614 IR Thermometer - bildr). Wenn ich dies so betreibe, dann erhalte ich einen fehlerhaften Wert von 1037°C. Entferne ich den Pullup am SCL, so erhalte ich den korrekten Temperaturwert. Warum ist dies so, bzw warum kann so ein Phänomen auftreten? Ich verstehe nicht, warum sämtliche Tutorials diesen zweiten Pullup (wohl auch mit Erfolg) einsetzen, dies aber bei mir absolut nicht funktioniert.

I2C ist ein Bussystem und benötigt diese Widerstände zur Terminierung.

Wie groß hast du diese gewählt?

Und du benötigst nur an einem Sensor diese Widerstände, bzw. nur am Arduino !

  1. Wenn ich mehrere IR-Sensoren anschließe und verdrahte, muss man zunächst die I2C-adresse von jedem Sensor ändern, dies habe ich auch erfolgreich geschafft, sodass ich nun die Sensoren parallel auslesen kann. Jedoch stürzt der Arduino nach einer Zeit X ab. Mal kann ich 1000+ Datensätze auslesen, mal nur 14 oder weniger.

Hierzu solltest du den Sketch posten.
Bitte in Code-Tags setzen. Schaltfläche </> oben links im Editorfenster.

I2C braucht die Widerstände nicht zur Terminierung sondern damit ein HIGH Level zustandkommt, da die einzelnen Devices die Busleitungen nur auf Masse ziehen können (Open Collektor bzw Open Drain Ausgang)

Der I2C Bus funktioniert nicht wenn die Pullupwiderstande zu hoch sind (relativ zur Leitungslänge und Anzahl der Devices) oder wenn diese zu niederohmig sind.

@napster1989
Welchen Widerstandswert hast Du verwendet?

Du kannst mehrere Melexis 90614 am I2C anschließen wenn sie verschiedene Adressen haben bzw wenn die Adresse einstellbar ist.

Grüße Uwe

Hi,

also nachdem Umadressieren habe ich den Beispielcode aus der Melexis bibliothek genommen.
Die Widerstände haben 4,7K. Ich habe die Sensoren nackt auf einer Steckplatine (wie im Link) angebunden. Die Sache ist ja, einzeln und auch beide kann ich mit nur EINEM Widerstand auslesen - klappt wunderbar. Sobald der 2. Pullup dazu kommt (Zwischen V+ und SCL) dann kommt kein Wert, bzw nur 1037°C … Warum funktioniert sowas dann mit einem Pullup?

Der Code ist folgender:

/*************************************************** 
  This is a library example for the MLX90614 Temp Sensor

  Designed specifically to work with the MLX90614 sensors in the
  adafruit shop
  ----> https://www.adafruit.com/products/1748
  ----> https://www.adafruit.com/products/1749

  These sensors use I2C to communicate, 2 pins are required to  
  interface
  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include <Wire.h>
#include <Adafruit_MLX90614.h>

Adafruit_MLX90614 mlx = Adafruit_MLX90614(0x5B); //Jeweils die definierte, neue Adresse...
Adafruit_MLX90614 mlx2 = Adafruit_MLX90614(0x5C);

void setup() {
  Serial.begin(9600);

  Serial.println("Adafruit MLX90614 test");  

  mlx.begin();  
}

void loop() {
  
  Serial.print("*C\tObject = "); Serial.print(mlx.readObjectTempC()); Serial.println("*C");
 
Serial.print("*C\tObject = "); Serial.print(mlx2.readObjectTempC()); Serial.println("*C");

  Serial.println();
  delay(500);
}

Manchmal läuft der Code “gut”, manchmal wie gesagt stürzt der Sketch ab, sprich die letzte Konsolenausgabe ist teilweise soetwas wie “Obj” oder “O” … also mitten in der Ausgabe bleibt alles hängen.
Wie klein kann ich die Pullups dimensionieren? würde 3,3K Sinn machen?

Besten Gruß

Eine Erklärung für das Verhalten mit den Pullup-Widerständen habe ich nicht, außer es ist ein zu kleiner Wert. Für das fehlerhafte Sketchverhalten könnte ein Kontaktfehler im Steckbrett schuld sein.

Hallo,
vielleicht fehlt noch ein mlx2.begin(); und ein kleines delay zwischen beiden Ausgaben schadet erst mal auch nicht.

/***************************************************
  This is a library example for the MLX90614 Temp Sensor

  Designed specifically to work with the MLX90614 sensors in the
  adafruit shop
  ----> https://www.adafruit.com/products/1748
  ----> https://www.adafruit.com/products/1749

  These sensors use I2C to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include <Wire.h>
#include <Adafruit_MLX90614.h>

Adafruit_MLX90614 mlx = Adafruit_MLX90614(0x5B); //Jeweils die definierte, neue Adresse...
Adafruit_MLX90614 mlx2 = Adafruit_MLX90614(0x5C);

void setup() {
  Serial.begin(9600);

  Serial.println("Adafruit MLX90614 test");

  mlx.begin();
  mlx2.begin();
}

void loop() {

  Serial.print("*C\tObject = "); Serial.print(mlx.readObjectTempC()); Serial.println("*C");
  delay(10);
  Serial.print("*C\tObject = "); Serial.print(mlx2.readObjectTempC()); Serial.println("*C");

  Serial.println();
  delay(500);
}

Ansonsten gibt es die MLXen mit 3,3V und 5V Versorgungsspannung. Die darfst du natürlich an einem Bus nicht mischen und musst auch die für deine Sensoren passende Spannung an VCC und die Pullup-Widerstände anschließen.

Gruß Peter

Welches Board wird überhaupt verwendet?
Manche Boards haben die Pullups schon fertig drauf.

combie: Welches Board wird überhaupt verwendet?

Wie in Post #3 wird nur ein Steckbrett verwendet. Da können natürlich auch viele Fehler auftreten.

Wire meldet Fehler, wenn diese auftreten. Die genannte Lib wertet diese Fehler nicht aus.

Tipp: Fehler werden nicht schöner oder besser, wenn man die Meldungen ignoriert.

Wurde bereits erwähnt, aber hast du darauf geachtet, ob deine Sensoren für 5 Volt geeignet sind.

Wenn nicht, benötigst du 3,3 Volt und Levelshifter für die Datenleitungen.

HotSystems: Wie in Post #3 wird nur ein Steckbrett verwendet. Da können natürlich auch viele Fehler auftreten.

Da steht, dass die Sensoren auf einem Steckbett stecken. Vom Arduino sehe ich da nichts.

Und ja, Steckbrettwackler usw.. Immer wieder gerne genommen

combie: Da steht, dass die Sensoren auf einem Steckbett stecken. Vom Arduino sehe ich da nichts.

Und ja, Steckbrettwackler usw.. Immer wieder gerne genommen

Stimmt, ohne Arduino kann es nicht funktionieren.

Hi und sorry für die späte Rückmeldung.

Also verwendet wird ein Arduino Uno R3.
Ich habe nun die Schaltung auf eine Streifenrasterplatine aufgelötet und es gibt einen Erfolg zu vermelden, es geht erst einmal!

Die Standard-library funktioniert aber meiner Meinung nach nicht! Mit dem folgenden, alternativen Quellcode kann ich aktuell 4 Sensoren gleichzeitig auslesen, ABER der Sketch funktioniert nur, nachdem ich den frisch hochgeladen habe und dann den seriellen Monitor anzeige.

->>> Trenne und verbinde ich die Stromverbindung vom Arduino und öffne dann erneut den seriellen Monitor, bleibt das Sketch in der Setuproutine hängen :confused: Any ideas?

Ich vermute mal, dass die Sensoren irgendwie noch ein paar Informationen gesetzt haben, die ggf. resettet werden müss(t)en?

Zu den Pullups: Das habe ich noch nicht ganz verstanden, im Sketch werden diese ja aktiviert, brauche ich die dann nicht mehr in meiner Schaltung zu verbauen? Das wäre ja optimal bis ideal!

/**
 * Two Infrared Thermometers MLX906114
 * by Jaime Patarroyo
 * based on 'Is it hot? Arduino + MLX90614 IR Thermometer' by bildr.blog
 * 
 * Returns the temperature in Celcius and Fahrenheit from two MLX90614 
 * Infrared Thermometers, connected to the TWI/I²C pins (on the Wiring v1 
 * board 0 (SCL) and 1 (SDA) and on Wiring S board 8 (SCL) and 9 (SDA)).
 */

#include <i2cmaster.h>

int device1Address = 0x5B<<1;   // 0x50 is the assigned address for I²C 
                                // communication for sensor 1.
                                // Shift the address 1 bit right, the 
                                // I²Cmaster library only needs the 7 most 
                                // significant bits for the address.
int device2Address = 0x5C<<1;   // 0x55 is the assigned address for I²C 
int device3Address = 0x5D<<1;                                // communication for sensor 2.
int device4Address = 0x5A<<1;                                // Shift the address 1 bit right, the 
                                // I²Cmaster library only needs the 7 most 
                                // significant bits for the address.

float celcius1 = 0;             // Variable to hold temperature in Celcius

float celcius2 = 0;             // Variable to hold temperature in Celcius
float celcius3 = 0; 
float celcius4 = 0; 
void setup()
{
  Serial.begin(9600);           // Start serial communication at 9600bps.
  Serial.print("Initialisierung...");
  i2c_init();   
 delay(500);  // Initialise the i2c bus.
  PORTC = (1 << PORTC4) | (1 << PORTC5);    // Enable pullups.
  delay(2000);
}

void loop()
{
  celcius1 = temperatureCelcius(device1Address);
  celcius2 = temperatureCelcius(device2Address);
  celcius3 = temperatureCelcius(device3Address);                                             
  celcius4 = temperatureCelcius(device4Address);                                    
 

  Serial.print("Sensor 1: Celcius: ");  
  Serial.print(celcius1);             

  Serial.print("Sensor 2: Celcius: ");
  Serial.print(celcius2);
   Serial.print("Sensor 3: Celcius: ");
  Serial.print(celcius3);
  Serial.print("Sensor 4: Celcius: ");
  Serial.print(celcius4);
  Serial.println("");
Serial.println(millis());
  delay(150);                         // Wait a second before printing again.
}

float temperatureCelcius(int address) {
  int dev = address;
  int data_low = 0;
  int data_high = 0;
  int pec = 0;

  // Write
  i2c_start_wait(dev+I2C_WRITE);
  i2c_write(0x07);

  // Read
  i2c_rep_start(dev+I2C_READ);
  data_low = i2c_readAck();       // Read 1 byte and then send ack.
  data_high = i2c_readAck();      // Read 1 byte and then send ack.
  pec = i2c_readNak();
  i2c_stop();

  // This converts high and low bytes together and processes temperature, 
  // MSB is a error bit and is ignored for temps.
  double tempFactor = 0.02;       // 0.02 degrees per LSB (measurement 
                                  // resolution of the MLX90614).
  double tempData = 0x0000;       // Zero out the data
  int frac;                       // Data past the decimal point


  // This masks off the error bit of the high byte, then moves it left 
  // 8 bits and adds the low byte.
  tempData = (double)(((data_high & 0x007F) << 8) + data_low);
  tempData = (tempData * tempFactor)-0.01;
  float celcius = tempData - 273.15;
  
  // Returns temperature un Celcius.
  return celcius;
}

Also ich habe nun alles getestet. Der Stand ist wie folgt:

Ich lade das Sketch hoch und klicke auf die Konsole: Sensoren können ausgelesen werden! Nach dem drücken der Reset-taste: Sensoren können ausgelesen werden! Nach dem Unterbrechen der Stromversorgung (durchaus realer Fall): Sensoren können nicht ausgelesen werden!

Das Programm bleibt an der Stelle stehene, wo die Funktion "temperatureCelcius" aufgerufen wird.

Hat von euch schon jemand dieses Problem gehabt? Ich vermute, dass dort tatsächlich irgendwelche Bytes im EEPROM(?) geleert werden müssen?

Vielen Dank euch schon einmal für weitere Anregungen ... :)

Aber zu der Anmerkung "Betriebsspannung der Sensoren" hast du dich bisher nicht geäußert.

5V

Ich verwende dazu 2 x 4,7k Pullups (die internen werden nicht verwendet)

Grüße