Reading serial output from /dev/ttyACM0 using python

Hi,

I'm trying to implement a simple python program that just dumps every output the Arduino Uno provides over serial. I've seen that a lot of people use pyserial for this. My first question is, does pyserial provide anything useful under linux? Because it seems that you can just read and write to and from /dev/ttyACM0 (or whatever the name of the special file happens to be). Now, my first attempt is quite simple:

#!/usr/bin/env python

from select import select

with open("/dev/ttyACM0") as f:
    while True:
        select([f], [], [])
        content = f.read()
        sys.stdout.write(f.read())

Given a sketch such as this one:

int incomingByte = 0;   // for incoming serial data

void setup() {
  Serial.begin(9600);   // opens serial port, sets data rate to 9600 bps
}

void loop() {
  // send data only when you receive data:
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();
    // say what you got:
    Serial.print("I received: ");
    Serial.println(incomingByte, DEC);
  }
}

I often receive the newline twice after the decimal value. That means, the decimal value is printed with a trailing newline (e.g. 110\n) followed by the text with a leading newline (\nI received) altough it should be printed only once. I read here that println() not only prints '\n', but '\r\n', so I thought this might lead to problems. In fact, changing the sketch to use sprintf() and print() instead of printf() seems to mitigate the problem:

   char tbs[32];
    sprintf(tbs, "I received: %3d\n", incomingByte);
    Serial.print(tbs);

But changing the python script shows that, with the previous sketch that uses println(), the bytes read are only newlines, not carriage returns:

content = f.read()
print(bytes(content, "ascii"))

So I still don't understand where the second newline is coming from.

Any help is appreciated.

Have a look at this Python demo

...R

My question is not how to read serial values using pyserial, I want to know why this particular script does not work as intended.

jcdenton: My question is not how to read serial values using pyserial, I want to know why this particular script does not work as intended.

What is your program doing (or not doing) that is different from mine ?

...R

It doesn't require pyserial.

I would like to avoid dependencies unless I actually need them. If it is possible, I would like to just read directly from /dev/ttyACM0. If it's not possible, I'd like to know why.

You can include the PySerial library as part of your code so it gets distributed with your program and your program would not require any external libraries. See my EzScrn demo.

I have no idea how to read from a serial port without PySerial.

I have seen other Threads where people were trying to communicate with an Arduino using /dev/ttyACM0 from a shell script and were having difficulties.

...R

Robin2: I have seen other Threads where people were trying to communicate with an Arduino using /dev/ttyACM0 from a shell script and were having difficulties.

That's good to know, thank you. I was just wondering if my code included some horrendously stupid error, but it seems that pyserial is doing a bit more on linux than just treating /dev/ttyACM0 like a normal file.

jcdenton: that pyserial is doing a bit more on linux

It also works the same on Windows and Mac.

...R