From 5950279dc45cf54f4e0ff250d6625fe5d4404caf Mon Sep 17 00:00:00 2001 From: Philipp_EndevourOS Date: Fri, 1 Aug 2025 16:42:14 +0200 Subject: [PATCH] buzzer without pwm, and feedback with embassy Sync. Error when more then 4 tasks spawn --- Cargo.toml | 3 +- src/drivers/buzzer.rs | 20 ----- src/drivers/nfc_reader.rs | 7 +- src/drivers/rtc.rs | 163 +++++++++++++++++++++++--------------- src/feedback.rs | 65 ++++++++++++++- src/init/hardware.rs | 7 +- src/main.rs | 72 ++++++++++------- 7 files changed, 214 insertions(+), 123 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6d2037e..9dc4a24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ embassy-net = { version = "0.7.0", features = [ ] } embedded-io = "0.6.1" embedded-io-async = "0.6.1" -esp-alloc = "0.8.0" +esp-alloc = "0.8.0" esp-hal = { version = "1.0.0-beta.1", features = ["esp32c6", "unstable"] } smoltcp = { version = "0.12.0", default-features = false, features = [ "medium-ethernet", @@ -59,6 +59,7 @@ edge-nal = "0.5.0" edge-nal-embassy = { version = "0.6.0", features = ["log"] } picoserve = { version = "0.16.0", features = ["embassy", "log"] } embassy-sync = { version = "0.7.0", features = ["log"] } + ds3231 = { version = "0.3.0", features = ["async", "temperature_f32"] } ws2812-spi = "0.5.1" chrono = { version = "0.4.41", default-features = false } diff --git a/src/drivers/buzzer.rs b/src/drivers/buzzer.rs index 3514967..e69de29 100644 --- a/src/drivers/buzzer.rs +++ b/src/drivers/buzzer.rs @@ -1,20 +0,0 @@ -use embassy_time::{Duration, Timer}; -use esp_hal::peripherals; -use log::{debug, error, info}; - -use crate::init; - - -#[embassy_executor::task] -pub async fn feedback_task(buzzer: peripherals::GPIO19<'static>) { - info!("Starting feedback task"); - let mut buzzer = init::hardware::setup_buzzer(buzzer).await; - loop { - debug!("Buzzer feedback task running"); - buzzer.set_high(); - Timer::after(Duration::from_millis(100)).await; - buzzer.set_low(); - Timer::after(Duration::from_millis(100)).await; - return ; - } -} diff --git a/src/drivers/nfc_reader.rs b/src/drivers/nfc_reader.rs index 0fbeb59..d35aad9 100644 --- a/src/drivers/nfc_reader.rs +++ b/src/drivers/nfc_reader.rs @@ -1,10 +1,9 @@ use embassy_time::{Duration, Timer}; -use esp_hal::{uart::Uart, Async}; -use log::{ debug, info }; +use esp_hal::{Async, uart::Uart}; +use log::{debug, info}; use crate::TallyPublisher; - #[embassy_executor::task] pub async fn rfid_reader_task(mut uart_device: Uart<'static, Async>, chan: TallyPublisher) { let mut uart_buffer = [0u8; 64]; @@ -26,4 +25,4 @@ pub async fn rfid_reader_task(mut uart_device: Uart<'static, Async>, chan: Tally } Timer::after(Duration::from_millis(200)).await; } -} \ No newline at end of file +} diff --git a/src/drivers/rtc.rs b/src/drivers/rtc.rs index c0dc6f5..c7f4cb4 100644 --- a/src/drivers/rtc.rs +++ b/src/drivers/rtc.rs @@ -1,79 +1,110 @@ -use ds3231::{Alarm1Config, DS3231Error, Seconds, DS3231}; -use embassy_time::{Timer, Duration}; -use esp_hal::{i2c::{self, master::I2c}, peripherals, Async}; -use log::{debug, error, info}; - -use crate::{drivers, init, UTC_TIME}; - -const RTC_ADDRESS: u8 = 0x57; +use embassy_time::{Duration, Timer}; +use log::info; #[embassy_executor::task] -async fn rtc_task( - i2c: i2c::master::I2c<'static, Async>, - sqw_pin: peripherals::GPIO21<'static>, -) { - debug!("init rtc interrupt"); - let mut rtc_interrupt = init::hardware::setup_rtc_iterrupt(sqw_pin).await; - debug!("configuring rtc"); - let mut rtc = drivers::rtc::rtc_config(i2c).await; - - let mut utc_time = UTC_TIME.lock().await; - let timestamp_result = drivers::rtc::read_rtc_time(&mut rtc).await; - *utc_time = timestamp_result.unwrap_or(0); +pub async fn rtc_task() { + info!("RTC task started"); + // Initialize I2C and RTC here loop { - debug!("Waiting for RTC interrupt..."); - rtc_interrupt.wait_for_falling_edge().await; - debug!("RTC interrupt triggered"); - utc_time = UTC_TIME.lock().await; - let timestamp_result = drivers::rtc::read_rtc_time(&mut rtc).await; - *utc_time = timestamp_result.unwrap_or(0); - Timer::after(Duration::from_secs(1)).await; // Debounce delay + // Read RTC time and update UTC_TIME signal + // let utc_time = read_rtc_time(&mut rtc).await.unwrap(); + // UTC_TIME.signal(utc_time); + + // Simulate waiting for an interrupt or event + Timer::after(Duration::from_millis(1000)).await; + info!("RTC tick"); } } -pub async fn rtc_config(i2c: I2c<'static, Async>) -> DS3231> { - let mut rtc: DS3231> = DS3231::new(i2c, RTC_ADDRESS); - let daily_alarm = Alarm1Config::AtTime { - hours: 0, // set alarm every day 00:00:00 to sync time - minutes: 0, - seconds: 10, - is_pm: None, // 24-hour mode - }; - // Replace 'main::UTC_TIME' with the correct path to UTC_TIME, for example 'crate::UTC_TIME' - let mut utc_time; - { - utc_time = crate::UTC_TIME.lock().await; - } - let naive_dt = chrono::NaiveDateTime::from_timestamp_opt(*utc_time as i64, 0) - .expect("Invalid timestamp for NaiveDateTime"); - rtc.set_datetime(&naive_dt).await.unwrap_or_else(|e| { - error!("Failed to set RTC datetime: {:?}", e); - panic!(); - }); - - if let Err(e) = rtc.set_alarm1(&daily_alarm).await { - error!("Failed to configure RTC: {:?}", e); - panic!(); - } - rtc -} -pub async fn read_rtc_time<'a>(rtc: &'a mut DS3231>) -> Result> { - match rtc.datetime().await { - Ok(datetime) => { - let utc_time = datetime.and_utc().timestamp() as u64; - Ok(utc_time) - } - Err(e) => { - error!("Failed to read RTC datetime: {:?}", e); - Err(e) - } - } -} + + + +/* ************************************************************************************** */ + + +// use ds3231::{Alarm1Config, DS3231, DS3231Error, Seconds}; +// use embassy_time::{Duration, Timer}; +// use esp_hal::{ +// Async, +// i2c::{self, master::I2c}, +// peripherals, +// }; +// use log::{debug, error, info}; + +// use crate::{UTC_TIME, drivers, init}; + +// const RTC_ADDRESS: u8 = 0x57; + +// #[embassy_executor::task] +// pub async fn rtc_task( +// //i2c: i2c::master::I2c<'static, Async>, +// //sqw_pin: peripherals::GPIO21<'static>, +// ) { +// //UTC_TIME.signal(155510); + +// // debug!("init rtc interrupt"); +// // let mut rtc_interrupt = init::hardware::setup_rtc_iterrupt(sqw_pin).await; +// // debug!("configuring rtc"); +// // let mut rtc = drivers::rtc::rtc_config(i2c).await; + +// // let timestamp_result = drivers::rtc::read_rtc_time(&mut rtc).await; +// // UTC_TIME.signal(timestamp_result.unwrap()); + +// debug!("rtc up"); +// loop { +// info!("Current UTC time: {}", UTC_TIME.wait().await); +// // debug!("Waiting for RTC interrupt..."); +// // rtc_interrupt.wait_for_falling_edge().await; +// // debug!("RTC interrupt triggered"); +// // let timestamp_result = drivers::rtc::read_rtc_time(&mut rtc).await; +// // UTC_TIME.signal(timestamp_result.unwrap()); +// // Timer::after(Duration::from_secs(1)).await; // Debounce delay +// } +// } + +// pub async fn rtc_config(i2c: I2c<'static, Async>) -> DS3231> { +// let mut rtc: DS3231> = DS3231::new(i2c, RTC_ADDRESS); +// let daily_alarm = Alarm1Config::AtTime { +// hours: 0, // set alarm every day 00:00:00 to sync time +// minutes: 0, +// seconds: 10, +// is_pm: None, // 24-hour mode +// }; + + // let naive_dt = chrono::NaiveDateTime::from_timestamp_opt(*utc_time as i64, 0) + // .expect("Invalid timestamp for NaiveDateTime"); + // rtc.set_datetime(&naive_dt).await.unwrap_or_else(|e| { + // error!("Failed to set RTC datetime: {:?}", e); + // panic!(); + // }); + + // if let Err(e) = rtc.set_alarm1(&daily_alarm).await { + // error!("Failed to configure RTC: {:?}", e); + // panic!(); + // } +// rtc +// } + +// pub async fn read_rtc_time<'a>( +// rtc: &'a mut DS3231>, +// ) -> Result> { +// match rtc.datetime().await { +// Ok(datetime) => { +// let utc_time = datetime.and_utc().timestamp() as u64; +// Ok(utc_time) +// } +// Err(e) => { +// error!("Failed to read RTC datetime: {:?}", e); +// Err(e) +// } +// } +// } + // TODO Update time when device is connected other device over Wifi /* pub async fn update_rtc_time<'a>(rtc: &'a mut DS3231>, datetime: u64) -> Result<(), DS3231Error> { @@ -86,4 +117,4 @@ pub async fn read_rtc_time<'a>(rtc: &'a mut DS3231>) -> Resu } } } - */ \ No newline at end of file + */ diff --git a/src/feedback.rs b/src/feedback.rs index ee4fba9..93accfb 100644 --- a/src/feedback.rs +++ b/src/feedback.rs @@ -1,4 +1,67 @@ +use embassy_time::{Delay, Duration, Timer}; +use esp_hal::{delay, gpio::Output, peripherals}; +use log::{debug, error, info}; +use crate::{FEEDBACK_STATE, init}; + +#[derive(Copy, Clone, Debug)] +pub enum FeedbackState { + Ack, + Nak, + Error, + Startup, + Idle, +} + +#[embassy_executor::task] +pub async fn feedback_task(buzzer: peripherals::GPIO19<'static>) { + debug!("Starting feedback task"); + let mut buzzer = init::hardware::setup_buzzer(buzzer); + loop { + let feedback_state = FEEDBACK_STATE.wait().await; + match feedback_state { + FeedbackState::Ack => { + buzzer.set_high(); + Timer::after(Duration::from_millis(100)).await; + buzzer.set_low(); + Timer::after(Duration::from_millis(50)).await; + } + FeedbackState::Nak => { + buzzer.set_high(); + Timer::after(Duration::from_millis(100)).await; + buzzer.set_low(); + Timer::after(Duration::from_millis(100)).await; + buzzer.set_high(); + Timer::after(Duration::from_millis(100)).await; + buzzer.set_low(); + } + FeedbackState::Error => {} + FeedbackState::Startup => { + buzzer.set_high(); + Timer::after(Duration::from_millis(10)).await; + buzzer.set_low(); + Timer::after(Duration::from_millis(10)).await; + buzzer.set_high(); + Timer::after(Duration::from_millis(10)).await; + buzzer.set_low(); + Timer::after(Duration::from_millis(50)).await; + buzzer.set_high(); + Timer::after(Duration::from_millis(100)).await; + buzzer.set_low(); + } + FeedbackState::Idle => { + // Do nothing + } + }; + debug!("Feedback state: {:?}", feedback_state); + } +} + +// async fn beep_ack() { +// buzzer.set_high(); +// buzzer.set_low(); +// //Timer::after(Duration::from_millis(100)).await; +// } /* pub async fn failure(&mut self) { let buzzer_handle = Self::beep_nak(&mut self.buzzer); @@ -95,4 +158,4 @@ async fn beep_startup(buzzer: &mut B) -> Result<()> { Ok(()) } - */ \ No newline at end of file + */ diff --git a/src/init/hardware.rs b/src/init/hardware.rs index 2bcb800..2fbc198 100644 --- a/src/init/hardware.rs +++ b/src/init/hardware.rs @@ -1,6 +1,7 @@ use embassy_executor::Spawner; use embassy_net::{driver, Stack}; -use embassy_sync::mutex::Mutex; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::blocking_mutex::Mutex; use esp_hal::config; use esp_hal::gpio::{Input, Pull}; use esp_hal::i2c::master::Config; @@ -40,6 +41,8 @@ fn panic(_: &core::panic::PanicInfo) -> ! { esp_bootloader_esp_idf::esp_app_desc!(); + + pub async fn hardware_init(spawner: &mut Spawner) -> (Uart<'static, Async>, Stack<'static>, I2c<'static, Async>, GPIO21<'static>, GPIO19<'static>) { let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let peripherals = esp_hal::init(config); @@ -121,7 +124,7 @@ pub async fn setup_rtc_iterrupt(sqw_pin: GPIO21<'static>) -> Input<'static> { sqw_interrupt } -pub async fn setup_buzzer(buzzer_gpio: GPIO19<'static>) -> Output<'static> { +pub fn setup_buzzer(buzzer_gpio: GPIO19<'static>) -> Output<'static> { let config = esp_hal::gpio::OutputConfig::default().with_drive_strength(esp_hal::gpio::DriveStrength::_40mA); let buzzer = Output::new(buzzer_gpio, esp_hal::gpio::Level::Low, config); diff --git a/src/main.rs b/src/main.rs index d854788..381c7ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,68 +3,82 @@ #![feature(type_alias_impl_trait)] #![feature(impl_trait_in_assoc_type)] +use esp_alloc::EspHeap; use embassy_executor::Spawner; use embassy_net::Stack; use embassy_sync::{ - blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}, mutex::Mutex, pubsub::{ + blocking_mutex::raw::{NoopRawMutex, CriticalSectionRawMutex}, + pubsub::{ PubSubChannel, Publisher, WaitResult::{Lagged, Message}, - } + }, + signal::Signal, }; use embassy_time::{Duration, Timer}; -use esp_alloc::psram_allocator; -use esp_hal::{gpio::Output, i2c, peripherals, Async}; -use esp_hal::uart::Uart; use log::{debug, info}; use static_cell::make_static; use crate::{store::TallyID, webserver::start_webserver}; -include!(concat!(env!("OUT_DIR"), "/build_time.rs")); - mod init; mod drivers; +mod feedback; mod store; mod webserver; -mod feedback; + +include!(concat!(env!("OUT_DIR"), "/build_time.rs")); + +static UTC_TIME: Signal = Signal::new(); +static FEEDBACK_STATE: Signal = Signal::new(); type TallyChannel = PubSubChannel; type TallyPublisher = Publisher<'static, NoopRawMutex, TallyID, 8, 2, 1>; -static UTC_TIME: Mutex = Mutex::new(0); - #[esp_hal_embassy::main] async fn main(mut spawner: Spawner) { - { - let mut utc_time = UTC_TIME.lock().await; - *utc_time = BUILD_UNIX_TIME; - info!("UTC Time initialized to: {}", *utc_time); - } - let (uart_device, stack, _i2c, sqw_pin, buzzer_gpio) = init::hardware::hardware_init(&mut spawner).await; + let (uart_device, stack, _i2c, sqw_pin, buzzer_gpio) = + init::hardware::hardware_init(&mut spawner).await; wait_for_stack_up(stack).await; + info!("Starting up..."); + let chan: &'static mut TallyChannel = make_static!(PubSubChannel::new()); - start_webserver(&mut spawner, stack); + //start_webserver(&mut spawner, stack); let publisher = chan.publisher().unwrap(); - debug!("spawing NFC reader task"); - spawner.must_spawn(drivers::nfc_reader::rfid_reader_task(uart_device, publisher)); - //debug!("spawing rtc task"); - //spawner.must_spawn(rtc_task(_i2c, sqw_pin)); - debug!("spawing feedback task"); - spawner.must_spawn(drivers::buzzer::feedback_task(buzzer_gpio)); + /****************************** Spawning tasks ***********************************/ + debug!("spawing NFC reader task..."); + spawner.must_spawn(drivers::nfc_reader::rfid_reader_task( + uart_device, + publisher, + )); + + debug!("spawing rtc task"); + spawner.must_spawn(drivers::rtc::rtc_task()); + + debug!("spawing feedback task.."); + spawner.must_spawn(feedback::feedback_task(buzzer_gpio)); + /******************************************************************************/ let mut sub = chan.subscriber().unwrap(); + + + debug!("everythig spwawned"); + FEEDBACK_STATE.signal(feedback::FeedbackState::Startup); + loop { - let wait_result = sub.next_message().await; - match wait_result { - Lagged(_) => debug!("Lagged"), - Message(msg) => debug!("Got message: {msg:?}"), - } + + info!("runnung in main loop"); + Timer::after(Duration::from_millis(1000)).await; + // let wait_result = sub.next_message().await; + // match wait_result { + // Lagged(_) => debug!("Lagged"), + // Message(msg) => debug!("Got message: {msg:?}"), + // } } } @@ -79,4 +93,4 @@ async fn wait_for_stack_up(stack: Stack<'static>) { } Timer::after(Duration::from_millis(500)).await; } -} \ No newline at end of file +}