BaseShield Class¶
- class automationshield.shields.BaseShield(port: str | None = None)[source]¶
Bases:
objectBase class for shield devices. Handles communication with Arduino, sensor calibration and unit conversions. The class can also install the proper firmware on an Arduino.
- Interface:
Actuator input should be provided in percent by default.
Potentiometer is provided in percent by default.
Sensor values are converted to relevant physical units in the child classes.
- Parameters:
port (str | None) – Port on which the Arduino is connected, defaults to None.
- TEST: int = 0¶
Flag to write to Arduino. This flag is used to check if the correct firmware is installed. The response from the Arduino should be the C++ software version and the id of the shield.
- RUN: int = 1¶
Flag to write to Arduino. This flag is used for normal running of the shield device. The actuator value is applied and the Arduino responds with the potentiometer and sensor values.
- STOP: int = 2¶
Flag to write to Arduino. This flag is used to stop the actuator. The Arduino will stop the actuator to ensure the shield is safely stopped.
- script: str = ''¶
Name of the script directory in which the
.inofile for the specific shield is located.
- shield_id: str = ''¶
ID assigned to shield. This is used to check whether the correct firmware is installed on the Arduino.
- class PlotInfo[source]¶
Bases:
objectThis class contains information to improve the plots generated by the
PlotterandLivePlotterclasses in the plotting package.- sensor_min: float = 0¶
Sets to lower bound of the sensor value. This is used to set up the
LivePlotter.
- sensor_max: float = 10¶
Sets the upper bound of the sensor value. This is used to set up the
LivePlotter.
- find_arduino() str[source]¶
Get the name of the port that is connected to Arduino. Raises exception if no port was found.
- Raises:
AutomationShieldException – Raised if no Arduino was found.
- Returns:
COM port of the Arduino.
- Return type:
- check_firmware() int[source]¶
Check that the correct firmware is installed on the Arduino. When the arduino reads the
BaseShield.TESTflag, it should respond with the code version and two bytes which, when converted to ASCII, should match the shield id.- Raises:
AutomationShieldException – If the arduino didn’t respond correctly.
- Returns:
version number of Arduino firmware.
- Return type:
- install_firmware(device: str) None[source]¶
Upload compiled firmware for the current shield to the Arduino.
- Parameters:
device (str) – FQBN of Arduino. FQBNs for common devices are provided in
automationshield.arduino, e.g.automationshield.arduino.LEONARDO:arduino:avr:leonardo.- Return type:
None
- convert_potentiometer_reading(raw: int) float[source]¶
Convert n-bit potentiometer reading to percentage value. A bit value of \(1023\) is mapped to \(100\) %.
- convert_actuator_input(percent: float) int[source]¶
Convert actuator input from percentage to n-bit value. A value of \(100\) (%) is mapped to \(2^n-1\) where \(n\) equals
BaseShield.actuator_bits.
- convert_sensor_reading(sensor: int) float[source]¶
Convert sensor reading to physical units. Should be implemented on subclasses. By default, the sensor value is returned unchanged.
- calibrate_sensor_reading(sensor: int) int[source]¶
Calibrate the sensor reading with the zero reference. Should be implemented on subclass. The default implementation is
\[y_c = y_r - y_0\]where \(y_c\) is the calibrated sensor value, \(y_r\) is the raw sensor value and \(y_0\) is the zero reference of the sensor value.
Note
The zero reference is obtained at the start of each experiment. It is therefore important that the system is at rest when an experiment is started.
- _read() tuple[int, float][source]¶
Construct potentiometer and sensor value from bytes received from arduino.
Three bytes are received from the arduino. The second and third byte contain the first eight bits of the potentiometer and sensor values. The first byte contains the remaining bits of the potentiometer and sensor values.
Byte 1:
7
6
5
4
3
2
1
0
0
0
\(p_9\)
\(p_8\)
\(s_{11}\)
\(s_{10}\)
\(p_9\)
\(p_8\)
Byte 2:
7
6
5
4
3
2
1
0
\(p_7\)
\(p_6\)
\(p_5\)
\(p_4\)
\(p_3\)
\(p_2\)
\(p_1\)
\(p_0\)
Byte 3:
7
6
5
4
3
2
1
0
\(s_7\)
\(s_6\)
\(s_5\)
\(s_4\)
\(s_3\)
\(s_2\)
\(s_1\)
\(s_0\)
The bits are extracted from the bytes and reconstructed, after which they are converted to base 10 (integer numbers).
- read(raw: bool = False) tuple[float][source]¶
Read data from Arduino. If
raw == False, the potentiometer value is rescaled to percentages; and the sensor is calibrated with the zero reference and converted to relevant units. This is the default. Ifraw == True, none of that happens and the potentiometer and sensor are returned as n-bit values. No calibration is performed either.- Parameters:
raw (bool) – If True, returns raw n-bit readings from potentiometer and sensor. Defaults to False, in which case the potentiometer is converted to percent and the sensor to appropriate units.
- Raises:
AutomationShieldException – Raised if no data was received. This can happen if there was no
BaseShield.write()command invoked preceding a call toBaseShield.read()or if there is something wrong with the serial connection or the cable.- Returns:
(Converted and calibrated) potentiometer and sensor readings, in that order.
- Return type:
- static saturate_bits(value: float, bits: int) int[source]¶
Saturate value between \(0\) and \(2^{bits - 1}\) inclusive.
- static saturate_percent(value: float) float[source]¶
Saturate value between \(0\) and \(100\) inclusive.
- _write(flag: int, output: int) None[source]¶
Put flag and output value into bytes and send them to the arduino.
The first byte is the flag value. Technically the flag only needs two bits, so the first byte looks like this:
7
6
5
4
3
2
1
0
0
0
0
0
0
0
\(f_1\)
\(f_0\)
Depending the on the number of output bits (set by
BaseShield.actuator_bits), the actuator value is sent in one or two bytes. IfBaseShield.actuator_bits\(\leq 8\), only the bottom byte is created and sent, otherwise both are constructed and sent in the order below.7
6
5
4
3
2
1
0
\(o_{15}\)
\(o_{14}\)
\(o_{13}\)
\(o_{12}\)
\(o_{11}\)
\(o_{10}\)
\(o_9\)
\(o_8\)
7
6
5
4
3
2
1
0
\(o_7\)
\(o_6\)
\(o_5\)
\(o_4\)
\(o_3\)
\(o_2\)
\(o_1\)
\(o_0\)
- Parameters:
flag (int) –
BaseShield.TEST,BaseShield.RUNorBaseShield.STOP.output (int) – Output value to send to the arduino, most often the actuator input.
- Return type:
None
- write(flag: int, actuator: float, raw: bool = False) int[source]¶
Write run/stop flag and actuator value to Arduino. Convert and saturate the actuator value before sending.
the flag must be one of
BaseShield.TEST,BaseShield.RUNorBaseShield.STOP.BaseShield.TESTreturns the version number of the Arduino code and a shield id, which should matchBaseShield.shield_id. The actuator input is irrelevant for this command.BaseShield.RUNmeans normal running mode. Set the actuator value.BaseShield.STOPtells the arduino to stop the actuator. The supplied actuator value is ignored by the Arduino.
- Parameters:
flag (int) –
BaseShield.TEST,BaseShield.RUNorBaseShield.STOP.actuator (float) – actuator value.
raw (bool) – If False, expects actuator as percentage [0, 100]. Value is converted before being sent. If True, expects actuator in range of [0, \(2^n - 1\) ] with \(n\) the number of
BaseShield.actuator_bits. Defaults to False.
- Returns:
Saturated n-bit motor value.
- Return type:
- calibrate() None[source]¶
Read out a zero reference and save it. System should be at rest when calling this method.
- Return type:
None
- stop() None[source]¶
Send
BaseShield.STOPsignal to Arduino.- Return type:
None
- open() None[source]¶
Reset buffers and open connection to Arduino if it is not open already. Wait for
BaseShield.TIMEOUTseconds to make sure connection is established.- Return type:
None
- __enter__() BaseShield[source]¶
Implements the
withcontext manager. This method calls- Returns:
Shield instance.
- Return type: