Compare commits

...

6 Commits

Author SHA1 Message Date
8b0ad14311 steinhart_hart: Beta Parameter uom dimensions
The Beta Parameter is not dimensionless, and has unit kelvin.
Incorporate that into the type system.
2024-08-08 13:26:35 +08:00
9d89104f50 README: Fix command to make firmware BIN (#115)
Co-authored-by: atse <atse@m-labs.hk>
Co-committed-by: atse <atse@m-labs.hk>
2024-08-07 18:22:48 +08:00
136c7a0b52 Calculate current_abs_max_tec_i from all channels
Instead of picking channels 0 and 1. Helps to generalise for more than 2
channels.
2024-08-07 16:14:28 +08:00
5000cae1b1 Grammar fixes 2024-08-07 16:09:30 +08:00
78ec77509f flake: Install LLVM in devShell too
So that developers can use `llvm-objcopy` in their devShells as well.
2024-08-07 16:06:19 +08:00
52aa3890c1 Update nix repos 2024-08-06 13:38:58 +08:00
6 changed files with 31 additions and 20 deletions

View File

@ -45,7 +45,7 @@ There are several options for flashing Thermostat. DFU requires only a micro-USB
### dfu-util on Linux
* Install the DFU USB tool (dfu-util).
* 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)
* Convert firmware from ELF to BIN: `llvm-objcopy -O binary target/thumbv7em-none-eabihf/release/thermostat thermostat.bin` (you can skip this step if using the BIN from Hydra)
* Connect to the Micro USB connector to Thermostat below the RJ45.
* Add jumper to Thermostat v2.0 across 2-pin jumper adjacent to JTAG connector.
* Cycle board power to put it in DFU update mode

8
flake.lock generated
View File

@ -2,16 +2,16 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1691421349,
"narHash": "sha256-RRJyX0CUrs4uW4gMhd/X4rcDG8PTgaaCQM5rXEJOx6g=",
"lastModified": 1722791413,
"narHash": "sha256-rCTrlCWvHzMCNcKxPE3Z/mMK2gDZ+BvvpEVyRM4tKmU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "011567f35433879aae5024fc6ec53f2a0568a6c4",
"rev": "8b5b6723aca5a51edf075936439d9cd3947b7b2c",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-23.05",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}

View File

@ -1,7 +1,7 @@
{
description = "Firmware for the Sinara 8451 Thermostat";
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-23.05;
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
inputs.rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
@ -47,6 +47,7 @@
'';
dontFixup = true;
auditable = false;
};
in {
packages.x86_64-linux = {
@ -61,7 +62,8 @@
devShells.x86_64-linux.default = pkgs.mkShellNoCC {
name = "thermostat-dev-shell";
packages = with pkgs; [
rust openocd dfu-util
rust llvm
openocd dfu-util
] ++ (with python3Packages; [
numpy matplotlib
]);

View File

@ -1,4 +1,4 @@
use core::{cmp::max_by, marker::PhantomData};
use core::marker::PhantomData;
use heapless::{consts::U2, Vec};
use num_traits::Zero;
use serde::{Serialize, Serializer};
@ -561,9 +561,10 @@ impl Channels {
}
pub fn current_abs_max_tec_i(&mut self) -> ElectricCurrent {
max_by(self.get_tec_i(0).abs(),
self.get_tec_i(1).abs(),
|a, b| a.partial_cmp(b).unwrap_or(core::cmp::Ordering::Equal))
(0..CHANNELS)
.map(|channel| self.get_tec_i(channel).abs())
.max_by(|a, b| a.partial_cmp(b).unwrap_or(core::cmp::Ordering::Equal))
.unwrap()
}
}

View File

@ -34,11 +34,13 @@ use uom::{
ElectricPotential,
ElectricalResistance,
ThermodynamicTemperature,
TemperatureInterval,
},
electric_current::ampere,
electric_potential::volt,
electrical_resistance::ohm,
thermodynamic_temperature::degree_celsius,
temperature_interval::kelvin,
},
};
@ -243,7 +245,7 @@ impl Handler {
use super::command_parser::ShParameter::*;
match parameter {
T0 => sh.t0 = ThermodynamicTemperature::new::<degree_celsius>(value),
B => sh.b = value,
B => sh.b = TemperatureInterval::new::<kelvin>(value),
R0 => sh.r0 = ElectricalResistance::new::<ohm>(value),
}
send_line(socket, b"{}");
@ -345,7 +347,7 @@ impl Handler {
fn set_fan(socket: &mut TcpSocket, fan_pwm: u32, fan_ctrl: &mut FanCtrl) -> Result<Handler, Error> {
if !fan_ctrl.fan_available() {
send_line(socket, b"{ \"warning\": \"this thermostat doesn't have fan!\" }");
send_line(socket, b"{ \"warning\": \"this thermostat doesn't have a fan!\" }");
return Ok(Handler::Handled);
}
fan_ctrl.set_auto_mode(false);
@ -374,7 +376,7 @@ impl Handler {
fn fan_auto(socket: &mut TcpSocket, fan_ctrl: &mut FanCtrl) -> Result<Handler, Error> {
if !fan_ctrl.fan_available() {
send_line(socket, b"{ \"warning\": \"this thermostat doesn't have fan!\" }");
send_line(socket, b"{ \"warning\": \"this thermostat doesn't have a fan!\" }");
return Ok(Handler::Handled);
}
fan_ctrl.set_auto_mode(true);

View File

@ -3,10 +3,12 @@ use uom::si::{
f64::{
ElectricalResistance,
ThermodynamicTemperature,
TemperatureInterval,
},
electrical_resistance::ohm,
ratio::ratio,
thermodynamic_temperature::{degree_celsius, kelvin},
temperature_interval::kelvin as kelvin_interval,
};
use serde::{Deserialize, Serialize};
@ -15,17 +17,21 @@ use serde::{Deserialize, Serialize};
pub struct Parameters {
/// Base temperature
pub t0: ThermodynamicTemperature,
/// Base resistance
/// Resistance at base temperature
pub r0: ElectricalResistance,
/// Beta
pub b: f64,
pub b: TemperatureInterval,
}
impl Parameters {
/// Perform the voltage to temperature conversion.
/// Perform the resistance to temperature conversion.
pub fn get_temperature(&self, r: ElectricalResistance) -> ThermodynamicTemperature {
let inv_temp = 1.0 / self.t0.get::<kelvin>() + (r / self.r0).get::<ratio>().ln() / self.b;
ThermodynamicTemperature::new::<kelvin>(1.0 / inv_temp)
let t0 = TemperatureInterval::new::<kelvin_interval>(self.t0.get::<kelvin>());
let inv_temp = 1.0 / t0 + (r / self.r0).get::<ratio>().ln() / self.b;
let temp = 1.0 / inv_temp;
ThermodynamicTemperature::new::<kelvin>(temp.get::<kelvin_interval>())
}
}
@ -34,7 +40,7 @@ impl Default for Parameters {
Parameters {
t0: ThermodynamicTemperature::new::<degree_celsius>(25.0),
r0: ElectricalResistance::new::<ohm>(10_000.0),
b: 3800.0,
b: TemperatureInterval::new::<kelvin_interval>(3800.0),
}
}
}