I'm fiddling a bit with python for serial communication, I have a switch that interacts with a screen and this screen in turn has 2 PCs connected to its HDMI ports, what I want to do is make this switch change from HDMI1 to HDMI2 port what I've been trying looks like this:
import pyserial
connection = serial.Serial(
'COM1',
baudrate=9600,
bytesize=8,
patity='N',
stopbits=1
)
I really believe that the connection is well established, when I do the following connection.is_open the answer is True.
However, I think that my problem is in what is the correct way to compose the chain that sends the commands to the switch through the function connection.write()
r source! ( Reading the input source at that time )
s source 1! ( Switch HDMI1 input(1:HDMI1,2:HDMI2,
3:HDMI3,4:DisplayPort,5:VGA/YPBPR/C-VIDEO) )
s hdmi1 auido 0! ( Choice of audio source as audio input
HDMI1 (0: Emb,1: Ext1,2: Ext2,3:Ext3,4:Ext4,5:Ext5) )
I really believe that my real problem is not knowing how to compose the command string that is sent with the function write() other aspect to consider is that I am using python 2.7 and windows.
the truth is that I am a newbie, if you can help me I will be very grateful.
just set a timeout and read until that happens
import pyserial
connection = serial.Serial(
'COM1',
baudrate=9600,
bytesize=8,
patity='N',
stopbits=1,
timeout=1 # could probably be less
)
# maybe .... are there some docs for whatever switch you are using?
connection.write("r source!\n")
# you might need connection.write(b"r source!")
print(connection.read(1000)) # try and read 1000 bytes or until timeout ocurres(1 sec)
# if you knew what the terminal character the device sends is you could just readuntil that character
Related
I am very new, learning Python specifically geared toward hardware (serial port and TCP/IP device) testing.
I have been trying to get PySerial based code to work and keep hitting roadblocks. Running Python 3.10.8 on Windows 10.
I worked through the 'import serial' problem (uninstalled and reinstalled Python); the serial.Serial problem (needed to add 'from serial import *). Now, it seems like all of the read syntax does not work. All I want to do at this point is open the port, read and print data - from here I will start working on which data I want).
Here is the code I am working with (this was found in a couple of places on the internet):
#test_sport
import serial
from serial import *
s = serial.Serial(port='COM9', baudrate=9600)
serial_string = ""
while(1):
# Wait until there is data waiting in the serial buffer
if(serialPort.in_waiting > 0):
# Read data out of the buffer until a carraige return / new line is found
serial_string = serial.readline()
# Print the contents of the serial data
print(serial_string.decode('Ascii'))
# Tell the device connected over the serial port that we recevied the data!
# The b at the beginning is used to indicate bytes!
#serialPort.write(b"Thank you for sending data \r\n")
Running this results in an error on serialPort.in_waiting (says serialPort not defined) if I change that to serial.in_waiting (says serial has no attribute 'in_waiting' (PySerial API site says this is correct(?). I've also tried simple commands like serial.read(), serial.readline(), ser.read(), etc. All fail for attributes.
Is the PySerial documentation online current? Does anyone know where to find basic serial port examples?
Thank you!
I'm trying to read data off of a sensor that I bought, using a conversion module (SSI to RS232). I have the module plugged into my Windows laptop via USB/serial converter.
When I use Putty in Serial mode, I can send the command $2RD and receive the appropriate response from the sensor unit. When I run a script to try to do the same thing, the unit returns: ''
Here is the code I am using:
import sys
import serial
import time
ser = serial.Serial(
port='COM4',
baudrate=9600,
timeout=1,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
)
while True:
ser.write('$2RD'.encode())
#time.sleep(1)
s = ser.read(26)
print s
A few other notes:
I've tried some variations using flushInput, flushOutput, sleeping, waiting, etc...nothing seems to help.
I know I have the COM ports right/the hardware all works in Putty, so pretty sure this is something with my code.
I've also tries 13,400 BAUD with no difference in outcome.
If I connect the TX and RX lines from the USB, I can read the command I'm sending...so it should be at least getting to the RS232/SSI conversion device.
s = ser.read(26) should probably be ser.read(size=26) since it takes keyword argument and not positional argument.
Also, you can try to set a timeout to see what was sent after a specific time because otherwise the function can block if 26 bytes aren't sent as specified in the read docs of pyserial :
Read size bytes from the serial port. If a timeout is set it may return less characters as requested. With no timeout it will block until the requested number of bytes is read.
I have a fermentor (NBS BioFlo 3000) connected to a PC (Windows XP) via a RS232 cable. I have downloaded a free software (http://www.foxylogic.com) to monitor the fermentor.
It works, so I know for a fact, that the hardware, cable, etc, are good.
The free software is not open source, and is very old. I'd like to use pySerial to monitor the fermentor. I know the port is COM1, 8 bit data, even parity, baudrate=9600. A paper I saw (http://dx.doi.org/10.1371/journal.pone.0092108, supplement S1, page 2) says that I should be using the "AFS communication protocol" and that the string requesting information looks like:
(MD#)RA(CR)
where (MD#) is the number of the reactor (0 in my case) and (CR) is carriage return.
So based on that, I did, in iPython terminal:
import serial
ser = serial.Serial(0)
ser.parity = serial.PARITY_EVEN
ser.timeout = 1
print ser
I get: Serial<id=0x1976cb0, open=True>(port='COM1', baudrate=9600, bytesize=8, parity='E', stopbits=1, timeout=1, xonxoff=False, rtscts=False, dsrdtr=False)
ser.write('0RA\r')
print ser.read(9999)
..., and I get nothing at all - just an empty string. I tried to change the timeout (up to 15 s, and I know it cannot take longer that that), I also tried readline() and read(1), but I did not change any of the other parameters. I also tried to alter the string:
b'0RA\r'
'0RA\r'.encode()
'00RA\r'
'0RA\r\n'
'0RA\n'
'MD0RA\r'
'(0)RA\r'
'0ra\r'
and many others, I don't remember them all. Nothing works, I always get an empty string. No errors.The serial device is just completely silent.
The only time I get something else than an empty string is, when I ser.read(1) in a loop, no writing, and I physically turn the fermentor either off or on. I get one space.
I googled this extensively, but it appears I am dealing with quite a unique problem, so I don't expect to find a simple answer here. I can't test all the combinations of the strings and all the settings, so my question rather is:
Where do I start troubleshooting?
(my python is 2.7)
Thanks!
You start troubleshooting by checking if anything is actually being communicated. In Windows, utilities capable of this include PortMon from the Sysinternals suite and SerialMon.
I noticed with my board from DIY drones a strange behavior when I use my custom firmware.
Here is an example function which is called in my firmware running on an Arduino board:
void send_attitude(float roll, float pitch, float yaw) {
hal.console->printf("{\"type\":\"sens_attitude\",\"roll\":%.4f,\"pitch\":%.4f,\"yaw\":%.4f}\n",
roll, pitch, yaw);
}
As you can see, the code just writing a message in the serial port set in setup (hal.uartA).
I call this function every 0.5s:
inline void medium_loop() {
static int timer = 0;
int time = hal.scheduler->millis() - timer;
// send every 0.5 s
if(time > 500) {
send_attitude(OUT_PIT, OUT_ROL, OUT_YAW);
timer = hal.scheduler->millis();
}
}
Now to the strange thing. If I use the serial monitor or read the board with another program or script everything is fine. Every 0.5s the proper LED is blinking and message is shown. But if I don't read it out, after appr. 10s the LED is flushing up continuously and no connection/communication is possible anymore. I have to unplug the board then. The same behavior is observed the other way round. If I send to my board over serial port (in my case USB) and don't flush the input buffer, the LED is flushing up continuously and I get a timeout. The following code works:
def send_data(line):
# calc checksum
chk = chksum(line)
# concatenate msg and chksum
output = "%s*%x\r\n" % (line, chk)
try:
bytes = ser.write(output)
except serial.SerialTimeoutException as e:
logging.error("Write timeout on serial port '{}': {}".format(com_port, e))
# Flush input buffer, if there is still some unprocessed data left
# Otherwise the APM 2.5 control boards stucks after some command
ser.flush() # Try to send old message
ser.flushInput() # Delete what is still inside the buffer
If I comment out this line:
ser.flushInput() # Delete what is still inside the buffer
I don't use more settings then this.
I get (depending on the message interval) a timeout sooner or later. In my case I send every 20ms a signal which results in a timeout after ~10s. Also dependent on the length of message. Bigger messages cause it faster than smaller ones.
My settings are shown in the following snippets. Client side python code:
com_port = '/dev/ttyACM0'
baud_rate = '115200'
try:
ser = serial.Serial(com_port, baud_rate, timeout=0.1, writeTimeout=0.1, rtscts=1)
The if these timeouts happen, then I also get one if I set the timeout to something like 2s. In my case I need a very low latency, which is indeed possible if I keep reading and flushing. Firmware code from my Arduino:
void setup() {
// Set baud rate when connected to RPi
hal.uartA->begin(115200);
hal.console->printf("Setup device ..\n");
// Followed by motor, compass, barometer initialization
My questions are:
What exactly happens with my board?
Why it is not reacting anymore if I just write in my serial port without reading or flushing the buffer?
Is it really a buffer or driver problem associated with this strange behavior and is this problem related to all Arduino boards or maybe just mine APM 2.5 from DIY drones?
Last but not least: I was finding no functions in the library which are targeting such problems. Are there maybe any I don't know?
The complete source code is #google code: https://code.google.com/p/rpicopter/source/browse/
What board are you using and what processor does it have? My guess would be that your board is based on the ATmega32U4, or some other microcontroller that has a built-in USB module. If so, I have seen similar behavior before here is what I think is happening:
There is a buffer on your microcontroller to hold serial data going to the computer. There is a buffer in the computer's USB serial driver to hold serial received from the chip. Since you are not reading bytes from the COM port, the buffer on the computer will fill up. Once the buffer on the computer fills up, it stops requesting data from the microcontroller. Therefore, the buffer on the microcontroller will eventually fill up.
Once the microcontroller's buffer is full, how do you expect printf command to behave? For simplicity, the printf you are using is probably designed to just wait in a blocking loop until buffer space is available and then send the next character, until the message is done. Since buffer space will never be available, your program gets stuck in an infinite loop.
A better strategy would be to check to see if enough buffer space is available before calling printf. The code might look something like this:
if(console_buffer_space() > 80)
{
hal.console->printf(...);
}
I don't know if this is possible in the DIY drones firmware, and I don't know if the max buffer space can actually ever reach 80, so you will have to research this a bit.
I don't understand the use of:
ser.flush() # Try to send old message
ser.flushInput() # Delete what is still inside the buffer
Lets say your device is connected to PC and the python code is writing the (line, chk):
ser.flush() - why are you using it?
ser.flushInput() - will "delete" the Serial input buffer at the PC
It looks like other people have the same problem. And thanks to the Mod-Braniac who deleted my minimal example. My bet is, that's a problem with Arduino USB controller chip or the firmware on it.
I am just wondering how the buffers work on a com port.. The code below is a snip of how I am reading a com port. I am wondering if by doing serial_connection.close() and serial_connection.open() I would be losing any data, or would it remain in the buffer? You might ask why I am closing and opening the comport.. The reason being is that it is actually a virtual port and for what ever reason when I stay connected to it for a length of time data stops transmitting...
import serial
serial_connection = serial.Serial(
port = self.SERIAL_PORT,
baudrate = self.BAUD_RATE,
timeout = 10
)
while true:
serial_connection.close()
serial_connection.open()
line = serial_connection.readline()
print line
PySerial has a separate thread that sits there listening for data to make sure that nothing gets lost. However, the OS itself does not buffer data. There is a slim chance that you could lose some data for the brief period of time between when you close the port and open it again.