3

I'm trying to communicate via serial between a BeagleBone running Ubuntu 10.04 and an Arduino. So far, I can send a string okay, but I'm having problems recognising the newline character.

From the BB side, in Python3 and using PySerial, I have (edited for just the relevant bits):

import serial
ser = serial.Serial('/dev/ttyACM0', 9600)

ser.write(chr(13).encode('ascii')) # establishes serial connection 
                                   # which will reset Arduino

delay(3000) # give time for reset. This method is from my own library

mesg = 'Beagle\n'
ser.write(mesg.encode('ascii'))

On the Arduino side I have:

boolean newMsg = false;
String incomingMsg = "";

void setup()
{
   /* some stuff - not relevant */
   Serial.begin(9600);
}

void loop()
{
    if(newMsg) {
        lcd.print(incomingMsg);
        newMsg = false;
    }
}

void serialEvent()
{
    incomingMsg = "";
    while (Serial.available() > 0) {
        char inByte = Serial.read();
        if (inByte == '\n') {
            newMsg = true;
        } else {
            incomingMsg = incomingMsg + inByte;
        }
    }
}

The problem is that newMsg never gets set to true because the if (inByte == '\n') never gets validated as true. I'even tried using '\r' on both sides and even a type-able character ('#'), but this test never works. The string 'Beagle' makes it through fine, though, so incomingMsg builds up okay.

Weirdly, I have this working between an Arduino and Processing (the Arduino on a robot connecting to Processing on a laptop via Bluetooth). I just can't see why it isn't working here. Any thoughts?

UPDATE: I have a partial answer, and one that will work for now, although I'd still like to know what's broken.

The if (inByte == '\n') is getting validated as true. But for some reason, the assignment of true to the global boolean var newMsg isn't working. Despite the assignment in serialEvent(), its value remains resolutely false inside loop(). Yet it's a global var (which, despite most programmers' aversion to them, are used quite a bit with the Arduino). I replaced the test in loop() with:

if (messageReceived != "")

and now it works. But I'd still like to know why that boolean problem exists.

2
  • 1
    Have you tried displaying each character to the LCD to ensure you are getting the \n you think you should be getting? Commented May 8, 2012 at 21:03
  • Yep, tried that. And yes - the cursor popped down one line, so the newline definitely arrived... :( Commented May 9, 2012 at 6:35

4 Answers 4

4

Since newMsg is being changed in an interrupt driven function you may need to declare newMsg as volatile:

volatile boolean newMsg = false;

The will inform the compiler that the value may change and it should not optimize it.

Arduino Volatile reference

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I'll give that a try. At the moment, I'm mired in other problems. Having partially solved the initial riddle, I decided to be rash and write a commport class. So everything's currently broken again... ;)
0

If you use Windows i propose this:

I donnot know Serial but i know files:

ser = serial.Serial('/dev/ttyACM0', 9600) # mode = 'w'

should open a file in read text mode. Whereas

ser = serial.Serial('/dev/ttyACM0', 9600, 'wb') # may not be correct

should open an file object in read binary mode.

Have a look at open(... mode = ...) for examples. Or look if you find a 'w' somewhere as option you can replace with 'wb'.

Under windows \r is removed for text file IO to be compatible to posix, I guess.

4 Comments

That line is instantiating a serial object, not writing a file, so the items in the parens are parameters to the constructor. There's no 'wb' option.
try this: replace .encode('ascii') with .encode('hex') and adjust the Serial.read().decode('hex') ( or base64 instead of hex )
Not sure that's supported on the Arduino side. On compiling, it throws an error: serBasic:31: error: request for member 'decode' in 'Serial.HardwareSerial::read()', which is of non-class type 'int'
Also, 'hex' turns out not to be a supported encoding on the Python side, either. I've tried utf-8. That or ascii are supposed to work - and do, in terms of the main string. It's just that, however the newline is coming across, if(inByte=='\n') isn't matching. Doesn't work, either, in a switch statement.
0

You are missing some relevant code. The function serialEvent contains a while loop that will not exit until all the data has been read, and does not call your loop function.

1 Comment

No, no relevant code missing. That's how the Arduino works. It runs the loop() function automatically. The serialEvent() function is called automatically whenever data arrives at the serial port. So loop() runs, pops over to serialEvent() when data arrives, then drops back to loop(). That part of it works! If, in the loop() function, I remove the if (newMsg) test, it prints out the incoming string no problem. It's just that it doesn't recognise the carriage return.
0

I was having this problem when I used PARITY_ODD/bytesize=serial.SEVENBITS Since I changed it to:

ser = serial.Serial(
    port='/dev/ttyUSB0',
    baudrate=9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_TWO,
    bytesize=serial.EIGHTBITS
)

works fine.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.