I am currently researching on I2C, and I made a configuration that has MasterWriter that transmits data to a SlaveReceiver that will store the data received from Master, into an SD card, and then transmit the same line of data by GPRS onto my back end.
Now the new requirement needs some kind of a caching system, so that if the GPRS failed to transmit, it'll instead save into the SD card under a different filename (the previous step of saving into SD Card is still done but it's for another purpose), so when the GSM signal needed has recovered it'll read the cached/backed-up data, and then transmit the backed-up data. So that means I'll use the loop block (which currently only has one line of delay function).
My question is, will the triggered function "receiveEvent" registered in setup for Wire Slave :
Wire.onReceive(receiveEvent);
conflict with the ongoing loop block where the system reads the backed-up data and sends the backed-up data?
Here's my SlaveReceiver code :
#define ONLINE_MODE 1 // turn on for GSM.
#define CACHE_MODE 1 // turn on for SD-based caching
#define I2C_MODE 1 // turn on for I2C mode SDA-SCL
#include <Arduino.h>
#include "Slave_GSM_SD.h"
#if ONLINE_MODE
// Sim900
#include "GSM.h"
SIM900 gprs;
#endif
#if I2C_MODE
#include <Wire.h>
#endif
#if CACHE_MODE
//SD Card
#include <SPI.h>
#include <SD.h>
#define DEBUG_SD 1
#define SD_CS_PIN 4
File cacheFile;
#endif
void setup()
{
console.begin(9600);
while (!console);
#if CACHE_MODE
//SD Card
Serial.print(F("Initializing SD card..."));
if (!SD.begin(SD_CS_PIN)) {
Serial.println(F("initialization failed!"));
while (1);
}
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
cacheFile = SD.open("CACHE.txt", FILE_WRITE);
Serial.println(F("SD Card initialization done."));
#endif
#if ONLINE_MODE
gprsSetup();
#endif
#if I2C_MODE
Wire.begin(8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
#endif
console.println(F("SLAVE GSM SD READY"));
}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
// [Q] : will this interrupt/conflict with loop() if loop is still ongoing?
void receiveEvent(int howMany) {
#if DEBUG_I2C
Serial.print(F("available bytes : "));
Serial.print(howMany);
Serial.print(F(" or "));
Serial.println(Wire.available());
#endif
#if I2C_MODE
char jsonData[128]="";
while (Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
int len = strlen(jsonData);
jsonData[len] = c;
jsonData[len+1] = '\0';
#if DEBUG_I2C
Serial.print(c); // print the character
#endif
if (c == '}'){
#if CACHE_MODE
writeToSd(jsonData);
#endif
#if ONLINE_MODE
gprsSequence(jsonData);
#endif
#if DEBUG_I2C
Serial.println(F("SAVING TRIGGERED"));
Serial.println(jsonData);
#endif
}
}
#endif
}
void writeToSd(char *jsonToWrite){
#if CACHE_MODE
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
cacheFile = SD.open("CACHE.txt", FILE_WRITE);
if (cacheFile) {
cacheFile.write(jsonToWrite);
cacheFile.close();
}
#if DEBUG_SD
Serial.println(F(" << "));
// re-open the file for reading:
cacheFile = SD.open("CACHE.txt");
if (cacheFile) {
Serial.println("CACHE.txt:");
// read from the file until there's nothing else in it:
while (cacheFile.available()) {
Serial.write(cacheFile.read());
}
// close the file:
cacheFile.close();
} else {
// if the file didn't open, print an error:
Serial.println(F("error opening CACHE.txt"));
}
#endif
#endif
}
void loop() {
// i wanted to code the cached-data sending here
delay(2000);
}
void gprsSetup() {
//... cleared for brevity
}
void gprsSequence(char *jsonData) {
//... cleared for brevity. the point is, this function is to send the jsonData by GPRS
}