How to Automate Lab Devices with Python

Secretly, many of the devices we use in the lab every day can be controlled by a computer. Analytical scales, syringe pumps, heating baths. But my colleagues in academia barely make use of these options. Why? Probably a combination of simply not knowing it can be done, laziness, and the supplier hiding the option behind a wall of jargon. I really think actually knowing how to build your own simple automation for these devices can make your life much easier sometimes. Just the fact that you know some devices can easily be automated unlocks a range of new experimental possibilities, that would normally be discarded outright because it would (for example) involve you sitting in front of water bath for 24 hours, changing the temperature every 30 minutes.

It has turned into a bit of a side-project slash hobby to automate some of the devices in our lab over the past few years.

It all started during my PhD where we used a Python script to control the water baths controlling the temperature of our sample. For several experiments1), we performed some (extremely) slow temperature ramps. The water bath was not programmable on the little display it had, but it did have a serial cable for “RS-232” communication at the back. Now, modern computers do not have a serial cable port anymore, but luckily, you can buy USB-to-serial cables (or actually, USB-to-DB9, as the thing is actually called) for cheap. We wrote a script to control the water bath over the serial port using pyserial, and boom, we can make the water bath do anything over the PC connection. As it turns out, generally speaking, running a simple Python command to change temperature is wayyy more convenient than using the annoyingly unresponsive buttons on the device itself.

Since then I have automated quite a few devices. Most devices are really surprisingly easy to write a bit of code for once you've done it once or twice before and got the hang of it. Others make life really really difficult. And for others the real problem is finding the right cable to connect your PC to the device - because it was only produced by a company that went out of business in 2004. Below, I will share the general steps you need to take if you want to start automating your laboratory device, followed by a list of devices I automated, with a few personal notes for each. I hope that helps in your own automation-adventures :). Knowing some programming is a prerequisite (ideally Python), but you honestly don't need much knowledge, some trial-and-erroring will hopefully get you most of the way.

Can I Automate My Device, and How?

First, we should probably see if controlling the device from a computer is possible at all:

  1. Check if there is a place to plug in a cable into your device that is not a power cable. If yes, there is a good chance you can control it using software. Typical are USB ports for relatively modern devices, and “DB-9” ports for older ones, but really, you never know what kind of weird connectors companies will use for whatever reason.
  2. Check if there is an official control program. If yes, maybe you want to use that instead of spending a few hours writing a not super-convenient script? If the software costs money, it is quite likely writing your own will not work because it uses some weird proprietary communication protocol. But not always!
  3. Before you do anything else, check if someone already did your work for you. It happens more often than you think. Just search “your device name” with “github”, “python”, or any other programming languages you may know.
  4. If that did not turn up anything, maybe look if your device has an official API (Application Programming interface) or SDK (Software Development Kit“) - basically a set of rules for software to interact with the device. This may be in the manual somewhere. If yes, great! This saves a lot of work! The company essentially gave you a way to directly send commands to their device. Just follow their instructions, and you can be up-and-running quickly. Hopefully they have a library in your favorite programming language available. A good example are Zaber stages, which are very easy to control over a USB-cable. Even if there is an official SDK, it may still be difficult to get started - see some notes below.
  5. If no official API or SDK exists, hopefully the manual does mention the computer connection. This is often given in the end of the manual, long after people normally give up reading. The main keyword here is probably RS-232, which is the protocol that is almost always used for communicate between PC and device. If you find this section, you are in business! In a few hours, you will control the device with ease.
  6. If no mention of computer-controlling can be found, this is going to get more difficult. Maybe send the company an email asking for help? You never know.

Controlling a Device over RS-232

As a case study, to give you a pointer on how to approach this, let's see how we control a Julabo F25 water bath using Python. The manual shows us where to start.

We always start with import of pyserial, a python module that controls a serial connection, and connect to the device:

import serial
import time
comport = "COM3"
connection = serial.Serial(
  comport,
  baudrate = 4800,
  bytesize=serial.EIGHTBITS,
  parity=serial.PARITY_NONE, 
  stopbits=serial.STOPBITS_ONE,
  xonxoff=False,
  rtscts=False,
)

The COMport is the name of the connection your PC makes with your device. In Windows, you will find it in the Device Manager (you can find elsewhere how to open that), under “Ports”. You need something like “COM3”. If you use Linux, you can use something like CuteCom, or search the internet how to do it, the comport will looks something like /dev/ttyUSB0.

The other options (baudrate, bytesize, etc.) are technical parameters of the connection that are specific to the device, and should be in the manual - no need to think too hard about what they mean.

After that, you can send commands to the device. The manual gives the possible commands in a nice table. For instance, OUT_SP_00, followed by a number is the command to set the bath temperature.

temperature = 35.21
connection.write( f"out_sp_00 {float(temperature):06.2f}\r".encode() )

Will set the temperature to 35.21. Note that the machine is a bit fussy about how you format the number: padded with zeros; e.g. 035.21, not 35.21. You also need to convert ('encode') the string to bits to make the machine understand it.

You can also read if the device answered to your command. For instance, the in_pv_00 command returns the current temperature.

connection.write( "in_pv_00\r".encode() )
time.sleep(0.1)
readlength = connection.inWaiting()
message = connection.read(readlength)
print(message.decode())

And that is more-or-less it. I would suggest wrapping this in functions as objects, but this is really just being fancy. The core is pretty simple!

My Automating Adventures

The following are just some things I automated with a link to the code I used, it might be useful to start from, or even to use directly.

Water baths

The water baths we had at the University of Amsterdam were great to work with. Simple standard serial connectors, simple commands that just work. You can find the code for controlling things here. It works with Julabo (F25), Haake (F6 and Phoenix), and Lauda (E200) baths, but can easily be extended.

Harvard Apparatus

For overnight experiments, I needed to control the flow rate on some Harvard Apparatus syringe pumps. Controlling the device is easy, the commands obvious, and the scripts thus easily written, see here. However, instead of the normal RS232 serial connectors (“DB-9”), Harvard Apparatus used RJ11 connectors, which you normally only find in your old wired phone. Great. So I had an RJ11-to-DB9 connector made by our excellent electrical workshop, which I could then plug into a serial-to-usb connector. Things worked smoothly after that.

Kern Analytical balance

Easy. No problems. Only difficulty was that the scale communicates with a DB-25 connector, which means you need a DB-25 to DB-9 connector first. Very annoying, but the internet provides.

Elveflow devices

We have an Elveflow pressure controller in our lab. It is actually mentioned in the specs of the machine quite clearly that we can control it programmatically - it has an SDK - a “software development kit”, you can just find it online. You would think that this makes life easy - but unfortunately this is not the case. You would think that the functions of the machine are not that complex: set a pressure, read the pressure, read data from a sensor, and a simple PID loop between a sensor and the pressure. However, to use the SDK you need to follow 5 steps including extracting DLLs and python scripts from a huge zip file, then place the SDK together with your scripts, it is kind of a nightmare to actually use. I wrote a wrapper to make things a bit easier. But still. Not very easy.

Zaber controllers

Extremely simple. Connection with the supplied cable, and a very elaborate API is provided. No complaints! See my code here!

ESE-LOG

The ESE-LOG is a small, simple fluorescence spectrometer. It is a nightmare to control with your PC. It is only controllable by a bunch of dll files, and you need to do some complicated bullshit to use it with Python. It works. But would not advice unless you have no other options.

DMD

A digital micro-mirror device (DMD) is a very complicated, very fancy device, with a very complicated way of controlling it over USB. It took me a week to make really work, cause I don't have a degree in software engineering, and that seems to be the assumption. Not for the faint of heart. See here for the code.

Scientific Camera's

Camera's from Thorlab and FLIR can be controlled via a USB connection, using an provided programming interface. Camera's are pretty complicated, with many obscure settings we mere mortals hardly ever think about, but at least they make an effort to make everything addressable by a scientist with a hobby. My code for controlling camera's can be found here.

1)
see here for the paper

Comments

Enter your comment: