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
}
user3704293
  • 471
  • 7
  • 19
user3060854
  • 600
  • 4
  • 9
  • 20

2 Answers2

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

Nick Gammon
  • 38,901
  • 13
  • 69
  • 125
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.

AMADANON Inc.
  • 2,383
  • 10
  • 9