Access sensor through serial port on Raspberry Pi 3B - python

I've got the following problem and after long hours of frustration I cannot get it to work, could somebody please help a noob out?
I've several SRF02 Ranging sensors which I wanted to use through I2C on my Raspberry Pi 3B Jessie.
I followed the tutorial and changed the first sensor to address 0xF2 (0x79 seen from Raspberry) and it all went perfectly. But the problem is that the addresses 0x78 to 0x7B are reserved for 10-bit I2C Adressing, so I have to use another one. But since I cannot access it anymore through I2C since I changed the address I decided to do it through the serial port.
I tried changing it as described in the tutorial but it doesn't work. Here is the code and what I did after research to get it done:
I checked the address of the Sensor. On powering up it sends one long and 9 short flashes so its address should be 0x09 in serial mode.
I updated and upgraded my Raspberry.
I connected the sensors RX pin to the Rasp TX and viceversa. +5V of the sensor to +3V of the Rasp (Is this a problem?). Sensors ground and mode pin to ground.
On raspi-config I changed the serial console to disabled and the serial harware ports to enabled.
Here is my /boot/cmdline.txt:
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles
I added the following to my /boot/config.txt:
enable_uart=1
dtoverlay=pi3-disable-bt
core_freq=250
My python code (By sending the range commands the sensor should flash once, but it doesn't, also I don't get any Result):
import serial
import time
ser = serial.Serial(port='/dev/serial0', baudrate = 9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_TWO, timeout=1, write_timeout=5)
USED_ADDRESS = '0x09'
TARGET_ADDRESS = '0x03'
# GET DISTANCE IN CM
ser.write(USED_ADDRESS)
ser.write('0x51')
time.sleep(0.07)
ser.write(USED_ADDRESS)
ser.write('0x5E')
results = ser.read(2)
if(results != None and len(results) > 0):
print 'RESULTS:'
for result in results:
print result
else:
print 'NO RESULT'
#CHANGING ADDRESS
#First command
ser.write(USED_ADDRESS)
ser.write('0xA0')
#Second command
ser.write(USED_ADDRESS)
ser.write('0xAA')
#Third command
ser.write(USED_ADDRESS)
ser.write('0xA5')
#Target Address
ser.write(USED_ADDRESS)
ser.write(TARGET_ADDRESS)
print "DONE"
Result of dmesg | grep tty:
[ 0.000000] Kernel command line: 8250.nr_uarts=1 bcm2708_fb.fbwidth=640 bcm2708_fb.fbheight=480 bcm2708_fb.fbswap=1 vc_mem.mem_base=0x3dc00000 vc_mem.mem_size=0x3f000000 dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles
[ 0.000312] console [tty1] enabled
[ 0.748748] 3f201000.serial: ttyAMA0 at MMIO 0x3f201000 (irq = 87, base_baud = 0) is a PL011 rev2
Result of ls -l /dev/serial*:
lrwxrwxrwx 1 root root 7 Feb 16 15:06 /dev/serial0 -> ttyAMA0
lrwxrwxrwx 1 root root 5 Feb 16 15:06 /dev/serial1 -> ttyS0
Somebody got an idea? I would be super-duper gratefull for any hint.

Ok guys I solved it! I found the solution here: https://www.raspberrypi.org/forums/viewtopic.php?t=63419
Connections as follows:
Pi 5V to device 5V Pi ground to device ground Pi ground to device mode
Pi TX to device RX
Then configure the Pi serial link to 9600.
stty -F /dev/ttyAMA0 9600
Then use echo to send commands to the device.
The first byte is the device address (0 - 15). The second byte is a
command.
To change the device from address 0 to address 5 use
echo -ne "\x00\xA0\x00\xAA\x00\xA5\x00\x05" >/dev/ttyAMA0
To change the device from address 5 back to address 0 use
echo -ne "\x05\xA0\x05\xAA\x05\xA5\x05\x00" >/dev/ttyAMA0
All the details are in the docs you linked.

Related

Python script for RTU Modbus

I am working on a automation of my home using a raspberry pi 3B+
I bought a electronic energy meter MEMO4-M-MOD.
https://docs-emea.rs-online.com/webdocs/152f/0900766b8152f22b.pdf
To connect it to raspberry pi i bought a cable RS485/USB.
I am interested to read some values from the energy meter
( exemple in the datasheet of the energy meter it says that the register adress of voltage is on the adress 2000(hexa) )
i wrote this code
#!/usr/bin/env python3
import minimalmodbus
import serial
instrument = minimalmodbus.Instrument('/dev/ttyUSB0',0)
instrument.serial.port
instrument.serial.baudrate = 9600
instrument.serial.bytesize = 8
instrument.serial.parity =serial.PARITY_NONE
instrument.serial.stopbits = 1
instrument.serial.timeout = 0.05
instrument.mode = minimalmodbus.MODE_RTU
try:
valeur= instrument.read_register(2000,1,3,False)
print(valeur)
except IOError:
print("no connection")
Problem I am facing here is it print no connection, so that make me think i use correctly the library.
Have you used this library?can you give me some advice to make that work?
thank you so much
#!/usr/bin/env python3
import minimalmodbus
import serial
instrument = minimalmodbus.Instrument('/dev/ttyUSB0',1)
instrument.serial.baudrate = 9600
instrument.close_port_after_each_call = True
valeur = instrument.read_float(2000, functioncode=3, number_of_registers=2, byteorder=0)
print(valeur)
Connect your RS485 USB device to your pi and make sure that your pi can see it... check by running "dmesg | grep ttyUSB" you will get an output of most likely ttyUSB0, use whatever this is as your device address.
You also need to set modbus address of power meter, I set it to 1 above...
Your register is big endian, I checked official documentation here on returning a big endian double register value (classed as read_float): https://minimalmodbus.readthedocs.io/en/stable/internalminimalmodbus.html

pyserial/Modbus - troubleshooting "No communication with instrument"

Beaglebone Black Wireless: Ubuntu 16.04,
Computer: Ubuntu 16.04,
Python 3.5.2
I am trying to communicate with a device via Modbus using a Beaglebone Black. I have read of people doing this same thing with a USB/RS485 dongle using minimalmodbus. I've tried changing up the settings; every possible baud rate, shorter cable, etc. There must be something within the Beagle that needs to be configured/is mis-configured for this type of work.
Code
#!/usr/bin/env python
# -*- coding; utf-8 -*-
import minimalmodbus
import serial
import time
i = minimalmodbus.Instrument(port='/dev/ttyUSB0', slaveaddress=1, mode='rtu')
i.serial.baudrate = 115200
i.serial.bytesize = 8
i.serial.parity = serial.PARITY_EVEN
i.serial.stopbits = 1
i.serial.timeout = 1
i.handle_local_echo = None
while True:
try:
print(i.read_registers(2008, 2, 3))
except serial.serialutil.SerialException as error:
print(error)
except FileNotFoundError as error2:
print(error2)
except IOError as error3:
print(error3)
time.sleep(1)
...using a USB/RS485 dongle. Using this dongle/code combination yields perfect results on my computer (for the past 4 months) but not the Beagle today.
Computer: Message received:
[0, 0]
Beagle: Error received:
IOError: No communication with instrument (no answer)
I am looking for possible avenues of troubleshooting. I have verified that the cable is not too long, and the USB dongle is OK. I have also ruled out any code issues.
Edit 1:
Forgot to include lsusb and ls /dev/ttyUSB*:
Bus 002 Device 004: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
Bus 002 Device 003: ID 04d9:0024 Holtek Semiconductor, Inc.
Bus 002 Device 002: ID 0409:0059 NEC Corp. HighSpeed Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
and
/dev/ttyUSB0
Edit 2:
I am able to achieve a loopback setup using pyserial and shorting the Rxd and Txd + and - terminals.
Edit 3:
I have tried all possible wiring configurations. Only one configuration works on the computer (Tx+ -> A and Tx- -> B). While using the minimalmodbus debug feature, I can see that the same message is being sent to the device on the Beagle and the computer ('\x01\x03\x07Ø\x00\x02ED' (01 03 07 D8 00 02 45 44)
). The computer receives a response while the Beagle does not.
The Beagle has no trouble mounting the adapter to /dev/ttyUSB0.
Edit 4:
#Carlo Zanocco requested the output of ls /dev/ | grep tty
tty
tty0
tty1
tty10
tty11
tty12
tty13
tty14
tty15
tty16
tty17
tty18
tty19
tty2
tty20
tty21
tty22
tty23
tty24
tty25
tty26
tty27
tty28
tty29
tty3
tty30
tty31
tty32
tty33
tty34
tty35
tty36
tty37
tty38
tty39
tty4
tty40
tty41
tty42
tty43
tty44
tty45
tty46
tty47
tty48
tty49
tty5
tty50
tty51
tty52
tty53
tty54
tty55
tty56
tty57
tty58
tty59
tty6
tty60
tty61
tty62
tty63
tty7
tty8
tty9
ttyGS0
ttyS0
ttyS1
ttyS2
ttyS3
ttyS4
ttyS5
ttyUSB0
Edit 5:
Output of stty -F /dev/ttyUSB0 -a:
speed 115200 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;
swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
discard = ^O; min = 0; time = 0;
parenb -parodd -cmspar cs8 hupcl -cstopb cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany
-imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl
-echoke -flusho -extproc
I experienced the same issues and it turned out it was a problem of termination and flow control.
I tried different USB dongles, all working with pcs and macs, and many different configurations on the BeagleBone, but nothing worked.
Low-cost USB dongles work well with PCs, but with microcontrollers, such as the BeagleBone, you need something that better handles the bus specifications.
I found out that some simple and low-cost TTL RS232 to RS485 boards work perfectly without any special configuration on the BeagleBone side since they automatically manage flow control.
You can search for RS485 automatic flow control on Ebay or similar websites.
Since the default serial port on your BeagleBone is already coupled to the system console, you need to enable another UART by properly editing the file /boot/uboot/uEnv.txt.
Then you need to connect 5V power supply and GND (available on P9_5 and P9_1 pins) and the correct serial pins (i.e. P9_26 and P9_24 if you enabled UART1) to the 5V, GND, RX and TX connectors of the adapter (do not bother with RTS and CTS since the adapter will manage those for you).
In your code change the port name to the new serial port (i.e. /dev/ttyO1 if you enabled UART1).
To easily debug your code, you can connect the USB dongle on a PC and the adapter on the BeagleBone through the RS485 wires and open two serial terminals.

Cannot set the UART baudrate of a bananaPi to 4Mb

I have a bananaPi M3, running a Rasbian, I need to transmit data on a bananaPi with 4MB/sec. The setup I found to do this on the Raspbian is:
Create a config.txt file in the /boot/ folder in which write:
init_uart_baud 4000000
init_uart_clock 64000000
From info I found the clock devider is 16, so to get 4MB I just need to set the clock to 64000000 which gives me 4000000(4Mb).
To send data and check if it's transmited with 4Mb/sec I use an oscilloscope connected to TX pin of the bananaPi and in a terminal write:
echo -ne '\xA' > /dev/ttyS2
I can see the data on the oscilloscope but it's transmited with no more than 1.5 Mb(which is the default max value of the UART settings)
I alos tried a Python script:
import serial
if __name__ == '__main__':
connection = serial.Serial()
connection.port = "/dev/ttyS2"
connection.baudrate = 4000000
connection.timeout = 1
connection.write('\xAA')
............
It is still transmitted with 1.5 Mb
Do anybody have an idea on how to setup the bananaPi to work with this higher frequency?
Thanks

python-serial OSError: [Errno 11] Resource temporarily unavailable

I am using Arduino Nano to serial communicated with ODROID (single-board computer installed Ubuntu 14.04).
The Arduino code:
void setup() {
Serial.begin(9600); // set the baud rate
Serial.println("Ready"); // print "Ready" once
}
void loop() {
char inByte = ' ';
if(Serial.available()){ // only send data back if data has been sent
char inByte = Serial.read(); // read the incoming data
Serial.println(inByte);
}
delay(100); // delay for 1/10 of a second
}
The Python code in ODROID:
#!/usr/bin/env python
from time import sleep
import serial
ser = serial.Serial('/dev/LIDAR', 9600, timeout=1) # Establish the connection on a specific port
sleep(1)
print "Arduino is initialized"
counter = 32 # Below 32 everything in ASCII is gibberish
while True:
if (ser.inWaiting()>0):
counter +=1
ser.write(str(chr(counter))) # Convert the decimal number to ASCII then send it to the Arduino
print ser.readline() # Read the newest output from the Arduino
sleep(.1) # Delay for one tenth of a second
if counter == 255:
counter = 32
ser.close
Traceback(most recent last):
File "./serial_test1.py", line 16, in <module>
print ser.readline() # Read the newest output from the Arduino
File "/usr/lib/python2.7/dis-package/serial/serialposix.py", line 43, in read
buf = os.read(self.fd, size-len(read))
OSError: [Errno 11]Resource temporarily unavailable
Then I had this issue after print some values, I know this problem maybe no data in available at current time. But how can I figure out this issue. Thanks for your help.
I don't know if this will work for ODROID, but I found a post about similar problem with Raspberry PI. In that post one of the answers redirected to this link
There it says the problems is caused by Raspberry Pi serial port, which is used by default to use the system console which conflicts when you try to use it for your own purposes
To disable the serial por for console you must edit the file /etc/inittab and comment the line T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100 (You comment it with a # at the begining of the line, like in python). You must reboot the ODROID and it should work
I suggest you to read the answer I linked cause it explains a bit more about how can you substitute the serial port to access the command line (It suggests using ssh) and another thing is that Raspberry PI (And assume ODROID works similar) sends at boot time a message through serial port that will be received by the Arduino. You can remove that message and it's explained there
Hope this helps you
You are receiving this error since your serial device is being used by os itself. You should stop os to use this device.
Serial getty is now a service and you should stop and/or disable it:
sudo systemctl stop serial-getty#ttyAMA0.service
sudo systemctl disable serial-getty#ttyAMA0.service
Note that my native serial device id is ttyAMA0.
to permanently disable serial service, use
sudo systemctl mask serial-getty#ttyAMA0.service
in this case serial service will not start even on reboot.

Python script to configure an XBee module fails on a raspberry pi

I have a python script that I want to use to configure some XBee modules. It works perfectly find when connect to a computer via an xbee development board, but fails when connect to a raspberry pi via the slice of pi board.
I have narrowed down the problem to it failing to enter the command mode, after sending the +++ the xbee never sends the OK message. Here is the relevant code:
...
CC = '+'
GT = '1.1' # Tried different values here
...
def startCommandMode(self):
self.emptyBuffer() # Tried with and without this line
sleep(self.GT) # Tried with and without this line
self.ser.write(self.CC + self.CC + self.CC)
sleep(self.GT)
return self.getReply() == 'OK'
...
def getReply(self):
count = 0
reply = ''
while True:
char = self.ser.read()
if char == '\r':
break
if len(char) == 0:
return None
reply += char
return reply
The full source is available on github if needed.
I know it is not a problem with the xbee module, the raspberry pi or the slice of pi board as it works perfectly fine if I try it manually using "picocom -lc /dev/ttyAMA0".
Some things to check:
Are you getting anything in response?
Have you enabled flow-control on the XBee? Make sure D6 and D7 are set to 0 since the Raspberry Pi serial port doesn't have flow control.
Is the Python code configured for flow control? It might be waiting for a CTS signal that is never asserted.
Can you try using the XBee Development Board on the Raspberry Pi's USB port?
Use the following:
....
if args.common:
args.at = ['ID', 'CH', 'MY', 'DL', 'DH', 'AP'] + args.at
xbee = XBee(args.port, args.baud);
sleep(2)
xbee.CC = args.CC
xbee.GT = args.GT
....
....
IMHO I thick Rpi need more time to initialize serial port, thats why I am using this delay
. Also is applicable for transparent mode so add a delay after port init.
I hope this will Ok for you. For me it is solved.
BR.
Manel.

Categories

Resources