I2C Sensor (MLX90614) hangs program when disconnected

Basically looking to incorporate a MLX90614 (surface temp sensor) and a DS18S20 (ambient sensor) in a small arduino project. Fairly new to this (more of a hardware guy than software/programming) but the problem I'm running into is that the MLX90614 is not always going to be connected. If I disconnect this sensor while the program is running, the entire program hangs until the sensor is plugged back in. The program I found for the DS18S20 is able to generate an error value (-1000) when it is disconnected and I would like to generate a similar error code for the surface temp sensor so that the program will continue to provide ambient readings. I tried to incorporate the I2C scanner (Arduino Playground - I2cScanner) but was unable to (and seems like a bit of overkill for what I need). Any help will be greatly appreciated.

#include <i2cmaster.h>
#include <OneWire.h>

int DS18S20_Pin = 2; //DS18S20 Signal pin on digital 2

//Temperature chip i/o
OneWire ds(DS18S20_Pin); // on digital pin 2

void setup(void) {
Serial.begin(9600);
i2c_init(); // Initialise the i2c bus for the MLX90614
PORTC = (1 << PORTC4) | (1 << PORTC5); // enable pullups on MLX90614
}

void loop(void) {
char tmpsign_ambient;
char tmpsign_surface;
float ambient_temp = DS18S20();
float surface_temp = MLX90614();
if (ambient_temp < 0.0) {
tmpsign_ambient = '-';
}
else {
tmpsign_ambient = '+';
}
if (surface_temp < 0.0) {
tmpsign_surface = '-';
}
else {
tmpsign_surface = '+';
}

Serial.print(tmpsign_ambient);
Serial.print(ambient_temp,1);
Serial.print(",");
Serial.print(tmpsign_surface);
Serial.println(surface_temp,1);

delay(200);
}

float DS18S20(){
// returns the temperature from one DS18S20 in DEG Celsius

byte data[12];
byte addr[8];

if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return -1000;
}

if ( OneWire::crc8( addr, 7) != addr[7]) {
//Serial.println("CRC is not valid!");
return -1000;
}

if ( addr[0] != 0x10 && addr[0] != 0x28) {
//Serial.print("Device is not recognized");
return -1000;
}

ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end

byte present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad

for (int i = 0; i < 9; i++) { // we need 9 bytes
data = ds.read();

  • }*

  • ds.reset_search();*

  • byte MSB = data[1];*

  • byte LSB = data[0];*

  • float tempRead = ((MSB << 8) | LSB); //using two's compliment*

  • float TemperatureSum = tempRead / 2;*

  • return TemperatureSum;*
    }
    float MLX90614(){

  • int dev = 0x5A<<1;*

  • int data_low = 0;*

  • int data_high = 0;*

  • int pec = 0;*

  • 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;*

  • return celcius;*
    }

No code tags, no link to the used hardware and libraries. Did you read the sticky post at the top of the forum?

Your problem is probably the I2C emulation in software you're using, but I don't waste my time looking through some library code to find out that you're using some other library code in the end. Provide the necessary information!

The I2C scanner program is hardly overkill. The heart of the program is really just three lines long, and detects whether a device with a given address is present. That is exactly what you want.

   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("  !");
      }

I actually experimented with the scanner but ran into the issue where if the scanner is running it would negate the ability to read the temp (from my limited experience I would assume since the scanner is constantly scanning for the address). I have thought of simply getting it to run once but then still run into my original issue. I've also looked into using a different library for communicating with the sensor (https://github.com/felias-fogg/SoftI2CMaster/blob/master/SoftI2CMaster.h) that supposedly allows for a timeout when there is a failure to read a device via I2C. Admittely I'm a bit out of my element in trying to figure out this library so may simply experiment with solving the issue with the sensor electrically (with a switch) rather than through the software.

jremington:
The I2C scanner program is hardly overkill. The heart of the program is really just three lines long, and detects whether a device with a given address is present. That is exactly what you want.

   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("  !");
      }

Just incorporate the three lines that I excerpted (with appropriate modifications) into your program, and it will work if the device is detected, or skip the operation if not.

Get rid of the software I2C, use the hardware and the detection method jremington suggested.