2

I have two Arduino boards and I want to make them communicate via I2C. The first board (slave) should read a temperature value from a DS18B20 sensor (OneWire) and send it to the second board (master) via I2C.

So, I tried to merge some code from the standard examples (Wire/master_reader, Wire/slave_sender and dallas/simple).

When I use the two sketches bellow, the serial monitor of the master board is printing the "hello " message, but when I enable the request temperature lines (slave code)

sensors.requestTemperatures();
sensors.getTempCByIndex(0);

the serial monitor shows nothing.

I wander if there is a conflict between OneWire and I2C, or if I've made some serious mistakes in the code.

Any suggestions would be appreciated.

Master

#include <Wire.h>

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

void loop(){
    Wire.requestFrom(2, 6);    
    while(Wire.available()){ 
        char c = Wire.read();
        Serial.print(c);     
        }
    delay(500);
   }

Slave

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup(){
    sensors.begin();
    Wire.begin(2);                
    Wire.onRequest(requestEvent); 
 }

void loop(){
}

void requestEvent(){

    //sensors.requestTemperatures();
    //sensors.getTempCByIndex(0);

    Wire.write("hello "); // respond with message of 6 bytes
}
  • The only thing I see in OneWire.cpp that could maybe cause a conflict, is the use of noInterrupts() -- OneWire has these timing-critical sections where the interrupts have to be disabled, and maybe that's conflicting with the I2C slave. What if you swap the master and slave roles, so the Master manages the OneWire interface (thus avoiding possible conflict with I2C slave listener), and let the Slave device echo to serial monitor? – MarkU May 12 '15 at 5:33
  • Indeed, when the master manages the OneWire, it seems to work OK . Nevertheless, I need to collect temperature data from two or more stations (slaves) and send them to central (master), so if slave cannot manage OneWire, that would be a problem. Thank you anyway. – user3060854 May 12 '15 at 8:12
1

The OneWire stuff can be quite slow. I think I timed doing a temperature read at 12.5 mS which is a long time to be in an ISR. I think you will find that the master assumes it is going to get no response and times out, in that time.

1-Wire Peripheral Interface - for Arduino

What I suggest you do, is get the temperature in the slave, as often as you want, and then just return the temperature when requested. eg.

volatile float lastTemp;

void loop(){
  sensors.requestTemperatures();
  float t = sensors.getTempCByIndex(0);
  // protect move of 4 bytes
  noInterrupts ();
  lastTemp = t;
  interrupts ();
}

void requestEvent(){
  Wire.write ((char *) lastTemp, sizeof lastTemp);
}

Untested, but that is the general idea.

Documentation about interrrupts, and why I am turning off interrupts when moving the temperature to a global variable: http://www.gammon.com.au/interrupts

1

If there is a conflict, could the slave switch between i2c and one wire?

I don't know how often your device needs to poll, but if you can get away with, say, once per minute, you could poll at regular intervals, and spend the rest of the time (99%) listening for the master. If it is not polled, the number read could be queued. When the master does manage to connect, it could collect the entire queue quickly.

The master, from it's side, could poll more frequently - say once every 53 seconds. About once or twice an hour, it would fail - it would need to handle that gracefully. No matter, it would get the data next time round. Even failing several times in a row wouldn't be a problem; the data would be queued at the slave for later transfer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.