RaspberryPi 3 temperature sensor remote I/O error (python) - python

I have a temperature and humidity sensor connected to my RPi via 3.3v power, GND and SDA and SCL. I am trying to get a temperature reading from it but I keep getting a
"OSerror: [Errno 121] Remote I/O error".
The i2c interface is enabled and everything is up to date. I can see the address of the device using sudo i2cdetect -y 1. Could it be possible that i should be sending some data to it first so that the sensor "knows" that i am about to read from it and it should be sending data ?
This is my code
import smbus
TEMP = 0x40
bus = smbus.SMbus(1)
state = 1
while (state):
print("1.Read temperature")
print("2.Exit")
choice = input("")
if choice =='1':
Ctemp = bus.read_byte(TEMP)
print ("%d" %Ctemp)
elif choice == '2':
state = 0

Yes, it's possible you might have to configure your I2C device (you don't mention what you use, so I can't look that up for you) but this error probably means something else.
You can try i2cdump -y 1 0x40 to see what data is available, but again, you should read the sensor's chip's datasheet in order to know what to work with.

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!

How to send an API frame to a remote XBee using Digi XBee Python module?

I am moving code from Python XBee library to Digi's Python XBee library and I am unable to locate syntax in the docs on how to send a API frame to a remote XBee. I am using S1 and S1 Pro devices where the "local" device is attached to a Beaglebone and the "remote" devices are standalone out in the wild.
I have the basic framework down:
from digi.xbee.devices import XBeeDevice, RemoteXBeeDevice, XBee64BitAddress
PORT = '/dev/ttyO1'
BAUD = 9600
API_FRAME = 'long-hex-string-here'
local_xbee = XBeeDevice(PORT, BAUD)
local_xbee.open()
# Instantiate a remote XBee device object.
remote_xbee = RemoteXBeeDevice(local_xbee, XBee64BitAddress.from_hex_string("0013A20040DD7DCD"))
# Transmit frame to remote_xbee - unsure of correct method and syntax
# perhaps XBeePacket.create_packet(hex string here)
# local_xbee.send_data(remote_xbee, "api frame here?") ??
local_xbee.close()
but I am unable to locate syntax for how to transmit my constructed API frame. Based upon the Introduction section in the docs I presume that is the correct approach. I am not interested in broadcasting to all devices on the network but rather unicast communication.
I have some older model of the source when I could get it to work.
…
I have some WiFi Xbee modules that I used w/ some converter boards (base boards). I used it to attach the communication of the Xbee from one computer to another, e.g. random desktop to BeagleBone Black via USB instead of UART. So, I would use the source, listed below, to attach my USB dongle for the Xbee communication from the BBB to the other field module.
Their I/O stuff can be found here: https://github.com/digidotcom/xbee-python/tree/master/examples/io.
Also...changing just some of their lines in their source w/ the USB dongle WiFi adapter boards proved valuable in signaling LEDs and other sensors.
Oh and you will need what they are now calling Carrier Boards. It is the adapter board I just typed out. So, if you have already got a Carrier Board, use lsusb as the command in Linux to find your USB "name."
So, for instance, if lsusb brings up /dev/ttyUSB0, then that is the port identification.
And you can use that section, from lsusb, to then change your xbee modules in the xtcu software from Digi.
…
from digi.xbee.devices import XBeeDevice
from digi.xbee.io import IOLine, IOMode
import time
import threading
# TODO: Replace with the serial port where your local module is connected to.
PORT = "/dev/ttyUSB0"
# TODO: Replace with the baud rate of your local module.
BAUD_RATE = 9600
REMOTE_NODE_ID = "Xbee_B"
IOLINE_IN = IOLine.DIO2_AD2
IOLINE_OUT = IOLine.DIO4_AD4
def main():
print(" +-----------------------------------------------+")
print(" | XBee Python Library Get/Set Remote DIO Sample |")
print(" +-----------------------------------------------+\n")
stop = False
th = None
local_device = XBeeDevice(PORT, BAUD_RATE)
try:
local_device.open()
print("local device: ", local_device.get_node_id())
# Obtain the remote XBee device from the XBee network.
xbee_network = local_device.get_network()
remote_device = xbee_network.discover_device(REMOTE_NODE_ID)
if local_device is None:
print("Could not find the remote device")
exit(2)
def io_detection_callback():
while not stop:
# Read the digital value from the input line.
io_value = remote_device.get_dio_value(IOLINE_IN)
print("%s: %s" % (IOLINE_IN, io_value))
# Set the previous value to the local output line.
local_device.set_dio_value(IOLINE_OUT, io_value)
time.sleep(2)
th = threading.Thread(target=io_detection_callback)
remote_device.set_io_configuration(IOLINE_IN, IOMode.DIGITAL_IN)
local_device.set_io_configuration(IOLINE_OUT, IOMode.DIGITAL_OUT_HIGH)
time.sleep(1)
th.start()
input()
finally:
stop = True
if th is not None and th.is_alive():
th.join()
if local_device is not None and local_device.is_open():
local_device.close()
if __name__ == '__main__':
main()
So, see the PORT = "/dev/ttyUSB0" section of the source?
This is where I attached my Xbee module to the Carrier Board and then attached the Carrier Board to the BBB by way of USB.
Um, this may not answer a question but give more insight as to how to handle Digi Devices/Modules.
I also think that if you want to venture in this direction of UART communication w/ Xbee and the BeagleBone Black, it may be more complicated. I will keep searching my text.
P.S. This book goes over some methods to connect, Experiment 10 and Experiment 16, your "BBB" to a UART, Xbee, and how to communicate. It is a bit too in depth to get all of the communication ideas from this book but this is it:
The Hands-on XBEE Lab Manual, Experiments that Teach you XBEE Wireless Communications – Jonathan A Titus

Multiple reproducible errors with a Brecknell Scale

I'm working on getting a weight from a usb scale using python and PyUSB. Here's my code
import sys
import usb.core
import usb.util
from reports import \
ReportFactory, STATUSES, ZERO_WEIGHT, STABLE_WEIGHT, DATA_REPORT
device = usb.core.find(idVendor=0x67b, idProduct=0x2303)
if device is None:
raise ValueError('Device Not Found')
if device.is_kernel_driver_active(0) is True:
device.detach_kernel_driver(0)
usb.util.claim_interface(device, 0)
device.set_configuration()
collected = 0
attempts = 50
while collected < attempts:
ret = device.read(0x2,0x0040)
sret=''.join([chr(x) for x in ret])
print "Return Raw: ",ret
print "Return : ", sret
print ReportFactory.build(ret)
# release the device
usb.util.release_interface(device, 0)
device.attach_kernel_driver(0)
The first time I run this program I get Resource busy error
The second run I get Operation timed out on the 5th dump.
Subsequent runs after that result in immediate timeouts.
There are several things going on here
Why do I get a resource busy error on first run? I would think the kernel_driver if statement I have should take care of it.
Why do I get data that looks nothing like what a USB scale should produce?
Why the timeout after 4 dumps of data? Everytime!
The device information is thus
Any help would be much appreciated!
Ok, anyone that is struggling to get anything from the GP100 Brecknell scale using PyUSB, switch to PySerial. Since this is one of the cheapest USB scales on the market, I'm guessing this information will help many.
I emailed the manufacturer for documentation and they've sent me some valuable serial protocol information.
If you set the protocol of the scale to 7010 you can use python code that looks like this
import time
import serial
ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate=2400,
bytesize=8,
parity='N',
stopbits=2
)
while 1:
x = ser.read(100)
print(x)
This will stream 8 bytes of data.
The first byte is status information that can be interpreted thusly
Bits 2-4
Bits 5-8
Bytes 2 & 3 can be safely ignored.
Bytes 4-8 have the weight information, represented by characters 0-9 (e.g. 00023 = 2.3 lbs). This scale is only accurate +- 0.6 lbs and does not work in ounces, perhaps other models using the same serial controller utilize the oz capabilities. The PG100 does not.

Can't communicate with Modbus device using minimalmodbus

I am failing to communicate with a device using minimalmodbus, Modbus RTU.
I have connected the device to a raspberry pi via a usb to rs-485 adapter (FTDI chip) A to A and B to B.
The device configurations are as follows:
Port settings:
Baud rate: 9600
Parity: No
Stop bits: 1
Silent Interval: 70 ms.
Transmission Mode: RTU
Interface 2 Wire RS485
Connector of ECM: DB9
Connections: A on pins 1, 4. B on pins 6, 9
Modbus Holding registers (simplified for the purpose of this example)
Swapped Floating point format:
40001 (address 0) Parameter 1
40003 (address 2) Parameter 2
I have tried using raw serial commands to communicate with the device, as well as using pymodbus, and now on my latest attempt minimal modbus. Please see below my code attempt using minimalmodbus.
Also, i know the serial adapter works as i use it for various other serial sensors. Only difference is that i am working with modbus now.
import minimalmodbus
instrument = minimalmodbus.Instrument('/dev/tty/USB1',1)
instrument.debug = True
instrument.handle_local_echo = True # The serial device echos back every write, hence this
instrument.serial.baudrate = 9600
instrument.serial.timeout = 1
value = instrument.read_register(0,2)
print value
I expected to receive some sort of reply even if an error or incorrect, but i am getting nothing. the debug output of minimalmodbus says "IOError: No communication with the instrument(no answer)"
Is there any obvious mistakes in my code vs the sensor requriements? I confirmed my wiring with the manufacturer, and is correct.
Quoting from the manual of your cable:
The USB-RS485-WE cable allows for local echo to be enabled/disabled by changing a bit in the FT232R
EEPROM. If CBUS4 in the EEPROM is set for “PWRON#” local echo is enabled. If CBUS4 in the EEPROM is
set for “TXDEN” local echo is disabled.
Users can set this with MPROG from www.ftdichip.com
The default for the local echo is disabled (CBUS4 set for “TXDEN)
Phew! lots of info in there. According to the thread of comments on your question you activated the software echo handling on minimalModbus because otherwise your routine would not wait for the response from the device on the other end. That makes one think whether your cable has the local echo enabled or disabled.
Fortunately, you can check that very easily. As the manual says just go get MPROG here. Extract and run (yeap, you need Windows for this tool, but you can run it on a Virtual Machine).
Connect your cable to the USB port (don't forget to send the device to the virtual machine if you are running one) and select Tools-->Read and Parse on MPROG.
This is what you should get:
Make sure you have TXEN selected on box C4. According to the manual, you should have TXEN by default, if you see PWRON# it means the local echo is active. Disable it and you should be good to go to use Modbus.
I don't see an obvious error from your side. That's rather difficult since you are working with hardware.
I'll provide some of my code. I used it for a prototype, which was a Raspberry Pi 3B with a USB to RS485 converter (This one).
from modbus import minimalmodbus
import serial
import time
from mqtt.client import Client as mqtt_client
class Slave:
def __init__(self, serial_port: str = '/dev/ttyUSB0', slave_id: int = 5,
baudrate: int = 38400, byte_size: int = 8,
parity: str = serial.PARITY_NONE, stopbits: int = 1,
timeout: float = 1.0):
self.slave = minimalmodbus.Instrument(serial_port, slave_id)
self.slave.serial.baudrate = baudrate
self.slave.serial.bytesize = byte_size
self.slave.serial.parity = parity
self.slave.serial.stopbits = stopbits
self.slave.serial.timeout = timeout
self.registers = ["header", "zero", "life_beat",
"test_int", "test_float"]
self.output = mqtt_client()
...
When I read a register I used e.g.:
self.slave.read_register(2)
//or
self.slave.read_float(5)
I'm not sure which python version I used. I think it was 3.6.x.

Reading output buffer of Agilent 4156C using PyVisa

I'm trying to use PyVisa to control an Agilent 4156C using its FLEX command set. The communication seems to be working OK, as I can query the instrument with *IDN? and read the status byte. I also think I'm setting up my voltage sweep properly now, as I don't see any errors on the screen of the 4156 when I execute the Python script. My problem is that when I try to read the measurement data using the RMD? command, the instrument doesn't respond, and the program errors due to timeout. Here is my current program:
import visa
rm = visa.ResourceManager()
inst = rm.open_resource('GPIB0::17::INSTR')
print(inst.query('*IDN?'))
inst.timeout = 6000
print(inst.write('US'))
print(inst.write('FMT 1,1'))
# Set short integration time
print(inst.write('SLI 1'))
# Enable SMU 3
print(inst.write('CN 3'))
# Set measurement mode to sweep (2) on SMU 3
print(inst.write('MM 2,3'))
# Setup voltage sweep on SMU 3
#print(inst.write('WV 3,3,0,0.01,0.1,0.01'))
print(inst.write('WV 3,3,0,-0.1,0.1,0.01,0.01,0.001,1'))
# Execute
print(inst.write('XE'))
# Query output buffer
print("********** Querying RMD **********")
print(inst.write('RMD? 0'))
print(inst.read())
print("********** Querying STB **********")
print(inst.query('*STB?'))
The program always hangs when I try to read after writing 'RMD? 0', or if I query that command. I feel like I am missing something simple, but just not able to find it in the available Agilent or PyVisa documentation. Any help would be greatly appreciated. I'm using the standard NI VISA that comes with LabView (I mention that because I came across this post).
I encountered the same problem and solved it.
Command XE launches the execution of current/voltages measurements with Agilent 4156C: it is thus not possible to send any additional GPIB command during execution. Even "STB?" does not work.
The only way I found to check status byte and measurement completion is checking continuously "inst.stb" paramter which is updated continuously by visa driver.
Hope this will help other users.
My code:
class Agilent4156C:
def __init__(self, address):
try:
rm = visa.ResourceManager(r'C:\\Windows\\system32\\visa32.dll')
self.com=rm.open_resource(address)
self.com.read_termination = '\n'
self.com.query_delay = 0.0
self.com.timeout=5000
except:
print("** error while connecting to B1500 **")
def execution(self):
self.com.write("XE")
while self.com.stb != 17:
time.sleep(0.5)

Categories

Resources