Mathematica 6 in the Laboratory

Aaron Golden

Perfectly Scientific, Inc.

Overview of the bTop device

The bTop can function as a data acquisition device and as a control device.

Each box has eight analog input channels (12 bits with a range of 0 to + 5 volts)

Eight analog output channels (8 bits with a range of 0 to + 2.56 volts)

13 individually assignable digital pins

One high current output port that can supply 500 mA on each of eight pins

The bTop communicates with the machine over a USB 2 port, and our control software communicates with the Mathematica notebook via the MathLink system.

Overview of the BTopTools add-on package for Mathematica

The BTopTools package makes almost every feature of the bTop available to Mathematica.  Most of the time, users will need to use only two functions:

BTopAnalog — in a few different contexts, can be used to control anything related to analog signals in the bTop.

BTopDigital — again, in different contexts, controls anything related to digital signals in the bTop.

We'll use a few different functions, for example we'll want to set the IO direction of the bTop's digital ports before using them, but a user with a fairly static hardware configuration will be able to control their system using the BTopAnalog and BTopDigital syntax almost exclusively.

Overview of the BTopTools package

We load the package in the usual way.  The package both loads necessary functions into the Mathematica kernel via MathLink, and launches a helper application that watches for newly connected devices.

<<BTopTools`

After the package is loaded, we can use the BTopDeviceAll command to get a list of any USB locations where bTop devices are connected.

BTopDeviceAll

Basic data acquisition

When a function in the BTopTools package has a non-null output, the output takes the form of a List, which Mathematica handles naturally.

(* Read the voltage on every A/D input channel of the first connected bTop device *)
BTopAnalog[BTopDevice[1],BTopChannelAll,BTopADModeUnipolar5V]

Similarly, when we want to send a command to the bTop, we can use a Mathematica friendly coding style.

(* Set the voltage on every D/A output channel of the first connected bTop device to 2.5 V *)
BTopAnalog[BTopDevice[1],BTopChannelAll]=Table[2.56,{8}]

Alternative syntax

Behind the scenes Mathematica replaces BTopAnalog with one of a few different functions, depending on the context in which it appears.  These other functions provide access to the raw data that the bTop produces, in case a user wants it.

(* Read the voltage on every A/D input channel of the first connected bTop device *)
BTopGetAD[BTopDevice[1],BTopChannelAll,BTopADModeUnipolar5V]

BTopAnalog[BTopDevice[1],BTopChannelAll,BTopADModeUnipolar5V]==5.0/4095BTopGetAD[BTopDevice[1],BTopChannelAll,BTopADModeUnipolar5V]

(* Set the voltage on every D/A output channel of the first connected bTop device to 2.5 V *)
BTopSetDA[BTopDevice[1],Range[4,7],Table[255,{8}]];
BTopSetDA[BTopDevice[1],Range[0,3],Table[0,{8}]];

BTopAnalog[BTopDevice[1],Range[0,3]]=Table[2.56,{8}];
BTopAnalog[BTopDevice[1],Range[4,7]]=Table[0,{8}];

More data acquisition

We can pass data acquired with the bTop, via the BTopTools package, directly into built-in Mathematica functions.

(* Read the voltage on the first A/D channel of the first connected bTop, 10 thousand times, at a rate of 1KHz *)
samples=BTopAnalog[BTopDevice[1],{0},10000,1000.0,BTopADModeUnipolar5V];
ListPlot[Flatten[samples],{PlotJoined->True}]

This thermometer is a little noisy, but since we're in Mathematica, and the output produced by BTopAnalog has the right style, correcting the noise is trivial.

(* Use the built-in function MovingAverage to average every 200 samples and cancel the noise *)
ListPlot[MovingAverage[Flatten[samples],200],{PlotJoined->True}]

Intuitive laboratory controls via the Dynamic function

The new Dynamic controls of Mathematica 6 allow us to easily set up intuitive user interfaces to control our lab devices.

{Slider[Dynamic[v],{1.6,2.56}],Dynamic[v]}
Dynamic[BTopAnalog[BTopDeviceAll,BTopChannelAll]=Table[v,{8}]]

Since I have some LED's connected to the analog output channels, we can use Animate to make a light show.  In the "real world" a user might turn the Mathematica/bTop combination into a highly programmable signal generator.

Animate[BTopAnalog[BTopDeviceAll,BTopChannelAll]=
{1.6+0.9Sin[t],1.6+0.9Sin[(1+1/7)t],1.6+0.9Sin[(1+2/7)t],1.6+0.9Sin[(1+3/7)t],1.6+0.9Sin[(1+4/7)t],1.6+0.9Sin[(1+5/7)t],1.6+0.9Sin[(1+6/7)t],1.6+0.9Sin[(1+7/7)t]};t,{t,0,π}]

Digital device control

First we set every pin of digital port A on the first connected bTop to do output.

BTopSetDigitalIODirections[BTopDevice[1], {BTopDigitalIOPort["A"]}, {255}]

(* Set every pin on port A high *)
BTopDigital[BTopDevice[1],{BTopDigitalIOPort["A"]}]={255}

We can use dynamic controls with the digital controls also.

x={};
{TogglerBar[Dynamic[x],Range[8]-1],Dynamic[BTopDigital[BTopDevice[1],{BTopDigitalIOPort["A"]}]={Sum[(2^(x[[j]])),{j,1,Length[x]}]}]}

The next cell is a Mathematica program for driving an LED light show via the bTop, showing generations of a (truncated) cellular automaton.  The wiring of the light show circuit is absolutely trivial thanks to our use of Mathematica' s built-in CellularAutomaton function.

state={1};
num=FromDigits[state,2];
oldX=0;
x=0;
{Trigger[Dynamic[x],{0,100},1],
Dynamic[
If[Floor[x]>oldX,
oldX=x;
(* Send the current state out through the bTop-2 *)
BTopDigital[BTopDevice[1],{BTopDigitalIOPort["A"]}]={num};
(* Apply Rule 30 to the old state one time *)
state=CellularAutomaton[30,{state,{0}},1,-1][[1]];
(* Extract the next number (which will be sent to the bTop-2,
from the current state, by considering the middle five cells
as binary digits *)
num=FromDigits[Table[state[[j]],{j,Max[1,Floor[Length[state]/2]-4],Min[Floor[Length[state]/2]+3,Length[state]]}],2]]],Dynamic[Floor[x]]}

Device communication through Mathematica

When we plug in a second bTop it appears in our device list.

BTopDeviceAll

We can control the second bTop just as the first.

BTopAnalog[BTopDevice[2],BTopChannelAll]=Table[2.56,{8}]

We can even communicate with multiple bTop devices in parallel.

BTopAnalog[BTopDeviceAll,BTopChannelAll]=Join[{2.56},Table[0,{7}]]

Now that we're talking with multiple devices, we can help them to communicate with one another.  So Mathematica can act as a medium through which laboratory devices communicate.  As a simple example, we'll trigger an action on the second bTop, based on the state of the first.

We need use the AddPeriodical function from the JLink package to make a periodic background task update a record of an analog signal every half of a second.

Needs["JLink`"]
task=AddPeriodical[adVoltage=BTopAnalog[BTopDevice[1],{0},BTopADModeUnipolar5V][[1]][[1]],0.5]

Now we can use Dynamic to watch the incoming voltages continuously.

Dynamic[adVoltage]

We can also trigger hardware actions based on the inputs we see.  In this way, Mathematica 6 can facilitate communication between devices.

Dynamic[BTopAnalog[BTopDevice[2],BTopChannelAll]=If[adVoltage<1.33,Table[2.56,{8}],Table[0.0,{8}]]]

Kill the background task.

RemovePeriodical[task]

Example applications

Environmental controls

Experiment automation

Robotics