v0.2:重写项目。 #6
@ -17,8 +17,10 @@ pio = ["esp-idf-sys/pio"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
embedded-hal = "0.2.7"
|
||||||
embedded-svc = "0.22.0"
|
embedded-svc = "0.22.0"
|
||||||
env_logger = "0.9.0"
|
env_logger = "0.9.0"
|
||||||
|
esp-idf-hal = "0.38.0"
|
||||||
esp-idf-svc = "0.42.1"
|
esp-idf-svc = "0.42.1"
|
||||||
esp-idf-sys = { version = "0.31.6", features = ["binstart"] }
|
esp-idf-sys = { version = "0.31.6", features = ["binstart"] }
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
|
47
src/blink.rs
Normal file
47
src/blink.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use embedded_hal::digital::v2::OutputPin;
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
pub struct Blink<T>
|
||||||
|
where
|
||||||
|
T: OutputPin,
|
||||||
|
{
|
||||||
|
state: bool,
|
||||||
|
pin: T,
|
||||||
|
stopped: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Blink<T>
|
||||||
|
where
|
||||||
|
T: OutputPin,
|
||||||
|
{
|
||||||
|
pub fn new(pin: T) -> Blink<T> {
|
||||||
|
return Blink {
|
||||||
|
state: false,
|
||||||
|
pin,
|
||||||
|
stopped: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toggle(&mut self) -> Result<(), T::Error> {
|
||||||
|
self.state = !self.state;
|
||||||
|
if self.state {
|
||||||
|
self.pin.set_high()
|
||||||
|
} else {
|
||||||
|
self.pin.set_low()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn play(&mut self) where <T as embedded_hal::digital::v2::OutputPin>::Error: std::fmt::Debug {
|
||||||
|
loop {
|
||||||
|
if self.stopped {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
self.toggle().unwrap();
|
||||||
|
thread::sleep(Duration::from_millis(30));
|
||||||
|
|
||||||
|
self.toggle().unwrap();
|
||||||
|
thread::sleep(Duration::from_millis(1930));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
src/main.rs
50
src/main.rs
@ -1,13 +1,22 @@
|
|||||||
use std::{env, thread::sleep, time::{Duration}};
|
|
||||||
use embedded_svc::mqtt::client::{Publish, QoS};
|
use embedded_svc::mqtt::client::{Publish, QoS};
|
||||||
use esp_idf_sys as _;
|
use esp_idf_sys as _;
|
||||||
use log::*;
|
use log::*;
|
||||||
|
use std::{
|
||||||
|
env,
|
||||||
|
thread::{self, sleep},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
mod blink;
|
||||||
mod message_queue;
|
mod message_queue;
|
||||||
mod wifi;
|
|
||||||
mod time;
|
mod time;
|
||||||
|
mod wifi;
|
||||||
|
mod voltage_detection;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
message_queue::MessageQueue, time::Time, wifi::Internet, voltage_detection::VoltageDetection,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{message_queue::MessageQueue, wifi::Internet, time::Time};
|
|
||||||
fn main() {
|
fn main() {
|
||||||
env::set_var("DEFMT_LOG", "trace");
|
env::set_var("DEFMT_LOG", "trace");
|
||||||
env::set_var("RUST_BACKTRACE", "1");
|
env::set_var("RUST_BACKTRACE", "1");
|
||||||
@ -18,7 +27,31 @@ fn main() {
|
|||||||
// or else some patches to the runtime implemented by esp-idf-sys might not link properly.
|
// or else some patches to the runtime implemented by esp-idf-sys might not link properly.
|
||||||
esp_idf_sys::link_patches();
|
esp_idf_sys::link_patches();
|
||||||
|
|
||||||
println!("Hello, world!");
|
info!("Hello, world!");
|
||||||
|
|
||||||
|
let peripherals = esp_idf_hal::peripherals::Peripherals::take().unwrap();
|
||||||
|
|
||||||
|
let blink_pin = peripherals.pins.gpio5;
|
||||||
|
let beep_pin = peripherals.pins.gpio6;
|
||||||
|
let ledc_timer0 = peripherals.ledc.timer0;
|
||||||
|
let ledc_channel0 = peripherals.ledc.channel0;
|
||||||
|
let dc_out_ctl_pin = peripherals.pins.gpio3;
|
||||||
|
let i2c0 = peripherals.i2c0;
|
||||||
|
let sda_pin = peripherals.pins.gpio4;
|
||||||
|
let scl_pin = peripherals.pins.gpio10;
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
let mut blink = blink::Blink::new(
|
||||||
|
blink_pin
|
||||||
|
.into_output()
|
||||||
|
.expect("Failed to set GPIO5 as output"),
|
||||||
|
);
|
||||||
|
blink.play();
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut voltage_detection = VoltageDetection::new();
|
||||||
|
|
||||||
|
voltage_detection.watching().expect("Can not watch voltages.");
|
||||||
|
|
||||||
let _wifi = Internet::new().unwrap();
|
let _wifi = Internet::new().unwrap();
|
||||||
|
|
||||||
@ -34,14 +67,15 @@ fn main() {
|
|||||||
let timestamps = time.get_time().as_millis();
|
let timestamps = time.get_time().as_millis();
|
||||||
|
|
||||||
info!("timestamps {}", timestamps);
|
info!("timestamps {}", timestamps);
|
||||||
mq_client.publish(
|
mq_client
|
||||||
|
.publish(
|
||||||
"ups-0.2/heartbeat",
|
"ups-0.2/heartbeat",
|
||||||
QoS::AtMostOnce,
|
QoS::AtMostOnce,
|
||||||
false,
|
false,
|
||||||
timestamps.to_string().as_bytes(),
|
timestamps.to_string().as_bytes(),
|
||||||
).map_err(|err| {
|
)
|
||||||
warn!("publish heartbeat failed {}", err)
|
.map_err(|err| warn!("publish heartbeat failed {}", err))
|
||||||
}).unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ impl MessageQueue {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let (mut client, mut connection) =
|
let (mut client, mut connection) =
|
||||||
EspMqttClient::new_with_conn("mqtt://192.168.31.8:1883", &conf)?;
|
EspMqttClient::new_with_conn("mqtt://192.168.31.11:1883", &conf)?;
|
||||||
|
|
||||||
info!("MQTT client started");
|
info!("MQTT client started");
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
|
124
src/voltage_detection.rs
Normal file
124
src/voltage_detection.rs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
use std::{
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use embedded_hal::{adc::Channel, prelude::_embedded_hal_adc_OneShot, digital::v2::OutputPin};
|
||||||
|
use embedded_svc::timer::{PeriodicTimer, TimerService};
|
||||||
|
use esp_idf_hal::{
|
||||||
|
adc::{
|
||||||
|
config::{self},
|
||||||
|
Analog, PoweredAdc, ADC1,
|
||||||
|
},
|
||||||
|
gpio::{Gpio1, Gpio2, Gpio3, Input, Pull},
|
||||||
|
};
|
||||||
|
use esp_idf_svc::timer::{EspTimer, EspTimerService};
|
||||||
|
use log::{info, warn};
|
||||||
|
|
||||||
|
pub struct VoltageDetection {
|
||||||
|
pub worker: VoltageDetectionWorker,
|
||||||
|
watch_timer: Option<EspTimer>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct VoltageDetectionWorker {
|
||||||
|
pub adapter_voltage: u16,
|
||||||
|
pub battery_voltage: u16,
|
||||||
|
pub output_voltage: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VoltageDetection {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
return Self {
|
||||||
|
worker: VoltageDetectionWorker::new(),
|
||||||
|
watch_timer: None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn watching(&mut self) -> anyhow::Result<()> {
|
||||||
|
let worker = Arc::new(Mutex::new(self.worker));
|
||||||
|
let mut timer = EspTimerService::new()?.timer(move || {
|
||||||
|
info!("One-shot timer triggered");
|
||||||
|
match worker.as_ref().lock().as_mut() {
|
||||||
|
Ok(worker) => {
|
||||||
|
if let Err(err) = worker.read_once() {
|
||||||
|
warn!("Read Failed. {}", err);
|
||||||
|
}
|
||||||
|
info!(
|
||||||
|
"Adapter: {},\tBattery: {},\t Output: {}",
|
||||||
|
worker.adapter_voltage, worker.battery_voltage, worker.output_voltage
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!("Lock VoltageDetection Worker Failed. {}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
timer.every(Duration::from_secs(1))?;
|
||||||
|
|
||||||
|
self.watch_timer = Some(timer);
|
||||||
|
return anyhow::Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl VoltageDetectionWorker {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
return Self {
|
||||||
|
adapter_voltage: 0,
|
||||||
|
battery_voltage: 0,
|
||||||
|
output_voltage: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_once(&mut self) -> anyhow::Result<()> {
|
||||||
|
let adapter_pin = unsafe { Gpio1::<Input>::new() }
|
||||||
|
.into_analog_atten_11db()
|
||||||
|
.map_err(|err| anyhow::anyhow!("Failed to set GPIO 1 as analog input. {}", err))?;
|
||||||
|
match self.read_pin_once(adapter_pin) {
|
||||||
|
Ok(voltage) => {
|
||||||
|
self.adapter_voltage = voltage;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!("Adapter Voltage read failed: {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let battery_pin = unsafe { Gpio2::<Input>::new() }
|
||||||
|
.into_analog_atten_11db()
|
||||||
|
.map_err(|err| anyhow::anyhow!("Failed to set GPIO 1 as analog input. {}", err))?;
|
||||||
|
match self.read_pin_once(battery_pin) {
|
||||||
|
Ok(voltage) => {
|
||||||
|
self.battery_voltage = voltage;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!("Adapter Voltage read failed: {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let output_pin = unsafe { Gpio3::<Input>::new() }
|
||||||
|
.into_analog_atten_11db()
|
||||||
|
.map_err(|err| anyhow::anyhow!("Failed to set GPIO 1 as analog input. {}", err))?;
|
||||||
|
match self.read_pin_once(output_pin) {
|
||||||
|
Ok(voltage) => {
|
||||||
|
self.output_voltage = voltage;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!("Adapter Voltage read failed: {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return anyhow::Ok(());
|
||||||
|
}
|
||||||
|
pub fn read_pin_once<AN: Analog<ADC1>, PIN: Channel<AN, ID = u8>>(
|
||||||
|
&mut self,
|
||||||
|
mut pin: PIN,
|
||||||
|
) -> anyhow::Result<u16> {
|
||||||
|
let mut adc = PoweredAdc::new(unsafe { ADC1::new() }, config::Config::new())?;
|
||||||
|
let voltage = adc.read(&mut pin);
|
||||||
|
match voltage {
|
||||||
|
Ok(voltage) => anyhow::Ok((self.adapter_voltage + voltage * 10) / 11),
|
||||||
|
Err(err) => {
|
||||||
|
anyhow::bail!("Adapter Voltage read failed: {:?}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user