A VDATP system typically consists of two units - the top unit and the bottom unit - as well as an aluminum rail structure. Each unit has the following features:
100 ultrasonic transducers, in a 10x10 array
a Cyclone 10LP (part number 10CL016YU256I7G) FPGA, with JTAG connector available. This generates the signals to drive the transducers, as well as controls various other parts of the unit
FPGA configuration memory (typically not populated)
350mA RGB LED drivers with LEDs (generally only available on upper units)
32MB DDR RAM
a connector for up to 2 external ultrasonic microphones
up to 36V power regulation, with reverse polarity protection
programmatically adjustable transducer power supply (4.5V-18V)
embedded Raspberry Pi Zero 2 W to program and control the FPGAs (generally only available on bottom board)
3D printed enclosures
The two units are connected with a 12 wire cable that is 12" long. This allows the distance between the top and bottom boards to be adjusted as required. This cable passes commands from the Pi, a synchronization signal between the two boards as well as signals necessary for the PI to program the FPGAs.
VDATP block diagram
1 - Assembling VDATP
Your system consists of the following parts:
VDATP kit of parts
Assembly
To assemble, you will need a hex key for M3 bolts.
Take an aluminum extrusion and insert it into one of the mounts on the bottom unit. You may need to loosen the bolt on the mount to allow the metal T-Nut to slip into the extrusion slot.
Align the bottom of the extrusion with the bottom of the unit and tighten the bolt snugly. Repeat on the other side.
Now take the top unit and slide it onto the two aluminum extrusions. It’s a tight fit so you may need to squeeze the aluminum extrusion together a bit to get them to fit into the mounting slots. Do not tighten bolts.
Using calipers or ruler, adjust the height at the bottom of the top unit so that it is 150mm from the top of the bottom unit. Once the height is adjusted, you can tighten the bolts.
Insert one end of the communications cable (doesn’t matter which) into the communications port of either unit. The connector is keyed so that it only fits in one orientation. The fit is quite tight and you may need to use a small flat head screwdriver to ensure the connector is fully seated. Do the same with the other side of the cable and the other unit.
Insert the power cables - again the connectors are keyed.
Connect the power cables to an adjustable power supply - 20V with a current limit of 2A works well.
At this point, you must decide how you wish to connect with the system. There are two ways:
Wifi
USB
Wifi set up
Note that you can also perform Wifi setup by following the instructions under USB setup, SSHing into the Pi and using the sudo raspi-config utility to configure Wifi.
Remove the Raspberry Pi cover from the bottom unit
Carefully remove the SD card and insert it into a PC (Windows/Mac/Linux)
Follow the instructions here to create a wpa_supplicant.conf file and load it on the SD card.
re-insert the SD card into the Pi and replace the cover
The IP address will likely be dynamically set by your Wifi router and you’ll have to examine the router logs to determine the address (should be displayed as VDATP in the logs).
USB set up
This will use the Pi’s USB connection to emulate an Ethernet port. This means you’ll be able to use SSH into the PI as well as see the hosted control webpage and use the REST and websocket APIs. The Windows driver for this is a little flaky and can cause a BSOD :(
Warning
Only use the supplied USB cable. This cable has been modified to disconnect the +5V wire. If you use a standard USB cable, it will damage the board. The next version of the boards will have a fix for this.
Connect the supplied USB cable between a PC
Follow these instructions for Mac or Windows but using 10.20.30.41 for the IP address and 10.20.30.1 for the Router/Gateway
The IP address of the PI is static and set to 10.20.30.40
Turning it on (and off)
Turn on the power supply - at idle with no FPGAs programmed, the current will be about 0.44A. The Raspberry Pi activity light will be visible through a small hole in the Pi Cover.
After about 30s, you can try to ssh into the Pi using either [email protected] or vdatp@{Pi IP address}. The password is raspberry. Feel free to change the password :)
To shutdown the system properly, it is highly recommended to issue the command
sudo shutdown now
to the Pi and wait for the activity LED to stop blinking so as to prevent any potential file system corruption. You can also set the file system to read-only through raspi-config to prevent file system corruption but that’s a bit of a pain when trying to update the system.
Completed
Congratulations on setting up your VDATP system
2 - Using VDATP with the web GUI
VDATP can be controlled using a web GUI or through a REST API. The web GUI is served by the Raspberry Pi. The web server can be started by SSHing into the Pi and typing in the following
cd vdatp; node build
Note that the environment variable VDATP_CONFIG_DIR needs to be set to point to the directory ~/vdatp/build/condig - this will likely have been set for you already. Once the server has been started, you can open the webpage at {ip address}:3000. This will open the following page:
VDATP web GUI
The parts of the GUI are as follows:
Mode Bar allows you to access various modes of operation of VDATP. At the time of this writing, only Levitate is enabled. You can also access the Settings tab, where you can upload a FPGA configuration file. The Sim Mode button disables communication to the units and can be used to try out new scripts or settings with affected the connected unit.
Sim Area displays a simulation of the acoustic fields. You can rotate and zoom into the simulation using mouse controls.
Controls these can change either the simulation visualization parameters or directly send commands to VDATP. More on this below.
Scripts allows you to write simple scripts to perform a set of actions in VDATP. More below.
Let’s levitate!
You first need to program the FPGA and to do so you need to acquire the FPGA programming file (called an RBF file). You can download the latest release here. Once you have the file, start up the GUI and select Settings in the Mode bar. Under the FPGA Parameters card,press the Choose file button to select the RBF file and then press Upload.
Once that is done, return to the Levitate screen. Make sure Sim Mode is off. You can verify that the FPGA was programmed correctly by setting the LED color to something other than black.LED heat generation
Note that the LEDs can generate a lot of heat (enough to melt the enclosure) and have been set in hardware to limit the amount of power they can consume. In general, they should be able to operate at reasonable light levels but you may want to check the LED mounts to ensure they aren’t getting too hot.
Once communications with the system is verified, you can then click txEnable which will enable the transducers. You can use the sliders under Point1 to issue a positioning command (e.g. move X to some value and then back to 0). You may hear the array emit a high pitch whine that changes as the focus point is moved - this is normal
Hearing protection
A Bit Embedded makes no claims as to the safety of this apparatus. Appropriate hearing protection should be used.
You should now be able to levitate a small foam ball or water droplet by placing it at the focus point of the array: coordinate (0, 0, 0) is exactly in the center of the array, centered between the top and bottom units. You can move the particle by clicking on the numbers next to the coordinate sliders and the pressing the up and down arrow keys - the sliders move the focus point too quickly and the particle tends to lose the focus if it is moved via the sliders. You can use the txPower to change the voltage the drivers apply to the transducers from about 9V to 36Vpp. Generally, low txPower (under 0.3) works great.Transducer driver heat generation
Note that transducer drivers can produce a lot of heat at higher voltage levels. It’s recommended you use only the transducer power required for the experiment and set it to a lower value (or disable the transducers) when not in use.
Simulation
Notice that as you use the controls to move the particle, the simulation is updated to show the pressure waves and transducer phases. The simulation grid has a resolution of 1mm, which should easily run on most PCs equipped with even an old GPU. The simulation controls are as follows:
pointSize increases the apparent size of the visualized grid points (try it to see)
showStats displays a Statistics box that shows the current Frames per Second, milliseconds to render the frame, and MB of allocated memory. Click on the stats box to change what is being shown.
showGrid displays the simulation grid
showTransducers displays the transducers
slideMode allows the user to visualize slices through the grid by changing the xSlicePlane, ySlicePlane, and zSlicePlane sliders. If sliceMode is none, all the slice planes are active and you can carve out a rectangular section of the grid to see inside it. Selecting a different slice mode literally shows just a thin slice of the grid.
showSlicePlanes displays the slice planes (they’re very faint and the same color as the axes)
minVal, maxVal and range work together to increase the contrast of the visualization. Note that grid points with power less than minVal are not displayed, making for a cleaner display.
particleGridVisible more details below
Levitating multiple particles
This version of VDATP can levitate multiple particles by driving the individual particles through time multiplexing the arrays. For each focus point, the transducer phases are calculated independently and these sets of phases (one for each point) are sent to the FPGA. The FPGA then switches from one set of phases to the next in a round-robin fashion every 1/40000 of second. Currently the system supports up to 4 points, set by numPoints. particleGridVisible selects which particle grid is being shown.
Scripting
Simple scripts can be written to automate experiments. At the moment, this is done with a custom scripting language but will be migrated to Javascript in a future release. A script looks like this:
There are three types of commands: system, particle and execute.
System commands control the overall systems as follows:
sys.color(r, g, b) - sets the LED colors to (r, g, b). Values can range from 0 to 255, hex or decimal.
sys.txPower(power) - set txPower to power. Valid values range from 0 to 1.
sys.numParticles(num) - set the number of particles to num. Valid values range from 1 to 4.
sys.timeScale(scale) - allows the simulation to run slower by the factor scale. Valid values are integers 1 or greater
sys.txEnable(enable) - enables (1) or disables (0) the transducers
Particle commands start with the letters {a, b, c, d}, representing a specific particle. Each particle has the concept of home which sets the particle position to a specific position instantaneously. All other particle commands are used to identify a specific location to travel to, which is used used to build a path of intervening particle positions. These paths can then be executed.
P.home(x, y, z) - set the particle home position and move the particle to that position instantaneously when executed.
P.moveTo( x, y, z) - generates a path for the particle to move in a straight line to the point (x, y, z)
P.moveToHome() - generates a path for the particle to move in a straight line to the previously set home point, or (0, 0, 0 ) if no home position has been set
Execute commands run the current particle paths. The paths are erased when the execute command finishes.
executeAndWait() - causes the particles to execute their paths once and then wait for the user to press the Continue button that will appear under the text editor. This is generally used to set a home position for the particles allowing the user to then insert particles (e.g. foam balls) into the sound field.
executeAndLoop() - causes the particles to continuously execute their paths until the Break button is pressed
execute - runs the paths a single time and continues script execution
Updating the software
Both the GUI and Raspberry Pi software can be updated using the following procedure on the Pi:
cd ~/vdatp
wget https://github.com/danfoisy/vdatp2_gui/releases/latest/download/build.tar
tar xzf build.tar
cd build
npm install --omit=dev
cd ..
node build
3 - VDATP REST API
Reference for the VDATP REST API
The VDATP units can be controlled via a REST API.
REST and the GUI
Note that changes made via REST API are not reflected in the GUI.
The APIs are described in the OpenAPI spec below - unfortunately the Try it out option doesn’t work as the Pi isn’t listening to a publicly accessible address. However, you can use Bruno, the nice Postman replacement tool, to test out the APIs and generate code specific to your environment. Simply import the Bruno API collection into Bruno and try out all REST calls available.
You will also have to change the {baseURL} variable to point to your local VDATP:
Network Security
These APIs are not authenticated - please ensure you install your VDATP on a secure network.
The diagram below shows how the transducers are named.