plasduino#

plasduino is an old project that has been running in the didactic labs at the University of Pisa since about 2013, and is currently not maintained (nor maintainable)—if you are into vintage stuff, you can glance through the original repository.

With our youthful exuberance, we thought we would do something awesome, and general, and extensible—something that would go viral. (Sure…) Needless to say, the project did not take off, although it served us well with the first-year Physics students for more than ten years. But we are now taking this chance to resurrect the project (or at least part of it) and adapt into this new framework.

plasduino is basically a collection of arduino sketches running onto an arduino uno (with a small custom board plugged on top), along with a graphical user interface to control the data acquisition.

The following rambling is essentially me reminding myself what we did years ago, and why certain things are clumsy—at least for the limited part of the original project we are trying to resurrect.

The communication protocol#

The plasduino communication protocol is based on a few markers and operational codes that are understood on both ends (the sketches running onto the arduino uno and the client code on the computer controlling the data acquisition). All of these are defined in the baldaquin.plasduino.protocol module.

In addition, there are two basic data structures that we use throughout:

  • baldaquin.plasduino.protocol.AnalogReadout encapsulates a simple analog readout, containing the information about the specific arduino analog input being latched, the timestamp (with ms resolution) of the readout and, obviously, the corresponding ADC value;

  • baldaquin.plasduino.protocol.DigitalTransition represents a digital transition that comes with its pin number, polarity (raising or falling edge) and timestamp (with us resolution).

The custom shields#

We pretty much limit ourselves to the Lab1 shield in use at the University of Pisa. All the information is available here.

For our purposes, anything that is relevant for interfacing to the shield from the standpoint of the data acqisition is coded in the baldaquin.plasduino.shields Python module.

The arduino sketches#

The code actually running on the arduino boards follows the typical arduino structure, where there is an initial setup that is executed exactly once, followed by an infinite loop.

Warning

The fact that on the arduino side the configuration is one-shot is somewhat clashing with the baldaquin philosophy that system can be reconfigured before each start run. In other words, all the board configuration (e.g., pin assignment and sampling parameters) are hard-coded into each application and cannot be changed at runtime.

While all the original code is available on the old repository, we only copied over the two relevant sketches, compiled for the arduino uno, in the new repo. They live in:

  • baldaquin/plasduino/sketches/digital_timer.hex (sketch number 1, version 3);

  • baldaquin/plasduino/sketches/analog_sampling.hex (sketch number 2, version 3).

Loading the appropriate sketch#

Module documentation#

Basic definition of the plasduino communication protocol.

class baldaquin.plasduino.protocol.Marker(value)[source]#

Relevant protocol markers, verbatim from https://bitbucket.org/lbaldini/plasduino/src/master/arduino/protocol.h

(In the old days we used to have this generated automatically from the corresponding header file, but the project is so stable now, that this seems hardly relevant.)

NO_OP_HEADER = 160#
DIGITAL_TRANSITION_HEADER = 161#
ANALOG_READOUT_HEADER = 162#
GPS_MEASSGE_HEADER = 163#
RUN_END_MARKER = 176#
class baldaquin.plasduino.protocol.OpCode(value)[source]#

Definition of the operational codes, verbatim from https://bitbucket.org/lbaldini/plasduino/src/master/arduino/protocol.h

(In the old days we used to have this generated automatically from the corresponding header file, but the project is so stable now, that this seems hardly relevant.)

OP_CODE_NO_OP = 0#
OP_CODE_START_RUN = 1#
OP_CODE_STOP_RUN = 2#
OP_CODE_SELECT_NUM_DIGITAL_PINS = 3#
OP_CODE_SELECT_DIGITAL_PIN = 4#
OP_CODE_SELECT_NUM_ANALOG_PINS = 5#
OP_CODE_SELECT_ANALOG_PIN = 6#
OP_CODE_SELECT_SAMPLING_INTERVAL = 7#
OP_CODE_SELECT_INTERRUPT_MODE = 8#
OP_CODE_SELECT_PWM_DUTY_CYCLE = 9#
OP_CODE_SELECT_POLLING_MODE = 10#
OP_CODE_AD9833_CMD = 11#
OP_CODE_TOGGLE_LED = 12#
OP_CODE_TOGGLE_DIGITAL_PIN = 13#
class baldaquin.plasduino.protocol.InterruptMode(value)[source]#

Definition of the interrupt modes.

DISABLED = 0#
CHANGE = 1#
FALLING = 2#
RISING = 3#
class baldaquin.plasduino.protocol.PlasduinoPacketBase(*args, data: bytes | None = None)[source]#

Base class for the plasduino packets.

OUTPUT_HEADERS = None#
OUTPUT_ATTRIBUTES = None#
OUTPUT_FMTS = None#
classmethod text_header(prefix: str = '# ', creator: str | None = None) str[source]#

Return the header for the output text file.

to_text(separator: str = ', ') str[source]#

Convert a readout to text for use in a custom sink.

_abc_impl = <_abc._abc_data object>#
_fields = ()#
_format = '@'#
layout = '@'#
size = 0#
class baldaquin.plasduino.protocol.AnalogReadout(*args, data: bytes | None = None)[source]#

A plasduino analog readout is a 8-byte binary array containing:

  • byte(s) 0 : the array header (Marker.ANALOG_READOUT_HEADER);

  • byte(s) 1 : the analog pin number;

  • byte(s) 2-5: the timestamp of the readout from millis();

  • byte(s) 6-7: the actual adc value.

layout = '>'#
header: <Format.UNSIGNED_CHAR: 'B'> = 162#
pin_number: <Format.UNSIGNED_CHAR: 'B'>#
milliseconds: <Format.UNSIGNED_LONG: 'L'>#
adc_value: <Format.UNSIGNED_SHORT: 'H'>#
OUTPUT_HEADERS = ('Pin number', 'Time [s]', 'ADC counts')#
OUTPUT_ATTRIBUTES = ('pin_number', 'seconds', 'adc_value')#
OUTPUT_FMTS = ('%d', '%.3f', '%d')#
_abc_impl = <_abc._abc_data object>#
_fields = ('header', 'pin_number', 'milliseconds', 'adc_value')#
_format = '>BBLH'#
size = 8#
class baldaquin.plasduino.protocol.DigitalTransition(*args, data: bytes | None = None)[source]#

A plasduino digital transition is a 6-byte binary array containing:

  • byte(s) 0 : the array header (Marker.DIGITAL_TRANSITION_HEADER);

  • byte(s) 1 : the transition information (pin number and edge type);

  • byte(s) 2-5: the timestamp of the readout from micros().

layout = '>'#
header: <Format.UNSIGNED_CHAR: 'B'> = 161#
info: <Format.UNSIGNED_CHAR: 'B'>#
microseconds: <Format.UNSIGNED_LONG: 'L'>#
OUTPUT_HEADERS = ('Pin number', 'Edge type', 'Time [s]')#
OUTPUT_ATTRIBUTES = ('pin_number', 'edge', 'seconds')#
OUTPUT_FMTS = ('%d', '%d', '%.6f')#
_abc_impl = <_abc._abc_data object>#
_fields = ('header', 'info', 'microseconds')#
_format = '>BBL'#
size = 6#

Plasduino shield information.

See the old plasduino repo for all the gory details: https://bitbucket.org/lbaldini/plasduino/src/main/shields/

class baldaquin.plasduino.shields.Lab1[source]#

Hardware description for the Lab1 shield, version 2.

VERSION = 2#
ANALOG_PIN_1 = 0#
ANALOG_PIN_2 = 1#
ANALOG_PINS = (0, 1)#
SHUNT_RESISTANCE = 10.0#
DIGITAL_PIN_1 = 0#
DIGITAL_PIN_2 = 1#
DIGITAL_PINS = (0, 1)#