# HPCS 6500 USB Protocol Reference Reverse-engineered from USB packet captures of the vendor software. ## Device Overview The HPCS 6500 is a spectrophotometer / integrating sphere system for LED and light source testing. It includes a built-in programmable AC/DC power supply. **Capabilities:** - Spectral power distribution (380-1050 nm, 350 points) - Photometric values (lumen, luminous efficacy, CCT, CRI Ra/R1-R15) - Chromaticity coordinates (CIE xy, uv, u'v') - Radiometric flux (total, UV, blue, yellow, red, far-red, IR) - CIE 1931 tristimulus (X, Y, Z), TLCI-2012, SDCM - Electrical parameters (voltage, current, power, power factor, frequency) - Harmonics analysis (50 harmonics voltage/current %, UThd, AThd, waveforms) - Built-in power supply: AC 100-240 V / 50-60 Hz, DC 1-60 V / 0-5 A **Connection:** - USB interface via STM32 Virtual COM Port (VID `0483`, PID `5741`) - Appears as a serial port (e.g. COM42 on Windows) - Baud rate: 115200 ## Frame Format Every command and response starts with the sync byte `0x8C` followed by a command ID byte. The device echoes the command ID in the response. All multi-byte numeric values are **little-endian**. ``` TX: 8C [payload...] RX: 8C [data...] ``` Write commands receive a 2-byte ACK (`8C `). Read commands return variable-length data after the 2-byte header. ## Command Table | Cmd | Direction | TX len | RX len | Description | |------|-----------|--------|----------------|--------------------------------------| | `00` | read | 2 | 16 | Identify device | | `01` | write | 6 | 2 | Set integration time (uint32 LE, µs) | | `03` | read | 2 | 9 | Poll instrument state | | `05` | read | 2 | 7 | Status check | | `0E` | write | 3 | 2 | Start (`01`) / Stop (`02`) measuring | | `13` | read | 2 | 4 hdr + 3904 | Read measurement block | | `25` | write | 2 | 2 | Reset instrument | | `26` | read | 2 | 196 | Read instrument ranges | | `2A` | read | 2 | 122 | Read device configuration | | `72` | write | 3 | 2 | PSU output on (`00`) / off (`01`) | | `73` | write | 7 | 2 | Set DC parameter (sub + float32) | | `77` | read | 2 | 4 hdr + 1584 | Read electrical / harmonics block | | `78` | write | 7 | 2 | Set AC parameter (sub + float32) | | `79` | read | 2 | 20 | Read power supply settings | | `7A` | write | 3 | 2 | Set output mode (`00`=AC, `01`=DC) | | `7B` | read | 2 | 2 | Read test config | | `2B` | write | var | 2 | Write test config (see below) | ## Measurement Sequences ### Single-Shot Measurement The vendor software uses this flow for one-off readings. No explicit start command is needed — the stop command (`8C 0E 02`) triggers a single reading. ``` 1. TX 8C 00 -> Identify (expect "HPCS6500" in response) 2. TX 8C 2A -> Read device config 3. TX 8C 01 -> Set integration time (µs), 0 = auto 4. TX 8C 0E 02 -> Stop / trigger single reading 5. TX 8C 03 -> Poll state until byte[2] = 0x01 (data ready) 6. TX 8C 13 -> Read measurement data (3904 bytes) 7. TX 8C 77 -> Read electrical data (1584 bytes) 8. TX 8C 25 -> Reset instrument ``` ### Continuous Measurement ``` 1. TX 8C 00 -> Identify (expect "HPCS6500" in response) 2. TX 8C 79 -> Read current PSU settings 3. TX 8C 7A -> Set output mode (00=AC, 01=DC) 4. TX 8C 78/73 ... -> Configure voltage/frequency/current as needed 5. TX 8C 01 -> Set integration time (µs), or skip for auto 6. TX 8C 72 00 -> Turn PSU output ON 7. TX 8C 0E 01 -> Start continuous measurement 8. TX 8C 03 -> Poll state until byte[2] = 0x01 (data ready) 9. TX 8C 13 -> Read measurement data (3904 bytes) 10. TX 8C 77 -> Read electrical data (1584 bytes) (repeat 8-10 for continuous readings, ~550 ms per cycle) 11. TX 8C 0E 02 -> Stop measurement 12. TX 8C 72 01 -> Turn PSU output OFF 13. TX 8C 25 -> Reset instrument ``` ## State Polling (`8C 03`) 9-byte response: `8C 03 ` | Byte | Meaning | |------|------------------------------------------------------| | b2 | Data flag: `00` = no new data, `01` = data available | | b3 | Mirrors b2 | | b4 | Always `00` | | b5 | State: `04` = idle, `01` = measuring | | b6 | Always `00` | | b7 | Always `00` | | b8 | Always `01` | ## Measurement Block (`8C 13` — 3904 bytes) The response has a 4-byte transport header (`8C 13 0F 40`) followed by a 3904-byte payload. All floats are IEEE 754 single-precision, little-endian. ### Device Header (offset 0-35) | Offset | Size | Type | Field | |--------|------|--------|---------------------------| | 0 | 10 | ASCII | Device ID (`"HPCS6500"`) | | 10 | 26 | — | Internal calibration data | ### Photometric (offset 36-75) | Offset | Type | Field | Unit | Example | |--------|---------|------------------------|---------|---------| | 36 | float32 | Luminous flux | lm | 479.57 | | 40 | float32 | Luminous efficacy | lm/W | 57.05 | | 44 | float32 | Correlated color temp | K | 5653 | | 48 | float32 | Duv | — | 0.00553 | | 52 | float32 | CIE x | — | 0.3289 | | 56 | float32 | CIE y | — | 0.3489 | | 60 | float32 | CIE u | — | 0.2015 | | 64 | float32 | CIE v | — | 0.3206 | | 68 | float32 | CIE u' | — | 0.2015 | | 72 | float32 | CIE v' | — | 0.4809 | ### Color Rendering (offset 76-143) | Offset | Type | Field | Example | |--------|---------|-------|---------| | 76 | float32 | SDCM | 4.71 | | 80 | float32 | Ra | 83.0 | | 84-140 | float32 | R1-R15 (4 bytes each) | R1=82 .. R15=76 | R*n* is at offset `80 + n × 4` (R1 at 84, R2 at 88, ..., R15 at 140). ### Radiometric (offset 144-175) | Offset | Type | Field | Unit | Example | |--------|---------|--------------------|------|----------| | 144 | float32 | Total radiant flux | mW | 1491.256 | | 148 | float32 | UV flux | mW | 0.000 | | 152 | float32 | Blue flux | mW | 469.836 | | 156 | float32 | Yellow flux | mW | 679.454 | | 160 | float32 | Red flux | mW | 330.864 | | 164 | float32 | Far-red flux | mW | 11.462 | | 168 | float32 | IR flux | mW | 0.000 | | 172 | float32 | Total (duplicate) | mW | 1491.256 | ### CIE Tristimulus & Sensor (offset 224-255) | Offset | Type | Field | Example | |--------|---------|----------------|---------| | 224 | float32 | CIE 1931 X | 661.9 | | 228 | float32 | CIE 1931 Y | 702.15 | | 232 | float32 | CIE 1931 Z | 648.535 | | 236 | float32 | TLCI-2012 | 68 | | 244 | float32 | Peak Signal | 53088 | | 248 | float32 | Dark Signal | 2267 | | 252 | float32 | Compensate lvl | 2834 | ### Timestamps (offset 272-291) | Offset | Size | Type | Field | Example | |--------|------|-------|-----------|----------------| | 272 | 11 | ASCII | Test date | `2026-02-04\0` | | 283 | 9 | ASCII | Test time | `16:04:17\0` | ### Spectral Data (offset 432-1831) | Offset | Type | Field | |-----------|---------------|----------------------------------| | 430-431 | uint16 | Spectrum header (zero) | | 432-1831 | float32 × 350 | Spectral irradiance (µW/cm²/nm) | The 350 floats cover **380 nm to 1050 nm** at ~1.92 nm steps ((1050-380) / (350-1) = 1.917 nm/step). Values are absolute spectral irradiance; the vendor software normalizes by dividing by the peak value. ### Unmapped Regions Offsets 176-223, 256-271, and 1832-3903 contain additional data not yet fully mapped. They likely hold extended parameters visible in the vendor software's advanced views. ## Electrical / Harmonics Block (`8C 77` — 1584 bytes) The response has a 4-byte transport header (`8C 77 06 30`) followed by a 1584-byte payload. ### Basic Electrical (always present) | Offset | Type | Field | Example | |--------|---------|------------------|---------| | 0-7 | — | Reserved (zero) | — | | 8 | float32 | Voltage | 230.30 V| | 12 | float32 | Current | 0.065 A | | 16 | float32 | Active power | 8.406 W | | 20 | float32 | Frequency | 50.02 Hz| | 24 | float32 | Power factor | 0.558 | ### Waveforms (when harmonics enabled, offset 28-543) | Offset | Type | Count | Field | |---------|--------------|-------|------------------------| | 30-285 | int16 LE | 128 | Voltage waveform | | 286-541 | int16 LE | 128 | Current waveform | Each waveform contains 128 signed 16-bit samples representing one complete AC cycle. ### Voltage Harmonics (when harmonics enabled, offset 544-747) | Offset | Type | Count | Field | |---------|--------------|-------|----------------------------| | 544-740 | float32 | 50 | H1..H50 voltage (% of H1) | | 744 | float32 | 1 | UThd (%) | H1 = 100.0%. H*n* is at offset `544 + (n-1) * 4`. ### Current Harmonics (when harmonics enabled, offset 800-1003) | Offset | Type | Count | Field | |---------|--------------|-------|----------------------------| | 800-996 | float32 | 50 | H1..H50 current (% of H1) | | 1000 | float32 | 1 | AThd (%) | H1 = 100.0%. H*n* is at offset `800 + (n-1) * 4`. ### Harmonics Detection When harmonics is disabled, offsets 28+ are all zero. To detect whether harmonics data is present, check if the float32 at offset 544 equals 100.0 (H1 voltage fundamental = 100%). ## Power Supply Control ### Output On/Off (`8C 72`) ``` TX: 8C 72 00 -> Output ON TX: 8C 72 01 -> Output OFF RX: 8C 72 -> ACK ``` The PSU output must be turned on before taking measurements. ### Output Mode (`8C 7A`) ``` TX: 8C 7A 00 -> AC mode TX: 8C 7A 01 -> DC mode RX: 8C 7A -> ACK ``` ### AC Parameters (`8C 78`) ``` TX: 8C 78 00 -> Set voltage (V), range 100-240 TX: 8C 78 01 -> Set frequency (Hz), 50 or 60 RX: 8C 78 -> ACK ``` ### DC Parameters (`8C 73`) ``` TX: 8C 73 00 -> Set current limit (A), range 0-5 TX: 8C 73 01 -> Set voltage (V), range 1-60 RX: 8C 73 -> ACK ``` ### Read Settings (`8C 79`) 20-byte response: `8C 79` + 18 bytes payload. | Offset | Type | Field | |--------|---------|--------------------| | 0 | float32 | AC voltage (V) | | 4 | float32 | AC frequency (Hz) | | 8 | float32 | DC voltage (V) | | 12 | float32 | DC current (A) | | 16 | uint8 | Mode (0=AC, 1=DC) | | 17 | uint8 | Marker (0xFF) | ### Integration Time (`8C 01`) ``` TX: 8C 01 -> Integration time in microseconds RX: 8C 01 -> ACK ``` Common values: 200000 (200 ms), 500000 (500 ms), 1000000 (1000 ms). ## Identify (`8C 00`) 16-byte response: `8C 00` + `"HPCS6500\0\0"` + 4 bytes device metadata. ## Test Configuration (`8C 2B`) The vendor software sends this before each measurement to configure test parameters. It consists of two sub-commands (sub `00` and sub `01`). ### Sub 00 — Test Parameters ``` TX: 8C 2B 00 <~58 bytes> -> Write test parameters RX: 8C 2B -> ACK ``` Known fields within the sub 00 payload (offsets from start of payload after sub byte): | Offset | Type | Field | Example | |--------|---------|---------------------|----------------| | 15 | float32 | Frequency? | 50.0 | | 35-55 | float32 | Five x 1.0 values | 1.0 each | | 55 | float32 | Scale factor? | 0.5 | ### Sub 01 — Auto-PSU Flag ``` TX: 8C 2B 01 <~44 bytes> -> Write test config RX: 8C 2B -> ACK ``` | Offset | Type | Field | |--------|-------|----------------------------------------| | 37 | uint8 | Auto-PSU: `01` = on with test, `00` = off | When auto-PSU is enabled (`01`), the device automatically turns the PSU on before measuring and off after. When disabled (`00`), the PSU must be controlled manually via `8C 72`. ### Read Configuration (`8C 7B`) ``` TX: 8C 7B -> Read current test config RX: 8C 7B -> ACK (config is returned via subsequent 8C 2B reads?) ``` ## Notes - The instrument computes all photometric, colorimetric, and radiometric values internally. The host software only reads and displays results. - During continuous measurement, the host polls `8C 03` and reads `8C 13` + `8C 77` on each cycle (~550 ms per reading). - All float values are IEEE 754 single-precision (4 bytes), little-endian. - All integer values are unsigned little-endian unless noted (waveform samples are signed int16).