Hello!
I am an engineering teacher doing some diligence for a student project. In the final product, one master Arduino will be interfaced with 16 slave Arduinos. In preparation, I've started small and have one master Arduino controlling two slave Arduinos. The expectation is that the the master can send to the slaves and also request data from the slaves. It currently works ... but only twice. An image of the Serial Monitor is attached. It scans the bus successfully. It sends one String successfully, then asks for the next command. It send another String successfully then freezes and never gets to Serial.print("Command:");.
If I reset the master Arduino, it is able to send two more commands and will then lockup again. The slave is able to receive all of these without resetting so I am working on the premise that the problem is with the master
For the circuit, the Arduinos share the following connections: A4, A5, 5V, GND. A4 & A5 are pulled-up with 1.8k resistors.
Code for Master
#include <Wire.h>
#include <MySerial.h>
#include <MemoryFree.h>
MySerial mySerial;
void setup() {
Wire.begin(); // Start I2C Bus as Master
mySerial.begin();
//Serial.begin(9600);
}
void loop() {
Serial.print("Command:");
String response = mySerial.waitForRead();
Serial.println(response);
if(response == "send") sendFunction();
else if(response == "request") requestFunction();
else if(response == "scan") scanFunction();
else Serial.println("\"" + response + "\" is an unknown command. Try again.");
}
void sendFunction() {
Serial.print("Send to:");
String addressString = mySerial.waitForRead();
byte address = addressString.toInt();
Serial.print(address);
Serial.print(". Contents:");
String contentString = mySerial.waitForRead();
Serial.print("\"" + contentString + "\"");
// turn content into a char[] so it can be written using the Wire.write() function.
char contentChars[contentString.length()];
contentString.toCharArray(contentChars, contentString.length()+1);
Wire.beginTransmission(address);
Wire.write(contentChars);
int errorCheck = Wire.endTransmission();
if(errorCheck == 0) Serial.println("SUCESS!");
else Serial.println("ERROR");
}
String requestFunction() {
String responseContent = "";
Serial.print("Request From:");
String addressString = mySerial.waitForRead();
byte address = addressString.toInt();
Serial.print(address);
Serial.println(".");
Wire.requestFrom(address, (byte)1); // asks for the max request size
while(!Wire.available()) {
delay(50);
Serial.println("Wire Not Available!");
}
while(Wire.available()) {
char c = Wire.read();
responseContent.concat(c);
}
Serial.print("Just received from Address ");
Serial.print(address);
Serial.println(":" + responseContent);
}
Code for Slave
#include <Wire.h>
#include <MySerial.h>
MySerial mySerial;
byte address = 1;
char dataLog[][10] = {"Data1", "Data2", "Data3", "Data4"};
int logIndex = 0;
boolean complete;
boolean receiveFlag;
boolean requestFlag;
void setup() {
Wire.begin(address); // Start I2C Bus as a Slave
Wire.onReceive(receiveEvent); // register event
Wire.onRequest(requestEvent);
mySerial.begin();
//Serial.begin(9600);
Serial.println("SERIAL READY");
complete = false;
receiveFlag = false;
requestFlag = false;
}
void loop() {
if(receiveFlag) {
String content = "";
complete = false;
while(Wire.available()) {
char c = Wire.read();
content.concat(c);
}
complete = true;
receiveFlag = false;
Serial.println("Just Received: " + content);
}
else if(requestFlag) {
Serial.print("The Master has made a request. I responded with: ");
Serial.println("confirm");//dataLog[logIndex-1]);
requestFlag=false;
}
else delay(10);
}
void receiveEvent(int byteCount) {
receiveFlag=true;
}
void requestEvent() {
requestFlag = true;
Wire.write('Z');//dataLog[logIndex++]);
//requestFlag = true;
}
I have done a great deal of research on I2C and the accompanying problems. In my troubleshooting, I have:
- Shortened the connections to avoid capacitance problems (they're currently 6" jumpers).
- Optimized the pull-up resistors to battle capacitance.
- Tried to isolate USB power by providing an external 7V to Vin
- Monitored SRAM to see if I'm running out.
- Removed a lot of the Serial.println() commands
- Simplified it to a 1 slave, 1 master bus
The MySerial Library
/*
MySerial.cpp - Library for serial bus interactions.
Created by Scott Swaaley, October 13, 2013
Released into the public domain.
*/
#include "Arduino.h"
#include "MySerial.h"
MySerial::MySerial()
{
}
void MySerial::begin() {
Serial.begin(9600);
Serial.println("MySerial Setup Complete");
}
String MySerial::waitForRead()
{
String justRead = "";
boolean readComplete = false;
while(!readComplete) {
if(Serial.available()) {
while(Serial.available()) {
char ch = Serial.read();
justRead.concat(ch);
delay(5);
}
readComplete = true;
}
}
return justRead;
}
String MySerial::checkForRead()
{
String justRead = "";
if(Serial.available()) {
while(Serial.available()) {
char ch = Serial.read();
justRead.concat(ch);
delay(5);
}
}
return justRead;
}
My biggest confusion, however, stems from the fact that it initially works - then doesn't. Any advice?
Hardware: Arduino Uno R3. IDE 1.05.
COM7_SCREENSHOT.bmp (706 KB)