Sending serial messages

Can someone please advise me with this problem, it seems I have not figured out something...

I have used already in three projects the SerialCommand library (link below)

It is a very nice piece that I can recommend to anyone. It allows you to send and parse commands via a serial link (either wired or wirelessly e.g. through XBees), from one micro microcontroller to another in a very elegant way. Using the library, you can assign call handler procedures. These are called automatically, whenever a pre-defined command is received over the serial link. With this library I am able to control Arduinos wirelessly from a central "router"-Arduino. The router arduino itself receives the serial command messages through a iobridge IO-204 Web Gateway from my iphone... so much for the background.

Let's assume I have defined the command "LIGHTON", in order to flip on a relay whenever I send this command. I found out that when I send the command from the iobridge dashboard, I have to add "%0D" (the code for a carriage return) to the actual command in order to make it work. In other words, sending "LIGHTON" does not trigger the call handler, while on the other hand "LIGHTON%0D" does. No big deal, every command defined in the dashboard got he extra little bit of code. So far so good....

However, now I am trying to build a handheld "remote control" by using an Arduino Fio equipped with an XBee. From this unit I want to simply broadcast out serial command, e.g. on button presses, to switch stuff on and off. I found out though, that sending "LIGHTON" does not work. The message gets sent out but it does not trigger the receiving Arduino (it is not an Xbee configuration problem, because I use the Xbee that that works fine in passing on the serial messages from the iobridge). Here below a flow scheme in order to explain better:

iobridge serial message --- cable to--- sender Arduino --> (serial command "LIGHTON%0D" via Xbee) --> ... receiver Arduino (with relay) = WORKS! :slight_smile:

Arduino sender (sends out serial commands directly: Serial.println"LIGHTON"):wink: --> (serial command "LIGHTON" via Xbee) --> .. Arduino receiver (with relay) = does NOT work. :frowning:

... also, adding the carriage return code to the command does not help:

Arduino sender (sends out serial commands directly) --> (serial command "LIGHTON%0D"" via Xbee) --> .. Arduino receiver (with relay) = does NOT work. :frowning:

I found here on the Arduino website and in the forum several pages that show the use of "\r", as in Serial.println("... \r");, in order to send the carriage return (which actually should be sent by using "Serial.println" in the first place. However, also this does not work.

Arduino sender (sends out serial commands directly) --> (serial command "LIGHTON\r"" via Xbee) --> .. Arduino receiver (with relay) = does NOT work. :frowning:

I also tried Serial.write(10) or Serial.write(13) for the carriage return or new line feed instead, both without success.

So, to cut a long story short: when I send the same serial command directly from an Arduino, instead from the iobridge, the receiver is not triggered. There must be something missing that I need to append in the Arduino code to the serial message, something like a carriage return or whatever, in order to get it to work.

Anyone any idea what my mistake is?

Anyone any idea what my mistake is?

Two errors

  1. not keeping to the point,

2 not posting your code.

Mark

I've used the below test code between two arduinos.

//zoomkat 3-5-12 simple delimited ',' string tx/rx 
//from serial port input (via serial monitor)
//and print result out serial port
//Connect the sending arduino rx pin to the receiving arduino rx pin. 
//Connect the arduino grounds together. 
//What is sent to the tx arduino is received on the rx arduino.
//Open serial monitor on both arduinos to test

String readString;

void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like wer,qwe rty,123 456,hyre kjhg,
  //or like hello world,who are you?,bye!,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >1) {
        Serial.print(readString); //prints string to serial port out
        Serial.println(','); //prints delimiting ","
        //do stuff with the captured readString 
        readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

holmes4:

Anyone any idea what my mistake is?

Two errors

  1. not keeping to the point,

2 not posting your code.

Mark

@Mark, sorry, I understand your point, always difficult to understand a problem when there is no code. Initially, I did not post it because it does not seem to be a problem related to the code itself, because the receiver side works correctly when I send the command from the iobridge module which broadcasts is wirelessly through an Xbee. But you are right, better posting the code so that people can see what is going on.

Here is the code for the Sender (e.g. a Arduino Fio with Xbee)

#include <Button.h>

Button OfficeLightOn = Button(2, BUTTON_PULLUP_INTERNAL, true, 50); 
Button OfficeLightOff = Button(3, BUTTON_PULLUP_INTERNAL, true, 50);

void setup(){
  Serial.begin(9600);
  OfficeLightOn.pressHandler(LightON);
  OfficeLightOff.pressHandler(LightOFF);
}


void loop(){
  OfficeLightOn.process();
  OfficeLightOff.process();
}

void LightON(Button&){
  Serial.println("OffLon");
//  Serial.println("\r"); // I tried this but it does not seem to help trigger the switching on the receiver side
  digitalWrite(13, 1);   // for debugging 
  delay(100);            // for debugging
  digitalWrite(13,0);    // for debugging
}

void LightOFF(Button&){
  Serial.println("OffLoff");
//  Serial.println("\r"); // I tried this but it does not seem to help trigger the switching on the receiver side
  digitalWrite(13, 1);   // for debugging 
  delay(100);            // for debugging
  digitalWrite(13,0);    // for debugging
}

and here comes the code for the receiver (again a Fio which receives the command through the attached XBee, does the parsing of the command and switches a relay)

#include <Button.h>
/*
http://log.liminastudio.com/itp/physical-computing/arduino-a-new-improved-button-library-with-some-handy-features
https://github.com/virgildisgr4ce/Button
*/
#include <SoftwareSerial.h>   // Required for the SerialCommand Library
#include <SerialCommand.h>    // SerialCommand Library, Steven Cogswell
#define arduinoLED 13         // Arduino LED on board
#define OfficeLightButtonPin 2         
#define WayLightButtonPin 3 
#define AlarmStatePin 4     // Alarm on/of indicator from XBee D0 --- with 20 kOhm pulldown
#define OfficeLightRelay 5 
#define WayLightRelay 6 
#define ArmedStatePin 7        // Alarmanlage extern/intern scharf from XBee D02 --- with 20 kOhm pulldown

Button OfficeButton = Button(OfficeLightButtonPin, BUTTON_PULLUP_INTERNAL, true, 50);  // Built-in debouncing, Sets 50ms debounce duration
Button WayButton = Button(WayLightButtonPin, BUTTON_PULLUP_INTERNAL, true, 50);

boolean OfficeLightState;
boolean WayLightState;
boolean PreviousAlarmState;
boolean OverrideOngoing;
unsigned long AlarmTimeStamp;
unsigned long AlarmOverrideDuration;
unsigned long CurrentTime;
SerialCommand SCmd;   // Initializes the SerialCommand object

void setup(){
  Serial.begin(9600);
//  Serial.println("Serial init");
  AlarmOverrideDuration = 5*60*60*1000;   // 5*60*60*1000 Lights stay on for 5 hours (5hx60minx60secx1000msec)
  OfficeButton.pressHandler(onPressOffice);
  WayButton.pressHandler(onPressWay);
  OfficeLightState = false;
  WayLightState = false;
  PreviousAlarmState = false;
  OverrideOngoing = false;
  pinMode(OfficeLightRelay, OUTPUT);
  pinMode(WayLightRelay, OUTPUT);
  pinMode(arduinoLED, OUTPUT);
  pinMode(AlarmStatePin, INPUT);
  pinMode(ArmedStatePin, INPUT);
  SCmd.addCommand("OffLon", OfficeLightOn);
  SCmd.addCommand("OffLoff", OfficeLightOff); 
  SCmd.addCommand("WayLon", WayLightOn);
  SCmd.addCommand("WayLoff", WayLightOff); 
  SCmd.addCommand("SBeac", SerialBeacon);     // SBeac = SerialBeacon - Echos the string argument back
  SCmd.addCommand("PLight", PanicLightOn);
  SCmd.addCommand("RstAlarm", ResetAlarmTimeOut);
}

void onPressOffice(Button&){  
//  Serial.println("onPressOffice: ");
  OfficeLightState = !OfficeLightState;
  digitalWrite(OfficeLightRelay, OfficeLightState);
}

void onPressWay(Button&){  
//  Serial.println("onPressWay: ");
  WayLightState = !WayLightState;
  digitalWrite(WayLightRelay, WayLightState);
}


void loop(){
  SCmd.readSerial();
  CurrentTime = millis();
  CheckForAlarm();    // Checks for Alarm signal, if positiv, starts timer and Override flag
  if (OverrideOngoing) {
    CheckIfOverrideExpired();
  }
  else {
    OfficeButton.process();
    WayButton.process();}  
}

void CheckForAlarm() {
  if ((digitalRead(AlarmStatePin) ==1) && (PreviousAlarmState == false)) {
    delay(200);                                 // for debouncing
    if (digitalRead(AlarmStatePin) == 1) {      // for debouncing
      PreviousAlarmState = true;
      AlarmTimeStamp = CurrentTime;  
      OverrideOngoing = true;
      WayLightState = true;
      digitalWrite(WayLightRelay, WayLightState);
      OfficeLightState = true;
      digitalWrite(OfficeLightRelay, OfficeLightState);
    }
  }  
}

void CheckIfOverrideExpired() {
  if ((CurrentTime - AlarmTimeStamp) > AlarmOverrideDuration) {
    OverrideOngoing = false; 
//    Serial.println("Override off");
  }
}

void OfficeLightOn(){
//  Serial.println("SC OfficeLightOn ");
  if (OfficeLightState == false) {
    OfficeLightState = true;
  }
  digitalWrite(OfficeLightRelay, OfficeLightState);
}

void OfficeLightOff(){
  if (OfficeLightState == true) {
    OfficeLightState = false;
  }
  digitalWrite(OfficeLightRelay, OfficeLightState);
}

void WayLightOn(){
  if (WayLightState == false) {
    WayLightState = true;
  }
  digitalWrite(WayLightRelay, WayLightState);
}

void WayLightOff(){
  if (WayLightState == true) {
    WayLightState = false;
  }
  digitalWrite(WayLightRelay, WayLightState);
}

void ResetAlarmTimeOut() {
  OverrideOngoing = false;  
}

void PanicLightOn() {
  OverrideOngoing = true;
  AlarmTimeStamp = CurrentTime;  
  WayLightOn();
  OfficeLightOn();
}

iobridge serial message --- cable to--- sender Arduino --> (serial command "LIGHTON%0D" via Xbee) --> ... receiver Arduino (with relay) = WORKS!

Does that, or does that not, append a carriage return and/or line feed to the "command"?

Arduino sender (sends out serial commands directly: Serial.println"LIGHTON")smiley-wink --> (serial command "LIGHTON" via Xbee) --> .. Arduino receiver (with relay) = does NOT work.

The println() method you are using does add a carriage return and line feed to the "command".

You might try just using print() to see whether that makes a difference. Or, it's possible that the library determines the end of the message based on carriage return OR line feed, but NOT both. A peek at the code shows that it expects a \r, not a \r\n, to terminate the message. The library really needs to understand that either \r or \n terminates the message and that the other should be not be stored as part of the message.

Try print(yourCommand); and print('\r').

PaulS:

iobridge serial message --- cable to--- sender Arduino --> (serial command "LIGHTON%0D" via Xbee) --> ... receiver Arduino (with relay) = WORKS!

Does that, or does that not, append a carriage return and/or line feed to the "command"?

Arduino sender (sends out serial commands directly: Serial.println"LIGHTON")smiley-wink --> (serial command "LIGHTON" via Xbee) --> .. Arduino receiver (with relay) = does NOT work.

The println() method you are using does add a carriage return and line feed to the "command".

You might try just using print() to see whether that makes a difference. Or, it's possible that the library determines the end of the message based on carriage return OR line feed, but NOT both. A peek at the code shows that it expects a \r, not a \r\n, to terminate the message. The library really needs to understand that either \r or \n terminates the message and that the other should be not be stored as part of the message.

Try print(yourCommand); and print('\r').

Paul,
thanks for your post. I tried a number of different things as you suggest:

  • print(Command); and print('\r').
  • print('Command\r')
  • also println instead of print and the whole thing also with \n and combinations of \r\n
    ... nothing seems to work.

Interestingly, when I check the serial monitor and send the command a couple of times, the combination print(Command); and then print('\r') does not result in:
Command
Command
Command

but in; CommandCommandCommand

It seems that the print('\r') actually does not result in a carriage return?

The way that the library is structured, I would expect this:

void LightON(Button&)
{
   Serial.print("OffLon");
   Serial.print("\r");

to send data that the receiver would understand.

If not, then it's time you ditched the crutches. There is nothing difficult about sending, receiving, and parsing serial data.