Send test config (8C 2B) before single-shot measurement

The device needs the test config commands to enter single-test mode.
Without them it behaves as continuous start+stop. Supports auto_psu flag
so the device can handle PSU on/off automatically.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-05 10:04:47 +07:00
parent 98101ab5d0
commit fe9ced5f5b

View File

@@ -39,6 +39,19 @@ CMD_SET_AC = 0x78
CMD_READ_PSU = 0x79
CMD_PSU_OUTPUT = 0x72
CMD_SET_MODE = 0x7A
CMD_TEST_CONFIG = 0x2B
# Single-test config payloads captured from vendor software.
# Sub 00: test parameters, sub 01: test config with auto-PSU flag at byte 37.
_TEST_CONFIG_SUB0 = bytes.fromhex(
"00003c00000001008813037c011a04000000484200000208"
"000000000001060000000000803f0000803f0000803f0000"
"803f0000803f00000000003f"
)
_TEST_CONFIG_SUB1_BASE = bytes.fromhex(
"017c010c037c010c037c010c030000803f000000000000000000000000"
"00000000000000000001000000400000803f"
)
# State polling byte[5] values
STATE_IDLE = 0x04
@@ -268,6 +281,23 @@ class HPCS6500:
state = resp[5]
return data_available, state
def send_test_config(self, auto_psu=False):
"""Send single-test configuration (8C 2B sub 00 + sub 01).
If auto_psu=True, device handles PSU on/off automatically."""
self.ser.reset_input_buffer()
self.ser.write(bytes([SYNC, CMD_TEST_CONFIG]) + _TEST_CONFIG_SUB0)
resp = self._recv(2, timeout=2.0)
if resp != bytes([SYNC, CMD_TEST_CONFIG]):
return False
sub1 = bytearray(_TEST_CONFIG_SUB1_BASE)
if auto_psu:
sub1[37] = 0x01
self.ser.reset_input_buffer()
self.ser.write(bytes([SYNC, CMD_TEST_CONFIG]) + bytes(sub1))
resp = self._recv(2, timeout=2.0)
return resp == bytes([SYNC, CMD_TEST_CONFIG])
def start_measurement(self):
"""Send 8C 0E 01 to start measurement."""
self.ser.reset_input_buffer()
@@ -426,10 +456,12 @@ class HPCS6500:
return result
def take_single_reading(self):
"""Trigger a single measurement (no PSU control).
Sends stop to trigger a one-shot reading, waits for data, reads it,
then resets. This matches the vendor software's single-test flow."""
def take_single_reading(self, auto_psu=False):
"""Trigger a single measurement matching the vendor's single-test flow.
Sends test config, then stop to trigger a one-shot reading, waits for
data, reads it, then resets.
If auto_psu=True, the device handles PSU on/off automatically."""
self.send_test_config(auto_psu=auto_psu)
self.stop_measurement()
if not self.wait_for_data(timeout=30.0):