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