forked from M-Labs/thermostat
Compare commits
6 Commits
c1b183ddd5
...
8b0ad14311
Author | SHA1 | Date | |
---|---|---|---|
8b0ad14311 | |||
9d89104f50 | |||
136c7a0b52 | |||
5000cae1b1 | |||
78ec77509f | |||
52aa3890c1 |
@ -45,7 +45,7 @@ There are several options for flashing Thermostat. DFU requires only a micro-USB
|
|||||||
|
|
||||||
### dfu-util on Linux
|
### dfu-util on Linux
|
||||||
* Install the DFU USB tool (dfu-util).
|
* 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.
|
* 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.
|
* Add jumper to Thermostat v2.0 across 2-pin jumper adjacent to JTAG connector.
|
||||||
* Cycle board power to put it in DFU update mode
|
* Cycle board power to put it in DFU update mode
|
||||||
|
8
flake.lock
generated
8
flake.lock
generated
@ -2,16 +2,16 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1691421349,
|
"lastModified": 1722791413,
|
||||||
"narHash": "sha256-RRJyX0CUrs4uW4gMhd/X4rcDG8PTgaaCQM5rXEJOx6g=",
|
"narHash": "sha256-rCTrlCWvHzMCNcKxPE3Z/mMK2gDZ+BvvpEVyRM4tKmU=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "011567f35433879aae5024fc6ec53f2a0568a6c4",
|
"rev": "8b5b6723aca5a51edf075936439d9cd3947b7b2c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-23.05",
|
"ref": "nixos-24.05",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
description = "Firmware for the Sinara 8451 Thermostat";
|
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 = {
|
inputs.rust-overlay = {
|
||||||
url = "github:oxalica/rust-overlay";
|
url = "github:oxalica/rust-overlay";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
@ -47,6 +47,7 @@
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
dontFixup = true;
|
dontFixup = true;
|
||||||
|
auditable = false;
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
packages.x86_64-linux = {
|
packages.x86_64-linux = {
|
||||||
@ -61,7 +62,8 @@
|
|||||||
devShells.x86_64-linux.default = pkgs.mkShellNoCC {
|
devShells.x86_64-linux.default = pkgs.mkShellNoCC {
|
||||||
name = "thermostat-dev-shell";
|
name = "thermostat-dev-shell";
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
rust openocd dfu-util
|
rust llvm
|
||||||
|
openocd dfu-util
|
||||||
] ++ (with python3Packages; [
|
] ++ (with python3Packages; [
|
||||||
numpy matplotlib
|
numpy matplotlib
|
||||||
]);
|
]);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use core::{cmp::max_by, marker::PhantomData};
|
use core::marker::PhantomData;
|
||||||
use heapless::{consts::U2, Vec};
|
use heapless::{consts::U2, Vec};
|
||||||
use num_traits::Zero;
|
use num_traits::Zero;
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{Serialize, Serializer};
|
||||||
@ -561,9 +561,10 @@ impl Channels {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_abs_max_tec_i(&mut self) -> ElectricCurrent {
|
pub fn current_abs_max_tec_i(&mut self) -> ElectricCurrent {
|
||||||
max_by(self.get_tec_i(0).abs(),
|
(0..CHANNELS)
|
||||||
self.get_tec_i(1).abs(),
|
.map(|channel| self.get_tec_i(channel).abs())
|
||||||
|a, b| a.partial_cmp(b).unwrap_or(core::cmp::Ordering::Equal))
|
.max_by(|a, b| a.partial_cmp(b).unwrap_or(core::cmp::Ordering::Equal))
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,11 +34,13 @@ use uom::{
|
|||||||
ElectricPotential,
|
ElectricPotential,
|
||||||
ElectricalResistance,
|
ElectricalResistance,
|
||||||
ThermodynamicTemperature,
|
ThermodynamicTemperature,
|
||||||
|
TemperatureInterval,
|
||||||
},
|
},
|
||||||
electric_current::ampere,
|
electric_current::ampere,
|
||||||
electric_potential::volt,
|
electric_potential::volt,
|
||||||
electrical_resistance::ohm,
|
electrical_resistance::ohm,
|
||||||
thermodynamic_temperature::degree_celsius,
|
thermodynamic_temperature::degree_celsius,
|
||||||
|
temperature_interval::kelvin,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -243,7 +245,7 @@ impl Handler {
|
|||||||
use super::command_parser::ShParameter::*;
|
use super::command_parser::ShParameter::*;
|
||||||
match parameter {
|
match parameter {
|
||||||
T0 => sh.t0 = ThermodynamicTemperature::new::<degree_celsius>(value),
|
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),
|
R0 => sh.r0 = ElectricalResistance::new::<ohm>(value),
|
||||||
}
|
}
|
||||||
send_line(socket, b"{}");
|
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> {
|
fn set_fan(socket: &mut TcpSocket, fan_pwm: u32, fan_ctrl: &mut FanCtrl) -> Result<Handler, Error> {
|
||||||
if !fan_ctrl.fan_available() {
|
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);
|
return Ok(Handler::Handled);
|
||||||
}
|
}
|
||||||
fan_ctrl.set_auto_mode(false);
|
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> {
|
fn fan_auto(socket: &mut TcpSocket, fan_ctrl: &mut FanCtrl) -> Result<Handler, Error> {
|
||||||
if !fan_ctrl.fan_available() {
|
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);
|
return Ok(Handler::Handled);
|
||||||
}
|
}
|
||||||
fan_ctrl.set_auto_mode(true);
|
fan_ctrl.set_auto_mode(true);
|
||||||
|
@ -3,10 +3,12 @@ use uom::si::{
|
|||||||
f64::{
|
f64::{
|
||||||
ElectricalResistance,
|
ElectricalResistance,
|
||||||
ThermodynamicTemperature,
|
ThermodynamicTemperature,
|
||||||
|
TemperatureInterval,
|
||||||
},
|
},
|
||||||
electrical_resistance::ohm,
|
electrical_resistance::ohm,
|
||||||
ratio::ratio,
|
ratio::ratio,
|
||||||
thermodynamic_temperature::{degree_celsius, kelvin},
|
thermodynamic_temperature::{degree_celsius, kelvin},
|
||||||
|
temperature_interval::kelvin as kelvin_interval,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -15,17 +17,21 @@ use serde::{Deserialize, Serialize};
|
|||||||
pub struct Parameters {
|
pub struct Parameters {
|
||||||
/// Base temperature
|
/// Base temperature
|
||||||
pub t0: ThermodynamicTemperature,
|
pub t0: ThermodynamicTemperature,
|
||||||
/// Base resistance
|
/// Resistance at base temperature
|
||||||
pub r0: ElectricalResistance,
|
pub r0: ElectricalResistance,
|
||||||
/// Beta
|
/// Beta
|
||||||
pub b: f64,
|
pub b: TemperatureInterval,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parameters {
|
impl Parameters {
|
||||||
/// Perform the voltage to temperature conversion.
|
/// Perform the resistance to temperature conversion.
|
||||||
pub fn get_temperature(&self, r: ElectricalResistance) -> ThermodynamicTemperature {
|
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;
|
let t0 = TemperatureInterval::new::<kelvin_interval>(self.t0.get::<kelvin>());
|
||||||
ThermodynamicTemperature::new::<kelvin>(1.0 / inv_temp)
|
|
||||||
|
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 {
|
Parameters {
|
||||||
t0: ThermodynamicTemperature::new::<degree_celsius>(25.0),
|
t0: ThermodynamicTemperature::new::<degree_celsius>(25.0),
|
||||||
r0: ElectricalResistance::new::<ohm>(10_000.0),
|
r0: ElectricalResistance::new::<ohm>(10_000.0),
|
||||||
b: 3800.0,
|
b: TemperatureInterval::new::<kelvin_interval>(3800.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user