Raspberry Pi Xbee serial.Serial timeout not working Python - python

I am trying to connect Rasberry Pi with Xbee on UART header ttyAMA0
Both are connected and I am getting response of +++ -> OK
Xbee is on mode 2 API
s = serial.Serial("/dev/ttyAMA0", 9600, timeout=5)
xb = ZigBee(s)
xb.send('at', command="SH")
print "working till now"
ansh = xb.wait_read_frame()
print "don't wait here there is a time out"
I am getting output
working till now
And code goes for infinite wait
Please help

I also had this problem with the "SH" at command. After a LOT of debugging and pretty much taking apart the Python-Xbee library I eventually found the solution!
Add "escaped=True" to the constructor:
xb = Zigbee(s, escaped=True)
It would seem that the SH (High Address) response contains bytes which need escaping. Also check your API mode matches.

Related

Sending serial commands to a Kangaroo motion controller with pyserial

Hi everybody, I need help with following problem please:
I try to drive a Dimension Engineering Kangaroo/Sabertooth motor controller from a Python script using pyserial.
Everything works so far except that the motor output stops after some time and the USB/serial connection becomes 'unresponsive'. The faster the rate at which the serial commands are sent, the quicker this happens.
This is how I initialize the serial connection:
# open serial port
Saber = serial.Serial("COM1", 19200, timeout=1, write_timeout=0)
# starting the motor
Saber.write("1,start\r".encode("gbk"))
Then the position commands are sent using a loop:
while True:
pos = 2000 # just an example, the script calculates a new required position every iteration
command = "1,p" + str(pos) + "s500\r"
Saber.write(command.encode("gbk"))
time.sleep(.1) # the lower this break, the faster the device becomes unresponsive...?
After the device stops, I have to disconnect it / power it down, to be able to open a serial connection again.
Could it be that some sort of buffer gets filled and 'locks' the port?
I have tried to free the read/write buffers using:
Saber.reset_input_buffer()
Saber.reset_output_buffer()
But that does not solve the problem :/ Any help is greatly apprechiated! Thanks!

Bind Bluetooth device programmatically to rfcomm via python in

i wrote a script in python for serial communication between my M5Stack Stick C (like raduino) and the raspberry pi.
all work fine. i can send "X","Y" or "Z" from raspberry py to the stick and he will reply the value (G-Force) back to the raspi! so far so good
Codes:
Python on raspy:
import serial
import time
import threading
ser = serial.Serial('/dev/rfcomm5') #init serial port
input_line = []#init input char array
def process_data(_data):
#called every time a sream is terminated by \n
#and the command string is ready to use
command = convert(_data)
print(command)
def convert(s): #convert the char list in a string
new = "" #init string to append all chars from char array
for x in s: # traverse in the string
new += str(x)
return new # return string
def processIncomingByte(inByte):#adding incoming chars to input_line
global input_line# globalize the input_line
if(inByte == '\n'):#if \n is incoming, end the chararray and release process data method
process_data(input_line)
input_line = []#reset input_line for next incoming string
elif(inByte == '\r'):
pass
else:#put all incoming chars in input_line
input_line.append(inByte)
while True:
while(ser.in_waiting > 0):#while some data is waiting to read....
processIncomingByte(ser.read())#.... process bytes whit method
ser.write(b'X\n')
time.sleep(0.5)
before the script work, i have to manually bind the m5Stak Stick-C over Blueman
to /dev/Rfcomm5. it work just fine over GUI or Console....
but now i would like to connect the stick via python to rfcomm5 (just by know the MAC adress, will be found in a config file later on...)
i startet to investigate a bit, but the more i research the more confused i am!!
i read some stuff over sockets and server-client aproaches. over a seperated script and so on....
i tested this code:
from bluetooth import *
target_name = "M5-Stick-C"
target_address = None
nearby_devices = discover_devices()
for address in nearby_devices:
if (target_name == lookup_name( address )):
target_address = address
break
if (target_address is not None):
print ("found target bluetooth device with address ", target_address)
else:
print ("could not find target bluetooth device nearby")
and indeed it found the device (just testing)!
but do i realy need to make a second script/process to connect to from my script?
is the the M5stack Stick-C the server? (i think so)
im so confused about all that stuff. i coded a lot, but never whit sockets, server-client stuff.
basically the communication (server/client?) works.
i just need to connect the device i found in the second script via macadress to rfcomm5 (or whatever rfcomm).
do i need a bluetooth socket? like in this example
https://gist.github.com/kevindoran/5428612
isnt the rfcomm the socket or am i wrong?
There are a number of layers that are used in the communication process and depending where you tap into that stack will depend what coding you need to do. The other complication is that BlueZ (the Bluetooth stack on linux) changed how it works over recent times leaving a lot of out of date information on the internet and easy for people to get confused.
With two Bluetooth devices, they need to establish a pairng. This is typically a one off provisioning step. This can be done with tools like Blueman or on the command line with bluetoothctl. Once you have a pairing established between your RPi and the M5Stack Stick, you shouldn't need to discover nearby devices again. Your script should just be able to connect if you tell it which device to connect to.
The M5Stack stick is advertising as having a Serial Port Profile (SPP). This is a layer on top of rfcomm.
There is a blog post about how this type of connection can be done with the standard Python3 installation: http://blog.kevindoran.co/bluetooth-programming-with-python-3/
My expectation is that you will only have to do the client.py on your RPi as the M5Stack Stick is the server. You will need to know its address and which port to connect on. Might be some trial and error on the port number (1 and 3 seem to be common).
Another library that I find helpful for SPP, is bluedot as it abstracts away some of the boilerplate code: https://bluedot.readthedocs.io/en/latest/btcommapi.html#bluetoothclient
So in summary, my recommendation is to use the standard Python Socket library or Bluedot. This will allow you to specify the address of the device you wish to connect to in your code and the underlying libraries will take care of making the connection and setting up the serial port (as long as you have already paired the two devices).
Example of what the above might look like with Bluedot
from bluedot.btcomm import BluetoothClient
from signal import pause
from time import sleep
# Callback to handle data
def data_received(data):
print(data)
sleep(0.5)
c.send("X\n")
# Make connection and establish serial connection
c = BluetoothClient("M5-Stick-C", data_received)
# Send initial requests
c.send("X\n")
# Cause the process to sleep until data received
pause()
Example using the Python socket library:
import socket
from time import sleep
# Device specific information
m5stick_addr = 'xx:xx:xx:xx:xx:xx'
port = 5 # This needs to match M5Stick setting
# Establish connection and setup serial communication
s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
s.connect((m5stick_addr, port))
# Send and receive data
while True:
s.sendall(b'X\n')
data = s.recv(1024)
print(data)
sleep(0.5)
s.close()

pyserial: how to receive rs232 answers from power supply correctly

I'm currently trying to set up a communication with a power supply (RND 320-KA3005P) through RS232 with pyserial.
The Problem is that after sending "*DIN?", which should return manufacturer, model name and software version, the connection seems to receive nothing. Also no other command was successful. Using the included software, after connecting, a LabView program opens and the device is remote controllable, so I think the problem is in my code.
Code Example:
Connection parameters as described in the manual.
As end-of-line characters I tried "\r\n","\r","\n" which seems to solve many other problems, but here with no success.
import io
import serial
import time
import sys
ser = serial.Serial('COM4',
baudrate = 9600,
bytesize=8,
timeout=1,
stopbits = serial.STOPBITS_ONE,
parity = serial.PARITY_NONE,
xonxoff = False)
eol_char = '\r\n'
sio = io.TextIOWrapper(io.BufferedReader(ser),newline=eol_char)
while True:
sending = input("type:\n")
ser.write((sending + eol_char).encode('utf-8'))
time.sleep(0.2)
ans = sio.read()
sys.stdout.write('received: ' + str(ans))
print('\ntry again\n')
Which after entering the command gives:
type:
*DIN?
received:
try again
type:
Also when I run the script on the loopback
ser = serial.serial_for_url('loop://',timeout=1)
...
output:
type:
*DIN?
received: *DIN?
try again
type:
it seems to work fine. I'm using Windows 10 and a USB to RS232 converter. Does anyone have an idea about what I'm missing here?
Thanks in advance.
The solution I figured out is rather disappointing. Turns out that with a USB to RS232 converter cable, instead of the USB connection I used before, the commands to set and get values work as expected. The command '*DIN?', which I tried initially, which I got from the manual:), still gives no reaction - probably just not supported.
I believe the *DIN? command, found under "Functionality check" which should return: "Manufacturer, model name, software version.", is actually a typo. When all commands are later listed in the manual, number 11 says *IDN? and should return the KA3005P identification.
It is also ironic that the example they give under number 11 says: "* IDN?"...

Using pySerial with Python 3.3

I've seen many code samples using the serial port and people say they are working codes too. The thing is, when I try the code it doesn't work.
import serial
ser = serial.Serial(
port=0,
baudrate=9600
# parity=serial.PARITY_ODD,
# stopbits=serial.STOPBITS_TWO,
# bytesize=serial.SEVENBITS
)
ser.open()
ser.isOpen()
print(ser.write(0xAA))
The error it gives me is : "SerialException: Port is already opened".
Is it me using python3.3 the problem or is there something additional I need to instal ? Is there any other way to use COM ports with Python3.3 ?
So the moral of the story is.. the port is opened when initialized. ser.open() fails because the serial port is already opened by the ser = serial.Serial(.....). And that is one thing.
The other problem up there is ser.write(0xAA) - I expected this to mean "send one byte 0xAA", what it actually did was send 170(0xAA) zeros. In function write, I saw the following :
data = bytes(data) where data is the argument you pass. it seems the function bytes() doesn't take strings as arguments so one cannot send strings directly with: serial.write(), but ser.write(bytearray(TheString,'ascii')) does the job.
Although I am considering adding:
if(type(data) == type('String')):
data = bytearray(data,'ascii')
in ser.write(), although that would make my code not work on other PCs.

PySerial API thinks the com port is still open during a write(), why?

I am using PySerial (a Python API for serial communication) to send AT commands to a Nokia phone via bluetooth.
import serial
com = serial.Serial()
com.port = 19
com.timeout = 0 #also tried a timeout value greater than 0.
try:
com.open()
# at this point I turn off the phone.
com.write("AT\r\n")
print com.readlines()
except SerialException, e:
print e
Just after I open() the com, I turn off the phone. Then, I write("AT\r\n"). At this point, the function blocks and the runtime hangs.
Do you have any solution?
With a timeout set to 0, you desactivate the timeout parameter, the read()/readlines() becomes a blocking call. The caller will be blocked until the device answers.
Try to set a non-zero timeout value to your serial connection com = serial.Serial(timeout=0.5).
If it still hangs, the problem should be in the bluetooth stack.
Actually, what you are looking for is the writeTimeout and not the timeout argument. Late answer, I know, but I still needed it and I guess I'm not the only one.

Categories

Resources