See https://sensapex-projects.slack.com/archives/C0257RWNZHC/p1624041208028300

Martin Chase Yesterday at 7:33 PM Meeting summary! ACQ4 has a basic configuration for all the already-supported hardware (Camera, Stage, DAQ, Clamps, Manipulators, Objective Changer, Pressure Control). Next steps: Shahar will be able to do calibrations next week. Luke or I can be available to help with that as needed, but hopefully the instructions and my summary will carry you through without too much confusion. Martin needs to commit the bugfixes he made during the meeting. Martin should find good examples of a USB device for Gregory to look at. Gregory is going to find his device code and think about porting it to python. We should have a conversation with Luke about the new device and how best to interface with it. We should also talk to Luke about general experiment setup and how best to run those experiments. Once we pick a strategy for the new device controller code, Martin should help get Gregory started on writing that, and continue helping as needed. :tophat: 1

39 replies

luke 16 hours ago What kind of device?

Martin Chase 15 hours ago @Gregory Jefferis I don't think I have a firm grasp on the device function. Could you explain it?

Shahar Frechter 14 hours ago Its a mass flow controller that effectively controls the flow of air through. In a typical experiment we use at least 3. I am not in the lab at the moment so don't have the exact model but thats the general make. https://www.alicat.com/product/mass-flow-controllers/ (edited) Alicat ScientificAlicat Scientific Mass Flow Controllers | Alicat Scientific Mass flow controllers accurate to 0.6% reading for 0.01-100% measurement range. Fast Track shipping and drop-in compatible. For fast, accurate mass flow, depend on the engineers at Alicat. Nov 13th, 2017 (5 kB) https://www.alicat.com/product/mass-flow-controllers/

:heavy_check_mark: 1

Gregory Jefferis 13 hours ago In more detail we need to control a custom odour delivery system. This switches between up to 64 odour channels selected by solenoid valves. The flow rates through the system are controlled by mass flow controllers as noted by Shahar. A full description is here. In terms of control we need the following software trigger to arm the valve control box via USB and define a sequence of valve open commands that will depend on a TTL out TTL out to indicate the start of each sweep RS-232 serial control of the mass flow controllers to set the flow rates. The TTL out is obv trivial.

Gregory Jefferis 13 hours ago The RS-232 is actually the least important part because we don’t vary the air flow rates dynamically and the often stay the same throughout an experiment. Nevertheless it would def be nice if we could recapitulate what we had set up in igor pro + Neuromatic (see picture of MFC tab). The full Igor Pro source code is here. I’m sure it would be simpler in Python. image.png image.png

luke 13 hours ago Yeah, it's certainly nicer if you can have the software guarantee that flow rates are set and recorded for each experiment.

luke 13 hours ago This all sounds pretty straightforward; I'm happy to provide assistance when you're ready to start. The basic approach might look like: Write python code that can control the valve controller and MFCs (if it doesn't already exist) Write Device classes that tell acq4 how to configure and use the devices Write user interfaces to allow the devices to be configured via the Manager and/or TaskRunner All of this code can be kept in your own package(s) and imported as extensions to acq4. :white_check_mark: 1

luke 13 hours ago You can probably start on the first step immediately; ideally that code will not depend on anything inside acq4.

Gregory Jefferis 13 hours ago The last piece is the most important and likely most awkward. The 64 channels are controlled by a 96 channel USB DIO board from a small company called ACCES IO. This currently works as follows Their v simple C API was used to write an external function (XOP) for Igor Pro (in separate thread from the Igor UI main thread) that expects a config file defining a sequence of odour channels and pulse durations starts polling a digital input on the acces board waiting for a hardware trigger For each sweep, a TTL out from our ITC18 AIO board triggers the C function to send the next digital out instruction to the USB DIO 96 board. The C function basically sends a small piece of data via libusb libusb_control_transfer to activate the desired digital out. We really need to recapitulate this at some level. The quick(er) and dirty hack would rewrite our Igor XOP as a standalone C command line tool have acq4 write a text config file and start that tool via shell/process at the start of a protocol

ACCES I/O ProductsACCES I/O Products USB-DIO-96 - ACCES I/O Products Features High-speed USB 2.0 device, USB 3.0 and 1.1 compatible 96 lines of digital I/O High retention type B USB connector Mini USB header connector in parallel with type B for stacking and embedded applications Twelve (12) 8-bit ports independently selectable for inputs or outputs All I/O lines buffered with 32 mA source, 64mA sink current capabilities I/O Buffers can be enabled or tri-stated under program control Drivers and sample application provided Jumper selectable I/O pulled up to 5V for contact monitoring, pulled down to ground or floating Jumper selectable power provided via USB cable or external power supply for higher source current capabilities Resettable fused +5VDC outputs per… Show more https://accesio.com/product/usb-dio-96/

Gregory Jefferis 13 hours ago Better would be to figure out if we can talk directly from Python to the USB device (the USB protocol in question is really basic) or link our C function to python. Note that the C function needs to run a loop in a separate thread.

luke 13 hours ago It's pretty simple to access C functions directly from a DLL in python, no compiling necessary. Most of this is handled by the ctypes library.

Gregory Jefferis 13 hours ago Note that the C function needs to run a loop in a separate thread. I’m not sure whether that imposes any restrictions or not.

luke 13 hours ago No, that's fine as well.

Gregory Jefferis 13 hours ago OK cool. Do you happen to have any vaguely similar examples that we could take a look at to get the gist?

luke 13 hours ago There's also a python wrapper around libusb: https://github.com/vpelletier/python-libusb1

luke 13 hours ago .. so yeah, either compile your function into a DLL and access via ctypes, or port your function to python using python-libusb

Gregory Jefferis 13 hours ago Are any of your drivers using python-libusb?

luke 13 hours ago The code in acq4/drivers implements python wrappers around a variety of devices in a mostly acq4-independent way. A few of them use pyserial (for RS-232) and the rest use ctypes. I haven't used libusb, though.

luke 13 hours ago The ctypes drivers all go through acq4.util.clibrary, which makes using ctypes a bit easier by incorporating information from the C header files. For a simple C interface, though, that's probably overkill and bare ctypes is easy enough.

luke 13 hours ago I think if you would have to compile the DLL yourself, then it's easier long-term to use python-libusb. If the DLL is provided by the manufacturer, then I'd go with ctypes.

luke 13 hours ago Hm, there is also https://github.com/pyusb/pyusb; might take a little research to pick between those.

Gregory Jefferis 13 hours ago OK. Our current situation is that the manufacturer supplied a DLL but we needed to write some small C extensions; I therefore assume we would still have to compile a DLL. It’s years since I did any C on Windows, but I have a feeling that may be necessarily eventually. :heavy_check_mark: 1

Gregory Jefferis 13 hours ago The only alternative I can think of to all this to interpose a little microcontroller arduino style that would run the trigger polling loop and to which one could probably define a much simpler communication protocol from python. Any recommendations if I wanted to investigate that? Specifically for a simple python → arduino communication strategy that I could use to send over the details of the odour stimulation protocol. (edited)

luke 13 hours ago Well that's certainly doable, but I imagine adding yet another component will make your system less robust overall (arduino eeproms, in particular, are prone to spontaneous corruption)

luke 13 hours ago Also windows gets cranky when you have lots of serial interfaces.

luke 13 hours ago Can you clarify what the arduino would be doing here–its job would be to pick up the TTL trigger and then ask the valve controller to play out a predefined series of actions?

luke 13 hours ago (after re-reading your message about the acces io board, I think I have a better idea) :eyes: 1

Gregory Jefferis 12 hours ago Can you clarify what the arduino would be doing here–its job would be to pick up the TTL trigger and then ask the valve controller to play out a predefined series of actions? exactly. but I imagine adding yet another component will make your system less robust overall yes. I agree, so I don’t think it would be my first choice.

luke 12 hours ago Looking at your webpage linked above, it seems like the solenoids are controlled by transistors with input coming from the USB-DIO? What if you just used digital outputs from the NI board instead? That should be possible with no new code, and looks much simpler to me.

luke 12 hours ago The NI digital outs can be given exact waveforms that are synchronized with the analog in/out channels, so no polling for triggers necessary.

luke 12 hours ago Hm, on second glance, the “64 independent odour channels” presents a bit more challenge than I expected, at least in the amount of rewiring that would be needed (and possibly this exceeds the DIO capacity of your NI board).

Gregory Jefferis 12 hours ago Thanks so much for the suggestions, Luke. In the past we never had enough digital IOs (we use ~ 80) the amount of data being transferred was too large for our system since we could not run the DIOs at a different sample frequency even though they only really need say 2-5ms precision / 200-500Hz but were running the DAC/ADC board at 20kHz+ If we adopted your suggestion, which is perfectly logical, there are two software considerations Can we expect Acq4 to conveniently configure that many digital out waveforms? Can we run the digital outs at a different sample freq from the main acquisition? On the hardware side we would need to have a 3rd NI board with high density digital outs synchronised with the other 2. We’d have to do a non-trivial rewiring of our control box (half the problem of building them was routing all 80 control signals.

Gregory Jefferis 12 hours ago “64 independent odour channels” presents a bit more challenge than I expected, at least in the amount of rewiring that would be needed (and possibly this exceeds the DIO capacity of your NI board) (crossed, but yes)

luke 12 hours ago Ok, scratch that :wink:

luke 12 hours ago The background thread polling for triggers seems like a simple enough option, and clearly you already know it works.

Gregory Jefferis 12 hours ago Yeah. So I have a strong suspicion that I will take that as the path of least resistance. We did once do a standalone control program with the trigger loop which we started only once and then we used sockets to allow the frontend to send the protocol details. If you had to do interprocess communication on windows from Python/acq4 what would you use? Or from everything I’ve said would you go for a small amount of custom c code → DLL + ctypes? (edited)

luke 12 hours ago I have a bit of allergy to compiling code lingering from my C++ days.. Personally, I'd write the loop in Python and run it as a subprocess just to make sure it polls reliably, and then use an existing python IPC system for communication (some of these IPC systems are extremely simple to use). However, if you want to resurrect your old standalone controller, then sockets are a great way to go.

luke 12 hours ago The standalone process and DLL approaches both sound like the same amount of work to me–either way, most of the effort is probably in figuring out how you want to serialize the command structure and communicate it to the poller.

Gregory Jefferis 11 hours ago Ok. That gives me enough to chew on. Thanks again for all the input.


Log In