1

My overall goal is to have an Arduino Uno with an Ethernet Shield send a short (5-character) string via a SoftwareSerial connection and a UDP packet when I press a button.

The device which is receiving the serial message is fixed at 9600 baud, no parity, one stop bit.

For the purposes of debugging my serial problem I have removed the Ethernet Shield. I mention it above only so that potential responders understand my intended final hardware configuration.

I am using a USB/serial adaptor and Kermit to check the serial output.

C-Kermit>show communications

Communications Parameters:
 Line: /dev/ttyUSB0, speed: 9600, mode: local, modem: none
 Parity: none, stop-bits: 1 (8N1)
 Duplex: full, flow: none, handshake: none
 Carrier-watch: off, close-on-disconnect: off
 Lockfile: /var/lock/LCK..ttyUSB0
 Terminal bytesize: 8, escape character: 28 (^\)

My first job on receiving garbled characters was to test my test rig. I connected the predecessor device and was able to receive the expected characters. (It cannot send the UDP packet, which is why it is being replaced.)

One button on the original device sends "X0401", exactly as expected:

$ od -b oldserial⋅
0000000 000 130 060 064 060 061
0000006

Another button on the original device sends "X0402" (which I expected) and also a whole bunch of nuls, which I didn't expect:

$ od -b oldserial⋅
0000000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
0000020 000 000 000 000 000 130 060 064 060 062
0000032

In any event, it seems that the terminal is actually receiving 8N1 data at 9600, so I can trust what it shows me.

I was going kind of nuts trying to figure out what was the problem, because nothing I sent from the Arduino came through properly. Then I stumbled on a suggestion that 'U' made a good test character because an ASCII 'U' is 0123 or 01010101. Indeed, I am able to send sequences of arbitrary length and so long as they contain only the 'U' caracter, they come through correctly.

(I've got three buttons and three different sets of messages, so my tests tend to run in sets of three attempts.)

Next step is to reintroduce a little bit of variety and see what comes through:

Here I send "UUUUU", "UUEUU", and then "UUQUU". 'E' and 'Q' were chosen because they are each just one bit different from 'U'.

What I saw when I sent the first message was:

UUUUU

Then sent the second:

UUUUUUU]UU

Then the third:

UUUUUUU]UUUUWUU

Kermit was also storing the session to a log file, which looked like this:

$ od -b serialUsequesnce⋅
0000000 125 125 125 125 125
0000005
$ od -b serialUsequesnce⋅
0000000 125 125 125 125 125 125 125 135 125 125
0000012
$ od -b serialUsequesnce⋅
0000000 125 125 125 125 125 125 125 135 125 125 125 125 127 125 125
0000017

Somehow, 'E' (0105) turned into 0135 and 'Q' (0121) turned into 0127. In each case, a sequence of three 0 bits were turned into 011, while no 1 bits were changed.

Sending:

UUAUU

Got me:

$ od -b serialUsequesnce2⋅
0000000 000 125 125 137 125 125
0000006

The five consecutive 0 bits in 01000001 were turned into 01111 to give me 01011111 or 0137

Longer strings get weirder.⋅

Test strings of:

UU0123456789UU
UUABCDEFGUU

Got me:

$ od -b serialUsequesnce3
0000000 125 125 326 266 226 166 126 066 026 366 215 125 125 000
0000016
$ od -b serialUsequesnce4
0000000 125 125 137 257 335 325 315 305 125 125 001
0000013

Now I'm seeing not just bits being replaced, but I'm getting fewer characters than I'm sending.

Since I wasn't getting good data from my SoftwareSerial port, I thought I would listen in on the USB traffic, which is also set to 9600 baud.

This text from the Arduino monitor:

UUAUU
Start button pressed
UU0123456789UU
Stop button pressed
UUABCDEFGUU
Light button pressed

Came through as this:

$ od -b serialUSB
0000000 125 125 137 125 125 171 275 165 324 332 027 277 073 025 027 027
0000020 041 043 277 037 031 031 065 067 345 353 000
0000033
$ od -b serialUSB2
0000000 125 125 326 266 226 166 126 066 026 366 215 125 125 345 353 131
0000020 027 041 037 277 073 025 027 027 041 043 277 037 031 031 065 067
0000040 345 353 000
0000043
$ od -b serialUSB3
0000000 125 125 137 257 335 325 315 305 125 125 225 353 147 055 061 057
0000020 027 277 073 025 027 027 041 043 277 037 031 031 065 067 345 353
0000040 000
0000041

I'm guessing that I'm doing something wrong with the hardware, but my serial connector simply has pin 5 connected to ground and pin 2 connected to digital 6 (or 2 when watching USB traffic).

I'm powering the Arduino Uno via its USB connection. When I checked the voltage at Vin and the adjacent ground, I got 4.51 volts.

/*
Listens on three buttons:
 - Start
 - Stop
 - Lights

Sends serial messages to a Color Kinetics iPlayer 2
9600 baud, 8 data bits, no parity, 1 stop bit
Commands are
 - X0100 Lights Off
 - X0288 Lights at half
 - X02FF Lights at full
 - X0401 Set Show #1


Created 2016-07-13
by David H. Silber
(Cribbing extensively from the Arduino examples.)
*/


#include <SPI.h>         // needed for Arduino versions later than 0018

#include <SoftwareSerial.h>
SoftwareSerial softSerial( 5, 6 ); // RX, TX


const int noButton = 100;
const int startButton = 2;
const int stopButton = 3;
const int lightButton = 4;
bool startTriggered = false;
bool stopTriggered = false;
bool lightTriggered = false;
int lastTriggered = noButton;
unsigned long lastButtonTime = 0;

const char startSerial[] = "UUUUU";
const char stopSerial[]  = "UUEUU";
const char lightSerial[] = "UUQUU";


void setup() {
  // initialize the pushbutton pin as an input:
  pinMode(startButton, INPUT);
  pinMode(stopButton, INPUT);
  pinMode(lightButton, INPUT);

  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Starting");  // prints hello with ending line break⋅


  // set the data rate for the SoftwareSerial port
  softSerial.begin(9600);
  delay( 1000 );
}

void loop() {
  // read the state of the pushbutton value:
  startTriggered = ( HIGH == digitalRead(startButton) );
  stopTriggered = ( HIGH == digitalRead(stopButton) );
  lightTriggered = ( HIGH == digitalRead(lightButton) );

  if ( startTriggered && (startButton != lastTriggered) ) {
    action( "Start button pressed", startSerial );

    lastTriggered = startButton;
    startTriggered = false;
  }

  if ( stopTriggered && (stopButton != lastTriggered) ) {
    action( "Stop button pressed", stopSerial );

    lastTriggered = stopButton;
    stopTriggered = false;
    }

  if ( lightTriggered && (lightButton != lastTriggered) ) {
    action( "Light button pressed", lightSerial );

    lastTriggered = lightButton;
    lightTriggered = false;
  }

  buttonTimeout();
}

void action( const char usbMessage[], const char serialMessage[] ) {
    Serial.println( serialMessage);⋅
    Serial.println( usbMessage);⋅

    softSerial.write( serialMessage );

    lastButtonTime = millis();
}

void buttonTimeout() {
  if ( millis() - lastButtonTime > 2000 ) {
    lastTriggered = noButton;
  }
}

1 Answer 1

1

A friend came and visited me with his oscilloscope and we determined that the 'serial' output from the Arduino was not actually RS-232. It was only an accident that any data came through at all.

I think my answer will be to add https://www.arduino.cc/en/Main/ArduinoBoardSerial or something like it.

One of our realizations was that we needed to level shift the output, searching on "arduino serial level shifter" led me to http://forum.arduino.cc/index.php?topic=18689.0 which in turn led us to the MAX232 chip and boards that provide it.

It would be a good thing if there were some mention in the Arduino documentation that the 'serial' connection one would get from it was not actually RS-232.

3
  • 1
    RS232 is old. And people have implemented it in many ways. So we are all bound to have problems with RS232 at some point. Depending on where you got your RS232 signal from, it could have swung as high/low as 15V / -15V respectively. So do check to make sure your Atmel processor is still working as expected. Good luck
    – st2000
    Jul 26, 2016 at 12:59
  • Arduino serial is UART 5V Logic. Just in case.
    – ammar.cma
    Aug 24, 2016 at 11:58
  • 1
    Of course, its not RS232. That protocol defines mark and space voltage levels, as well as other signals to be used in asynchronous serial communication. RS232 does not define the actual signalling protocol used on the TX/RX lines. That protocol is a lot older and encompasses more than RS-232. The Uno is a 5V device and has no built-in RS232 level shifter, so the serial output is directly from its UART peripheral or in your SoftwareSerial case, merely a result of toggling the pins at the desired baud rate. Not unlike digitalWrite(). Aug 24, 2016 at 17:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.