I am communicating two arduinos using the I2C protocol and sending from the slave to the master the integer value of UTC to update the time in the RTC module. When the master receives the UTC value from I2C and tries to set the time by the RTC.set () command the Arduino hangs and needs to be restarted, however, if I use RTC.set () in the loop () method it works perfectly. I do not understand why the system for when it is updated by I2c, is there any conflict?
This is the code with the loop()
and Wire.onReceive()
:
#include <Thread.h>
#include <ThreadController.h>
#include <SoftwareSerial.h>
#include <LinkedList.h>
#include <SPI.h>
#include <TimeLib.h>
#include <DS3232RTC.h>
#include <Wire.h>
void setup() {
Serial.begin(9600);
Wire.begin(1);
Wire.onReceive(receiveEvent);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
setSyncProvider(RTC.get);
if (timeStatus() != timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
}
void loop() {
digitalClockDisplay();
delay(2000);
// test only
/*time_t t = processUTCFromI2c("1560810413");
if (t != 0) {
RTC.set(t); // it's works
setTime(t);
}*/
}
// ================================ INIT ONRECEIVE ===========================================
void receiveEvent(int howMany) {
char* vectorAction;
char c;
Serial.println(howMany);
LinkedList<char> myLinkedList = LinkedList<char>();
//while (1 < Wire.available()) { // loop through all but the last
for (int i = 0; i < howMany; i++){
c = Wire.read(); // receive byte as a character
myLinkedList.add(c);
}
vectorAction = new char[myLinkedList.size()+1];
for(int i=0; i < myLinkedList.size(); i++) {
vectorAction[i] = myLinkedList.get(i);
}
vectorAction[myLinkedList.size()] = '\0';
getParamsAndValues(vectorAction);
}
void getParamsAndValues(char* i2cValueString) {
char* getValue;
char* getParam;
char* endValue;
getValue = strchr (i2cValueString, '=');
getParam = strchr (i2cValueString, '@');
endValue = strchr (i2cValueString, '#');
const size_t maxBuffLength = 15;
char valueBuffer[maxBuffLength+1]; // allocate local buffer with space for trailing null char
char paramBuffer[maxBuffLength+1];
valueBuffer[0] = '\0';
while(getValue && getParam && endValue && (getValue > getParam) && (endValue > getValue)) {
Serial.println(i2cValueString);
if (getValue && getParam && (getValue > getParam)) {
size_t paramLength = getValue-getParam-1;
valueBuffer[0] = '\0';
if (paramLength <= maxBuffLength) {
strncpy(paramBuffer, getParam+1, paramLength);// http://www.cplusplus.com/reference/cstring/strncpy/
paramBuffer[paramLength] = '\0'; // properly terminate the c-string
}
} else {
// handle Wrong Input
}
if (getValue && endValue && (endValue > getValue)) {
size_t valueLength = endValue-getValue-1;
valueBuffer[0] = '\0';
if (valueLength <= maxBuffLength) {
strncpy(valueBuffer, getValue+1, valueLength);// http://www.cplusplus.com/reference/cstring/strncpy/
valueBuffer[valueLength] = '\0'; // properly terminate the c-string
} else {
// handle buffer too small
}
} else {
// handle Wrong Input
}
getValue = strchr (getValue+1, '=');
getParam = strchr (getParam+1, '@');
endValue = strchr (endValue+1, '#');
i2cActionReceived(paramBuffer, valueBuffer);
}
}
void i2cActionReceived(char* param, char* value) {
if(strcmp(param, "setTime") == 0) {
time_t t = processUTCFromI2c(value);
if (t != 0) {
RTC.set(t); // It's not works
setTime(t);
}
}
}
// ================================ END ONRECEIVE ===========================================
// ================================ CONVERT UTC char* TO long ===============================
unsigned long processUTCFromI2c(char* utc) {
unsigned long auxTime = 0L;
if (strlen(utc)>0) {
auxTime = atol(utc);
}
return auxTime;
}
The slave sends a string through I2C in the format @setTime=1560810413#
.
In the loop()
this commented the code that works onorata and on i2cActionReceived (char* param, char* value)
is where the update fails by onReceive.
"1560810413"
... in the second instance you use a parameter in a function