I have an interesting problem when I try to send an int value over i2c from a master to a slave data-logger. I have a couple of functions that pass various messages in the form of a single byte to the data logger, and the logger uses String to write the appropriate message to an SD card for later retrieval and analysis. That part works fine. Now, I wish to also send an integer (2 byte) value to be displayed along with the message, and that's where I have the issue; I have to send the same message twice to record the correct value. The first iteration is ALWAYS wrong; it is either a zero, or it is the last value that was sent. It's like the Wire buffer is not being cleared for some reason.
This is the data logger (slave) code:
#include <SD.h>
#include <Wire.h>
#include <RTClib.h>
#include <SPI.h>
#define LOGGER_ADDRESS 118
#define chipSelect 10
#define cardDetect 8
//RTC_DS1307 rtc; //uncomment for old datalogger
RTC_PCF8523 rtc; //uncomment for new datalogger
File logFile;
byte loByte, hiByte;
volatile boolean eventFlag = false;
volatile boolean status = 0;
volatile byte event;
int intValue;
void setup ()
{
rtc.begin();
// rtc.adjust(DateTime(2019, 2, 10, 15, 12, 10));
Serial.begin(9600);
pinMode(chipSelect,OUTPUT);
pinMode(cardDetect, INPUT_PULLUP);
Wire.begin(LOGGER_ADDRESS);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
Serial.begin(9600);
SD.begin(chipSelect);
}
////////////////////////////////////////////////////////////////////////////////////
void receiveEvent(int howMany)
{
if(Wire.available() == 1)
{
event = Wire.read();
eventFlag = true;
}
if(Wire.available() == 2)
{
hiByte = Wire.read();
loByte = Wire.read();
intValue = word(hiByte,loByte);
eventFlag = true;
}
}
////////////////////////////////////////////////////////////////////////////////////
void requestEvent()
{
Wire.write(status);
}
////////////////////////////////////////////////////////////////////////////////////
void loop ()
{
if(digitalRead(cardDetect))
{
status = 0;
}
else status = 1;
if(eventFlag)
{
writeToSD(event);
eventFlag = false;
}
}
////////////////////////////////////////////////////////////////////////////////////
void writeToSD(byte event)
{
String dataString = "";
DateTime now = rtc.now();
dataString += String(now.year());
dataString += "/";
dataString += String(now.month());
dataString += "/";
dataString += String(now.day());
dataString += " ";
dataString += String(now.hour());
dataString += ":";
dataString += String(now.minute());
dataString += ":";
dataString += String(now.second());
dataString += " ";
switch (event){
case 97: //a
dataString += F("Data Logger test");
break;
case 100: //d
dataString += F("This is the first test");
dataString += F(" Sent value: ");
dataString += String(intValue);
break;
case 119: //w
dataString += F("This is the second test");
dataString += F(" Sent value: ");
dataString += String(intValue);
break;
}
logFile = SD.open("Log.txt",FILE_WRITE);
if(logFile)
{
logFile.println(dataString);
logFile.close();
status = 1;
}
else
status = 0;
}
And this is the master code:
#include <Wire.h>
#define LOGGER_ADDRESS 118
byte loByte, hiByte;
void setup() {
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(LOGGER_ADDRESS);
Wire.write(97);
if(Wire.endTransmission() != 0)
{
Serial.println("Logger not connected");
}
else Serial.println("Logger connected");
}
void loop() {
byte code;
byte r;
if(Serial.available())
{
code = Serial.read();
Serial.print("Code sent:");
Serial.println(code);
if(code == 'd')
{
Wire.beginTransmission(LOGGER_ADDRESS);
Wire.write(code);
Wire.endTransmission();
delay(10); // Changed this to 1 millisecond and now it works fine.
sendInt(500);
}
else if(code == 'w')
{
Wire.beginTransmission(LOGGER_ADDRESS);
Wire.write(code);
Wire.endTransmission();
delay(10); // Changed this to 1 millisecond and now it works fine.
sendInt(10000);
}
else
{
Wire.beginTransmission(LOGGER_ADDRESS);
Wire.write(code);
Wire.endTransmission();
delay(10);
}
Wire.requestFrom(LOGGER_ADDRESS,1);
while(Wire.available())
{
r = Wire.read();
}
if(r == 0)
{
Serial.println("Card removed");
}
else if(r == 1)
{
Serial.println("Logging successful");
}
}
}
//////////////////////////////////////////////////////
void sendInt(int valueToSend)
{
loByte = lowByte(valueToSend);
hiByte = highByte(valueToSend);
Wire.beginTransmission(LOGGER_ADDRESS);
Wire.write(byte(hiByte));
Wire.write(byte(loByte));
Wire.endTransmission();
Serial.print("Value:");
Serial.println(valueToSend);
}
This is the results on the serial monitor:
Logger connected
Code sent:97
Logging successful
Code sent:100
Value:500
Logging successful
Code sent:100
Value:500
Logging successful
Code sent:119
Value:10000
Logging successful
Code sent:119
Value:10000
Logging successful
This is the data written to the SD card:
2019/2/15 13:24:18 Data Logger test
2019/2/15 13:24:20 This is the first test Test value: 0
2019/2/15 13:24:20 This is the first test Test value: 500
2019/2/15 13:24:21 This is the second test Test value: 500
2019/2/15 13:24:22 This is the second test Test value: 10000
Note that the first test value should always be 500, and the second test value should always be 10000
It's most likely something stupid that I'm just not seeing. I have stared at it so long at this point that my mind is like a hamster in a wheel, going round and round. Thank you for any help you may offer!
Edit---made the changes Paul S suggested. Same issue, unfortunately.