Serial communications between PySerial and VEX EDR Cortex - python-3.x

I have been struggling with this for the last 24 hours, I am trying to get PySerial to talk to a VEX Cortex over bluetooth using UART / HC-05. I guess this would be very similar to communicating with a Arduino.
The devices are connected together and data is flowing but its junk
In RobotC:(as you can see no encoding is apparent, i believe its just going over as bytes)
#include "BNSlib_HC05.h"
task main()
{
setBaudRate(UART1, baudRate19200);
bnsATGetBaudrate(UART1)
char stringBuffer[100];;
while(1==1)
{
bnsSerialRead(UART1, stringBuffer, 100, 100);
writeDebugStreamLine(stringBuffer);
delay(500);
bnsSerialSend(UART1, (char*)&"simon");
}
}
In python PySerial
import serial
import time
import struct
ser = serial.Serial(port='COM8', baudrate=19200)
print("connected to: " + ser.portstr)
message = "Simon"
while True:
ser.write(message.encode()) # I guess this is encoding via utf8?
#for b in bytearray("simon was here","UTF-8"):
#ser.write(b)
print("sent")
time.sleep (100.0 / 1000.0);
result = ser.read(25) # tried readline, just hangs
print(">> " + result.decode('cp1252')) # tried utf8, ascii
ser.close()
print("close")
In robotC I get back f˜fžþžøž
In Python I am getting back ýýýýýýýýýýýýýýýýýýýýýýýýý

It turned out the HC-05 module was not configured correctly :(

Related

I'm trying to read sensor data through serial communication but when I try to read it just kept on runnin in python but it doesn't display any value

I have light detector sensors connected to a data acquisition box and it is connected to my laptop via RS232 usb cable. I have stabilized serial communication to that port in python. But when I try to read the data it just keeps on running and it doesn't display any value. I have tried this same think in MATALB and it works properly, so I know that port and sensors are working fine. I am just not able to read the data in python. I have three ways(shown below in python code) but nothing works. Please help me.
Here is my python code:
import serial
from serial import Serial
s = serial.Serial('COM3') # open serial port
print(ser.name)
# Set the serial port to desired COM
s = serial.Serial(port = 'COM3', bytesize = serial.EIGHTBITS, parity = serial.PARITY_NONE, baudrate = 9600, stopbits = serial.STOPBITS_ONE)
# Read the data(method 1)
while 1:
while (s.inWaiting() > 0):
try:
inc = s.readline().strip()
print(inc)
# Read the data(method 2)
data = str(s.read(size = 1))
print(data)
# Read all the data(method 3)
while i <10:
b = s.readlines(100) # reading all the lines
in matlab it gave values with a space but in same line
That indicates there are no newline characters sent by the device.
I've never used your device or the Python serial module. But from the docs, this is what I would do:
from time import sleep
while s.is_open():
n = s.in_waiting()
if n == 0:
print "no data"
sleep(1)
continue
try:
inc = s.read(n)
print(inc)
catch serial.SerialException as oops:
print(oops)
catch serial.SerialTimeoutException as oops:
print(oops)
print("serial port closed")
This gives you feedback for each condition: port open/closed, data ready/not, and the data, if any. From there you can figure out what to do.
The documentation says inWaiting is deprecated, so I used in_waiting.
I wouldn't be surprised if the problem lies in configuring the serial port in the first place. Serial ports are tricky like that.

UART send no bytes

I'm trying to write test code for sending data via UART on my Raspberry PI 3 b+ , but I cannot receive back the data I've sent . Raspberry is connected via UART module to my laptop , so I can see in Putty results. Anyone can tell me what Am I doing wrong?
I've checked if port isOpen and it returned True , msg=b'Hello' returned Hello showed hello , but no bytes received . Sending single bytes give also no bytes detected . Erasing the timeout showed that it is reached.
Edit: did little testing if port's are working properly
from __future__ import print_function
import serial
test_string = "Testing 1 2 3 4".encode('utf-8')
#test_string = b"Testing 1 2 3 4" ### Will also work
port_list = ["/dev/serial0", "/dev/ttyS0"]
for port in port_list:
try:
serialPort = serial.Serial(port, 9600, timeout = 2)
serialPort.flushInput()
serialPort.flushOutput()
print("Opened port", port, "for testing:")
bytes_sent = serialPort.write(test_string)
print ("Sent", bytes_sent, "bytes")
loopback = serialPort.read(bytes_sent)
if loopback == test_string:
print ("Received", len(loopback), "valid bytes, Serial port", port, "working \n")
else:
print ("Received incorrect data", loopback, "over Serial port", port, "loopback\n")
serialPort.close()
except IOError:
print ("Failed at", port, "\n")
That give me information that tty0 is not working properly but , also got absolutly no answer about correctness on port serial0
import serial
import struct
import time
port = serial.Serial("/dev/ttyS0", baudrate=115200, timeout=2.0)
i = 0
while True:
msg = struct.pack('>HBBB', 3000, 243, 234, 254)
port.write(msg)
time.sleep(0.3)
bytesToRead = port.inWaiting()
print("Found {} bytes in serial".format(bytesToRead))
if bytesToRead == 5:
rcv = port.read(5)
# port.write('\r\nYou sent:' + repr(rcv))
for i in range(5):
print('\r {} - {}'.format(i, bytes(rcv[i])))
idCode = struct.pack('BB', rcv[0], rcv[1])
idCode = struct.unpack('>H', idCode)
idCode = idCode[0]
# value = struct.unpack_from('HBBB', decode)
i += 1
if i == 4:
exit()
Expected Results:
Found 5 bytes in serial
(index) - (byte at that index)
Got:
Found 0 bytes in serial
Solved. It was just matter of wiring .
If someone in future would like to run test like that - they must remember to connect RX with TX line . Or if it connected with laptop there's it should be better to create code responsible for communication on it (but instead of ttyS0 or Serial0 , port should be set to proper COM e.g. "COM3")

Converting arduino serial readings into float or int on the raspberry pi with python3

I have a serial connection between my raspberry pi and my arduino. I can send data from arduino to the pi but when I try to convert the receiving data into a int or a float I get an error message.
Let's say I try to send the number 35 to the pi, and try to convert it on the python side I get following message:
invalid literal for int() with base 10:''
and when I try to convert it to float I get the following message:
could not convert string to float.
I'm using Idle 3.5.3 on the raspberry pi. I tried many things I've seen in this forum: like strip() but nothing seems to work. What could be wrong?
Arduino Code:
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(35);
delay(5000);
}
Python Code:
#!/usr/bin/env python3
import time
import serial
from array import array
import csv
arduino = serial.Serial(
port='/dev/ttyACM0',
baudrate = 9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=1
)
arduino.flushInput()
print("test")
while 1:
incoming = arduino.readline().decode('ascii').strip()
float(incoming)
print(incoming)
I expected a cast to int or float but I get only error messages
I got it.
incoming = arduino.readline().decode('ascii')
if not incoming is "":
if int(incoming.strip()) == 1:
data.append(float(arduino.readline().decode('ascii').strip())/100)

Reading data from a Bluetooth device low energy rfcomm python3

Faced a problem. There is a bluetooth device with low power consumption. BLE. The goal is to send a command to the device and get the data back.
For example: command - 0x** 0x** 0x**, where first 0x** - code command, second 0x - data lenght. Response mast be - 0x** 0x** 0x**. I can not send a command to the device. The device works by RFCOMM. Actually the code that is available, but it does not give a result - it says that the device is off.
from bluetooth import *
import socket
class Work:
def __init__(self):
self.rfcon = BluetoothSocket(RFCOMM)
# self.socket = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM)
self.server = '**:**:**:**:**:**'
self.port = 1
self.data = '0x01 0x00 0x00'
def scan_device(self):
connection = self.rfcon.connect((self.server, self.port))
print('con ===>>> ', connection)
senddata = self.rfcon.send(self.data)
print('senddata ====>>>> ', senddata)
data = self.rfcon.recv(256)
if not data:
print("no data!!!")
self.rfcon.close()
else:
print(data)
self.rfcon.close()
if __name__ == '__main__':
a = Work()
a.scan_device()
a.rfcon.close()
I made it through another library - the code:
from bluepy.btle import *
class Work:
def __init__(self):
self.initialize = Peripheral()
def scan_devices(self):
scanner = Scanner()
devices = scanner.scan(10.0)
for dev in devices:
print("Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi))
for (adtype, desc, value) in dev.getScanData():
print(" %s = %s" % (desc, value))
def connect_to_device(self):
print('start con')
connection = self.initialize.connect('**:**:**:**:**:**', 'public')
print('initialize complite')
return connection
def check_device_status(self):
print('test ====>>> ', self.initialize.getCharacteristics())
cmd = '0x01 0x00 0x00 0x20 0x00'.encode('UTF-8')
print(cmd)
status_device = self.initialize.readCharacteristic(cmd)
print('Device status => ', status_device)
def diconnect(self):
self.initialize.disconnect()
if __name__ == '__main__':
a = Work()
a.connect_to_device()
a.check_device_status()
a.diconnect()
It gives a connection but does not send a command and does not return a value since this library does not know what RFCOMM is. Perhaps someone faced this problem in the python and knows how to solve it?
RFCOMM is a protocol of Bluetooth Classic, BLE does not support it. It is impossible to use RFCOMM for communicating with a BLE device.
You should read an introduction to BLE, it will give you a basic understanding of BLE.
Anything further will be guessing, it depends on how the BLE device is configured.
If you are using your own device that you can configure, one possibility is to create a characteristic that supports Write and Indicate. You can indicate (to be notified when the characteristic value changes and what is the new value) and write the command. The response will be received via an indication.
For most practical purposes the answer that RFCOMM is only available in Bluetooth "Classic" is true: most Bluetooth LE devices don't support RFCOMM. However, in principle the Bluetooth Core Spec describes how a channel for RFCOMM can be opened between two LE devices using LE credit-based control flow with an L2CAP_LE_CREDIT_BASED_CONNECTION_REQ command (introduced in Core Spec v4.1 Vol 3 Part A Chapter 4.22 and the Assigned Numbers document).

Storing Value in Arduino Sent From Python via Serial

I have been trying to send a value from a Python program via serial to an Arduino, but I have been unable to get the Arduino to store and echo back the value to Python. My code seems to match that I've found in examples online, but for whatever reason, it's not working.
I am using Python 3.5 on Windows 10 with an Arduino Uno. Any help would be appreciated.
Arduino code:
void readFromPython() {
if (Serial.available() > 0) {
incomingIntegrationTime = Serial.parseInt();
// Collect the incoming integer from PySerial
integration_time = incomingIntegrationTime;
Serial.print("X");
Serial.print("The integration time is now ");
// read the incoming integer from Python:
// Set the integration time to what you just collected IF it is not a zero
Serial.println(integration_time);
Serial.print("\n");
integration_time=min(incomingIntegrationTime,2147483648);
// Ensure the integration time isn't outside the range of integers
integration_time=max(incomingIntegrationTime, 1);
// Ensure the integration time isn't outside the range of integers
}
}
void loop() {
readFromPython();
// Check for incoming data from PySerial
delay(1);
// Pause the program for 1 millisecond
}
Python code:
(Note this is used with a PyQt button, but any value could be typed in instead of self.IntegrationTimeInputTextbox.text() and the value is still not receieved and echoed back by Arduino).
def SetIntegrationTime(self):
def main():
# global startMarker, endMarker
#This sets the com port in PySerial to the port with the Genuino as the variable arduino_ports
arduino_ports = [
p.device
for p in serial.tools.list_ports.comports()
if 'Genuino' in p.description
]
#Set the proper baud rate for your spectrometer
baud = 115200
#This prints out the port that was found with the Genuino on it
ports = list(serial.tools.list_ports.comports())
for p in ports:
print ('Device is connected to: ', p)
# --------------------------- Error Handling ---------------------------
#Tell the user if no Genuino was found
if not arduino_ports:
raise IOError("No Arduino found")
#Tell the user if multiple Genuinos were found
if len(arduino_ports) > 1:
warnings.warn('Multiple Arduinos found - using the first')
# ---------------------------- Error Handling ---------------------------
#=====================================
spectrometer = serial.Serial(arduino_ports[0], baud)
integrationTimeSend = self.IntegrationTimeInputTextbox.text()
print("test value is", integrationTimeSend.encode())
spectrometer.write(integrationTimeSend.encode())
for i in range(10): #Repeat the following 10 times
startMarker = "X"
xDecoded = "qq"
xEncoded = "qq"
while xDecoded != startMarker: #Wait for the start marker (X))
xEncoded = spectrometer.read() #Read the spectrometer until 'startMarker' is found so the right amound of data is read every time
xDecoded = xEncoded.decode("UTF-8");
print(xDecoded);
line = spectrometer.readline()
lineDecoded = line.decode("UTF-8")
print(lineDecoded)
#=====================================
spectrometer.close()
#===========================================
#WaitForArduinoData()
main()
First, this is a problem:
incomingValue = Serial.read();
Because read() returns the first byte of incoming serial data reference. On the Arduino the int is a signed 16-bit integer, so reading only one byte of it with a Serial.read() is going to give you unintended results.
Also, don't put writes in between checking if data is available and actual reading:
if (Serial.available() > 0) {
Serial.print("X"); // Print your startmarker
Serial.print("The value is now ");
incomingValue = Serial.read(); // Collect the incoming value from
That is bad. Instead do your read immediately as this example shows:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
That's two big issues there. Take care of those and let's take a look at it after those fundamental issues are corrected.
PART 2
Once those are corrected, the next thing to do is determine which side of the serial communication is faulty. Generally what I like to do is determine one side is sending properly by having its output show up in a terminal emulator. I like TeraTerm for this.
Set your python code to send only and see if your sent values show up properly in a terminal emulator. Once that is working and you have confidence in it, you can attend to the Arduino side.

Resources