Title: Experimental control using Erlang/OTP
Author: Matt McDonnell
Notes: Preliminary draft, expect changes soon
The research group of which I am a member performs quantum information processing experiments using trapped ions. The experimental side of this research involves setting up optical and electronic systems to enable control of the quantum state of the trapped ions using laser pulses. This requires hard real-time control with microsecond resolution for the actual pulse sequences.
At present control of the experimental system as a whole is via a control program written in Pascal on a computer running DOS 6.2. This computer has a number of data acquisition cards attached to it that allow access to analog-to-digital converters (ADCs) for input, digital-to-analog converters (DACs) and digital outputs (DOs) for output.
The advantage of using DOS as the underlying operating system is that real-time low level access to the computer hardware is obtained.
The main disadvantage of the present approach is that high level drivers for devices are unavailable, for example there are no USB drivers for DOS, and the GUI for the control program must also be written in Pascal. This means that higher level programming tools are unavailable such as lexer/parser constructors, GUI construction toolkits, version control software, etc. Additionally the networking capabilities of the controller are limited, as DOS is not a multiprocessing operating system and so the flow of execution must go from control of the experimental apparatus to networking when data needs to be transferred over the network.
The basic problem is to retain the low level real-time hardware access for the computer controlling the experimental hardware, while at the same time allowing access to modern device drivers and higher level programming tools to enable scalability of the system. The ability to use scripting or batch processing of the behaviour of the hardware in a high level language would also be useful.
A number of possible solutions exist:
- Install a modern real-time operating system on the control computer, that allows access to modern programming tools and drivers. The timing constraints make this solution infeasible in the short term. Additionally, the existing control program works already so any modification needs to be minimally disruptive. Trying another program that runs under DOS is ok, reinstalling the operating system is not.
- Regard the existing control computer as a microcontroller and use a separate computer running a more modern operating system as the overall control computer.
The second approach has the advantage that modern devices can be attached to the overall control computer and controlled by the main control program. These devices tend to be things such as oscilloscopes or function generators that can be triggered by an external TTL pulse, so hard real-time control is retained by triggering the devices from the microncontroller.
This approach is similar to the satellite real-time control example in Chapter 14 of "Concurrent Programming in Erlang" (2nd Ed) by J. Armstrong et al. The basic structure of the system in this example is a data manager that controls the external data handler that accesses the underlying hardware, and marshals data from external controllers to the hardware and from the hardware to display clients. Eventually I plan to implement this system using the Open Telecom Platform (OTP) behaviours, but to start with a simpler system is considered as discussed below.
The application consists of:
- a gen_server controlling access to the port that connects to the experiment computer. This module is called port_server and encompasses some aspects of the data manager and the external data handler in the same module.
- a program written in Pascal that controls access to the hardware communication channel that links to the microcontroller, eg a serial port or GPIB.
- A supervisor process to watch the gen_server and restart it if necessary.
In addition there is an extra Erlang module currently outside the OTP application:
- a GUI that represents the DACs of the microcontroller and displays data read from the microcontroller (currently just by setting the value of a "data" slider).
Modifications required for the existing experimental program:
- add a variable that tells the microcontroller whether it is in LOCAL or REMOTE mode. If in LOCAL mode the microcontroller expects input from the attached keyboard (i.e. the existing setup), while in REMOTE mode the microcontroller expects input from serial port (or GPIB, ethernet, etc).
- read (write) from (to) the external control computer on each loop through the event loop.
- write a function to map a resource name and value to the appropriate function call on the microcontroller. For example if the external controller transmits the string "set DAC397 1200" the microcontroller should know to call setDAS1200(4, 1200) where DAC397 is connected to channel 4 of the DAS1200 data acquisition card.
Write a test "microcontroller program" ie a Pascal program that represents the experimental control program on the existing experimental computer. An extra layer of communication (over say the serial port or GPIB) is required for the actiual experimental control application, however this is just a process that echoes its input to the communications channel. Hence the complete set of non-Erlang programs are:
- A program to access the serial port.
- A program that represents the microcontroller process running on the remote machine.
In the current implementation only the second program is currently implemented, in the Pascal program testport.pas.
(WARNING: the Pascal port simulating the microcontroller drops core when it terminates, I haven't been able to fix this yet.)
The initial stage of development of the Erlang program to control the
microcontroller didn't use the OTP libraries. Instead separate basic
Erlang modules were written and loosely coupled together.
The files can be found in [erl_expt_basic.tgz], to run them do:
- compile testport.pas with a Pascal comipler such as FreePascal
- start an Erlang shell and compile the erlang files
- start the group of programs with control:start().
With this as a basis the construction of the OTP version was fairly simple, following the directions of [Pete Kazmier's "Writing an Erlang Port using OTP Principles"] tutorial. One difference is that my port_server module expects asynchronous inputs (casts) instead of synchronous inputs (calls). This is closer to the behaviour described in the real-time control example in the book, and is appropriate for the case where the hardware "pushes" data to the data manager. To change to the data manager "pulling" data from the hardware would require the microcontroller to store data until it is requested by a "get data" command from the port. This is not a problem for the current system, where the microcontroller is actually a full computer with a several GB hard drive, but could be impossible with a small microcontroller.
The code for the OTP version of the experimental control program is in [erl_expt_otp.tgz], to run them do:
change to the src directory and compile the .erl files
erlc -W -o ../ebin *.erl
change to the priv directory and compile tesport.pas
start the erlang shell so that it knows where the ebin directory is, for example (if you install the files off the root of your username)
erl -pa /home/