In my project, there's a Raspberry Pi Zero W, linked with Arduino Pro Micro over the serial TX/RX lines (through 5 - 3.3V logic level converter). At power-on, the Arduino starts sending "are you there" command over the serial, until Pi has finished booting and launched a python program that listens on serial port, and it replies with "yes". Then Arduino proceeds with sending regular updates with sensor data.
For some reason not yet understood, the Arduino can disconnect and reboot, while the Pi is still running. And, for some reason, the connection on the Python end is severed in a way that does not raise exception if connection.in_waiting is read.
import serial
import time
ser = serial.Serial('/dev/serial0')
ser.baudrate = 9600
cmd = b''
while True:
time.sleep(1)
print(ser.is_open)
while ser.in_waiting:
ch = ser.read()
if ch == b'\n':
print('New command:', cmd)
cmd = b''
ser.write(b'OK\n')
continue
else:
cmd = cmd + ch
I have tested with this simple code, but in my tests, if I disconnect the Arduino and connect it back, the ser.is_open never is False, and the old connection works just fine also with reconnected Arduino. So, unfortunately I can not exactly replicate the loss of connection scenario when the data stop coming after disconnection. However, in order to investigate further, I'd like to add some monitoring code that would log serial disconnection incidents in file. But is there a way? If connection.is_open is always true, even without Arduino connected, then how one can detect if there is no connection?
The port remains open if there's a disconnection so your example code will loop continuously.
import serial
def connect(port):
return serial.Serial(port, baudrate=9600, timeout=1)
ser = connect('/dev/serial0')
buf = bytearray()
while True:
i = buf.find(b'\n')
if i >= 0:
buf = buf[i + 1:]
ser.write('OK\n')
num_bytes = max(1, min(1024, ser.in_waiting))
data = ser.read(num_bytes)
if data:
buf.extend(data)
else:
# no data to read aka disconnection has occurred
ser = connect('/dev/serial0')
if ser.isOpen():
continue
else:
# could not reconnect
break
Related
I'm having trouble with a python script running on an RPI0 reading serial input from an Arduino. I know the Arduino's code is correct as everything works as intended interacting with the Arduino over the built in serial monitor in the Arduino software(send code a10(code to drive a relay HIGH), Arduino sends back 11(basically asking for how long), send code b5, Arduino will hold pin HIGH for 5 seconds(b5)).
However when I attempt to read any serial input in python using the pyserial module, nothing happens. I know it does successfully send the code to the arduino as it will hold the pin HIGH for the specified seconds when I rewrite the python script with ser.write("a10b5").
The serial connection is NOT USB. I'm using jumper wires with a voltage shifter in between them using the Arduino's and Pi's GPIO TX and RX pins.
using python -V in the terminal it tells me I'm running version 3.8
I've tried multiple baud rates(300, 1200, 9600, 57600) with no change in behavior
I've also tried changing if x == 11: to if x == "11": in case for some reason it was receiving strings and not ints, also to no avail.
Here is the code:
import time
import serial
ser = serial.Serial(
port='/dev/ttyAMA0',
baudrate = 9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=None
)
print("sending data over serial now")
ser.write("a10") #a10 is relay HIGH code
while True:
x = ser.read()
if x == 11: ##arduino code 11(asking for how long)
print("recieved code 11")
print("arduino recieved relay HIGH code and is waiting for time to hold relay for")
print("sending time now")
ser.write('a5') # 5 seconds
time.sleep(1)
if x == 13: #arduino code 13(water success)
print("recieved code 13")
print("arduino reports watering complete")
x = 0 ##this is to clear the variable every loop. Not sure if it's needed
And here is a simple serial reader I've pulled from online. Opening it up in a second terminal and running it at the same time with my own script it will actually read the codes from the arduino business as usual.
#!/usr/bin/env python
import time
import serial
ser = serial.Serial(
port='/dev/ttyAMA0',
baudrate = 57600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=1
)
while True:
x=ser.readline()
print x
What gives?
Answering my own question. In the arduino code I used
Serial.println(whatevergoeshere)
instead of
Serial.print(whatevergoeshere)
So the arduino was sending out '\n' at the end of every serial line that was not being printed by either the arduino serial console and the python script. Updating my IF statements in python to
if x == "11\n":
Solves the issue and everything works as intended.
I'm trying to have a Beaglebone Black Wireless(debian image 2017-07-01) communicate to another device using UART serial communication. In an example program, the bone waits for the device to send the letter "A", then, upon receiving the right letter, outputs a message and transmits the letter "B". Here is the following program:
import Adafruit_BBIO.UART as UART
import serial
#Enabling the serial ports
UART.setup("UART1")
#Serial setup values
ser = serial.Serial()
ser.port = "/dev/ttyO1"
ser.baudrate = 9600
READ_LEN = 1
ser.close()
rx = ""
while True:
print "Waiting for A... "
ser.open()
rx = ser.read()
ser.close()
if (rx == 'A'):
print "Got it!"
ser.open()
ser.write("B")
ser.close()
break
The program doesn't throw any errors, however, when testing it out with the device, the program gets stuck on the "Waiting for A" line. I have thoroughly checked that all connections are correct and that the other device is sending data. Additionally, the program runs perfectly on an older Beaglebone (debian image 2015-11-12).
Any help into this matter would be greatly appreciated.
config-pin "Whatever Pin You Are Using" uart
example:
config-pin P9.14 uart
Seth
I set up a bluetooth connection between Raspberry and a computer. I wish to carry out a pilot icon which would allow me to check if connection is always present. For that I carried out a Thread. For the test, I sending a message on the link of the PC towards RPi, if the Rpi receive something , she reference me a message and if I receive it on my computer is that the connection is always present. The probelm is that I have an error at the time of the reception side PC.
Here the detail: The operation of E/S was abort because of the stop of a thread or the request of an application.
Here two codes for the connection series:
Pc side with VB :
Private Sub checkBT()
Dim buffer As String = ""
While True
BluetoothPort.Write("Test")
buffer = BluetoothPort.ReadLine()
While buffer = ""
buffer = BluetoothPort.ReadLine()
End While
WriteInLog("" & buffer)
checkBT_thread.Sleep(20000)
End While
End Sub
Rpi side with Python:
import serial
serial_com = serial.Serial("/dev/rfcomm0", baudrate = 115200, timeout = 0, writeTimeout = 5)
print "INIT Bluetooth connection"
while 1:
x = serial_com.readline()
if x == "Test":
print x
serial_com.write("Recu")
Do you have an idea about the problem please?
Can the error come owing to the fact that I use of Windows forms?
I solved my problem with the serialPort.ReadExisting() method.
I'm trying to write a function which continuously reads serial input. The function must be able to handle unexpected disconnections from the serial port and reconnect when possible. Despite reading several question posts on stackOverflow and looking through the pySerial documentation, I have yet to find a solution.
Here's my code:
def serialRead(serialPort, queue):
"""Adds serial port input to a queue."""
ser = serial.Serial(serialPort - 1, timeout = 2)
ser.parity = "O"
ser.bytesize = 7
while(True):
try:
if(ser == None):
ser = serial.Serial(serialPort - 1, timeout = 2)
ser.parity = "O"
ser.bytesize = 7
print("Reconnecting")
queue.put(ser.read(27))
ser.write(chr(6).encode())
print("Writing Data...")
except:
if(not(ser == None)):
ser.close()
ser = None
print("Disconnecting")
print("No Connection")
time.sleep(2)
Here's my output:
Enter a Serial Port: 7
Writing Data...
Writing Data...
Writing Data...
Writing Data...
I start with my device connected. After leaving the program run, neither "Disconnecting" or "No Connection" display and the program stops (it doesn't crash).
This code works. Batman tested the program on an Arduino connection and I found that my program had successfully reconnected with the device after a period of time. I hope this code will be useful for those struggling with something similar.
Is it possible to achieve full-duplex communication using PySerial? Specifically, would it be possible to monitor the port continuously for input and write whenever needed? I imagine it should be possible using threads (and serial interfaces are full duplex no?). If not, what would be the best approach to monitoring a serial port when not transmitting? A timeout?
Edit: Here's my attempt at it. This code is targeting TI's CC2540 Bluetooth LE chip. On sending the GATT init message I expect a reply (detailing the operating parameters of the chip)...I'm getting nothing though
import serial
import threading
from time import sleep
serial_port = serial.Serial()
GAP_DeviceInit = \
"\x01\x00\xfe\x26\x08\x03\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"
def read():
while True:
data = serial_port.read(9999);
if len(data) > 0:
print 'Got:', data
sleep(0.5)
print 'not blocked'
def main():
serial_port.baudrate = 57600
serial_port.port = '/dev/ttyACM0'
serial_port.timeout = 0
if serial_port.isOpen(): serial_port.close()
serial_port.open()
t1 = threading.Thread(target=read, args=())
while True:
try:
command = raw_input('Enter a command to send to the Keyfob: \n\t')
if (command == "1"):
serial_port.write(message)
except KeyboardInterrupt:
break
serial_port.close()
Yes serial port hardware is full duplex. Yes, you can use threads to do Rx and Tx at the same time. Alternatively, you can use a single thread loop that does reads with a short timeout and alternates between reading and writing.
You didn't specify a timeout, so the read waits for the full number of bytes to receive and only then displays anything.