Problem 1:
I'm trying to read serial data coming from my arduino using pySerial.
Sometimes the code seems to work well but sometimes it prints strange
things. The arduino monitor always prints the normal data, the strange
behavior just happens on the python code.
Another thing: this just happens
when I increase the baudrate from 9600 to 115200, but I really need this
higher baudrate.
Output example:
Opening COM port...
Port successfully opened
b'7\r\n'
b'133\r\n'
b'125\r\n'
b'114\r\n'
b'104\r\n'
(...) (and suddenly here comes again)
b'\xbaj\xea2\x93j\n'
b'\xa6\x13j\n'
b'&\x13j\n'
b'&\x93j\n'
b'\xa6\xd3j\n'
(...)
[Finished in 2.0s]
Sometimes I need to cancel the build because it gets stuck
in the for loop.
Problem 2:
Besides that, after reading the data I need to convert it to int.
Just tried "int(data)" but obviously It didn't worked. Certainly because of the Problem 1.
When I change this:
print(data)
To this:
print(int(data))
I get this:
ValueError: invalid literal for int() with base 10: b'\xa1j\n'
Python Code:
import serial
print("Opening COM port...")
# open and prepare serial port
ser = serial.Serial('COM3', 115200, timeout=8,
parity=serial.PARITY_EVEN, rtscts=1)
print("Port successfully opened")
for i in range(50):
data = ser.readline()
print(data) # print(int(data))
ser.close()
Arduino Code:
void setup() {
Serial.begin(115200); // set baudrate
}
void loop() {
int data = 0;
int analogPin = 1;
data = analogRead(analogPin); // read pin
Serial.println(data, DEC); // print data to the serial port
}
Data validity suffers at higher data transfer speeds because the hardware can't read the data sent in the right sequence. Try lowering your baudrate to 57600.
Related
My Python and Arduino code together are producing the most baffling behaviour. I am running a test to see if Pyserial is writing to and reading from my Arduino correctly, but it seems like Pyserial will only write to Arduino when a user input is taken. Note, this user input doesn't even need to be the message that is sent to the Arduino, but as long as such input is taken, whatever message that I meant to send to the Arduino will send. If no user input is taken, it seems that either Pyserial is not writing to Arduino, or Arduino is not responding to the serial input.
Here is my python code:
import serial
import time
arduino = serial.Serial(port='/dev/cu.usbmodem2101', baudrate=9600, timeout=.1)
def write_read(x):
#arduino.write(bytes(x, "utf-8"))
arduino.write(b'V6Com9P500zI0zO2zR50zG0zF8zT4zN1zC0r0zZ')
arduino.flush()
data1 = arduino.readline()
time.sleep(0.1)
data2 = arduino.readline()
return data1, data2
#num = input("Enter a number: ") # This is the trigger that allows the serial communication
message ="V6Com9P500zI0zO2zR50zG0zF8zT4zN1zC0r0zZ" # dummy message
value1, value2 = write_read(message)
value1 = value1.decode("utf-8").strip("\r\n")
print(value1) # printing the value
print(value2)
And here is my Arduino code:
int DAC = 1000;
int Velec = 300;
String dataread = "";
boolean readcomplete = false;
String inChar;
void setup() {
Serial.begin(9600);
Serial.setTimeout(1);
}
void serialEvent() {
while (Serial.available()) {
inChar = Serial.readString();
dataread += inChar;
if (inChar == "Z") {
readcomplete = true;
Serial.println(dataread); // a testing point
}
}
}
void loop() {
while (readcomplete) {
Serial.println(DAC);
Serial.println(dataread);
readcomplete = false;
}
}
Those are just testing code, I took out the lines that are irrelevant to this question. The Arduino code works fine by itself, if I manually enter the serial input in the serial monitor.
As I said earlier, it works fine if the 'num' input is not commented out in the Python code:
Enter a number: 8
V6Com9P500zI0zO2zR50zG0zF8zT4zN1zC0r0zZ
b'1000\r\n'
I don't even need to enter a number, I can basically enter anything, and it will work. But as soon as I comment out the 'num' line in the Python code, there will be no output, value1 and value2 in the python code will return empty, even though 'num' isn't even used anywhere else in the code:
b''
(first line is an empty line because it is decoded and stripped of \r\n)
I've tested this on both my Arduino Uno and Arduino Due, so it is not the board that is the problem. I am so confused, please accept my sincere gratitude for anyone that can shed even the tiniest of light on this problem.
One possible cause that I have encountered when using PySerial and Arduino is that the serial communication takes a small amount of time to be initialized, but in the provided code, it goes straight to the arduino.write() line. I'd try adding a time.sleep() of about 10 secs before writing and reduce the delay if it works.
I'd have added this as a comment if I could but I don't have enough reputation, yet.
I'm currently trying to rotate a motor on my Arduino Uno through serial communication from my Raspberry Pi 3. My code itself currently works however sometimes when running the python script the motor will not turn or indicate any response. From what I've been able to find online, I feel like I'm sending signals faster than the Arduino is reading them, and I can't seem to find a way to minimize the delay and make my motor response consistent.
Here is my Arduino code:
#include <Stepper.h>
#define STEPS 128
Stepper stepper(STEPS, 8, 10, 9, 11);
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.read() == 50) {
stepper.setSpeed(8); // rpm
stepper.step(128); // do n steps -- corresponds to one revolution in one minute
}
else if (Serial.read() == 51) {
stepper.setSpeed(8); // rpm
stepper.step(-128); // do n steps -- corresponds to one revolution in one minute
}
}
Here is my Python code
import serial
import time
ser = serial.Serial('/dev/ttyACM0', 9600)
time.sleep(1)
num="3"
ser.write(bytes(num.encode()))
Also I'm not sure how Arduino is reading my ser.write, as when num = 2, I see "50" in my Serial Monitor, when num = 3, "51" appears in my Serial Monitor, and so forth.
Thank you!
Serial communication is always done in Bytes. So whatever you send through your interface will be received as a sequence of Bytes. As you encoded your "3" as UTF-8 it will be sent as 0x33 (51). Your "2" is 0x32 (50) respectively.
Increasing the baudrate as suggested in a comment won't help you as it will only increase the speed data is transmitted/received. Without a measurement you won't notice a difference betweeen sending a single byte with 9600 or 115200 baud.
As long as both device operate on the same baudrate and you do not exceed the max baudrate of any device (somewhere around 2 million baud for Arduino Uno) you cannot send to fast. (given a suitable cable and distance)
You might run into problems with too long cables but that's several meters for 9600 baud even in noisy industrial environment.
Usually you wait for data to be available in the receive buffer befor you read.
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);
}
}
Maybe not doing so causes some delay. I cannot tell for sure as you did not provide the length of the observed delay.
If the Arduino is already running when you execute your Python code I don't see any other issue with your code. If it is booting while you send you might observe some delay because of the Arduino bootloader. It will wait some time for possible firmware updates befor it starts the actual application code.
Small pieces of data may sit around in the output buffer before being sent. Try using Serial.flush() after write to let the os know you want the data sent asap.
I am stuck and dont know why. I am trying to transmit from an Arduino Nano to a RPi via the TX and Rx pins respectively.
This my code so far:
Arduino TX:
void setup(){
Serial.begin(9600);
}
void loop(){
bProgramLoop = 1
while(bProgramLoop == 1){
Serial.write(1);
}
}
The Raspberry Side:
import serial
oSer = serial.Serial("/dev/ttyAMA0",baudrate=9600,timeout=1)
while True:
sSerialInput = oSer.read(1)
#sSerialInput = oSer.readline()
print sSerialInput
After loading the sketch onto the Arduino and starting the python script, the Raspberry simply does not read anything.
NOTE:
I have connected the Tx pin from the Arduino to the Rx pin from the RPi via a Voltage divider and some jumper wires.
I have tried "readline()" too, but no luck
Any suggestions?
I have found the a solution to the problem I am having. I am still a proper noob, but as far as I can figure it out, sending serial data over the Tx pin is problematic because it is used by the usb port and then to your PC.
Thus the solution is to use the SoftwareSerial library. I have modified my two code sketches as follows:
Arduino:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(4,3); // (RX,TX) - Pin Setup for any digital pins you want as Rx or Tx
void setup(){
Serial.begin(9600);
mySerial.begin(57600); // initialize serial communication with serial pin
}
void loop(){
bProgramLoop = 1
while(bProgramLoop == 1){
mySerial.write("Anything");
}
}
Raspberry:
import serial
oSer = serial.Serial("/dev/ttyAMA0",baudrate=9600,timeout=1)
while True:
sSerialInput = oSer.readline()
print sSerialInput
As it is I am able to transmit data from the Arduino to the RPi. HOWEVER, I am still having issues converting the string to an integer or float.
see this post for details: Python readline() returns string that wont convert to int or float
i was working on a project that includes sending 4 characters from arduino to python so that the first variable in python reads the first sent character and the second variable reads the second character but when i print them on the screen it's not stable and out of sync.
i.e:
i send 'a','b','c','d',and i expect to receive the same in python : 'a','b','c','d'.
but what i receive might be like this : 'c','d','a','b' or 'b','c','d','a'.
Arduino
`
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.write('a');
Serial.write('b');
Serial.write('c');
Serial.write('d');
}
`
Python
ser = serial.Serial('COM4',9600,timeout=0)
ser.close()
ser.open()
up = ser.read()
right = ser.read()
left =ser.read()
down = ser.read()
I'm guessing it is because there is no synchronization between the two. The ardi sits there and spits out a,b,c,d,a,b,c,d,a,b,c,d etc. When the python code connects, there's nothing to make the ardi start at 'a', it just keeps doing with it's doing and the python code gets data starting with whatever the ardi is on at the time. Notice in your problem description how the characters are always in order, if you allow for a repeating cycle?
Try having the python code (when it starts) to send something to the ardi so that it restarts the sequence from the beginning.
I am trying to read frames sent to a ZigBee module plugged in the USB. Every frame gets discarded by the Python xBee package because the delimiter is 0x00 when it should be 0x7E. Actually it seems that every byte is also zero.
XCTU receives the frames perfectly.
I work with OS X, PyCharm, Python 3.4 and borrowed this code from Internet:
# Open serial port
ser = serial.Serial(PORT, BAUD_RATE)
# Create API object
xbee = ZigBee(ser,escaped=True)
# Continuously read and print packets
while True:
try:
response = xbee.wait_read_frame()
sa = hex(response['source_addr_long'][4:])
rf = hex(response['rf_data'])
datalength=len(rf)
# if datalength is compatible with two floats
# then unpack the 4 byte chunks into floats
if datalength==16:
h=struct.unpack('f',response['rf_data'][0:4])[0]
t=struct.unpack('f',response['rf_data'][4:])[0]
print (sa,' ',rf,' t=',t,'h=',h)
# if it is not two floats show me what I received
else:
print (sa,' ',rf)
except KeyboardInterrupt:
ser.close()
break
ser.close()
The program executes the xbee.wait_read_frame() call and waits there forever because no frame arrives.
I have tracked the call to "base.py" from the xBee package:
while True:
if self._callback and not self._thread_continue:
raise ThreadQuitException
if self.serial.inWaiting() == 0:
time.sleep(.01)
continue
byte = self.serial.read()
if byte != APIFrame.START_BYTE:
continue
The call to serial.read() always returns a zero.
I can't see anything wrong in code fragments you have provided. If you are reading just zeroes (are you?) from that serial port - there most likely something is wrong with serial port settings (e.g. you are reading at 115200 while data is being transmitted at 9600). What is the BAUD_RATE that you are using?
It's also could be a worth to test if you can access device with just dumb terminal.