Can a device have two UMDF Drivers? - python

This may seem like a bit of an odd question, but I was wondering if it is possible to associate two drivers with a peripheral device?
The reason I ask is that I am building an input device for Maya using an Arduino microcontroller. The Arduino already has its own device driver, but I was thinking of developing a UMDF driver to take the data that comes in from Arduino over the serial port and pre-process it ready to go into Maya.
Right now, I have two Python programs running - a 32-bit Python program running outside of Maya which listens to the serial port and converts the data to a form which a second 64-bit program inside the 64-bit version of Maya can understand and use in the Maya scene. This works fine, but it is a bit annoying having to start that external server program every time I want to use this device in Maya. If I can have a UMDF driver ready to jump into action when the appropriate type of data comes in off the Arduino then this would help immensely. Will this approach work?

It's more a comment/suggestion than an answer, but maybe it would be worth to invest some time and check if the filter driver would do the job for you. In WDM you can put it above the kernel device driver on the driver stack for that device, and use it to pre-process your device data. I think it is also possible in UMDF.
See Creating a New Filter Driver (MSDN).

You may always try to use Teensy/Teensyduino instead of Arduino to implement a virtual keyboard, mouse, joystick or other HID device. This does not require Windows drivers, and accessing the keyboard or joystick from Maya may be easier that the serial port.

Related

Barcode scanners (Netum Scan) in python

I'm writing code which takes input from several barcode scanners, and I want a way to differentiate between each scanner. I'm on windows 10, and my python version is 3.11.1. And as the title suggests, I'm using scanners from a company called Netum.
I've tried using them as HID devices, but this seems incredibly slow and impractical. If the computer sees them each as keyboards, I have to validate each individual keystroke, rather than entire barcodes. So I've abandoned this approach under that assumption.
I discovered these scanners have what's called "USB COM Port Emulation," and that seems promising. It almost never works, but when it does, it just shoves an entire barcode into my code as a string. The problem is that, most of the time, when it's in this mode, it disconnects the USB dongle the instant I scan anything. But it makes a reference to "needing drivers" for this mode. I checked the device manager, which tells me all my drivers are totally up-to-date. This is really the crux of the problem, as my code works if this mode works reliably.
Also, I'm using PySerial to decode the inputs from the scanners. I dunno if that matters, but I figured I'd mention it. The following is the code I'm using to talk to these janky scanners, and it only works when the scanners don't disconnect from my PC for seemingly no reason.
import serial
scanner = serial.Serial(port='COM3', baudrate=9600, bytesize=8, timeout=1, stopbits=serial.STOPBITS_ONE)
string = scanner.read()
print(string.decode())
scanner.close()
If anyone has any advice, insights, or even just general directions to point me in, it would be appreciated. I'm at the point where I don't even know how to begin solving this.
Comment to answer
Have you installed any Virtual Com Port (VCP) drivers such as from FTDI? ftdichip.com/drivers/vcp-drivers They do a executable for easy install - this may help with your stability issues

Using Python and pyserial to run python scripts on a pico (RP2040)

My ultimate goal is to control a number of peripheral chips on a PCB from a GUI interface on a PC. To do so, my plan was to incorporate a RP2040 (and memory) on the PCB in order to hold all the python scripts and to program/monitor all the peripheral chips. Then, using a PC to interface with the RP2040, send commands over the serial port to execute specific python files on the pico.
I realize that is a bit confusing, so the attached block diagram should help.
Block diagram
Starting on the left of the block diagram, I have a PC running a tkinter GUI. I am currently running the tkinter gui in Thonny. (eventually i would like it to be an executable, but that is beyond the scope of this post) The gui has a number of buttons to choose which python scripts to run. The PC is connected to the PCB through the USB cable. The USB data lines are routed to the RP2040's USB inputs (pins 47,48). The memory on the PCB holds a number of python scrips that correspond to the buttons in the GUI. Ideally, pressing a button on the PC would execute the corresponding py file on the pcb.
What I've got working so far:
My real expertise lies in peripheral chips and PCB design, in this case the front end for a 2-18GHz transceiver, so bare with me if some of my python questions seem basic or misinformed. I've written and tested all the .py files on the pico's memory. To test those scripts I used Thonny to connect to my pico and simply ran (f5) the scripts with the peripherals connected to the right GPIOs. I was also able to get tkinter working and create functioning buttons that can execute commands. Using the pyserial module, I am also able to connected to the pico through the USB and write... strings. Not very useful, but a start.
import serial
ser = serial.Serial('COM3', 38400, timeout=1, parity=serial.PARITY_EVEN, rtscts=1)
s = ser.read(100) # read up to one hundred bytes or as much is in the buffer
print(ser.name) # check which port was really used
ser.write(b'ToggleLED.py') # write a string
ser.close() # close port
Remaining task: The final task I have been failing miserably at the past 2 days has been actually trying to execute the .py files located on the pico's memory through the serial port. My unexperienced/naïve notion was to simply send a string with the files name, obviously not correct. Any thoughts on how to execute those py files using that pyserial module?
BTW, if there is a better solution, please feel free to share! Perhaps the files should be located on the PC and i send 1 command at time?
I can't say anything about your serial problems until you clarify just what is running on the pi (see my comment: I'll update this answer when you do), but re 'is there a better way': possibly.
Since the Pi is running a full operating system, there are a few options. You are basically creating a network connection to the Pi. Whilst this can be done over serial (with the Pi, presumably, acting as a fake USB serial device), it can also be done more conventionally over wifi or ethernet. Lastly, you could host your interface on the Pi and interact with it in a webbrowser, cutting the second computer out of the picture. Exactly which option you decide to take is up to you, and is really off topic here (though it might be on topic elsewhere on SE).
Sending commands to the pi and having it run scripts is Remote Procedure Call. You might want to lookup some of the protocols (like JSON-RPC) generally used to do that, but the basic approach will have code running on the pi:
def do_something():
pass
def do_something_else():
pass
functions = {"something": do_something, "something_else": do_something_else}
while True:
cmd = get_input() # blocks until input comes
if cmd in functions:
reply(f"Running {cmd}")
output = functions[cmd]()
reply(f"{cmd} returned with output {output}")
else:
reply(f"Invalid command {cmd}")
This is schematic: exactly what get_input() on the pi is will depend on how you end up connecting, and what protocol (if any) you end up using. Notice that I have built in confirmation: you want to know if things work or fail.
Whilst you could store these commands in separate scripts and invoke them, if they are just python scripts there is no reason not to call the functions directly from the code running on the pi.
I've seen two different solutions to the question:
With the Pi pico running the REPL (python shell), text strings can simply be sent from a python program running on the host (Windows or Raspberry Pi, etc., connected to the USB com port, with Thonny window closed), and sent to the pico as python commands. This approach is detailed in:
https://blog.rareschool.com/2021/01/controlling-raspberry-pi-pico-using.html
On the pico side, one just need to define a number of functions that will execute from the REPL. E.g.,:
from machine import Pin
# use onboard LED which is controlled by Pin 25
led = Pin(25, Pin.OUT)
# Turn the LED on
def on():
led.value(1)
# Turn the LED off
def off():
led.value(0)
Any string sent to the pico, such as
on()
will be executed accordingly.
In the 2nd approach, the pico will read each line from the USB serial port and parse the line into command and additional parameters, to be compared against a list of predefined commands and executed accordingly. I did that using the Arduino Due, and I'm in the process of porting it to the pico (= no code to show yet :-().

Raspberry Pi Keyboard Splitter

I would like to program a Raspberry Pi to take a single keyboards inputs in one USB port and then output through the Pi's two other USB ports in order to control two Macs at once with one keyboard.
I'm very new to Python. Which functions and commands do I need in order to program this function to my Pi?
I've been searching for the proper command, but I came here for help.
This isn't exactly something easily done with Python. This is because you're delving into developing device drivers on your Macs' side. Please allow me to explain:
Assuming you're using Raspbian on the Raspberry Pi (a flavor of Linux, and thus a Posix system onto itself), you would need to read the appropriate /dev/tty* file which maps to your keyboard first, and then appropriately convert and write out to the appropriate /dev/usb* files. Do note, most computers also send handshakes back and forth to the USB devices (for example, to register them on their own USB busses).
To be frank, you'd probably have better luck splicing wires from your keyboard, and connecting it to another USB male-socket, and then plugging both male-socket ends into your Macs.

Detect when new USB device is connected (plug'n'play)

Using this answer, we are able to query all the USB devices connected at a precise moment.
I have a Python program running on Linux (Debian or RaspBian) that does a specific task, but I also want that this program listens if new USB device is connected, and when this happens, trigger a specific action.
I'm thinking about doing a new thread that does:
while True:
list_USB_devices() # using https://stackoverflow.com/a/8265634/1422096
see_if_new_devices_in_this_list()
time.sleep(2) # wait 2 seconds
but I don't find this solution very elegant.
What's a cleaner solution to detect in the background of a Python program if a new USB device is connected?
Example of application for my program: listen if a new USB-MIDI keyboard/device is connected, and if so, attach it with rtmidi-python "Plug and play!"
Look into the gio library (part of glib). You can attach watches and connect callbacks when devices are created. This way you don't have to poll at all. Set a watch on the devices directory, look for file creation. Filter out files not interested in.
You can probably also look at 'udev' system itself, and write a rule to execute something on apparition of a new usb device.

Simulate keyboard input linux

I work on a project to control my PC with a remote, and a infrared receptor on an Arduino.
I need to simulate keyboard input with a process on linux who will listen arduino output and simulate keyboard input. I can dev it with Python or C++, but i think python is more easy.
After many search, i found many result for... windows u_u
Anyone have a library for this ?
thanks
EDIT: I found that /dev/input/event3 is my keyboard. I think write in to simulate keyboard, i'm searching how do that
To insert input events into the Linux input subsystem, use the user-mode input device driver, uinput. This might help: http://thiemonge.org/getting-started-with-uinput (Note that while the tutorial references /dev/input/uinput, the correct file on my Ubuntu 12.04 PC is /dev/uinput.
The most generic solution is to use pseudo-terminals: you connect tttyn to the standard in and standard out of the program you want to monitor, and use pttyn to read and write to it.
Alternatively, you can create two pipes, which you connect to the standard in and standard out of the program to be monitored before doing the exec. This is much simpler, but the pipes look more like a file than a terminal to the program being monitored.

Categories