STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
sense_testing_gui Namespace Reference

Classes

class  OTAWorker
class  UDPReceiver
class  SenseTestingGUIWindow

Functions

List[int] parse_sensor_ids_from_text (str text)
Optional[Tuple[int, int, int]] parse_packet_header (bytes data)
Optional[Tuple[tuple, bytes, int, int, int]] parse_board_heartbeat_packet (bytes data)
Optional[Tuple[dict, List[dict]]] parse_self_test_packet (bytes data)
str board_state_name (int state)
Optional[Tuple[dict, List[dict]]] parse_sensor_data_packet (bytes data)
float code_to_voltage (int code_uint32, float ref_voltage)
Optional[float] k_type_voltage_to_temperature_c (float v_volts)
Optional[float] pt1000_voltage_to_temperature_c (float v_volts, float excitation_ua=1000.0)
Optional[float] code_to_force (int code_uint32, float adc_ref_voltage, float excitation_voltage, float sensitivity_mv_per_v, float pga_gain, float full_scale_force)
str find_pio_command ()
Path compile_firmware (Path project_dir, str env_name, Optional[int] board_id=None)
None upload_firmware_to_esp32 (Path bin_path, str ip, int port, Optional[Callable[[str], None]] progress_cb=None)
bytes _make_header (int packet_type)
bytes build_server_heartbeat_packet ()
bytes build_sensor_config_packet (List[int] sensor_ids, bool necessary_for_abort, Optional[str] controller_ip, int reference_voltage=0, int enable_serial_printing=0)
bytes build_header_only_packet (int packet_type)
 main ()

Variables

str LEADERBOARD_JSON = Path(__file__).resolve().parent / "sense_testing_leaderboard.json"
 _qt_plugins = os.environ.get("QT_QPA_PLATFORM_PLUGIN_PATH")
list _candidates
 reverse
 _p
int MAX_PACKET_SIZE = 512
str PACKET_HEADER_FORMAT = "<BBI"
int PACKET_HEADER_SIZE = 6
tuple BOARD_HEARTBEAT_BODY_FORMAT
int BOARD_HEARTBEAT_BODY_SIZE = 35
 PacketType
 BoardState
int DIABLO_COMMS_VERSION = 0
str SENSOR_DATA_PACKET_FORMAT = "<BB"
int SENSOR_DATA_PACKET_SIZE = 2
str SENSOR_DATA_CHUNK_FORMAT = "<I"
int SENSOR_DATA_CHUNK_SIZE = 4
str SENSOR_DATAPOINT_FORMAT = "<BI"
int SENSOR_DATAPOINT_SIZE = 5
int DEFAULT_PORT = 5006
tuple DEFAULT_REF_VOLTAGE
float DEFAULT_WINDOW_SECONDS = 10.0
int MAX_POINTS = 10000
int MAX_DISPLAY_CHANNELS = 10
int UPDATE_INTERVAL_MS = 50
tuple HEARTBEAT_TIMEOUT_SEC
int HEARTBEAT_RATE_WINDOW = 20
int SERVER_HEARTBEAT_INTERVAL_MS = 500
int DEFAULT_SEND_PORT = 5005
str DEFAULT_TARGET_IP = "192.168.2.101"
list SENSOR_COLORS
tuple _K_TYPE_INVERSE
float PT1000_R0 = 1000.0
float PT1000_A = 3.9083e-3
float PT1000_B = -5.775e-7
float PT1000_EXCITATION_UA = 1000.0
float ADC32_FULL_SCALE = 2147483648.0

Detailed Description

Sense Testing GUI
Receives BOARD_HEARTBEAT and SENSOR_DATA UDP packets from DAQv2-Comms boards.
- Plots sensor data as voltage over time.
- Tracks board heartbeat rate, current board state, and connection status (lost when heartbeats stop).
- Send server heartbeat, sensor config, and abort packets to boards.

Requirements: pip install pyqt6 pyqtgraph numpy

Function Documentation

◆ _make_header()

bytes sense_testing_gui._make_header ( int packet_type)
protected
Build 6-byte packet header: type, version, timestamp (little-endian).

Definition at line 640 of file sense_testing_gui.py.

References time.time().

Referenced by build_header_only_packet(), build_sensor_config_packet(), and build_server_heartbeat_packet().

◆ board_state_name()

str sense_testing_gui.board_state_name ( int state)

Definition at line 282 of file sense_testing_gui.py.

◆ build_header_only_packet()

bytes sense_testing_gui.build_header_only_packet ( int packet_type)
Abort, Clear Abort, No Connection Abort: header only.

Definition at line 709 of file sense_testing_gui.py.

References _make_header().

Referenced by sense_testing_gui.SenseTestingGUIWindow._send_header_only().

◆ build_sensor_config_packet()

bytes sense_testing_gui.build_sensor_config_packet ( List[int] sensor_ids,
bool necessary_for_abort,
Optional[str] controller_ip,
int reference_voltage = 0,
int enable_serial_printing = 0 )
Build SENSOR_CONFIG packet matching DAQv2-Comms SensorConfigPacket layout.

Wire format after standard 6-byte header:
  - uint8  num_sensors (N)
  - N x uint8 sensor_id
  - uint8  reference_voltage  (0 = 2.5V internal, 1 = VDD, 2 = ignore/board default)
  - uint8  necessary_for_abort (0/1)
  - if necessary_for_abort: uint32 controller_ip (big-endian)
  - uint8  enable_serial_printing (0/1)

Definition at line 651 of file sense_testing_gui.py.

References _make_header(), and split().

Referenced by sense_testing_gui.SenseTestingGUIWindow._send_sensor_config().

◆ build_server_heartbeat_packet()

bytes sense_testing_gui.build_server_heartbeat_packet ( )
Server heartbeat: header + 1 byte engine_state (0 = SAFE).

Definition at line 646 of file sense_testing_gui.py.

References _make_header().

Referenced by sense_testing_gui.SenseTestingGUIWindow._send_server_heartbeat_once().

◆ code_to_force()

Optional[float] sense_testing_gui.code_to_force ( int code_uint32,
float adc_ref_voltage,
float excitation_voltage,
float sensitivity_mv_per_v,
float pga_gain,
float full_scale_force )
Ratiometric load-cell force from raw 32-bit ADC code (no voltage conversion).
Assumes 32-bit signed ADC: code / 2^31 = (V_ADC_input / V_ref).
At full-scale force: V_bridge_fs = excitation * (sensitivity_mV_V / 1000),
V_ADC_fs = V_bridge_fs * pga_gain, so code_fs = (V_ADC_fs / V_ref) * 2^31.
Force = (code / code_fs) * full_scale_force.

Definition at line 464 of file sense_testing_gui.py.

Referenced by sense_testing_gui.SenseTestingGUIWindow._on_add_max_force_to_leaderboard(), and sense_testing_gui.SenseTestingGUIWindow._update_plots().

◆ code_to_voltage()

float sense_testing_gui.code_to_voltage ( int code_uint32,
float ref_voltage )
Convert raw ADC code to voltage. Assumes 32-bit signed ADC.

Definition at line 335 of file sense_testing_gui.py.

Referenced by sense_testing_gui.SenseTestingGUIWindow._update_plots().

◆ compile_firmware()

Path sense_testing_gui.compile_firmware ( Path project_dir,
str env_name,
Optional[int] board_id = None )
Compile a PlatformIO project and return firmware.bin path.

If board_id is provided, append a BOARD_ID build flag so Hotfire
firmware uses that ID instead of the default. This is done via the
PLATFORMIO_BUILD_FLAGS environment variable so it doesn't require changes
to platformio.ini.

Definition at line 529 of file sense_testing_gui.py.

References find_pio_command().

Referenced by sense_testing_gui.OTAWorker.run().

◆ find_pio_command()

str sense_testing_gui.find_pio_command ( )
Try to find the 'pio' command in PATH or common installation locations (Windows).

Definition at line 500 of file sense_testing_gui.py.

Referenced by compile_firmware().

◆ k_type_voltage_to_temperature_c()

Optional[float] sense_testing_gui.k_type_voltage_to_temperature_c ( float v_volts)
Convert K-type thermocouple voltage (in V) to temperature (°C). Returns None if out of range.

Definition at line 412 of file sense_testing_gui.py.

Referenced by sense_testing_gui.SenseTestingGUIWindow._update_plots().

◆ main()

sense_testing_gui.main ( void )

Definition at line 1823 of file sense_testing_gui.py.

References main().

◆ parse_board_heartbeat_packet()

Optional[Tuple[tuple, bytes, int, int, int]] sense_testing_gui.parse_board_heartbeat_packet ( bytes data)
Returns (header, firmware_hash, board_id, engine_state, board_state) or None.

firmware_hash is the 32-byte SHA-256 of the running firmware binary.

Definition at line 217 of file sense_testing_gui.py.

References parse_packet_header().

Referenced by sense_testing_gui.UDPReceiver.run().

◆ parse_packet_header()

Optional[Tuple[int, int, int]] sense_testing_gui.parse_packet_header ( bytes data)

◆ parse_self_test_packet()

Optional[Tuple[dict, List[dict]]] sense_testing_gui.parse_self_test_packet ( bytes data)
Parse SELF_TEST packet sent by Hotfire boards.

Wire format (after 6-byte header):
  - uint8  adc_good
  - uint8  num_sensors (N)
  - N * (uint8 sensor_id, uint8 result)

Definition at line 240 of file sense_testing_gui.py.

References parse_packet_header().

Referenced by sense_testing_gui.UDPReceiver.run().

◆ parse_sensor_data_packet()

Optional[Tuple[dict, List[dict]]] sense_testing_gui.parse_sensor_data_packet ( bytes data)

Definition at line 298 of file sense_testing_gui.py.

References parse_packet_header().

Referenced by sense_testing_gui.UDPReceiver.run().

◆ parse_sensor_ids_from_text()

List[int] sense_testing_gui.parse_sensor_ids_from_text ( str text)
Parse a comma/space-separated list of sensor IDs into a cleaned uint8 list.

Definition at line 142 of file sense_testing_gui.py.

References split().

Referenced by sense_testing_gui.SenseTestingGUIWindow._send_sensor_config().

◆ pt1000_voltage_to_temperature_c()

Optional[float] sense_testing_gui.pt1000_voltage_to_temperature_c ( float v_volts,
float excitation_ua = 1000.0 )
Convert Pt1000 RTD differential voltage (V) to temperature (°C). excitation_ua = IDAC current in µA (default 1000). Returns None if out of range.

Definition at line 437 of file sense_testing_gui.py.

Referenced by sense_testing_gui.SenseTestingGUIWindow._update_plots().

◆ upload_firmware_to_esp32()

None sense_testing_gui.upload_firmware_to_esp32 ( Path bin_path,
str ip,
int port,
Optional[Callable[[str], None]] progress_cb = None )
Send firmware binary to ESP32 over TCP using Ethernet OTA protocol.

Definition at line 579 of file sense_testing_gui.py.

References decode(), emit(), max, and time.time().

Referenced by sense_testing_gui.OTAWorker.run().

Variable Documentation

◆ _candidates

list sense_testing_gui._candidates
protected
Initial value:
1= [
2 "/opt/homebrew/share/qt/plugins/platforms",
3 "/opt/homebrew/opt/qt/share/qt/plugins/platforms",
4 "/usr/local/share/qt/plugins/platforms",
5 "/usr/local/opt/qt/share/qt/plugins/platforms",
6 "/opt/homebrew/Cellar/qtbase/6.10.1/share/qt/plugins/platforms",
7 ]

Definition at line 33 of file sense_testing_gui.py.

◆ _K_TYPE_INVERSE

tuple sense_testing_gui._K_TYPE_INVERSE
protected

Definition at line 343 of file sense_testing_gui.py.

◆ _p

sense_testing_gui._p
protected
Initial value:
1= os.path.join(
2 "/opt/homebrew/Cellar/qtbase",
3 _name,
4 "share",
5 "qt",
6 "plugins",
7 "platforms",
8 )

Definition at line 44 of file sense_testing_gui.py.

◆ _qt_plugins

sense_testing_gui._qt_plugins = os.environ.get("QT_QPA_PLATFORM_PLUGIN_PATH")
protected

Definition at line 31 of file sense_testing_gui.py.

◆ ADC32_FULL_SCALE

float sense_testing_gui.ADC32_FULL_SCALE = 2147483648.0

Definition at line 461 of file sense_testing_gui.py.

◆ BOARD_HEARTBEAT_BODY_FORMAT

tuple sense_testing_gui.BOARD_HEARTBEAT_BODY_FORMAT
Initial value:
1= (
2 "<32sBBB" # firmware_hash[32], board_id, engine_state, board_state
3)

Definition at line 70 of file sense_testing_gui.py.

◆ BOARD_HEARTBEAT_BODY_SIZE

int sense_testing_gui.BOARD_HEARTBEAT_BODY_SIZE = 35

Definition at line 73 of file sense_testing_gui.py.

◆ BoardState

sense_testing_gui.BoardState
Initial value:
1= type(
2 "BoardState",
3 (),
4 {
5 "SETUP": 1,
6 "ACTIVE": 2,
7 "CONNECTION_LOSS_DETECTED": 3,
8 "NO_CONNECTION_ABORT": 4,
9 "NO_CONN_ABORT_FOLLOWER": 5,
10 "PT_ABORT": 6,
11 "NO_PT_ABORT": 7,
12 "ABORT_FINISHED": 8,
13 "STANDALONE_ABORT": 9,
14 "SELF_TEST": 10,
15 },
16)()

Definition at line 88 of file sense_testing_gui.py.

◆ DEFAULT_PORT

int sense_testing_gui.DEFAULT_PORT = 5006

Definition at line 112 of file sense_testing_gui.py.

◆ DEFAULT_REF_VOLTAGE

tuple sense_testing_gui.DEFAULT_REF_VOLTAGE
Initial value:
1= (
2 2.5 # Internal ref / PT typical; use 3.3 for TC_Board VDD reference
3)

Definition at line 113 of file sense_testing_gui.py.

◆ DEFAULT_SEND_PORT

int sense_testing_gui.DEFAULT_SEND_PORT = 5005

Definition at line 125 of file sense_testing_gui.py.

◆ DEFAULT_TARGET_IP

str sense_testing_gui.DEFAULT_TARGET_IP = "192.168.2.101"

Definition at line 126 of file sense_testing_gui.py.

◆ DEFAULT_WINDOW_SECONDS

float sense_testing_gui.DEFAULT_WINDOW_SECONDS = 10.0

Definition at line 116 of file sense_testing_gui.py.

◆ DIABLO_COMMS_VERSION

int sense_testing_gui.DIABLO_COMMS_VERSION = 0

Definition at line 104 of file sense_testing_gui.py.

◆ HEARTBEAT_RATE_WINDOW

int sense_testing_gui.HEARTBEAT_RATE_WINDOW = 20

Definition at line 123 of file sense_testing_gui.py.

◆ HEARTBEAT_TIMEOUT_SEC

tuple sense_testing_gui.HEARTBEAT_TIMEOUT_SEC
Initial value:
1= (
2 2.5 # Show "Connection: Lost" after this many seconds without a heartbeat
3)

Definition at line 120 of file sense_testing_gui.py.

◆ LEADERBOARD_JSON

str sense_testing_gui.LEADERBOARD_JSON = Path(__file__).resolve().parent / "sense_testing_leaderboard.json"

Definition at line 25 of file sense_testing_gui.py.

◆ MAX_DISPLAY_CHANNELS

int sense_testing_gui.MAX_DISPLAY_CHANNELS = 10

Definition at line 118 of file sense_testing_gui.py.

◆ MAX_PACKET_SIZE

int sense_testing_gui.MAX_PACKET_SIZE = 512

Definition at line 67 of file sense_testing_gui.py.

◆ MAX_POINTS

int sense_testing_gui.MAX_POINTS = 10000

Definition at line 117 of file sense_testing_gui.py.

◆ PACKET_HEADER_FORMAT

str sense_testing_gui.PACKET_HEADER_FORMAT = "<BBI"

Definition at line 68 of file sense_testing_gui.py.

◆ PACKET_HEADER_SIZE

int sense_testing_gui.PACKET_HEADER_SIZE = 6

Definition at line 69 of file sense_testing_gui.py.

◆ PacketType

sense_testing_gui.PacketType
Initial value:
1= type(
2 "PacketType",
3 (),
4 {
5 "BOARD_HEARTBEAT": 1,
6 "SERVER_HEARTBEAT": 2,
7 "SENSOR_DATA": 3,
8 "SENSOR_CONFIG": 5,
9 "ABORT": 7,
10 "CLEAR_ABORT": 9,
11 "NO_CONNECTION_ABORT": 11,
12 "SELF_TEST": 12,
13 },
14)()

Definition at line 74 of file sense_testing_gui.py.

◆ PT1000_A

float sense_testing_gui.PT1000_A = 3.9083e-3

Definition at line 432 of file sense_testing_gui.py.

◆ PT1000_B

float sense_testing_gui.PT1000_B = -5.775e-7

Definition at line 433 of file sense_testing_gui.py.

◆ PT1000_EXCITATION_UA

float sense_testing_gui.PT1000_EXCITATION_UA = 1000.0

Definition at line 434 of file sense_testing_gui.py.

◆ PT1000_R0

float sense_testing_gui.PT1000_R0 = 1000.0

Definition at line 431 of file sense_testing_gui.py.

◆ reverse

sense_testing_gui.reverse

Definition at line 42 of file sense_testing_gui.py.

◆ SENSOR_COLORS

list sense_testing_gui.SENSOR_COLORS
Initial value:
1= [
2 (255, 80, 80),
3 (80, 255, 80),
4 (80, 150, 255),
5 (255, 200, 80),
6 (200, 80, 255),
7 (80, 255, 255),
8 (255, 150, 150),
9 (150, 255, 150),
10 (150, 200, 255),
11 (255, 255, 80),
12]

Definition at line 128 of file sense_testing_gui.py.

◆ SENSOR_DATA_CHUNK_FORMAT

str sense_testing_gui.SENSOR_DATA_CHUNK_FORMAT = "<I"

Definition at line 107 of file sense_testing_gui.py.

◆ SENSOR_DATA_CHUNK_SIZE

int sense_testing_gui.SENSOR_DATA_CHUNK_SIZE = 4

Definition at line 108 of file sense_testing_gui.py.

◆ SENSOR_DATA_PACKET_FORMAT

str sense_testing_gui.SENSOR_DATA_PACKET_FORMAT = "<BB"

Definition at line 105 of file sense_testing_gui.py.

◆ SENSOR_DATA_PACKET_SIZE

int sense_testing_gui.SENSOR_DATA_PACKET_SIZE = 2

Definition at line 106 of file sense_testing_gui.py.

◆ SENSOR_DATAPOINT_FORMAT

str sense_testing_gui.SENSOR_DATAPOINT_FORMAT = "<BI"

Definition at line 109 of file sense_testing_gui.py.

◆ SENSOR_DATAPOINT_SIZE

int sense_testing_gui.SENSOR_DATAPOINT_SIZE = 5

Definition at line 110 of file sense_testing_gui.py.

◆ SERVER_HEARTBEAT_INTERVAL_MS

int sense_testing_gui.SERVER_HEARTBEAT_INTERVAL_MS = 500

Definition at line 124 of file sense_testing_gui.py.

◆ UPDATE_INTERVAL_MS

int sense_testing_gui.UPDATE_INTERVAL_MS = 50

Definition at line 119 of file sense_testing_gui.py.