130 lines
4.2 KiB
Rust
130 lines
4.2 KiB
Rust
use anyhow::{bail, Result};
|
|
use log::info;
|
|
use std::{
|
|
sync::{Arc, Mutex},
|
|
thread,
|
|
};
|
|
|
|
use esp_idf_svc::{
|
|
eventloop::EspSystemEventLoop,
|
|
hal::{
|
|
delay::FreeRtos,
|
|
gpio::{self, Level, PinDriver},
|
|
i2c::{I2cConfig, I2cDriver},
|
|
peripherals::Peripherals,
|
|
prelude::FromValueType,
|
|
uart::{self, UartDriver},
|
|
units::Hertz,
|
|
},
|
|
log::EspLogger,
|
|
nvs::EspDefaultNvsPartition,
|
|
sys::CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT,
|
|
wifi::{AuthMethod, BlockingWifi, ClientConfiguration, Configuration, EspWifi},
|
|
};
|
|
use pmme_device::{display::oled_task, sensors::sensors_task, wifi::wifi_task, Pms7003Data};
|
|
|
|
fn main() -> Result<()> {
|
|
// It is necessary to call this function once. Otherwise some patches to the runtime
|
|
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
|
|
esp_idf_svc::sys::link_patches();
|
|
|
|
// Initialize NVS
|
|
EspLogger::initialize_default();
|
|
let nvs = EspDefaultNvsPartition::take()?;
|
|
|
|
FreeRtos::delay_ms(100);
|
|
|
|
let peripherals = Peripherals::take()?;
|
|
FreeRtos::delay_ms(100);
|
|
|
|
let mut button = PinDriver::input(peripherals.pins.gpio5)?;
|
|
let mut led = PinDriver::output(peripherals.pins.gpio19)?;
|
|
led.set_low()?;
|
|
|
|
let i2c = peripherals.i2c0;
|
|
let sda = peripherals.pins.gpio21;
|
|
let scl = peripherals.pins.gpio22;
|
|
|
|
let config = I2cConfig::new().baudrate(100.kHz().into());
|
|
let i2c = I2cDriver::new(i2c, sda, scl, &config)?;
|
|
|
|
let tx = peripherals.pins.gpio17;
|
|
let rx = peripherals.pins.gpio16;
|
|
|
|
let config = uart::config::Config::new().baudrate(Hertz(9600));
|
|
let uart = UartDriver::new(
|
|
peripherals.uart2,
|
|
tx,
|
|
rx,
|
|
Option::<gpio::Gpio0>::None,
|
|
Option::<gpio::Gpio1>::None,
|
|
&config,
|
|
)?;
|
|
|
|
let sysloop = EspSystemEventLoop::take()?;
|
|
let sysloop_clone = sysloop.clone();
|
|
let modem = peripherals.modem;
|
|
|
|
let pm_data = Arc::new(Mutex::new(Pms7003Data::default()));
|
|
let oled_arc = Arc::clone(&pm_data);
|
|
let sensors_arc = Arc::clone(&pm_data);
|
|
// let wifi_arc = Arc::clone(&pm_data);
|
|
|
|
let handles = vec![
|
|
thread::spawn(move || {
|
|
if let Err(e) = oled_task(oled_arc, i2c) {
|
|
log::error!("OLED Task Error: {:?}", e);
|
|
}
|
|
}),
|
|
thread::spawn(move || {
|
|
if let Err(e) = sensors_task(sensors_arc, &uart) {
|
|
log::error!("PM Sensor Task Error: {:?}", e);
|
|
}
|
|
}),
|
|
std::thread::Builder::new()
|
|
// NOTE: According to CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT, this was set to 3072 and the wifi task
|
|
// was getting a stack overflow
|
|
.stack_size(12288)
|
|
.spawn(move || {
|
|
unsafe {
|
|
let free_stack =
|
|
esp_idf_svc::sys::uxTaskGetStackHighWaterMark(std::ptr::null_mut());
|
|
let stack_size = CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT;
|
|
log::info!(
|
|
"Pthread stack size configured: {} bytes, Current free stack: {} bytes",
|
|
stack_size,
|
|
free_stack * 4
|
|
);
|
|
}
|
|
if let Err(e) = wifi_task(modem, sysloop_clone, nvs) {
|
|
log::error!("PM Wifi Task Error: {:?}", e);
|
|
}
|
|
})?,
|
|
thread::spawn(move || {
|
|
let mut is_pressed = false;
|
|
let mut curr_state = Level::High;
|
|
loop {
|
|
if curr_state == Level::High && button.is_low() {
|
|
led.set_high().unwrap();
|
|
curr_state = Level::Low;
|
|
is_pressed = true;
|
|
} else if curr_state == Level::Low && button.is_high() {
|
|
led.set_low().unwrap();
|
|
curr_state = Level::High;
|
|
is_pressed = true;
|
|
}
|
|
if is_pressed {
|
|
FreeRtos::delay_ms(100);
|
|
} else {
|
|
FreeRtos::delay_ms(10);
|
|
}
|
|
}
|
|
}),
|
|
];
|
|
for h in handles {
|
|
h.join().unwrap();
|
|
}
|
|
|
|
Ok(())
|
|
}
|