The Arduino and Spark Core communicate fine most of the time but I noticed at some point the Arduino is not able to send messages to the Spark Core. The Arduino can still receive the messages from the Spark Core just fine though. I don’t understand what could cause an issue with the UART even though the code is simple.
In this case, I have a push button connected to an Arduino, whenever a user presses it, it sends ‘High’ to the Spark Core which turns on an LED, and when they let go it sends ‘Low’ to turn off the led. Can someone help me understand why sometimes the UART freeze up or something?
How do I detect the issue and fix it?
Arduino Code:
#define buttonPin 7
int buttonState = 0; // variable for reading the pushbutton status
int sendonce = 0;
void setup() {
Serial.begin(9600);
// Serial.print("BEGIN\n");
}
void loop() {
isButtonPressed();
}
void isButtonPressed () {
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {
if (sendonce == 0)
{
Serial.print("High\n");
// ser.write('1');
sendonce = 1;
}
}
else if (buttonState == LOW && sendonce == 1) {
sendonce = 0;
Serial.print("Low\n");
}
}
Spark Core Code:
#include "Serial2/Serial2.h"
// name the pins
int led1 = D7;
int led2 = D1;
String txtMsg = "";
char s;
char lightStatus[20] ;
// This routine runs only once upon reset
void setup()
{
// Configure the pins to be outputs
pinMode(led1, OUTPUT);
// Initialize both the LEDs to be OFF
digitalWrite(led1, LOW);
//Serial1.begin(9600);
Serial2.begin(9600);
//Serial2.println("Hello From Spark");
}
// This routine loops forever
void loop()
{
while (Serial2.available() > 0) {
s=(char)Serial2.read();
if (s == '\n') {
if(txtMsg=="High") {
digitalWrite(led1, 1);
strcpy(lightStatus, "Light On");
}
if(txtMsg=="Low") {
digitalWrite(led1, 0);
strcpy(lightStatus, "Light Off");
}
// Serial.println(txtMsg);
txtMsg = "";
} else {
txtMsg +=s;
}
}
}
Just to be on the save side, could you add some debounce in your Arduino code to avoid flooding the out buffer of the Arduino or the in buffer of the Core, ending up with truncated/misaligned messages?
Another suggestion might be to not use String for your txtMsg.
As I take it from your int led2 = D1; you’ve got an LED on the Core’s Serial2 TX pin, could you also add one to D0 to see any RX activity?
And how does it behave? If it stops doing anything you Arduino stalls, if it still works but the Core doesn’t respond your Core code needs fixing.
@ammar, to add to what @ScruffR said, doing a pinMode() and digitalWrite() on the Serial2 pins will be overridden by the Serial2.begin() command. Is the LED connected via a current limiting resistor to GND? I also agree with @ScruffR that not using Strings is a good approach since they have a tendency to fragment memory.
I had adapted a cool Arduino serial command parser for the Core that you might want to look at here.
How do you add a debounce? There is no LED on D1, I am using the built in LED on D7. By the way I am connecting 7 sensors to the Arduino, I think my problem is related to voltage. If I connect just three sensors, everything works fine but I add more I get inconsistent behavior.
The easiest would be to add a delay(100); at the end of your isButtonPressed() function.
But there are more sophisticated ways to do that too - e.g. here clickButton library - Libraries - Particle
@ammar, perhaps you can share which sensors and how they are connected and powered so we can give guidance. And you are correct on the LED on D1 which we misread.
I note that you are eventually trying to send seven channels.
To simplify the code you could transmit a single character to represent the on/off command, for instance ‘A’ or ‘B’ for channel 1. You would not need a string to receive the stream of characters from Serial2, which would help memory management.
I’ve not tried any of this but I would look at something along these lines:
void loop()
{
while (Serial2.available() > 0) {
s=(char)Serial2.read();
if (s == 'A') {
digitalWrite(led1, 1);
} else if (s == 'B') {
digitalWrite(led1, 0);
}
// extend the if clause, using C/D, E/F, G/H, etc to control channels 2,3,4, etc
}
}
In your Arduino code, I think you need a variable per channel that holds its current state (on/off) and only send the ‘A’ or ‘B’ command if the state changes.
To do debounce, put a delay of a few milliseconds in your Arduino loop. After you’ve sent a state change, set an integer counter to about 30 and decrement it by one in each loop(). Don’t check that particular input again until the counter reaches zero.