Use fixed-precision decimal numbers
This commit is contained in:
parent
95e253efed
commit
e7aa77494b
|
@ -41,12 +41,24 @@ version = "0.3.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m"
|
||||
version = "0.7.7"
|
||||
|
@ -94,6 +106,12 @@ version = "1.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "debug-helper"
|
||||
version = "0.3.13"
|
||||
|
@ -175,6 +193,18 @@ dependencies = [
|
|||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixed"
|
||||
version = "1.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02c69ce7e7c0f17aa18fdd9d0de39727adb9c6281f2ad12f57cbe54ae6e76e7d"
|
||||
dependencies = [
|
||||
"az",
|
||||
"bytemuck",
|
||||
"half",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "float-cmp"
|
||||
version = "0.9.0"
|
||||
|
@ -199,6 +229,35 @@ version = "2.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||
dependencies = [
|
||||
"hash32",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
|
@ -407,7 +466,9 @@ dependencies = [
|
|||
"display-interface",
|
||||
"embedded-graphics",
|
||||
"embedded-hal",
|
||||
"fixed",
|
||||
"fugit",
|
||||
"heapless",
|
||||
"nb 1.1.0",
|
||||
"panic-halt",
|
||||
"rp-pico",
|
||||
|
@ -446,6 +507,12 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.10"
|
||||
|
|
|
@ -11,7 +11,9 @@ cortex-m-rt = "0.7.3"
|
|||
display-interface = "0.4.1"
|
||||
embedded-graphics = "0.8.0"
|
||||
embedded-hal = "0.2.7"
|
||||
fixed = "1.24.0"
|
||||
fugit = "0.3.7"
|
||||
heapless = "0.8.0"
|
||||
nb = "1.1.0"
|
||||
panic-halt = "0.2.0"
|
||||
rp-pico = "0.7.0"
|
||||
|
|
91
src/main.rs
91
src/main.rs
|
@ -3,7 +3,8 @@
|
|||
|
||||
mod max6675;
|
||||
|
||||
use core::str;
|
||||
use core::fmt::Write;
|
||||
use core::write;
|
||||
|
||||
use cortex_m::delay::Delay;
|
||||
|
||||
|
@ -23,7 +24,9 @@ use embedded_hal::{
|
|||
|
||||
use fugit::{ExtU64, MicrosDurationU64, RateExtU32};
|
||||
|
||||
use max6675::{Error, Max6675};
|
||||
use heapless::String;
|
||||
|
||||
use max6675::{Error, FixedU16, Max6675};
|
||||
|
||||
use nb::Error::WouldBlock;
|
||||
|
||||
|
@ -49,19 +52,14 @@ use usb_device::{bus::UsbBus as UsbBusTrait, bus::UsbBusAllocator, prelude::*};
|
|||
|
||||
use usbd_serial::{SerialPort, USB_CLASS_CDC};
|
||||
|
||||
const HYSTERESIS: u16 = 10;
|
||||
const HYSTERESIS: FixedU16 = FixedU16::const_from_int(5);
|
||||
|
||||
const PEAK_TEMPERATURE: u16 = 240;
|
||||
const PEAK_TEMPERATURE: FixedU16 = FixedU16::const_from_int(240);
|
||||
|
||||
const POWER_FACTOR: u16 = 10;
|
||||
const POWER_MAX: u16 = 1000;
|
||||
|
||||
const PREHEAT_TEMPERATURE: u16 = 150;
|
||||
const PREHEAT_TEMPERATURE: FixedU16 = FixedU16::const_from_int(150);
|
||||
|
||||
const SOAK_TIME: MicrosDurationU64 = MicrosDurationU64::secs(90);
|
||||
|
||||
const TEMPERATURE_BUFF: u16 = 10;
|
||||
|
||||
enum State<'a> {
|
||||
Off,
|
||||
Preheat,
|
||||
|
@ -70,14 +68,6 @@ enum State<'a> {
|
|||
Cooling,
|
||||
}
|
||||
|
||||
fn clamp(value: u16, max: u16) -> u16 {
|
||||
if value > max {
|
||||
max
|
||||
} else {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
fn print_serial<'a, B: UsbBusTrait>(
|
||||
serial: &mut SerialPort<'a, B>,
|
||||
msg: &str,
|
||||
|
@ -230,7 +220,6 @@ fn main() -> ! {
|
|||
let so = pins.gpio6.into_floating_input();
|
||||
let cs = pins.gpio7.into_push_pull_output_in_state(PinState::High);
|
||||
let sck = pins.gpio8.into_push_pull_output();
|
||||
|
||||
let mut thermocouple = Max6675::new(cs, sck, so);
|
||||
|
||||
let button = pins.gpio15.into_pull_up_input();
|
||||
|
@ -246,7 +235,7 @@ fn main() -> ! {
|
|||
let mut counter = 0;
|
||||
let mut state = State::Off;
|
||||
let mut heating = false;
|
||||
let mut power = 0;
|
||||
let mut error_counter = 0;
|
||||
loop {
|
||||
delay.delay_ms(5);
|
||||
counter = (counter + 1) % 2000;
|
||||
|
@ -271,15 +260,13 @@ fn main() -> ! {
|
|||
if counter % 50 == 0 {
|
||||
let thermocouple_result = thermocouple.read_temperature(&mut timer.count_down());
|
||||
|
||||
if let Some(mut temperature) = thermocouple_result.as_ref().copied().ok() {
|
||||
temperature = (temperature >> 2) + ((temperature & 2) >> 1);
|
||||
if let Some(temperature) = thermocouple_result.as_ref().copied().ok() {
|
||||
error_counter = 0;
|
||||
|
||||
match state {
|
||||
State::Off => (),
|
||||
State::Preheat => {
|
||||
if temperature < PREHEAT_TEMPERATURE {
|
||||
heating = true;
|
||||
power = clamp((PREHEAT_TEMPERATURE - temperature + TEMPERATURE_BUFF) * POWER_FACTOR, POWER_MAX);
|
||||
} else {
|
||||
let mut time = timer.count_down();
|
||||
time.start(SOAK_TIME);
|
||||
|
@ -289,58 +276,61 @@ fn main() -> ! {
|
|||
State::Soak(ref mut time) => match time.wait() {
|
||||
Ok(_) => state = State::Reflow,
|
||||
Err(WouldBlock) => {
|
||||
if temperature < PREHEAT_TEMPERATURE - HYSTERESIS {
|
||||
if temperature < PREHEAT_TEMPERATURE {
|
||||
heating = true;
|
||||
power = clamp((PREHEAT_TEMPERATURE - temperature + TEMPERATURE_BUFF) * POWER_FACTOR, POWER_MAX);
|
||||
} else if temperature > PREHEAT_TEMPERATURE + HYSTERESIS * 2 {
|
||||
state = State::Reflow;
|
||||
} else if temperature > PREHEAT_TEMPERATURE {
|
||||
}
|
||||
if temperature > PREHEAT_TEMPERATURE + HYSTERESIS {
|
||||
heating = false;
|
||||
}
|
||||
}
|
||||
Err(_) => state = State::Off,
|
||||
Err(_) => unreachable!(),
|
||||
},
|
||||
State::Reflow => {
|
||||
if temperature < PEAK_TEMPERATURE {
|
||||
heating = true;
|
||||
power = clamp((PEAK_TEMPERATURE - temperature + TEMPERATURE_BUFF) * POWER_FACTOR, POWER_MAX);
|
||||
} else {
|
||||
heating = false;
|
||||
|
||||
state = State::Cooling;
|
||||
}
|
||||
}
|
||||
State::Cooling => state = State::Off,
|
||||
State::Cooling if temperature < PREHEAT_TEMPERATURE => {
|
||||
state = State::Preheat;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
} else {
|
||||
error_counter += 1;
|
||||
}
|
||||
|
||||
if error_counter >= 4 {
|
||||
state = State::Off;
|
||||
}
|
||||
|
||||
let mut bytes: [u8; 7] = [32, 32, 32, 32, 194, 176, 67];
|
||||
let text = match thermocouple_result {
|
||||
Ok(mut temperature) => {
|
||||
temperature = (temperature >> 2) + ((temperature & 2) >> 1);
|
||||
let mut text: String<9> = String::new();
|
||||
let text_str;
|
||||
|
||||
for i in (0..3).rev() {
|
||||
bytes[i] = 48u8 + (temperature % 10) as u8;
|
||||
temperature /= 10;
|
||||
|
||||
if temperature == 0 {
|
||||
break;
|
||||
match thermocouple_result {
|
||||
Ok(temperature) => {
|
||||
if let Err(_) = write!(&mut text, "{}", temperature) {
|
||||
text_str = "format error";
|
||||
} else {
|
||||
text_str = text.as_str();
|
||||
}
|
||||
}
|
||||
|
||||
str::from_utf8(&bytes).unwrap()
|
||||
Err(Error::IOError) => {
|
||||
text_str = "i/o error";
|
||||
}
|
||||
Err(Error::OpenThermocouple) => {
|
||||
text_str = "n/c";
|
||||
}
|
||||
Err(Error::IOError) => "i/o error",
|
||||
Err(Error::OpenThermocouple) => "n/c",
|
||||
};
|
||||
|
||||
let _ = println_serial(&mut serial, text);
|
||||
let _ = println_serial(&mut serial, text_str);
|
||||
|
||||
display.clear_buffer();
|
||||
|
||||
if let Err(err) = display_text(&mut display, text, Baseline::Bottom) {
|
||||
if let Err(err) = display_text(&mut display, text_str, Baseline::Bottom) {
|
||||
let _ = println_serial(&mut serial, stringify_display_error(err));
|
||||
}
|
||||
|
||||
|
@ -362,16 +352,11 @@ fn main() -> ! {
|
|||
}
|
||||
|
||||
if let State::Off = state {
|
||||
relay.set_low().unwrap();
|
||||
heating = false;
|
||||
}
|
||||
|
||||
if heating {
|
||||
if counter == 0 {
|
||||
relay.set_high().unwrap();
|
||||
} else if counter >= power {
|
||||
relay.set_low().unwrap();
|
||||
}
|
||||
} else {
|
||||
relay.set_low().unwrap();
|
||||
}
|
||||
|
|
|
@ -3,10 +3,14 @@ use embedded_hal::{
|
|||
timer::CountDown,
|
||||
};
|
||||
|
||||
use fixed::types::extra::U2;
|
||||
|
||||
use fugit::{ExtU64, MicrosDurationU64};
|
||||
|
||||
use nb::block;
|
||||
|
||||
pub type FixedU16 = fixed::FixedU16<U2>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
IOError,
|
||||
|
@ -34,7 +38,7 @@ where
|
|||
Self { cs, sck, so }
|
||||
}
|
||||
|
||||
pub fn read_temperature<CD>(&mut self, timer: &mut CD) -> Result<u16, Error>
|
||||
pub fn read_temperature<CD>(&mut self, timer: &mut CD) -> Result<FixedU16, Error>
|
||||
where
|
||||
CD: CountDown,
|
||||
CD::Time: From<MicrosDurationU64>,
|
||||
|
@ -61,7 +65,7 @@ where
|
|||
if d & 0x4 == 0x4 {
|
||||
Err(Error::OpenThermocouple)
|
||||
} else {
|
||||
Ok(d >> 3)
|
||||
Ok(FixedU16::from_num(d >> 3))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue