Hello, this is my first post here, I am no expert with arduino/coding but I am studying mechatronics engineering and I have this project where I am sending temperature information to a master Arduino uno through another slave Arduino uno via I2C using the Wire library. The temperature sensor I am using is DS18B20 which uses one wire so I am using Teensy's OneWire library OneWire Arduino Library, connecting 1-wire devices (DS18S20, etc) to Teensy and also milesurton's Dallas Temperature library GitHub - milesburton/Arduino-Temperature-Control-Library: Arduino Temperature Library. In addition to this I have a motion sensor HC-SR501 that which outputs a high when detecting motion and I use as an interrupt in pin 2 to turn on a LED on pin 13 for 10 seconds.
I started by placing the temperature measurements in my slave inside void loop () as you can see below in my code and it went very well, my master prints the slave number and the temperature measurement received by the slave every 5 seconds, it works properly and also my motion sensor interruption works fine.
This is what I get in my console:
MASTER READER NODE
Maximum Slave Nodes: 6
Payload size: 5
1
25.13
1
25.13
1
25.13
Then I realised I only wanted to measure the temperature when asked by the master, which is why I thought putting all measurement code inside the requestEvent handle would be a good idea. However when I place my measurement code inside the requestEvent handle I don't get the correct temperature information sent to my master, some information gets sent at the beginning 3-4 random numbers and then it stops. And not only that, also my motion sensor interrupt gets stuck. It looks as if all code went wrong when doing this. This leads me to think the problem is mainly in the slave's code, since both the temperature measurements and motion interrupt stop working properly. Maybe master nad slave get desynchronized or something?
This is what I get in my console:
MASTER READER NODE
Maximum Slave Nodes: 6
Payload size: 5
135
0.00
97
0.00
0
nan
I am thinking maybe it's just that I can't be much time inside my requestEvent handle and that's why it works when the temperature measurement is done outside of it, but maybe I am missing something else and it is possible to do the measurement inside the handle? This is my starting point on the project and I want to do the measurement only when requested because the end goal is to save as much energy as possible (I will be implementing power management in the near future using a solar panel and a battery, and some other tricks I learned in other sites to reduce power consumption in arduino. I need to measure temperature just once per hour but I am printing every 5 seconds now so that I can check it is working). I'd appreciate if someone could advise me on this. Maybe I am using the wrong approach to my problem.
Thanks in advance!
Master
#include <Wire.h>
#define PAYLOAD_SIZE 5 // how many bytes to expect from each I2C salve node
#define NODE_MAX 6 // maximum number of slave nodes (I2C addresses) to probe
#define START_NODE 1 // The starting I2C address of slave nodes
#define NODE_READ_DELAY 5000 // Some delay between I2C node reads
typedef union
{
float number;
byte bytes[3];
} FLOATUNION_t;
FLOATUNION_t myFloat;
int nodePayload[PAYLOAD_SIZE];
void setup()
{
Serial.begin(9600);
Serial.println("MASTER READER NODE");
Serial.print("Maximum Slave Nodes: ");
Serial.println(NODE_MAX);
Serial.print("Payload size: ");
Serial.println(PAYLOAD_SIZE);
Serial.println("***********************");
Wire.begin(); // Activate I2C link
}
void loop()
{
for (int nodeAddress = START_NODE; nodeAddress <= NODE_MAX; nodeAddress++) { // we are starting from Node address 2
Wire.requestFrom(nodeAddress, PAYLOAD_SIZE); // request data from node#
if(Wire.available() == PAYLOAD_SIZE) { // if data size is avaliable from nodes
for (int i = 0; i < PAYLOAD_SIZE; i++) nodePayload[i] = Wire.read(); // get nodes data
for (int j = 0; j < PAYLOAD_SIZE; j++)
myFloat.bytes[0] = nodePayload[1];
myFloat.bytes[1] = nodePayload[2];
myFloat.bytes[2] = nodePayload[3];
myFloat.bytes[3] = nodePayload[4];
Serial.println(nodePayload[0]);
Serial.println(myFloat.number);
Serial.println("*************************");
}
}
delay(NODE_READ_DELAY);
}
Slave with temperature measurement inside void loop () working fine
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <elapsedMillis.h>
#define ONE_WIRE_BUS 7 // Data wire is plugged into pin 7 on the Arduino
#define NODE_ADDRESS 1 // Change this unique address for each I2C slave node
#define PAYLOAD_SIZE 5 // Number of bytes expected to be received by the master I2C node
typedef union
{
float number;
byte bytes[3];
} FLOATUNION_t;
FLOATUNION_t myFloat;
byte nodePayload[PAYLOAD_SIZE];
// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;
elapsedMillis move_begin;
void setup()
{
Serial.begin(9600);
Serial.println("SLAVE SENDER NODE");
Serial.print("Node address: ");
Serial.println(NODE_ADDRESS);
Serial.print("Payload size: ");
Serial.println(PAYLOAD_SIZE);
Serial.println("***********************");
// Start up the library
sensors.begin();
Wire.begin(NODE_ADDRESS); // Activate I2C network
Wire.onRequest(requestEvent); // Request attention of master node
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, RISING);
}
void loop()
{
sensors.requestTemperatures(); // Send the command to get temperatures
myFloat.number = sensors.getTempCByIndex(0);
nodePayload[0] = NODE_ADDRESS;
nodePayload[1] = myFloat.bytes[0];
nodePayload[2] = myFloat.bytes[1];
nodePayload[3] = myFloat.bytes[2];
nodePayload[4] = myFloat.bytes[3];
if (move_begin >= 10000) {
digitalWrite(ledPin, 0);
}
}
void requestEvent()
{
Wire.write(nodePayload,PAYLOAD_SIZE);
}
void blink() {
if (digitalRead(2)==1)
move_begin = 0;
state = HIGH;
digitalWrite(ledPin, state);
}
Slave with temperature measurement inside requestEvent handle, not sending the correct information to the master
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <elapsedMillis.h>
#define ONE_WIRE_BUS 7 // Data wire is plugged into pin 7 on the Arduino
#define NODE_ADDRESS 1 // Change this unique address for each I2C slave node
#define PAYLOAD_SIZE 5 // Number of bytes expected to be received by the master I2C node
typedef union
{
float number;
byte bytes[3];
} FLOATUNION_t;
FLOATUNION_t myFloat;
byte nodePayload[PAYLOAD_SIZE];
// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;
elapsedMillis move_begin;
void setup()
{
Serial.begin(9600);
Serial.println("SLAVE SENDER NODE");
Serial.print("Node address: ");
Serial.println(NODE_ADDRESS);
Serial.print("Payload size: ");
Serial.println(PAYLOAD_SIZE);
Serial.println("***********************");
// Start up the library
sensors.begin();
Wire.begin(NODE_ADDRESS); // Activate I2C network
Wire.onRequest(requestEvent); // Request attention of master node
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, RISING);
}
void loop()
{
if (move_begin >= 10000) {
digitalWrite(ledPin, 0);
}
}
void requestEvent()
{
sensors.requestTemperatures(); // Send the command to get temperatures
myFloat.number = sensors.getTempCByIndex(0);
nodePayload[0] = NODE_ADDRESS;
nodePayload[1] = myFloat.bytes[0];
nodePayload[2] = myFloat.bytes[1];
nodePayload[3] = myFloat.bytes[2];
nodePayload[4] = myFloat.bytes[3];
Wire.write(nodePayload,PAYLOAD_SIZE);
}
void blink() {
if (digitalRead(2)==1)
move_begin = 0;
state = HIGH;
digitalWrite(ledPin, state);
}