PyVISA SerialInstrument requires hard reset to connect after failure - python

I am working with a Keysight waveform generator and pyVisa and I notice that if my code doesn't complete successfully and ends I need to perform a hard reset of the device to attempt my code again.
I have tried resetting the device under the __del__ method so that the device is in a known state but that doesn't seem to work. I've also tried using pyvisa.resources.SerialInstrument.clear(). Has anyone else had a problem like this and how did you solve it?
The host computer is running windows 7. PyVISA version is 1.8. After the program fails by me cancelling the python script I will try to send a simple *IDN? SCPI command to the device and I get error:
pyvisa.errors.VisaIOError: VI_ERROR_TMO (-1073807339): Timeout expired before operation completed.
If I try to call pyvisa.resources.SerialInstrument.clear() on the device I get error
pyvisa.errors.VisaIOError: VI_ERROR_INV_SETUP (-1073807302): Unable to start operation because setup is invalid (usually due to attributes being set to an inconsistent state).

The problem was that the device was still being connected to by another instance. The cause of that was because running visa.ResourceManager().list_resources() was listing the device twice, once as a USB device and also as an ASRL.
The solution was to call visa.ResourceManager().list_resources(query='USB?*') to make sure that the instrument is only listed once in my results. (Alternately, I could have disabled USB or GPIB in the device settings.) Then call device.clear() immediately after opening the resource to make sure that the buffers were empty because at the error there might have been unread data there. This solved the problem.

Related

How do you connect PyVisa to an Arduino Uno?

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.

Bitcoin RPC connection keeps failing

Im trying to get an RPC connection to my bitcoin core to work, but no matter what I try, it keeps failing.
I'm running Win 10 and have bitcoin core qt V0.21 running.
I have tried several options to get the RPC connection to work. I tried several docker container like btc-rpc-explorer but those keep on failing with a ECONNREFUSED error. Worried about some IP problem with docker, I also tried running different python scripts (like this on: https://pypi.org/project/bitcoinrpc/) but that also gives an exception indicating that no rpc connection is possible.
So, it must be my bitcore node then, right? So I tried many different bitcoin.conf configurations without luck. My latest:
server=1
rpcallowip=0.0.0.0/0
rpcbind=127.0.0.1
rpcbind=0.0.0.0
rpcport=8332
rpcuser=myuser
rpcpass=mypass
txindex=1
Just trying to open it up as much as possible.
I also tried running bitcoind on commandline in stead of bitcoin-qt gui. The commandline output shows me that it takes the correct bitcoin.conf file. So thats okay. But what is wrong???
server=1
rpcallowip=127.0.0.1
rpcport=8332
rpcuser=myuser
rpcpass=mypass
txindex=1
If you are doing your rpc calls within localhost this conf file should be enough.
I would bind to 0.0.0.0 only if you need to query from an external ip.
rpcallowip=0.0.0.0/0 is also insecure

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

Pyserial persistent configuration

I have this code for sending file size from linux machine to embedded device:
#send length
device_port = serial.Serial("/dev/ttyUSB1", 115200, timeout=3)
device_port.write(program_length_str)
#get response
answer = device_port.readline()
if answer != "OK":
print "Size transmit failed:"
print `answer`
device_port.close()
quit()
The problem is that when I run this code (it always quits here) the programmer (which loads firmware to the device over the same serial port) quits with the bad file descriptor error. Replugging the device (no internal energy source in it) doesn't help, I have to reboot my computer. What is wrong with the Python code? How is it possible that the bad setting stays even when I replug the device (FT2232)?
Opening the port with cutecom enables programming the device, but when I close it again, the error is back.
UPDATE 1: Using strace I found out that first difference is in locks:
open("//var/lock/LCK..ttyUSB1", O_RDONLY) = 4 in the beginning of successfull load,
open("//var/lock/LCK..ttyUSB1", O_RDONLY) = -1 ENOENT (No such file or directory)
on failure. The second difference (and the whole error) may be bug in the loader, so I wrote on the toolchain forum (they consider read() returning 0 to be an error, call perror(), but there was no error, so EBAFD is stored in errno from earlier). But I am curious about the the locks. I couldn't find any reference in cutecom or python scripts (using strace), but the locks are affected somehow. Would it be possible to migrate this question to the Unix & Linux site?
UPDATE 2: As I mentioned before, the problem is that read() on the serial port returns 0. When I focused on this, I found out that read() should block or return EAGAIN in non-blocking mode. Under what circumstances the read() call can return 0?
UPDATE 3: I "resolved" the problem with the loader by wating for the device with the select() call. There is still the problem with PySerial changing something in the port.
I don't think your problem has anything to do with Python.
I faced the same problem when programming my Arduino using Ubuntu - sometimes, after a few times of plugging it in and unplugging it again, Ubuntu wouldn't recognize my device anymore. It then simply didn't show up in /dev/.
I guess that's also the source of your problems. bad file descriptor most like tells you that the path you specified doesn't actually exist. Have you checked /dev/ttyUSB0 ? If that doesn't work, I suggest to upgrade your installation to the newest one available.
I worked quite a lot with python serial and ubuntu, and the problem is about how ubuntu 'mount' serial ports, sometimes fails, and ...
could you post your dmesg output? this may help to double check the root of the problem.

What are the functions / AT commands to reconnect a disconnected GSM modem?

I have a GSM modem that disconnect after a while, maybe because of low signal. I am just wondering is there an AT command that can detect the disconnection and re-establish a reconnection.
Is there a way in code (preferably python) I can detect the disconnection and re-establish a reconnection?
Gath
Depending on what type of connection, circuit switched (CS) or packet switched (PS), the monitoring will be a little bit different. To detect a disconnect you can enable UR (unsolicited result) code AT+CPSB=1 to monitor PDP context activity (aka packet switched connections). For circuit switched calls you can monitor with the +CIEV: UR code enabled with AT+CMER=3,0,0,2.
To re-establish the connection you have to set up the connection again. For CS you will either have to know the phone number dialed, or you can use the special form of ATD, ATDL [1] which will dial the last dialed number. You can use ATDL for PS as well if the call was started with ATD (i.e. "ATD*99*....") which is quite common, but I do not think there is any way if started with AT+CGDATA for instance.
However, none of the above related to ATD matters, because it is not what you want. For CS you might set up a call from your python script, but then so what? After receiving CONNECT all the data traffic would be coming on the serial connection that your python script are using. And for PS the connection will not even finish successfully unless the phone receives PPP traffic from the PC as part of connection establishment. Do you intend your python script to supply that?
What you really want is to trigger your PC to try to connect again, whether this is standard operating system dial up networking or some special application launching it. So monitor the modem with a python script and then take appropriate action on the PC side to re-establish the connection.
[1]
Side note to ATDL: notice that if you want to repeat the last voice call you should still terminate with a semicolon, i.e. ATDL;, otherwise you would start a data call.
Here is how I do it with Telit devices:
I use AT+CGREG=1 to subscribe to unsolicited messages. Extract from documentation:
+CGREG - GPRS Network Registration Status
AT+CGREG=[<n>]
Set command controls the presentation of an unsolicited result code
+CGREG: (see format below).
Parameter:
<n> - result code presentation mode
0 - disable network registration unsolicited result code
1 - enable network registration unsolicited result code; if there is a change in the terminal GPRS network registration status, it is issued the unsolicited result code:
+CGREG: <stat>
And I wait on the modem's serial line for +CGREG messages. When something comes I check to see if stat is 1 (connected to the home network) or 5 (connected in roaming).
NOTE: A different response +CGREG comes when issuing the AT+CGREG? which is not hard to isolate.
You can try to check the signal strength on a regular basis with AT+CSQ. If the signal goes under a given threshold consider that you are disconnected and force a new connection.
You can try the very nice pyserial http://pyserial.sourceforge.net/ Python library to send the AT commands to the modem.
I hope it helps

Categories

Resources