Why doesn't pyserial write on Linux? - python

I've coded a simple script for Windows that works fine and I have adapted it to Linux (Ubuntu). The problem is that it doesn't read the byte sent.
I tried all the different serial ports available according to the Arduino IDE but the problem persists.I also used \n and \r without success and different encodings.
Code working on win10:
import serial
import time
import keyboard
arduino = serial.Serial('COM4', 9600, timeout=0)
while True:
arduino.write('a'.encode())
time.sleep(0.1)
print(arduino.readline())
Code not working on Ubuntu:
import serial, time
arduino = serial.Serial('/dev/ttyAMC0', 9600, timeout = 0)
while True:
arduino.write('a'.encode())
time.sleep(0.1)
print(arduino.readline())
So the first script prints continuously a\r\n, the second doesn't. Simply shows b'' continuously. So I think it doesn't simply write the letter.

Solved. No idea what exactly was thr issue but worked sending capital letter.

Related

What is the "send" button on the Arduino serial monitor doing?

This has been resolved!!
I have to wait a few seconds after opening serial port.
I want to execute the python program that is being done with the send button on the Arduino serial monitor.
if (Serial.available() > 0){
Serial.print(hoge);
}
is written in arduino, and I want to make Serial.available ()> 0 by python program.
I tried...
1.
If I send something like A or 3 on the IDE serial monitor, the contents of hoge will be output on the serial monitor.
2.
Using pyserial
ser = serial.Serial('/dev/ttyACM0', 115200,timeout=None)
ser.write(str.encode('A'))
data = ser.readline()
print(data)
When this is executed, it waits for reception before ser.read ().
After deleting the if (Serial.available ()> 0) of the program on Arduino and executing it, the contents of hoge were printed properly on the terminal.
The contents of hoge are
b'0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\r\n'
What do I need to write to do the same thing as 'send'? How do I get Serial.available ()> 0 ...?
It would be very helpful if you could tell someone.
The first data of 'hoge[]' is NULL character. Therefore there's no chance for 'Serial.print()' function to print out the whole content.
Serial.print(hoge) immediately returns because the first character is NULL character.
ser.readline() is waiting forever because there's no newline incoming from Arduino.
Simply changing the content will solve this issue or use write() function (but if you keep the same content then you need to adapt your python code as well without using readline()).
In your python code, you need to add "time.sleep()" before "ser.write()" so that Arduino is ready to receive the serial data. More than 1 seconds would be required.

pyserial readline() times out after reconnection

I use pyserial to communicate with a 3D printer (Monoprice Select Mini V2) via USB. Everything works well when I connect to the printer for the first time, but when I try to reopen a connection I can still send commands but do not receive any character.
This happens when I close the port and reopen it in the same program or when I rerun for the second time a python script opening the port after the first script has returned. The only way to reconnect properly is to restart my printer or to unplug and replug it. Changing the timeout value or trying to read only one byte does not solve the problem.
Short nonworking example:
import serial
ser = serial.Serial('/dev/ttyACM0', baudrate=115200, timeout=5)
ser.write("\n".encode())
print(ser.readline().decode())
# prints 'echo:Unknown command: "~"' (Not sure why)
print(ser.readline().decode())
# prints 'ok N0 P15 B15'
ser.write("M105\n".encode())
# prints expected response
ser.close()
print(ser.isOpen())
# prints 'False'
ser.open()
print(ser.isOpen())
# prints 'True'
ser.write("\n".encode())
print(ser.readline().decode())
# times out
ser.write("M105\n".encode())
print(ser.readline().decode())
# times out

Pyserial Com3 Port no output? Windows 7

Im trying to read data from a simple COM3 USB Serial Port with PySerial.
My Code is as follows:
import serial
import time
ser = serial.Serial("COM3", 230400, timeout=2) #Also tried timeout=None, loads to infinity then
print (ser)
while True:
line = ser.readline() #also tried read()
print(line)
time.sleep(1)
Console Outupt:
print(ser)
=>Serial<id=0x2757c50, open=True>(port='COM3', baudrate=230400, bytesize=8, parity='N', stopbits=1, timeout=2, xonxoff=False, rtscts=False, dsrdtr=False)
I tried to mess around with the boolean-attributes of the Serial object ser(e.g. xonxoff) with no success
print(line)
=> empty string or b''
I tried to test this in Python 2.7 and Python 3.6.5.
Listing all COM Ports via serial.tools.list_ports.comports() returns this:
COM3 - USB Serial Port (COM3)
COM46 - com0com - serial port emulator CNCA0 (COM46)
COM47 - com0com - serial port emulator CNCB0 (COM47)
When I use the program HDTerm I get the following output:
Screenshot_HDTerm_COM3_Port_Output
So the Port actually returns something, but I can't read the data from python somehow. The parameters are the same in my Python Code as they are in HDTerm.
Any idea why Python is printing nothing (or loading to infinity if timeout=None)?
PS.: COM46 & COM47 are working perfectly fine in Python and HDTerm. But they have other outputs (sending and receiving data from each other only).
I solved the problem by myself now.
I had to do ser.dtr=False
Even though print(ser)showed that the parameter dsrdtr=False (which I interprete as "dsr and dtr") the attributeset.dtr remained to be True (test with print(set.dtr).
You have to manually set dtr to False as shown above. Seems a bit odd to me, maybe a bugg?
if i get you right.
try
type(ser)
that way you will know the type of 'ser', if it's an iterable(list, tuple,etc...), you can try:
for s in ser:
print s
time.sleep(1)
hope this help.

Following Code works in python interpreter but not as a script

I just made a tiny code to change the colors of my led strip in Linux too (I already did it in C# on Windows).
import serial
ser = serial.Serial('/dev/ttyACM0', 9600)
ser.write(b'a')
When I type this into bash like this:
$sudo python2
>>>import serial
>>>ser = serial.Serial('/dev/ttyACM0', 9600)
>>>ser.write(b'a')
1
it's working fine, but if I then execute the .py script like this:
$sudo python2 light.py
The ser.write part seems not to work. I dont get an err msg or anything. But I know that it's communicatin with the arduino cause the Onboard LED flashes when I execute the script.
Okay, got it, the Arduino resets after getting serial input, I just added a 3 Seconds delay before writing the Serial data

Reading binary data with PySerial from serial port

PyQT 4.7 does not have inherited class from QIODevice that allows to talk with serial port directly (e.g. QSerialDevice). So I thought that it would be easier for me to use QProcess class and implement the actual reading/writing to serial port from a different process that will interface with my main QT application using QProcess interface.
Now the problem is that amount of bytes sent and received is not the same when I am using the code below. So my question is how to correctly read binary data from a serial port and then forward everything to the stdout?
This is an excerpt from my main QT program that creates QProcess:
self.micromouse_socket = QProcess()
self.micromouse_socket.start("/home/ansis/Source/Perforce-pele/Pele/tools/console/comtalker.py", "")
self.micromouse_socket.started.connect(self.on_micromouse_socket_started)
self.label_8.setText("Starting COM...")
And this is the Process that will talk with Serial port (comtalker.py; non blocking part is not yet finished):
#!/usr/bin/python
import serial
import sys
if __name__ == "__main__":
ser = serial.Serial(0)
while 1 :
x = ser.read(1)
sys.stdout.write(x)
sys.stdout.flush()
P.S. It could be that problem is somewhere else and not in PySerial. On the other computer I am writing to ttyS0 with this command "./binary_data_generator > /dev/ttyS0". The same code seemed to work fine when I was sending only ASCII characters (text+numbers)
It seems that PySerial (or a library that Pyserial depends on) is translating a single "0x0a" (\n) character into two characters "0x0d 0x0a"(\r\n). Both communication end-points are running on Linux, so I am not sure why someone would like to even translate those line endings at all...
Here strace indicates that sender sends only \n to ttyS0:
write(1, "M\n", 2) = 2
write(1, "\n", 1) = 1
write(1, "M\n", 2) = 2
write(1, "\n", 1) = 1
While debugging PySerial output I saw that each \n is prefixed with a \r.
Before claiming that this as a Bug I will do further investigation to find out who and why adds this carriage return...
I think the stdout is not in binary mode by default. That's hy the non-ascii bytes seems to be lost. See this question, it may help.
If I am understanding correctly, you want to use the std i/o as communication pipe between two processes. I would recommend to use one of the multiprocess module for that
I hope it helps

Categories

Resources