mirror of
https://github.com/Djeeberjr/fw-anwesenheit.git
synced 2025-08-02 22:54:17 +00:00
rtc is synchronized with compile time. start pub sub approach to share time
This commit is contained in:
parent
5950279dc4
commit
2f502e908e
@ -1,108 +1,164 @@
|
|||||||
use embassy_time::{Duration, Timer};
|
use core::time;
|
||||||
use log::info;
|
|
||||||
|
use chrono::NaiveDate;
|
||||||
|
use ds3231::{
|
||||||
|
Alarm1Config, Config, DS3231, DS3231Error, InterruptControl, Oscillator, Seconds,
|
||||||
|
SquareWaveFrequency, TimeRepresentation,
|
||||||
|
};
|
||||||
|
use embassy_time::{Duration, Timer, WithTimeout};
|
||||||
|
use esp_hal::{
|
||||||
|
Async,
|
||||||
|
i2c::{self, master::I2c},
|
||||||
|
peripherals,
|
||||||
|
};
|
||||||
|
use log::{debug, error, info};
|
||||||
|
|
||||||
|
use crate::{FEEDBACK_STATE, UTC_TIME, drivers, feedback, init};
|
||||||
|
use chrono::{NaiveDateTime, TimeZone, Utc};
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/build_time.rs"));
|
||||||
|
|
||||||
|
const RTC_ADDRESS: u8 = 0x68;
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
pub async fn rtc_task() {
|
pub async fn rtc_task(
|
||||||
info!("RTC task started");
|
i2c: i2c::master::I2c<'static, Async>,
|
||||||
// Initialize I2C and RTC here
|
sqw_pin: peripherals::GPIO21<'static>,
|
||||||
|
) {
|
||||||
|
UTC_TIME.signal(BUILD_UNIX_TIME);
|
||||||
|
info!("Build time: {}", BUILD_UNIX_TIME);
|
||||||
|
|
||||||
|
// i2c.write_async(RTC_ADDRESS, &[0x0E, 0b00000000]) // Clear control register
|
||||||
|
// .await
|
||||||
|
// .unwrap_or_else(|e| {
|
||||||
|
// FEEDBACK_STATE.signal(feedback::FeedbackState::Error);
|
||||||
|
// error!("Failed to clear RTC control register: {:?}", e);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
debug!("rtc up");
|
||||||
loop {
|
loop {
|
||||||
// Read RTC time and update UTC_TIME signal
|
//set_rtc_alarm(&mut rtc).await;
|
||||||
// let utc_time = read_rtc_time(&mut rtc).await.unwrap();
|
// debug!("Waiting for RTC interrupt...");
|
||||||
// UTC_TIME.signal(utc_time);
|
// rtc_interrupt.wait_for_falling_edge().await;
|
||||||
|
// debug!("RTC interrupt triggered");
|
||||||
|
|
||||||
// Simulate waiting for an interrupt or event
|
|
||||||
Timer::after(Duration::from_millis(1000)).await;
|
Timer::after(Duration::from_millis(1000)).await;
|
||||||
info!("RTC tick");
|
//TODO use pub sub channel or something similar to send the time when needed
|
||||||
|
let timestamp = drivers::rtc::read_rtc_time(&mut rtc).await;
|
||||||
|
match timestamp {
|
||||||
|
Ok(ts) => {
|
||||||
|
UTC_TIME.signal(ts);
|
||||||
|
info!("Current UTC time: {}", UTC_TIME.wait().await);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
FEEDBACK_STATE.signal(feedback::FeedbackState::Error);
|
||||||
|
error!("Failed to read RTC datetime: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn rtc_config(i2c: I2c<'static, Async>) -> DS3231<I2c<'static, Async>> {
|
||||||
|
let mut rtc: DS3231<I2c<'static, Async>> = DS3231::new(i2c, RTC_ADDRESS);
|
||||||
|
let naive_dt = Utc
|
||||||
|
.timestamp_opt(BUILD_UNIX_TIME as i64, 0)
|
||||||
|
.single()
|
||||||
|
.unwrap()
|
||||||
|
.naive_utc();
|
||||||
|
|
||||||
|
let rtc_config = Config {
|
||||||
|
time_representation: TimeRepresentation::TwentyFourHour,
|
||||||
|
square_wave_frequency: SquareWaveFrequency::Hz1,
|
||||||
|
interrupt_control: InterruptControl::Interrupt, // Enable interrupt mode
|
||||||
|
battery_backed_square_wave: false,
|
||||||
|
oscillator_enable: Oscillator::Disabled,
|
||||||
|
};
|
||||||
|
|
||||||
|
match rtc.configure(&rtc_config).await {
|
||||||
|
Ok(_) => info!("DS3231 configured successfully"),
|
||||||
|
Err(e) => {
|
||||||
|
info!("Failed to configure DS3231: {:?}", e);
|
||||||
|
panic!("DS3231 configuration failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc.set_datetime(&naive_dt).await.unwrap_or_else(|e| {
|
||||||
|
FEEDBACK_STATE.signal(feedback::FeedbackState::Error);
|
||||||
|
error!("Failed to set RTC datetime: {:?}", e);
|
||||||
|
});
|
||||||
|
info!("RTC datetime set to: {}", naive_dt);
|
||||||
|
|
||||||
|
|
||||||
|
match rtc.status().await {
|
||||||
|
Ok(mut status) => {
|
||||||
|
status.set_alarm1_flag(false);
|
||||||
|
status.set_alarm2_flag(false);
|
||||||
|
match rtc.set_status(status).await {
|
||||||
|
Ok(_) => info!("Alarm flags cleared"),
|
||||||
|
Err(e) => info!("Failed to clear alarm flags: {:?}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => info!("Failed to read status: {:?}", e),
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn read_rtc_time<'a>(
|
||||||
|
rtc: &'a mut DS3231<I2c<'static, Async>>,
|
||||||
|
) -> Result<u64, DS3231Error<esp_hal::i2c::master::Error>> {
|
||||||
|
let timestamp_result = rtc.datetime().await?;
|
||||||
|
Ok(timestamp_result.and_utc().timestamp() as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ************************************************************************************** */
|
|
||||||
|
|
||||||
|
|
||||||
// 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<I2c<'static, Async>> {
|
|
||||||
// let mut rtc: DS3231<I2c<'static, Async>> = 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<I2c<'static, Async>>,
|
|
||||||
// ) -> Result<u64, DS3231Error<esp_hal::i2c::master::Error>> {
|
|
||||||
// match rtc.datetime().await {
|
// match rtc.datetime().await {
|
||||||
// Ok(datetime) => {
|
// Ok(datetime) => {
|
||||||
// let utc_time = datetime.and_utc().timestamp() as u64;
|
// let utc_time = datetime.and_utc().timestamp() as u64;
|
||||||
// Ok(utc_time)
|
// Ok(utc_time)
|
||||||
// }
|
// }
|
||||||
// Err(e) => {
|
// Err(e) => {
|
||||||
|
// FEEDBACK_STATE.signal(feedback::FeedbackState::Error);
|
||||||
// error!("Failed to read RTC datetime: {:?}", e);
|
// error!("Failed to read RTC datetime: {:?}", e);
|
||||||
// Err(e)
|
// Err(e)
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let alarm_config = Alarm1Config::AtSeconds { seconds: 0};
|
||||||
|
|
||||||
|
// match rtc.set_alarm1(&alarm_config).await {
|
||||||
|
// Ok(_) => info!("Alarm 1 set to trigger at seconds"),
|
||||||
|
// Err(e) => {
|
||||||
|
// FEEDBACK_STATE.signal(feedback::FeedbackState::Error);
|
||||||
|
// error!("Failed to set Alarm 1: {:?}", e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/* ************************************************************************************** */
|
||||||
|
|
||||||
|
// #[embassy_executor::task]
|
||||||
|
// pub async fn rtc_task() {
|
||||||
|
// info!("RTC task started");
|
||||||
|
// // Initialize I2C and RTC here
|
||||||
|
|
||||||
|
// loop {
|
||||||
|
// // 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");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// TODO Update time when device is connected other device over Wifi
|
// TODO Update time when device is connected other device over Wifi
|
||||||
|
@ -35,7 +35,15 @@ pub async fn feedback_task(buzzer: peripherals::GPIO19<'static>) {
|
|||||||
Timer::after(Duration::from_millis(100)).await;
|
Timer::after(Duration::from_millis(100)).await;
|
||||||
buzzer.set_low();
|
buzzer.set_low();
|
||||||
}
|
}
|
||||||
FeedbackState::Error => {}
|
FeedbackState::Error => {
|
||||||
|
buzzer.set_high();
|
||||||
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
|
buzzer.set_low();
|
||||||
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
|
buzzer.set_high();
|
||||||
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
|
buzzer.set_low();
|
||||||
|
}
|
||||||
FeedbackState::Startup => {
|
FeedbackState::Startup => {
|
||||||
buzzer.set_high();
|
buzzer.set_high();
|
||||||
Timer::after(Duration::from_millis(10)).await;
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
17
src/main.rs
17
src/main.rs
@ -3,11 +3,10 @@
|
|||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
#![feature(impl_trait_in_assoc_type)]
|
#![feature(impl_trait_in_assoc_type)]
|
||||||
|
|
||||||
use esp_alloc::EspHeap;
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_net::Stack;
|
use embassy_net::Stack;
|
||||||
use embassy_sync::{
|
use embassy_sync::{
|
||||||
blocking_mutex::raw::{NoopRawMutex, CriticalSectionRawMutex},
|
blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex},
|
||||||
pubsub::{
|
pubsub::{
|
||||||
PubSubChannel, Publisher,
|
PubSubChannel, Publisher,
|
||||||
WaitResult::{Lagged, Message},
|
WaitResult::{Lagged, Message},
|
||||||
@ -15,19 +14,18 @@ use embassy_sync::{
|
|||||||
signal::Signal,
|
signal::Signal,
|
||||||
};
|
};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
|
use esp_alloc::EspHeap;
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use static_cell::make_static;
|
use static_cell::make_static;
|
||||||
|
|
||||||
use crate::{store::TallyID, webserver::start_webserver};
|
use crate::{store::TallyID, webserver::start_webserver};
|
||||||
|
|
||||||
mod init;
|
|
||||||
mod drivers;
|
mod drivers;
|
||||||
mod feedback;
|
mod feedback;
|
||||||
|
mod init;
|
||||||
mod store;
|
mod store;
|
||||||
mod webserver;
|
mod webserver;
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/build_time.rs"));
|
|
||||||
|
|
||||||
static UTC_TIME: Signal<CriticalSectionRawMutex, u64> = Signal::new();
|
static UTC_TIME: Signal<CriticalSectionRawMutex, u64> = Signal::new();
|
||||||
static FEEDBACK_STATE: Signal<CriticalSectionRawMutex, feedback::FeedbackState> = Signal::new();
|
static FEEDBACK_STATE: Signal<CriticalSectionRawMutex, feedback::FeedbackState> = Signal::new();
|
||||||
|
|
||||||
@ -36,7 +34,6 @@ type TallyPublisher = Publisher<'static, NoopRawMutex, TallyID, 8, 2, 1>;
|
|||||||
|
|
||||||
#[esp_hal_embassy::main]
|
#[esp_hal_embassy::main]
|
||||||
async fn main(mut spawner: Spawner) {
|
async fn main(mut spawner: Spawner) {
|
||||||
|
|
||||||
let (uart_device, stack, _i2c, sqw_pin, buzzer_gpio) =
|
let (uart_device, stack, _i2c, sqw_pin, buzzer_gpio) =
|
||||||
init::hardware::hardware_init(&mut spawner).await;
|
init::hardware::hardware_init(&mut spawner).await;
|
||||||
|
|
||||||
@ -58,7 +55,7 @@ async fn main(mut spawner: Spawner) {
|
|||||||
));
|
));
|
||||||
|
|
||||||
debug!("spawing rtc task");
|
debug!("spawing rtc task");
|
||||||
spawner.must_spawn(drivers::rtc::rtc_task());
|
spawner.must_spawn(drivers::rtc::rtc_task(_i2c, sqw_pin));
|
||||||
|
|
||||||
debug!("spawing feedback task..");
|
debug!("spawing feedback task..");
|
||||||
spawner.must_spawn(feedback::feedback_task(buzzer_gpio));
|
spawner.must_spawn(feedback::feedback_task(buzzer_gpio));
|
||||||
@ -66,13 +63,11 @@ async fn main(mut spawner: Spawner) {
|
|||||||
|
|
||||||
let mut sub = chan.subscriber().unwrap();
|
let mut sub = chan.subscriber().unwrap();
|
||||||
|
|
||||||
|
debug!("everything spawned");
|
||||||
debug!("everythig spwawned");
|
|
||||||
FEEDBACK_STATE.signal(feedback::FeedbackState::Startup);
|
FEEDBACK_STATE.signal(feedback::FeedbackState::Startup);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
info!("running in main loop");
|
||||||
info!("runnung in main loop");
|
|
||||||
Timer::after(Duration::from_millis(1000)).await;
|
Timer::after(Duration::from_millis(1000)).await;
|
||||||
// let wait_result = sub.next_message().await;
|
// let wait_result = sub.next_message().await;
|
||||||
// match wait_result {
|
// match wait_result {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user