i think we're basically done
This commit is contained in:
@@ -28,51 +28,48 @@ def _row(e: dict) -> list:
|
||||
e.get('time_str', ''),
|
||||
name,
|
||||
f"{e.get('bat_V', 0):.3f}",
|
||||
f"{e.get('drive_A', 0):.2f}",
|
||||
f"{e.get('jack_A', 0):.2f}",
|
||||
f"{e.get('aux_A', 0):.2f}",
|
||||
f"{e.get('current_A', 0):.2f}",
|
||||
str(e.get('counter', 0)),
|
||||
_sensor_str(e.get('sensors_stable', 0)),
|
||||
_sensor_str(e.get('sensors_raw', 0)),
|
||||
f"{e.get('drive_heat', 0):.1f}",
|
||||
f"{e.get('jack_heat', 0):.1f}",
|
||||
f"{e.get('aux_heat', 0):.1f}",
|
||||
f"{e.get('heat', 0):.1f}",
|
||||
f"0x{e.get('i2c_out', 0):04X}",
|
||||
]
|
||||
elif t == LOG_TYPE_BAT:
|
||||
return [
|
||||
e.get('time_str', ''),
|
||||
'BAT',
|
||||
f"{e.get('bat_V', 0):.3f}",
|
||||
'—', '—', '—', '—', '—', '—', '—', '—', '—',
|
||||
'—', '—', '—', '—', '—', '—',
|
||||
]
|
||||
elif t == LOG_TYPE_CRASH:
|
||||
return [
|
||||
e.get('time_str', ''),
|
||||
f"*** CRASH: {e.get('reason_str', '?')}",
|
||||
'—', '—', '—', '—', '—', '—', '—', '—', '—', '—',
|
||||
'—', '—', '—', '—', '—', '—', '—',
|
||||
]
|
||||
elif t == LOG_TYPE_BOOT:
|
||||
return [
|
||||
e.get('time_str', ''),
|
||||
f"BOOT rst={e.get('reason_str', '?')} wake={e.get('wake_str', '?')}",
|
||||
'—', '—', '—', '—', '—', '—', '—', '—', '—', '—',
|
||||
'—', '—', '—', '—', '—', '—', '—',
|
||||
]
|
||||
elif t == LOG_TYPE_TIME_SET:
|
||||
return [
|
||||
e.get('time_str', ''),
|
||||
'TIME_SET',
|
||||
'—', '—', '—', '—', '—', '—', '—', '—', '—', '—',
|
||||
'—', '—', '—', '—', '—', '—', '—',
|
||||
]
|
||||
else:
|
||||
return [
|
||||
e.get('time_str', ''),
|
||||
name,
|
||||
'—', '—', '—', '—', '—', '—', '—', '—', '—', '—',
|
||||
'—', '—', '—', '—', '—', '—', '—',
|
||||
]
|
||||
|
||||
|
||||
_HEADERS = ['Time', 'State', 'Bat(V)', 'Drive(A)', 'Jack(A)', 'Aux(A)',
|
||||
'Counter', 'Stable', 'Raw', 'DrHeat', 'JkHeat', 'AxHeat']
|
||||
_HEADERS = ['Time', 'State', 'Bat(V)', 'Cur(A)',
|
||||
'Counter', 'Stable', 'Raw', 'Heat', 'I2COut']
|
||||
|
||||
|
||||
def print_table(entries: list, type_filter: str = None):
|
||||
|
||||
@@ -73,15 +73,12 @@ def show_plots(entries: list, title: str = "SC-F001 Log"):
|
||||
add_crash_lines(ax0)
|
||||
ax0.grid(True, alpha=0.3)
|
||||
|
||||
# 2. Currents
|
||||
# 2. Current (single channel — V5 has one shared sensor)
|
||||
ax1 = axes[1]
|
||||
ax1.set_ylabel('Current (A)')
|
||||
if fsm:
|
||||
ts = to_dt(_ts_arr(fsm))
|
||||
ax1.plot(ts, _val_arr(fsm, 'drive_A'), label='Drive', linewidth=1)
|
||||
ax1.plot(ts, _val_arr(fsm, 'jack_A'), label='Jack', linewidth=1)
|
||||
ax1.plot(ts, _val_arr(fsm, 'aux_A'), label='Aux', linewidth=1)
|
||||
ax1.legend(fontsize=8, loc='upper right')
|
||||
ax1.plot(ts, _val_arr(fsm, 'current_A'), color='orange', linewidth=1)
|
||||
add_crash_lines(ax1)
|
||||
ax1.grid(True, alpha=0.3)
|
||||
|
||||
@@ -102,15 +99,12 @@ def show_plots(entries: list, title: str = "SC-F001 Log"):
|
||||
add_crash_lines(ax2)
|
||||
ax2.grid(True, alpha=0.3)
|
||||
|
||||
# 4. Thermal accumulators
|
||||
# 4. Thermal accumulator (single — max of bridge heats)
|
||||
ax3 = axes[3]
|
||||
ax3.set_ylabel('Heat (I²t)')
|
||||
if fsm:
|
||||
ts = to_dt(_ts_arr(fsm))
|
||||
ax3.plot(ts, _val_arr(fsm, 'drive_heat'), label='Drive', linewidth=1)
|
||||
ax3.plot(ts, _val_arr(fsm, 'jack_heat'), label='Jack', linewidth=1)
|
||||
ax3.plot(ts, _val_arr(fsm, 'aux_heat'), label='Aux', linewidth=1)
|
||||
ax3.legend(fontsize=8, loc='upper right')
|
||||
ax3.plot(ts, _val_arr(fsm, 'heat'), color='red', linewidth=1)
|
||||
add_crash_lines(ax3)
|
||||
ax3.grid(True, alpha=0.3)
|
||||
|
||||
@@ -140,17 +134,11 @@ def live_plot(url: str, interval_s: float = 2.0):
|
||||
ax.grid(True, alpha=0.3)
|
||||
|
||||
lines = {
|
||||
'bat': axes[0].plot([], [], color='green', linewidth=1)[0],
|
||||
'drive': axes[1].plot([], [], label='Drive', linewidth=1)[0],
|
||||
'jack': axes[1].plot([], [], label='Jack', linewidth=1)[0],
|
||||
'aux': axes[1].plot([], [], label='Aux', linewidth=1)[0],
|
||||
'state': axes[2].step([], [], where='post', linewidth=1, color='navy')[0],
|
||||
'drheat': axes[3].plot([], [], label='Drive', linewidth=1)[0],
|
||||
'jkheat': axes[3].plot([], [], label='Jack', linewidth=1)[0],
|
||||
'axheat': axes[3].plot([], [], label='Aux', linewidth=1)[0],
|
||||
'bat': axes[0].plot([], [], color='green', linewidth=1)[0],
|
||||
'current': axes[1].plot([], [], color='orange', linewidth=1)[0],
|
||||
'state': axes[2].step([], [], where='post', linewidth=1, color='navy')[0],
|
||||
'heat': axes[3].plot([], [], color='red', linewidth=1)[0],
|
||||
}
|
||||
axes[1].legend(fontsize=8, loc='upper right')
|
||||
axes[3].legend(fontsize=8, loc='upper right')
|
||||
axes[3].xaxis.set_major_formatter(mdates.AutoDateFormatter(axes[3].xaxis.get_major_locator()))
|
||||
|
||||
state = {'current_tail': 0, 'first': True}
|
||||
@@ -181,13 +169,9 @@ def live_plot(url: str, interval_s: float = 2.0):
|
||||
|
||||
if fsm:
|
||||
ts = to_dt([e['ts_ms'] for e in fsm])
|
||||
lines['drive'].set_data(ts, [e.get('drive_A', 0) for e in fsm])
|
||||
lines['jack'].set_data( ts, [e.get('jack_A', 0) for e in fsm])
|
||||
lines['aux'].set_data( ts, [e.get('aux_A', 0) for e in fsm])
|
||||
lines['current'].set_data(ts, [e.get('current_A', 0) for e in fsm])
|
||||
lines['state'].set_data(ts, [e.get('entry_type', 0) for e in fsm])
|
||||
lines['drheat'].set_data(ts, [e.get('drive_heat', 0) for e in fsm])
|
||||
lines['jkheat'].set_data(ts, [e.get('jack_heat', 0) for e in fsm])
|
||||
lines['axheat'].set_data(ts, [e.get('aux_heat', 0) for e in fsm])
|
||||
lines['heat'].set_data(ts, [e.get('heat', 0) for e in fsm])
|
||||
|
||||
all_bat = sorted(
|
||||
[e for e in all_entries if 'bat_V' in e],
|
||||
|
||||
@@ -109,28 +109,32 @@ def _ts_to_str(ts_ms: int) -> str:
|
||||
|
||||
|
||||
def _unpack_fsm(payload: bytes, fsm_states: dict) -> dict:
|
||||
if len(payload) < 27:
|
||||
raise ValueError(f"FSM payload too short: {len(payload)} < 27")
|
||||
ts_ms, bat_V, drive_A, jack_A, aux_A, counter, sensors = \
|
||||
struct.unpack_from('<QffffhB', payload, 0)
|
||||
drive_heat = jack_heat = aux_heat = 0.0
|
||||
if len(payload) >= 31:
|
||||
drive_heat, = struct.unpack_from('<f', payload, 27)
|
||||
if len(payload) >= 39:
|
||||
jack_heat, aux_heat = struct.unpack_from('<ff', payload, 31)
|
||||
"""Single-current FSM payload (25 bytes):
|
||||
ts(8) bat(4) current(4) counter(2) sensors(1) heat(4) i2c_out(2).
|
||||
V5 hardware has one shared current sensor; V4 had three but only one
|
||||
bridge is active at a time, so the single channel suffices.
|
||||
i2c_out is the last-written 16-bit TCA9555 output state
|
||||
(high byte = OUTPUT0 / LEDs, low byte = OUTPUT1 / relays)."""
|
||||
if len(payload) < 19:
|
||||
raise ValueError(f"FSM payload too short: {len(payload)} < 19")
|
||||
ts_ms, bat_V, current_A, counter, sensors = \
|
||||
struct.unpack_from('<QffhB', payload, 0)
|
||||
heat = 0.0
|
||||
i2c_out = 0
|
||||
if len(payload) >= 23:
|
||||
heat, = struct.unpack_from('<f', payload, 19)
|
||||
if len(payload) >= 25:
|
||||
i2c_out, = struct.unpack_from('<H', payload, 23)
|
||||
return {
|
||||
'ts_ms': ts_ms,
|
||||
'time_str': _ts_to_str(ts_ms),
|
||||
'bat_V': round(bat_V, 3),
|
||||
'drive_A': round(drive_A, 3),
|
||||
'jack_A': round(jack_A, 3),
|
||||
'aux_A': round(aux_A, 3),
|
||||
'current_A': round(current_A, 3),
|
||||
'counter': counter,
|
||||
'sensors_stable': sensors & 0x0F,
|
||||
'sensors_raw': (sensors >> 4) & 0x0F,
|
||||
'drive_heat': round(drive_heat, 2),
|
||||
'jack_heat': round(jack_heat, 2),
|
||||
'aux_heat': round(aux_heat, 2),
|
||||
'heat': round(heat, 2),
|
||||
'i2c_out': i2c_out,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user