How do you connect PyVisa to an Arduino Uno? - python

I'm trying to connect my Arduino Uno to my computer and writing code in python using PyVisa. I have installed PyVisa correctly, since it has worked with other devices. For some reason the Arduino Uno never returns a response. I'm using the NI Visa package, because I was hoping the pyvisa-py was the problem. Is there something I'm missing?
The code I am using to connect is:
import pyvisa_py as pv
port = "ASRL4::INSTR"
rm = pv.ResourceManager()
device = rm.open_resource(port)
The ResourceManager finds the correct port, and I don't get an error making the device. When I try to use a query however, like
print(device.query("*IBN?"))
It gives the following error:
pyvisa.errors.VisaIOError: VI_ERROR_TMO (-1073807339): Timeout expired before operation completed.

I haven't tried to use an Arduino with PyVisa in a long time. I always use the PySerial library instead. Here is a personal note I wrote about four years ago (in 2017) for a Python module interfacing with an Arduino.
This driver does not use the VISA layer to communicate with the device. Instead, it uses the more low-level and less general PySerial library. The reason for that is that the Arduino reboots ("resets itself") whenever the serial port is opened through VISA. This is a feature, not a bug, so that you don't have to manually reset it every time you flash a new firmware version from the Arduino IDE. As a consequence, though, the controller will not respond to requests for about two seconds after opening its serial port. The only way to avoid the reboot is making sure that the serial port's DTR line is not toggled when opening the resource. VISA, however, does so by default, and there seems to be no way to disable this disruptive behavior. In fact, VISA attributes cannot be set until after the resource has been opened. The PySerial library, on the other hand, does not have this limitation.
As the note is four years old, take it with a grain of salt. Things may have changed. But using PySerial instead of PyVisa is still your best bet. See my answer here for a few more details. And maybe do a web search with the keywords "Arduino" and "DTR" to see if there have been any recent developments.

Related

Bleak (python) does not respond on connect

I have found the correct Bluetooth address of the device I want to connect to. When I run the code below, it prints "Connecting to device..." but then hangs and never prints "Connected" or finishes running. No errors are thrown.
import asyncio
from bleak import BleakClient
address = "24:71:89:cc:09:05" # Replaced with actual bluetooth address
async def main(address):
print("Connecting to device...")
async with BleakClient(address) as client:
print("Connected")
asyncio.run(main(address))
Is this issue related to my PC software/drivers? I am on a Lenovo laptop running Windows 11.
Or, do some devices not respond to simple "connection requests"? The device I am connecting to is a Tesla Model 3, and I know there is a particular set of data I should be sending to authenticate. If this is the case, how do I send data without connecting with a BleakClient in this way?
Update: I should mention that scanning / discovering devices works just fine via Bleak. And, I tried connecting to other devices via Bleak and the same issue occurred. Bluetooth through the Windows Settings app works fine though.
I was also having issues using any bleak commands beyond discover(). I downgraded from 0.14.3 to 0.14.0 and that resolved my problem.
When I looked up "python tesla bluetooth api" I found my way to this site, which documents the API which seems great for what you are doing. That lets you do lots of things like unlocking, opening trunk, etc.
It sounds like the main problem is that you can't connect at all in order to do stuff. The way that site is written glosses over that part, just saying "send it over".
I would ensure that you have the right address, you should use this scanning code from the Bleak doc. Also, make sure that you can use bluetooth normally, like by connecting to a wireless speaker.
Sadly, this error is still unsolved in Bleak, in the project they claim: still waiting for someone to capture bluetooth packets.
Trying to connect, you get either an endless hang with no response or if the device is paired upfront:
Connection error: [WinError -2147483629] The object has been closed
It seems the Library isn't very mature for windows:
https://github.com/hbldh/bleak/issues?q=label%3A%22Backend%3A+WinRT%22+

Sniffing data of serial port without removing data from buffer

I am using the bgapi library to manage bluetooth communication using a USB dongle. The library will take a command from my program and will handle all serial communications through the COM port in its own thread. I want to echo back all data coming out of the COM port, but the library only gives me access to what it chooses to parse out itself.
I could go into the bgapi library and change the functionality of the code, setting up a variable or function to return what data is currently being read, but other people are also working on this project and changing the library could cause larger problems or invalidate updates.
Is there any way for me to access the data coming into the COM port without interfering with the library, like sniffing the data going through the COM port without taking it out of the buffer for the library? The library holds the port open for itself and discards the extra data that I want to see.
I'm not sure I understood completely how your library works so I'm not sure this will work for you but you can give it a try anyway.
What you can do (on Windows) is use Termite as a man-in-the-middle with port forwarding.
Since you probably want to keep everything inside one computer you can use com0com to create a couple of virtual ports.
To activate port forwarding on Termite you have to go to settings and then forward on the bottom-left side of the screen. You'll see a menu where you can choose the port you want to forward to. On the following screenshot I can forward from COM1 to COM2:
After selecting the right settings for COM1 you accept and connect by clicking on the big button marked COM1 57000 bps... and you'll see everything incoming on COM1 forwarded to COM2 and displayed on the console.

how can i connect and send commands to a serial port while another program is using it?

I am using a telit he910g card. it is connected to my PC directly using a miniPCI slot.
I am using it for 3G internet connection and A-GPS/GPS services.
My system is running linux mint 17.1, the 3G connection is handled using the network manager APP and works great. The 3G connection is started and handled using a module that is part of a program I am writing.
The code I am using in order to connect to the serial port is this:
def _connect_to_device(self):
""" Connect to a serial port """
try:
self._device = serial.Serial(self._filename, baudrate=self._baud_rate)
except StandardError, e:
raise StandardError("Couldn't connect to GPS device. Error: %s" % str(e))
When I use the python program alone it works great. But when I try and use it while the 3G is on i cant connect to the serial device. The wierd thing is that if I try to connect to it using a program like "minicom" while 3G is turned on it DOES work.
So my question is: how can I make both run and work together? since now they are mutually exclusive.
thanks to all who help. :)
Glad you found a way round your problem. Just for completeness:
Normally, serial ports can be opened by multiple processes.
If one of them does ioctl(,TIOCEXCL) on the open file then further opens will return EBUSY until everyone closes the device. Only root can get past this and open the device at all times.
If root opens the device and does an ioctl(,TIOCNXCL), then other processes can open the device too.
In python, TIOCNXCL isnt defined anywhere, but you can do the ioctl (eg on stdin) with:
import fcntl
TIOCEXCL = 0x540c # from /usr/lib64/perl5/asm-generic/ioctls.ph
TIOCNXCL = 0x540d
print fcntl.ioctl(0, TIOCNXCL)
Ok, so it is solved.
the issue was that the telit module has 2 ports /dev/ttyACM0 (high speed) and /dev/ttyACM3 (lower speed).
I tried to connect to the high speed one, but apparently the 3G uses that one and it causes contentions.
So moving to use the lower speed port in my script solved the issue.

PsychoPy: send triggers over parallel port of PC with XP 32 bit

I am having problems with sending triggers from a 32 bit PC with Windows XP Professional and Psychopy v.1.81.03 to the parallel port.
I am positive that the port address is 378, and am able to send triggers with Eprime and I am able to turn specific pins on and off with the software parmon (http://english.eazel.com/lv/group/view/kl35264/Parmon.htm)
I have tried using the experiment posted by Stéphanie and Nicholas (see this post in the psychopy google group: https://groups.google.com/forum/#!topic/psychopy-users/PxPhRDkuu2A)
I have verified that pywin32 (version 217) and parallel are installed, and tried both
port = parallel.ParallelPort(address=0x0378)
port = parallel.PParallelInpOut32(address=0x0378)
When using ParallelPort, I get:
Traceback (most recent call last):
File “ D:\SebastianKorb\untitled2_lastrun.py”, line 65, in
port = parallel.ParallelPort(address=0x0378) AttributeError: ‘module’
object has no attribute ‘ParallelPort’
Line 65 is where the command port = parallel.ParallelPort(address=0x0378)
is executed (note though that before that there is the line from psychopy import parallel)
When using PParallelInpOut32 I get the same (only now the error is about ‘PParallelInpOut32’)
I also tried to run the few lines of code shown on the psychopy reference manual (http://www.psychopy.org/api/parallel.html):
from psychopy import parallel
port = parallel.ParallelPort(address=0x0378)
port.setData(4)
port.readPin(2)
port.setPin(2, 1)
But again, I get the same type of error.
I should mention that I have also verified that I have administrator access to the file C:\Windows\system32\drivers\parport.sys
Can you please advise me on what I should try next?
I overlooked that it's actually the other way around. The direct calls to the parallel-port functions (as below) are deprecated. Nevertheless, they should still work. So maybe give it a try:
from psychopy import parallel
parallel.setPortAddress(0x378) #address for parallel port on many machines
parallel.setData(0) #sets all pins low
parallel.setPin(2,1) # set a certain pin high
parallel.setData(0) #sets all pins low
You should leave the pin high for a while or leave out the last line. Otherwise, you won't be able to detect the change. That's also how it is done in the Coder hardware demo "parallelPortOutput.py". Maybe try this first.
Best,
Axel
Addition:
Sebastian, my hunch at the moment is that the port does not even get initiated. I think the problem at the moment is that the respective error messages are only logged, but no informative error message is thrown (check the log files). That means that actually somehow the port drivers cannot be accessed on your system for some reason.
In the Coder Shell type from psychopy import parallel and then do next port = parallel.ParallelPort() (no address). Now just type port and paste the output here. My guess is that you only get the base class (ParallelPort) with which you cannot do anything, i.e., something like <psychopy.parallel.ParallelPort object at 0xe4805b0>. In that case, you would need to fix access to the drivers somehow.
I'm gong to back Axel's "hunch" here. I think it's extremely likely that either you don't have a parallel port driver installed or it isn't working. Try installing the InpOut32 driver from here, restart your computer and see if that fixes it:
http://www.highrez.co.uk/Downloads/InpOut32/
cheers,
Jon

Twisted's Serialport and disappearing serial port devices

I'm using twisted.internet.serialport to have my program be continuously connected to a device on a serial port.
Unfortunately my serial port is just a usb device, which means it can be disconnected or reset by the OS at any time (port 2 disabled by hub (EMI?), re-enabling... ). I see that pyserial has support for this for a few weeks and raises a SerialException.
What I would love to do is try to reconnect to the serial port that just disappeared every few seconds.
So, is there any way how I can tell twisted to notify me about a disconnect? Or should I go ahead and write a threaded wrapper for pyserial?
Thanks
It seems the only relevant change in branched version is a call to connectionLost() in the protocol.
Until it's fixed in the trunk I use a:
class fixedSerialPort(SerialPort):
def connectionLost(self, reason):
SerialPort.connectionLost(self, reason)
self.protocol.connectionLost(reason)
I tested it with Twisted 10.1 (on ubuntu) and 8.1 (on my trusty debian). Both works fine. No idea about other OSs though.
http://twistedmatrix.com/trac/ticket/3690 may be related.
The ticket appears blocked on proper Windows support. I'm not sure if this kind of disconnect event will trigger Twisted's internal connection lost detection code, but I would expect it to (even without a recent version of pyserial).
You could probably try out the branch linked from that ticket pretty easily to see if it does what you want, at least. And if so, perhaps you could help get the ticket actually resolved (the 10.2 release is coming up pretty soon).

Categories

Resources