Hello! I've been using Arduinos for hobby projects for a couple of years, but recently I've jumped off the deep end in trying to design something a bit complex for a work-related project. I'm designing an apparatus that will use two Arduinos (a Giga and a UNO R3) to power some lights, drive a couple of stepper motors, take temperature/light intensity/time readings (all of this on the Giga) and drive two Arducam OV5642s (Uno R3) at user-specified times to run some simple biology behavioral experiments. User-specified settings will be incorporated into the programming using the Giga display as well. I've figured out LVGL (for the most part) and have my Master (the Giga) sending messages to the Slave (Uno) reliably. I had hoped to be able to have the Slave send data to its Master when requested by Wire.requestFrom(), to get readings from a sensor that is not compatible with Giga architecture (Sparkfun Spectral Triad) and perhaps even to have the Arducams send a picture to the Giga display in order to allow focusing of the Arducams without needing a computer. Herein lies my problem.
No matter what I do, I have been unable to get reliable data transfer using Wire.requestFrom(). After 1-3 successful transfers the Master begins to receive noise. I've also noticed that this causes any other devices connected through SCL/SDA to also give garbage readings. I tried to reduce the code to the core functions required to transmit a reading from a sensor (Spectral Triad) on the Slave to the Master which has an RTC DS3231 connected to it. I've included the code for this simplified setup along with a fritzing diagram and screenshots of the resultant outputs on my Serial monitor. In my original code the Master will send a data request when a button on the screen is pressed, here the master requests data every 10 seconds, either way I get the same error. I also did already try putting pullup resistors (10k) on both SCL and SCA lines at both the Master and Slave sides of the connection and neither did anything. I also tried adding memset() to "clear" the char array in the Master before each new read, by replacing all data in the array with '0' and that also did not help. Any advice on how to fix this issue is appreciated! (Also, I know this project is overly complex for Arduino and I should just do it on Raspberry Pi, but I don't have the time or energy to learn Raspberry Pi right now and I already have all the Arduino components!) Thank you!
Master code:
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
DateTime now;
char msg[5];
void setup() {
Serial.begin(115200);
Wire.begin();
rtc.begin();
}
void loop() {
delay(10000);
now = rtc.now();
Wire.beginTransmission(4);
Wire.write(3);
Wire.endTransmission();
Wire.requestFrom(4, 5);
int i = 0;
while(Wire.available()){
char c = Wire.read();
delay(2);
if(c== '\0' || i == 4){
break;
}
msg[i] = c;
i++;
}
msg[i] = '\0';
Serial.println(msg);
Serial.println(now.hour());
}
Slave code:
#include "SparkFun_AS7265X.h"
AS7265X sensor;
#include <Wire.h>
int Controller;
float A;
const int LED_PIN = 13;
void setup() {
Serial.begin(115200);
Wire.begin(4);
pinMode(LED_PIN, OUTPUT);
Wire.onReceive(Doit);
while (sensor.begin() == false){
sensor.begin();
}
}
void loop() {
sensor.takeMeasurements();
A = sensor.getCalibratedA();
delay(100);
}
void Doit(int Press){
Controller = Wire.read();
if (Controller == 1){
digitalWrite(LED_PIN, HIGH);
}
if (Controller == 2){
digitalWrite(LED_PIN, LOW);
}
if (Controller == 3){
//delay(100);
Wire.onRequest(requestEvent);
}
}
void requestEvent(){
char buf[4];
dtostrf(A, 5, 2, buf);
static const int msgLength = sizeof(buf);
Wire.write(buf, (msgLength+1));
//Serial.println(A);
Serial.println(buf);
}
Fritzing diagram (shows a Mega because I couldn't find a Giga in the software):
Screenshot of outputs: (the master is supposed to print the hour and the data received - notice the hour becomes 165 after the received message becomes garbage):