{"id":19195274,"url":"https://github.com/quartiq/thermostat","last_synced_at":"2025-07-31T17:05:36.804Z","repository":{"id":38334600,"uuid":"263026542","full_name":"quartiq/thermostat","owner":"quartiq","description":"Sinara Thermostat firmware. Currently a potentially outdated mirror of http://git.m-labs.hk/M-Labs/thermostat","archived":false,"fork":false,"pushed_at":"2023-12-12T16:07:23.000Z","size":5182,"stargazers_count":2,"open_issues_count":3,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-29T09:26:00.686Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quartiq.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-11T11:45:21.000Z","updated_at":"2023-12-12T16:07:29.000Z","dependencies_parsed_at":"2022-07-25T20:31:03.839Z","dependency_job_id":null,"html_url":"https://github.com/quartiq/thermostat","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/quartiq/thermostat","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quartiq%2Fthermostat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quartiq%2Fthermostat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quartiq%2Fthermostat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quartiq%2Fthermostat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quartiq","download_url":"https://codeload.github.com/quartiq/thermostat/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quartiq%2Fthermostat/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268074292,"owners_count":24191527,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-31T02:00:08.723Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T12:09:27.096Z","updated_at":"2025-07-31T17:05:36.767Z","avatar_url":"https://github.com/quartiq.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Firmware for the Sinara 8451 Thermostat\n\n- [x] [Continuous Integration](https://nixbld.m-labs.hk/job/mcu/thermostat/thermostat)\n- [x] Download latest firmware build: [ELF](https://nixbld.m-labs.hk/job/mcu/thermostat/thermostat/latest/download/1) [BIN](https://nixbld.m-labs.hk/job/mcu/thermostat/thermostat/latest/download/2)\n\n\n## Building\n\n### Reproducible build with Nix\n\nThermostat firmware is packaged using the [Nix](https://nixos.org) Flakes system. Install Nix 2.4+ and enable flakes by adding ``experimental-features = nix-command flakes`` to ``nix.conf`` (e.g. ``~/.config/nix/nix.conf``). \n\nOnce you have Flakes enabled, you can use ``nix build`` to build the firmware.\n\n### Development environment\n\nClone this repository and with Nix Flakes enabled, use the following commands:\n\n```shell\nnix develop\ncargo build --release\n```\n\nThe resulting ELF file will be located under `target/thumbv7em-none-eabihf/release/thermostat`.\n\nAlternatively, you can install the Rust toolchain without Nix using rustup; see the Rust manifest file pulled in `flake.nix` to determine which Rust version to use.\n\n## Debugging\n\nConnect SWDIO/SWCLK/RST/GND to a programmer such as ST-Link v2.1. Run OpenOCD:\n```shell\nopenocd -f interface/stlink-v2-1.cfg -f target/stm32f4x.cfg\n```\n\nYou may need to power up the programmer before powering the device.\nLeave OpenOCD running. Run the GNU debugger:\n```shell\ngdb target/thumbv7em-none-eabihf/release/thermostat\n\n(gdb) source openocd.gdb\n```\n\n## Flashing\nThere are several options for flashing Thermostat. DFU requires only a micro-USB connector, whereas OpenOCD needs a JTAG/SWD adapter.\n\n### dfu-util on Linux\n* Install the DFU USB tool (dfu-util).\n* Convert firmware from ELF to BIN: `arm-none-eabi-objcopy -O binary thermostat thermostat.bin` (you can skip this step if using the BIN from Hydra)\n* Connect to the Micro USB connector to Thermostat below the RJ45.\n* Add jumper to Thermostat v2.0 across 2-pin jumper adjacent to JTAG connector.\n* Cycle board power to put it in DFU update mode\n* Push firmware to flash: `dfu-util -a 0 -s 0x08000000:leave -D thermostat.bin`\n* Remove jumper\n* Cycle power to leave DFU update mode\n\n### st.com DfuSe tool on Windows\nOn a Windows machine install [st.com](https://st.com) DfuSe USB device firmware upgrade (DFU) software. [link](https://www.st.com/en/development-tools/stsw-stm32080.html).\n- add jumper to Thermostat v2.0 across 2-pin jumper adjacent to JTAG connector\n- cycle board power to put it in DFU update mode\n- connect micro-USB to PC\n- use st.com software to upload firmware\n- remove jumper\n- cycle power to leave DFU update mode\n\n### OpenOCD\n```shell\nopenocd -f interface/stlink-v2-1.cfg -f target/stm32f4x.cfg -c \"program target/thumbv7em-none-eabihf/release/thermostat verify reset;exit\"\n```\n\n## Network\n\n### Connecting\n\nEthernet, IP: 192.168.1.26/24\n\nUse netcat to connect to port 23/tcp (telnet)\n```sh\nrlwrap nc -vv 192.168.1.26 23\n```\n\ntelnet clients send binary data after connect. Enter \\n once to\ninvalidate the first line of input.\n\n\n### Reading ADC input\n\nSet report mode to `on` for a continuous stream of input data.\n\nThe scope of this setting is per TCP session.\n\n\n### TCP commands\n\nSend commands as simple text string terminated by `\\n`. Responses are\nformatted as line-delimited JSON.\n\n| Syntax                           | Function                                                                      |\n|----------------------------------|-------------------------------------------------------------------------------|\n| `report`                         | Show current input                                                            |\n| `report mode`                    | Show current report mode                                                      |\n| `report mode \u003coff/on\u003e`           | Set report mode                                                               |\n| `pwm`                            | Show current PWM settings                                                     |\n| `pwm \u003c0/1\u003e max_i_pos \u003camp\u003e`      | Set maximum positive output current                                           |\n| `pwm \u003c0/1\u003e max_i_neg \u003camp\u003e`      | Set maximum negative output current                                           |\n| `pwm \u003c0/1\u003e max_v \u003cvolt\u003e`         | Set maximum output voltage                                                    |\n| `pwm \u003c0/1\u003e i_set \u003camp\u003e`          | Disengage PID, set fixed output current                                       |\n| `pwm \u003c0/1\u003e pid`                  | Let output current to be controlled by the PID                                |\n| `center \u003c0/1\u003e \u003cvolt\u003e`            | Set the MAX1968 0A-centerpoint to the specified fixed voltage                 |\n| `center \u003c0/1\u003e vref`              | Set the MAX1968 0A-centerpoint to measure from VREF                           |\n| `pid`                            | Show PID configuration                                                        |\n| `pid \u003c0/1\u003e target \u003cdeg_celsius\u003e` | Set the PID controller target temperature                                     |\n| `pid \u003c0/1\u003e kp \u003cvalue\u003e`           | Set proportional gain                                                         |\n| `pid \u003c0/1\u003e ki \u003cvalue\u003e`           | Set integral gain                                                             |\n| `pid \u003c0/1\u003e kd \u003cvalue\u003e`           | Set differential gain                                                         |\n| `pid \u003c0/1\u003e output_min \u003camp\u003e`     | Set mininum output                                                            |\n| `pid \u003c0/1\u003e output_max \u003camp\u003e`     | Set maximum output                                                            |\n| `s-h`                            | Show Steinhart-Hart equation parameters                                       |\n| `s-h \u003c0/1\u003e \u003ct0/b/r0\u003e \u003cvalue\u003e`    | Set Steinhart-Hart parameter for a channel                                    |\n| `postfilter`                     | Show postfilter settings                                                      |\n| `postfilter \u003c0/1\u003e off`           | Disable postfilter                                                            |\n| `postfilter \u003c0/1\u003e rate \u003crate\u003e`   | Set postfilter output data rate                                               |\n| `load [0/1]`                     | Restore configuration for channel all/0/1 from flash                          |\n| `save [0/1]`                     | Save configuration for channel all/0/1 to flash                               |\n| `reset`                          | Reset the device                                                              |\n| `dfu`                            | Reset device and enters USB device firmware update (DFU) mode                 |\n| `ipv4 \u003cX.X.X.X/L\u003e [Y.Y.Y.Y]`     | Configure IPv4 address, netmask length, and optional default gateway          |\n| `fan`                            | Show current fan settings and sensors' measurements                           |\n| `fan \u003cvalue\u003e`                    | Set fan power with values from 1 to 100                                       |\n| `fan auto`                       | Enable automatic fan speed control                                            |\n| `fcurve \u003ca\u003e \u003cb\u003e \u003cc\u003e`             | Set fan controller curve coefficients (see *Fan control* section)             |\n| `fcurve default`                 | Set fan controller curve coefficients to defaults (see *Fan control* section) |\n| `hwrev`                          | Show hardware revision, and settings related to it                            |\n\n\n## USB\n\nThe firmware includes experimental support for acting as a USB-Serial\nperipheral. Debug logging will be sent there by default (unless build\nwith logging via semihosting.)\n\n**Caveat:** This logging does not flush its output. Doing so would\nhang indefinitely if the output is not read by the USB host. Therefore\noutput will be truncated when USB buffers are full.\n\n\n## Temperature measurement\n\nConnect the thermistor with the SENS pins of the\ndevice. Temperature-depending resistance is measured by the AD7172\nADC. To prepare conversion to a temperature, set the Beta parameters\nfor the Steinhart-Hart equation.\n\nSet the base temperature in degrees celsius for the channel 0 thermistor:\n```\ns-h 0 t0 20\n```\n\nSet the resistance in Ohms measured at the base temperature t0:\n```\ns-h 0 r0 10000\n```\n\nSet the Beta parameter:\n```\ns-h 0 b 3800\n```\n\n### 50/60 Hz filtering\n\nThe AD7172-2 ADC on the SENS inputs supports simultaneous rejection of\n50 Hz ± 1 Hz and 60 Hz ± 1 Hz (dB). Affecting sampling rate, the\npostfilter rate can be tuned with the `postfilter` command.\n\n| Postfilter rate | Rejection | Effective sampling rate |\n| ---             | :---:     | ---                     |\n| 16.67 Hz        | 92 dB     | 8.4 Hz                  |\n| 20 Hz           | 86 dB     | 9.1 Hz                  |\n| 21.25 Hz        | 62 dB     | 10 Hz                   |\n| 27 Hz           | 47 dB     | 10.41 Hz                |\n\n## Thermo-Electric Cooling (TEC)\n\n- Connect TEC module device 0 to TEC0- and TEC0+.\n- Connect TEC module device 1 to TEC1- and TEC1+.\n- The GND pin is for shielding not for sinking TEC module currents.\n\nWhen using a TEC module with the Thermostat, the Thermostat expects the thermal load (where the thermistor is located) to cool down with a positive software current set point, and heat up with a negative current set point.\n\nTesting heat flow direction with a low set current is recommended before installation of the TEC module.\n\n### Limits\n\nEach of the MAX1968 TEC driver has analog/PWM inputs for setting\noutput limits.\n\nUse the `pwm` command to see current settings and maximum values.\n\n| Limit       | Unit    | Description                   |\n| ---         | :---:   | ---                           |\n| `max_v`     | Volts   | Maximum voltage               |\n| `max_i_pos` | Amperes | Maximum positive current      |\n| `max_i_neg` | Amperes | Maximum negative current      |\n| `i_set`     | Amperes | (Not a limit; Open-loop mode) |\n\nExample: set the maximum voltage of channel 0 to 1.5 V.\n```\npwm 0 max_v 1.5\n```\n\nExample: set the maximum negative current of channel 0 to -3 A.\n```\npwm 0 max_i_neg 3\n```\n\nExample: set the maximum positive current of channel 1 to 3 A.\n```\npwm 0 max_i_pos 3\n```\n\n### Open-loop mode\n\nTo manually control TEC output current, omit the limit parameter of\nthe `pwm` command. Doing so will disengage the PID control for that\nchannel.\n\nExample: set output current of channel 0 to 0 A.\n```\npwm 0 i_set 0\n```\n\n## PID-stabilized temperature control\n\nSet the target temperature of channel 0 to 20 degrees celsius:\n```\npid 0 target 20\n```\n\nEnter closed-loop mode by switching control of the TEC output current\nof channel 0 to the PID algorithm:\n```\npwm 0 pid\n```\n\n## LED indicators\n\n| Name | Color | Meaning                        |\n| ---  | :---: | ---                            |\n| L1   | Red   | Firmware initializing          |\n| L3   | Green | Closed-loop mode (PID engaged) |\n| L4   | Green | Firmware busy                  |\n\n## Reports\n\nUse the bare `report` command to obtain a single report. Enable\ncontinuous reporting with `report mode on`. Reports are JSON objects\nwith the following keys.\n\n| Key            | Unit            | Description                                          |\n| ---            | :---:           | ---                                                  |\n| `channel`      | Integer         | Channel `0`, or `1`                                  |\n| `time`         | Seconds         | Temperature measurement time                         |\n| `adc`          | Volts           | AD7172 input                                         |\n| `sens`         | Ohms            | Thermistor resistance derived from `adc`             |\n| `temperature`  | Degrees Celsius | Steinhart-Hart conversion result derived from `sens` |\n| `pid_engaged`  | Boolean         | `true` if in closed-loop mode                        |\n| `i_set`        | Amperes         | TEC output current                                   |\n| `vref`         | Volts           | MAX1968 VREF (1.5 V)                                 |\n| `dac_value`    | Volts           | AD5680 output derived from `i_set`                   |\n| `dac_feedback` | Volts           | ADC measurement of the AD5680 output                 |\n| `i_tec`        | Volts           | MAX1968 TEC current monitor                          |\n| `tec_i`        | Amperes         | TEC output current feedback derived from `i_tec`     |\n| `tec_u_meas`   | Volts           | Measurement of the voltage across the TEC            |\n| `pid_output`   | Amperes         | PID control output                                   |\n\n## PID Tuning\n\nThe thermostat implements a PID control loop for each of the TEC channels, more details on setting up the PID control loop can be found [here](./doc/PID%20tuning.md).\n\n## Fan control\n\nFan control is available for the thermostat revisions with integrated fan system. For this purpose four commands are available:\n1. `fan` - show fan stats: `fan_pwm`, `abs_max_tec_i`, `auto_mode`, `k_a`, `k_b`, `k_c`.\n2. `fan auto` - enable auto speed controller mode, which correlates with fan curve `fcurve`.\n3. `fan \u003cvalue\u003e` - set the fan power with the value from `1` to `100` and disable auto mode. There is no way to disable the fan.\nPlease note that power doesn't correlate with the actual speed linearly.\n4. `fcurve \u003ca\u003e \u003cb\u003e \u003cc\u003e` - set coefficients of the controlling curve `a*x^2 + b*x + c`, where `x` is `abs_max_tec_i/MAX_TEC_I`, \ni.e. receives values from 0 to 1 linearly tied to the maximum current. The controlling curve should produce values from 0 to 1,\nas below and beyond values would be substituted by 0 and 1 respectively.\n5. `fcurve default` - restore fan curve settings to defaults: `a = 1.0, b = 0.0, c = 0.0`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquartiq%2Fthermostat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquartiq%2Fthermostat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquartiq%2Fthermostat/lists"}