Best way to communicate with an Arduino?

I am currently using my electric imp breakout board with an arduino. I am communicating over serial (9600 baud - NewSoftSerial library on the arduino side) and it mostly works for me. When I need to send short strings (10 chars or less) everything gets communicated in a timely manner. However when I need to send more data (~300 chars) things start to break down. I do not receive all the data on the Arduino. Usually the first ~30 characters come through no problem, but at some point the data is corrupted. Below is the source code and general data flow of my app. I am not sure if I am following best practices. Logging from the imp indicates the data is all there, it is lost on route from imp to arduino. Any advice is appreciated. Let me know if any more info is needed.

General Dataflow

  • arduino sends “r” to imp over serial
  • imp receives this and sends “req” to agent
  • agent receives “req” and makes a web request
  • agent extracts needed info and sends a “res” to imp
  • imp communicates the contents of “res” over serial to arduino

Source Code

Agent
++++

`// Basic wrapper to create an execute an HTTP GET
function HttpGetWrapper (url, headers) {
local request = http.get(url, headers);
local response = request.sendsync();
return response;
}

function pollGithub(e) {
local url = “https://api.github.com/orgs/myorg/events?access_token=nope”;
local result = HttpGetWrapper(url, {});
local body = result[“body”];
local obj = http.jsondecode(body);

local to_send = "";
foreach(event in obj) {
    local actor = event["actor"]["login"];
    local type = event["type"];
    to_send += actor + "." + type + ",";
}

local actor = obj[obj.len()-1]["actor"]["login"];
device.send("res", to_send)

}

device.on(“req”, pollGithub)`

Imp
+++

`function readSerial() {
imp.sleep(0.1);
local result = hardware.uart57.read();
if (result == -1) {
server.show(“No data returned.”);
} else {
server.show("from arduino: " + result);
agent.send(“req”, result)
}

imp.wakeup(0.1, readSerial);

}

function printGithub(payload) {
server.log("payload: " + payload);
hardware.uart57.write(payload);
}

agent.on(“res”, printGithub);

hardware.uart57.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS);
server.log(“starting…”);
readSerial();`

Arduino
+++++

`//Adding the library for the software serial
#include <SoftwareSerial.h>
//defining the Pins for TX and RX serial communication
SoftwareSerial electricimpSerial = SoftwareSerial(9,10);

void setup() {
//open Arduino serial port so values are shown in the Arduino serial monitor
Serial.begin(9600);
//open software serial port so values can be passed on to the electric imp
electricimpSerial.begin(9600);
}
void loop() {
Serial.println(“about to send ‘r’”);
//Write information to electric imp
electricimpSerial.print(“r”);

String content = “”;
char character;

while(electricimpSerial.available() > 0) {
character = electricimpSerial.read();
content += character;
}

if (content != “”) {
Serial.println( content);
}

// Wait a bit
delay(5000);
}`

So, I think the problem is simply that the arduino software serial can’t keep up. When you are concatenating data to a string (with “content += character”), the arduino is doing more and more work as the string gets longer.

Try defining a fixed length array (eg “char buffer[300]”) and writing the received byte directly to this array (eg buffer[n]=electricimpSerial.read()).

Hi Hugo,

That did not seem to work. I think the problem is that the serial buffer is too small. When I chunked my data down to 60 bytes I was able to get error free transmission. Here is the imp and arduino code that works for me:

imp
+++

`local old_payload = “”;

function readSerial() {

local result = hardware.uart57.read();
if (result == 99) {  //"c" in ASCII
    server.log("chunk - " + result);
    server.log("calling sendNextChunk()")
    sendNextChunk();
} else if (result == 108) { //"l" in ASCII
    server.log("load - " + result);
    server.log("sending req to agent")
    agent.send("req", result);
}

imp.wakeup(0.1, readSerial);

}

function sendNextChunk() {
server.log(“sendNextChunk() called”);
local chunk_size = 60;
local to_send = “”;
if (old_payload.len() < chunk_size) {
to_send = old_payload;
old_payload = “”;
} else {
to_send = old_payload.slice(0, chunk_size);
old_payload = old_payload.slice(chunk_size);
}
server.log("to_send: " + to_send)
hardware.uart57.write(to_send);
}

function saveGithub(payload) {
server.log("payload: " + payload);
old_payload = “^” + payload + “$”;
}

agent.on(“res”, saveGithub);

hardware.uart57.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS);
server.log(“starting…”);
readSerial();`

Arduino
+++++
`
#include <SoftwareSerial.h>

//defining the Pins for TX and RX serial communication
SoftwareSerial electricimpSerial = SoftwareSerial(9,10);

char character;
String content;

void setup() {
Serial.begin(9600);
electricimpSerial.begin(9600);
electricimpSerial.print(“l”); //load giithub data
delay(500);
electricimpSerial.print(“c”); //prepare first chunk

}

void loop() {
while(electricimpSerial.available() > 0) {
character = electricimpSerial.read();
content += character;
}
if (character == ‘$’) {
electricimpSerial.print(“l”);
delay(500);
Serial.println(content);
content = “”;
}
electricimpSerial.print(“c”);
delay(500);
}`

You could confirm that this is what’s happening by calling Serial.overflow(). Seems like the buffer size they provide is 64 bytes so that’s close to what you’ve seen!

I know this is an old post, but for future reference you could try increasing the Arduino buffer size in HardwareSerial.cpp and SoftwareSerial.h