pique_nandClaude Opus 5 251357bcd6 support logging several boards at once, identified by UID
Each board reports the 96-bit STM32 unique ID as its USB serial number
(Application/usb_descriptors.c), so a board can be told apart from the
others and is recognised again on any COM port.

ptlogger:
- find_devices()/find_device() resolve a board by port, UID (or its tail)
  or an assigned name; VID/PID 0xCAFE:0x4001 with a product-string fallback
- persistent uid -> name map in pt_devices.json ($PT_DEVICE_DB to relocate)
- PTLogger knows its uid/name, adds open(), rename() and reconnect()

log_to_csv:
- takes several devices or --all; all boards are sampled in parallel per
  tick, so one CSV row is one moment in time
- columns prefixed with the board name, --split writes one file per board
- --name DEV=NAME to label a board, --list shows port/uid/name
- a board that drops off the bus leaves empty cells and is picked up again
  automatically, following its UID to whatever port it gets
- <file>.meta.json records which board produced which columns

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 15:11:53 +02:00
2026-06-18 10:42:11 +02:00

PT1000 Temperature Logger

A Python host-side library and logging utility for a 12-channel PT1000 temperature logger device.

Overview

This project provides:

  • ptlogger.py: Host-side library for communicating with a 12-channel PT1000 temperature logger via USB-CDC protocol
  • log_to_csv.py: Example logger utility that continuously samples all channels and logs temperatures to CSV files

Features

  • 12-channel temperature monitoring
  • Real-time temperature readout
  • Several boards logged simultaneously, sampled in parallel onto one time axis
  • Device recognition by UID — each board reports its STM32 unique ID as USB serial number, so it is identified again on any COM port
  • Persistent per-board names (pt_devices.json) used as CSV column prefixes
  • Automatic reconnect when a board is unplugged/replugged mid-run
  • Per-channel state monitoring (OK, open, short, fault, communication error)
  • CSV logging with timestamps
  • Configurable sampling intervals
  • Zero-calibration support
  • Reliable serial communication via pyserial

Installation

  1. Ensure Python 3.6+ is installed
  2. Install dependencies:
    pip install -r requirements.txt
    

Usage

List Connected Boards and Serial Ports

python log_to_csv.py --list

Shows every logger board with its port, UID and name, then all serial ports, then boards that are known by name but currently not plugged in.

Start Logging (Default: 1 second interval)

python log_to_csv.py COM5

Log All Connected Boards at Once

python log_to_csv.py --all

All boards are read in parallel each tick, so one CSV row is one moment in time.

Name the Boards (Recognition)

python log_to_csv.py --name COM5=oven --name COM7=bath --list

The name is stored against the board's UID in pt_devices.json, so it survives a replug and a different COM port. Afterwards boards can be addressed by name:

python log_to_csv.py oven bath -i 5 -o run1.csv

A device argument may be a port (COM5), a UID or its last digits (0A1B2C), or an assigned name (oven).

One CSV Per Board

python log_to_csv.py --all --split -o run1.csv

Writes run1_oven.csv, run1_bath.csv, ... instead of one wide file.

Zero-Calibrate Before Logging

python log_to_csv.py --all -z

Calibrate all sensors of every board (each board's sensors must be in a homogeneous bath). Per-channel offsets are stored on the device.

Command-Line Options

  • devices: One or more boards — port, UID (or its tail), or assigned name
  • -a, --all: Log every connected logger board
  • -o, --output: CSV file name (default: pt_log_<date_time>.csv)
  • -i, --interval: Sample interval in seconds (default: 1.0)
  • -z, --zero: Zero-calibrate before logging
  • --split: One CSV per board instead of one combined file
  • --name DEV=NAME: Permanently name a board by its UID (repeatable)
  • --list: List connected boards / serial ports and exit

Device Identification

The firmware exposes the 96-bit STM32 unique ID as the USB serial-number string (Application/usb_descriptors.c), and the board uses VID/PID 0xCAFE:0x4001. The host library uses this to:

  • find all logger boards on the bus (find_devices())
  • map a UID to a stable, user-chosen name (pt_devices.json, override the location with the PT_DEVICE_DB environment variable)
  • follow a board to a new COM port after a replug, during a running log

Library Usage

from ptlogger import PTLogger, find_devices, set_device_name

for dev in find_devices():
    print(dev.name, dev.port, dev.uid)

# open by port, by UID, or by name
with PTLogger.open("oven") as pt:
    print(pt.name, pt.uid, pt.version())
    for ch, (temp, state) in enumerate(pt.read_all()):
        print(f"Channel {ch}: {temp}°C (state: {pt.state_name(state)})")

# several boards at the same time
boards = [PTLogger.open(spec) for spec in ("oven", "bath")]

CSV Output Format

Combined file (default): a timestamp column plus 12 temperature columns per board, prefixed with the board name:

timestamp,oven_T0_degC,...,oven_T11_degC,bath_T0_degC,...,bath_T11_degC
2026-06-18T12:29:56.000,25.3,...,25.1,31.0,...,30.8

With --split, each board gets its own file with plain T0_degC ... T11_degC columns.

Empty cells indicate a disconnected or faulty channel — or a board that was temporarily off the bus (shown as .... in the live console view, while an open channel shows ----).

Next to the CSV a <file>.meta.json records which board (name, UID, port, firmware) produced which columns.

Requirements

  • Python 3.6+
  • pyserial >= 3.5

Notes

  • Stop logging by pressing Enter (recommended for reliable exit) or Ctrl+C
  • CSV files are flushed after every row, ensuring no data loss on interrupt
  • Per-channel state codes match the MAX31865 sensor states
S
Description
SW for reading and logging temperatures with the MultiPT1000Readoutx12 PCB
Readme
49 KiB
Languages
Python 100%