Read temperature from thermocouple
This commit is contained in:
parent
722a38f633
commit
0956055d6a
|
@ -408,6 +408,7 @@ dependencies = [
|
|||
"embedded-graphics",
|
||||
"embedded-hal",
|
||||
"fugit",
|
||||
"nb 1.1.0",
|
||||
"panic-halt",
|
||||
"rp-pico",
|
||||
"ssd1306",
|
||||
|
|
|
@ -12,6 +12,7 @@ display-interface = "0.4.1"
|
|||
embedded-graphics = "0.8.0"
|
||||
embedded-hal = "0.2.7"
|
||||
fugit = "0.3.7"
|
||||
nb = "1.1.0"
|
||||
panic-halt = "0.2.0"
|
||||
rp-pico = "0.7.0"
|
||||
ssd1306 = "0.8.0"
|
||||
|
|
100
src/main.rs
100
src/main.rs
|
@ -1,21 +1,27 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
mod max6675;
|
||||
|
||||
use core::str;
|
||||
|
||||
use cortex_m::delay::Delay;
|
||||
|
||||
use display_interface::DisplayError;
|
||||
|
||||
use embedded_graphics::{
|
||||
mono_font::{ascii::FONT_6X10, MonoTextStyleBuilder},
|
||||
mono_font::{iso_8859_1::FONT_6X10, MonoTextStyle},
|
||||
pixelcolor::BinaryColor,
|
||||
prelude::*,
|
||||
text::{Baseline, Text},
|
||||
text::{Alignment, Text},
|
||||
};
|
||||
|
||||
use embedded_hal::digital::v2::{InputPin, ToggleableOutputPin};
|
||||
|
||||
use fugit::RateExtU32;
|
||||
|
||||
use max6675::{Error, Max6675};
|
||||
|
||||
use panic_halt as _;
|
||||
|
||||
use rp_pico::{
|
||||
|
@ -25,13 +31,13 @@ use rp_pico::{
|
|||
gpio::PinState,
|
||||
i2c::I2C,
|
||||
usb::UsbBus,
|
||||
Sio, Watchdog,
|
||||
Sio, Timer, Watchdog,
|
||||
},
|
||||
pac::{CorePeripherals, Peripherals},
|
||||
Pins,
|
||||
};
|
||||
|
||||
use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306};
|
||||
use ssd1306::{mode::BufferedGraphicsMode, prelude::*, I2CDisplayInterface, Ssd1306};
|
||||
|
||||
use usb_device::{bus::UsbBus as UsbBusTrait, bus::UsbBusAllocator, prelude::*};
|
||||
|
||||
|
@ -58,6 +64,14 @@ fn print_serial<'a, B: UsbBusTrait>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn println_serial<'a, B: UsbBusTrait>(
|
||||
serial: &mut SerialPort<'a, B>,
|
||||
msg: &str,
|
||||
) -> Result<(), UsbError> {
|
||||
print_serial(serial, msg)?;
|
||||
print_serial(serial, "\r\n")
|
||||
}
|
||||
|
||||
fn stringify_display_error(err: DisplayError) -> &'static str {
|
||||
match err {
|
||||
DisplayError::InvalidFormatError => "invalid format",
|
||||
|
@ -71,6 +85,27 @@ fn stringify_display_error(err: DisplayError) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
fn display_text<DI, SIZE>(
|
||||
display: &mut Ssd1306<DI, SIZE, BufferedGraphicsMode<SIZE>>,
|
||||
text: &str,
|
||||
) -> Result<(), DisplayError>
|
||||
where
|
||||
DI: WriteOnlyDataCommand,
|
||||
SIZE: DisplaySize,
|
||||
{
|
||||
let (w, h) = display.dimensions();
|
||||
|
||||
Text::with_alignment(
|
||||
text,
|
||||
Point::new((w / 2).into(), (h / 2).into()),
|
||||
MonoTextStyle::new(&FONT_6X10, BinaryColor::On),
|
||||
Alignment::Center,
|
||||
)
|
||||
.draw(display)?;
|
||||
|
||||
display.flush()
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut p = Peripherals::take().unwrap();
|
||||
|
@ -110,7 +145,7 @@ fn main() -> ! {
|
|||
.device_class(USB_CLASS_CDC)
|
||||
.build();
|
||||
|
||||
for _ in 0..2000 {
|
||||
for _ in 0..1000 {
|
||||
delay.delay_ms(5);
|
||||
|
||||
if !usb_dev.poll(&mut [&mut serial]) {
|
||||
|
@ -124,7 +159,7 @@ fn main() -> ! {
|
|||
}
|
||||
}
|
||||
|
||||
let _ = print_serial(&mut serial, "Hello, world!\r\n");
|
||||
let _ = println_serial(&mut serial, "Hello, world!");
|
||||
|
||||
let i2c = I2C::i2c0(
|
||||
p.I2C0,
|
||||
|
@ -148,26 +183,15 @@ fn main() -> ! {
|
|||
panic!();
|
||||
}
|
||||
|
||||
let text_style = MonoTextStyleBuilder::new()
|
||||
.font(&FONT_6X10)
|
||||
.text_color(BinaryColor::On)
|
||||
.build();
|
||||
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 result = Text::with_baseline("Hello, world!", Point::zero(), text_style, Baseline::Top)
|
||||
.draw(&mut display)
|
||||
.map_err(stringify_display_error);
|
||||
if let Err(msg) = result {
|
||||
let _ = print_serial(&mut serial, msg);
|
||||
panic!();
|
||||
}
|
||||
|
||||
let result = display.flush().map_err(stringify_display_error);
|
||||
if let Err(msg) = result {
|
||||
let _ = print_serial(&mut serial, msg);
|
||||
}
|
||||
let mut thermocouple = Max6675::new(cs, sck, so);
|
||||
let timer = Timer::new(p.TIMER, &mut p.RESETS);
|
||||
|
||||
let mut relay = pins.gpio14.into_push_pull_output_in_state(PinState::Low);
|
||||
let tmp_button = pins.gpio15.into_pull_up_input();
|
||||
let button = pins.gpio15.into_pull_up_input();
|
||||
|
||||
let mut led = pins.led.into_push_pull_output_in_state(PinState::Low);
|
||||
|
||||
|
@ -179,10 +203,36 @@ fn main() -> ! {
|
|||
if counter == 0 {
|
||||
led.toggle().unwrap();
|
||||
|
||||
let _ = print_serial(&mut serial, "ping\r\n");
|
||||
let mut bytes: [u8; 8] = [32, 32, 32, 32, 32, 194, 176, 67];
|
||||
let text = match thermocouple.read_temperature(&mut timer.count_down()) {
|
||||
Ok(mut temperature) => {
|
||||
temperature >>= 2;
|
||||
|
||||
for i in (0..4).rev() {
|
||||
bytes[i] = 48u8 + (temperature % 10) as u8;
|
||||
temperature /= 10;
|
||||
|
||||
if temperature == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if tmp_button.is_low().unwrap() {
|
||||
str::from_utf8(&bytes).unwrap()
|
||||
}
|
||||
Err(Error::IOError) => "i/o error",
|
||||
Err(Error::OpenThermocouple) => "n/c",
|
||||
};
|
||||
|
||||
let _ = println_serial(&mut serial, text);
|
||||
|
||||
display.clear_buffer();
|
||||
|
||||
if let Err(err) = display_text(&mut display, text) {
|
||||
let _ = println_serial(&mut serial, stringify_display_error(err));
|
||||
}
|
||||
}
|
||||
|
||||
if button.is_low().unwrap() {
|
||||
relay.toggle().unwrap();
|
||||
delay.delay_ms(1000);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
use embedded_hal::{
|
||||
digital::v2::{InputPin, OutputPin},
|
||||
timer::CountDown,
|
||||
};
|
||||
|
||||
use fugit::{ExtU64, MicrosDurationU64};
|
||||
|
||||
use nb::block;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
IOError,
|
||||
OpenThermocouple,
|
||||
}
|
||||
|
||||
pub struct Max6675<CS, SCK, SO>
|
||||
where
|
||||
CS: OutputPin,
|
||||
SCK: OutputPin,
|
||||
SO: InputPin,
|
||||
{
|
||||
cs: CS,
|
||||
sck: SCK,
|
||||
so: SO,
|
||||
}
|
||||
|
||||
impl<CS, SCK, SO> Max6675<CS, SCK, SO>
|
||||
where
|
||||
CS: OutputPin,
|
||||
SCK: OutputPin,
|
||||
SO: InputPin,
|
||||
{
|
||||
pub fn new(cs: CS, sck: SCK, so: SO) -> Self {
|
||||
Self { cs, sck, so }
|
||||
}
|
||||
|
||||
pub fn read_temperature<CD>(&mut self, timer: &mut CD) -> Result<u16, Error>
|
||||
where
|
||||
CD: CountDown,
|
||||
CD::Time: From<MicrosDurationU64>,
|
||||
{
|
||||
self.cs.set_low().map_err(|_| Error::IOError)?;
|
||||
delay(timer, 10.micros());
|
||||
|
||||
let mut d = 0u16;
|
||||
|
||||
for i in (0..16).rev() {
|
||||
self.sck.set_low().map_err(|_| Error::IOError)?;
|
||||
delay(timer, 10.micros());
|
||||
|
||||
if self.so.is_high().map_err(|_| Error::IOError)? {
|
||||
d |= 1 << i;
|
||||
}
|
||||
|
||||
self.sck.set_high().map_err(|_| Error::IOError)?;
|
||||
delay(timer, 10.micros());
|
||||
}
|
||||
|
||||
self.cs.set_high().map_err(|_| Error::IOError)?;
|
||||
|
||||
if d & 0x4 == 0x4 {
|
||||
Err(Error::OpenThermocouple)
|
||||
} else {
|
||||
Ok(d >> 3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn delay<CD>(timer: &mut CD, t: MicrosDurationU64)
|
||||
where
|
||||
CD: CountDown,
|
||||
CD::Time: From<MicrosDurationU64>,
|
||||
{
|
||||
timer.start(t);
|
||||
block!(timer.wait()).unwrap();
|
||||
}
|
Loading…
Reference in New Issue