Troubleshooting serial communication from Python to Arduino - python

I'm using software which has Python scripting capabilities. I want to use it to move a Clearpath servo and run internal software commands intermittently.
Using an Arduino, I can control the servo, but it starts going wrong once I start using serial communication. After reading through other post, I'm thinking the problems are arising because serial communication is 8bit and I'm wanting to send large int.
For example, a section of the Arduino code shows:
void loop(){
if(Serial.available()){
inByte = Serial.readStringUntil('\n');
ser = inByte.toInt();
X.move(ser);
while(!X.commandDone()||!X.readHLFB())
{ }
Serial.print (inByte);
delay(1000);
}
}
Before I started using serial communication, I'd utilize integers in X.move(ser) and get flawless results. Now that I'm using the serial port, I can tell there's something wrong with this code. Even though it seems to work using the Serial Monitor, the more I try it (especially using larger numbers) the more I realize its probably not doing what it did before I used serial.
Then add Python into the mix and it gets even worse.
To give you an idea of what I'm trying to do, here was an example of Python code:
ser = serial.Serial('COM3', 9600, timeout=1)
ser.close()
ser.open()
while True:
var = "1000"
ser.write(var.encode())
time.sleep(1)'
Using this code, the servo moves but it's not right at all.
How can I send large integers (for example, 50502) from Python to Arduino through serial without it getting mangled during serial communication?

Related

Serial.write() not received by Arduino

I am trying to get an LED to respond to a python program (using python 3.8), and it is not receiving anything. When I connect to the port, the led blinks to indicate it is connected, but then does nothing. Here is my code:
import serial
ser=serial.Serial('/dev/cu.usbmodem1411', 2000000, timeout=1)
ser.write(b'H')
time.sleep(200)
while True:
#read echo back from arduino verify receipt of message
#will show printing of x from arduino program
data = ser.readline()[:-2]
if data:
print (data.decode())
The while loop doesn't print out anything, and I also tried using the Arduino interface and it send signals fine, so my wiring is correct, but there is something missing with the python code. Has anyone run into this before?
The problem seems to be due to the wrong band speed you are using for the serial port. ser=serial.Serial('/dev/cu.usbmodem1411', 2000000, timeout=1) The value 2000000 here can never be true. There is no such value. The default is 9600, but I'll share a photo showing you the band speed on the Arduino side, the band speeds here and there should be equal.

Difficulty in python reading and writing to arduinos connected to serial ports

I'm working with a python program on a Windows PC running under Anaconda that is talking to multiple USB-attached arduino megas. I can create a string on the python side and successfully encode it as bytes and send it to the arduino where it is correctly interpreted. I can read a string from the arduino into the python program and correctly interpret it. The issue I'm having is when I try to read from one arduino and then send that message back out to another arduino. Example:
Python side code:
response = ser1.readline() #Read from arduino #1
ser2.write(response) #Write the response read from #1 out to #2
Arduino side (for serial 2):
if (Serial.available()>0) {
newStr = Serial.readString();
}
The Serial.readString() never completes; the arduino just hangs at that point.
I'm sure it's something stupidly simple, but python is a new language for me so I haven't been able to figure it out.

Python serial write doesn't work FIRST run

I have 2 programs to test serial communication, an simple arduino program that echoes whatever is on the serial port and a python program that writes to the serial port and prints the reply.
I'm having an issue where whenever I upload the arduino program and try to run the python the first time after I uploaded, it would be stuck on print ser.readline() which I'm assuming means for some reason python is not writing to the serial port. I would have to quit the python program and run it again to get it to get a reply from arduino. The program would continue to work until I re-upload the arduino then once again python wouldn't work on first run. Also if I open and close the serial monitor before I run the python program it will work the first run. Does anyone know what is the issue? This is on Ubuntu.
arduino
String str;
void setup() {
// Turn the Serial Protocol ON
Serial.begin(115200);
}
void loop() {
if (Serial.available()) {
str = Serial.readStringUntil('\n'); // Read the serial input
Serial.println(str); // sends ascii code
}
}
Python
import serial
ser = serial.Serial('/dev/ttyACM1', 115200)
for i in range(0,4):
str = "test string\n"
ser.write(str)
print ser.readline()
The issue is likely related to many Arduinos resetting when a new serial connection is made.
The solution is to either add a delay (about 2 seconds works) to the python program between the serial connection being created and the first data being sent or modifying the hardware to prevent a reset on serial connect.
By default python Serial might be blocking by default try removing the timeout:
ser = serial.Serial('/dev/ttyACM1', 115200,timeout=0)
additionally have a peek at the serial.threaded in the docs
I added
time.sleep(1)
ser.setDTR(level=0)
time.sleep(1)
after opening the serial port and the issue was fixed.

pySerial program doesn't read serial correctly

I have a problem using pySerial, and I don´t know from where to start looking for.
I have a 64 bits Windows Seven OS, with Python 2.7.5 (32 bits), and pySerial and Arduino (Arduino working correctly) already installed.
My Arduino code is the following:
// the setup routine runs once when you press reset:
void setup() {
// initialize the serial in 19200 baud rate
Serial.begin(19200);
}
// the loop routine runs over and over again forever:
void loop() {
delay(1000); // wait for a second
Serial.print("hello");
}
(Arduino conected in COM8, when using Serial Monitor I can see it saluting)
And my PySerial code looks like this:
import serial
import time
arduino = serial.Serial("COM8", 19200)
time.sleep(2)
while True:
print arduino.readline()
When I start this script, the program runs, but I can´t see the serial output (I think the configuration in the Python script is OK because if something - e.g. the port - is wrong, it crashes).
I don´t know what to do to find a solution.
Can you help me?
You might try using println instead of print on the Arduino/C side, and/or set a timeout for the serial read on the Python side.
Since serial.readline() waits for a \n, and you never send one using print, the serial read will just wait for a timeout. (But it's a bit more complicated than this, and it's worth reading the docs on readline and EOL.)
If this doesn't work, at least switch readline to just read and print out each character you may (or may not) be reading, but don't make it more complicated by waiting for the \n that readline requires.
From the demo docs:
Be carefully when using readline(). Do specify a timeout when opening the serial port otherwise it could block forever if no newline character is received. Also note that readlines() only works with a timeout. readlines() depends on having a timeout and interprets that as EOF (end of file). It raises an exception if the port is not opened correctly.

Sending hex data over RS-232 between an Arduino and a Mac OS X system

I'm using Voice Recognition Module -- Arduino Compatible. It says there to use AccessPort, but since I'm on Mac OS X it won't work. I don't know of any other solution but to write my own in Python while I'm open to any other language that works.
I found some solutions over here about pySerial but as of now it doesn't seem to work.
import serial
import struct
def C(val):
return struct.pack('H', val)
ser = serial.Serial(port='/dev/tty.PL2303-00001004', baudrate=9600, timeout=1)
ser.nonblocking()
ser.write(C(0xaa11))
print ser.read().__repr__()
ser.close()
It opens, write two bytes and doesn't read anything. 0xaa11 is used to start recording. My device seems to be in waiting mode since the red LEDs flash rapidly. Even if I do 0xaa00, it doesn't do much either. I even tried to change the byte order to 0x00aa, 0x11aa and so on, but I never receive my 0xcc or 0xe0 error code.
In the documentation it says to send it as hex, so my guess is that accessport converts hex to a Short which use two bytes. 0xaa00 is a two bytes number. I even tried to change the baud rate to 38400 in case someone before me did set that to this speed.
I'd be happy to read anything from that serial port because as of now I can write, it does nothing and reads nothing...
As of now, I'll try to install AccessPort with crossover. If it still doesn't work, I'll have to find a Windows box. I could even write my own bridge with my Arduino board since the driver I'm using might be buggy.
In case it matters, I'm using a USB to Serial PL2303.
Edit
I plugged my output and input pin to test my USB-to-serial. I do read what I write so the driver is working fine.
I'll try to set it up directly with Arduino and test directly from there.
Sending 0xaa11 is different than sending 0xaa and then 0x11. The serial seems to reverse the byte order.
On the other hand, the documentation doesn't tell about bit endianess, so it might be the problem too.
I kind of solved my problem while it was pretty dumb after all.
Here is my final script:
import serial
import struct
from time import sleep
def C(val):
return struct.pack('!H', val)
ser = serial.Serial(port='/dev/tty.PL2303-00002006', baudrate=9600)
sleep(2)
ser.write(C(0xaa00))
sleep(1)
ser.write(C(0xaa36))
sleep(1)
ser.write(C(0xaa11))
sleep(1)
while True:
print ser.readline()
If someone ever want to use that module, it works. It will switch to a mode where it puts to output words instead of bytes so you can read it using readline...
I used in struct.pack "!H" to use network endianess it change 0xaa00 to 0xaa 0x00 like it should be.
But the real problem here wasn't in the script. Since the usb to serial did work I thought that it was strange that the module didn't respond anything... not even a byte for errors. Every command in this module must return something. That's why I looked back at my cable and checked the pins... gnd to gnd, power supply to power supply and then rxd to txd, txd to rxd... While everything seems ok... I should receive something... And then I really thought... what if it's not supposed to use a cross cable and txd should be plugged to txd and rxd to rxd... Apparently it does.
I switch the cable and now data is sent and received.
So anyone using that module should check that it's correctly plugged in. If it doesn't work, switch the data pins.

Categories

Resources