reworked RTC without alarms and without own thread

This commit is contained in:
Philipp_EndevourOS 2025-08-04 18:12:46 +02:00
parent 2f502e908e
commit 1ae5250449
3 changed files with 54 additions and 133 deletions

View File

@ -1,64 +1,43 @@
use core::time;
use chrono::NaiveDate;
use ds3231::{ use ds3231::{
Alarm1Config, Config, DS3231, DS3231Error, InterruptControl, Oscillator, Seconds, Config, DS3231, DS3231Error, InterruptControl, Oscillator, SquareWaveFrequency,
SquareWaveFrequency, TimeRepresentation, TimeRepresentation,
}; };
use embassy_time::{Duration, Timer, WithTimeout};
use esp_hal::{ use esp_hal::{
Async, Async,
i2c::{self, master::I2c}, i2c::{self, master::I2c},
peripherals,
}; };
use log::{debug, error, info}; use log::{debug, error, info};
use crate::{FEEDBACK_STATE, UTC_TIME, drivers, feedback, init}; use crate::{FEEDBACK_STATE, drivers, feedback};
use chrono::{NaiveDateTime, TimeZone, Utc}; use chrono::{TimeZone, Utc};
include!(concat!(env!("OUT_DIR"), "/build_time.rs")); include!(concat!(env!("OUT_DIR"), "/build_time.rs"));
const RTC_ADDRESS: u8 = 0x68; const RTC_ADDRESS: u8 = 0x68;
#[embassy_executor::task] pub struct RTCClock {
pub async fn rtc_task( dev: DS3231<I2c<'static, Async>>,
i2c: i2c::master::I2c<'static, Async>, }
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;
impl RTCClock {
pub async fn new(i2c: i2c::master::I2c<'static, Async>) -> Self {
debug!("configuring rtc...");
let rtc = drivers::rtc::rtc_config(i2c).await;
debug!("rtc up"); debug!("rtc up");
loop {
//set_rtc_alarm(&mut rtc).await;
// debug!("Waiting for RTC interrupt...");
// rtc_interrupt.wait_for_falling_edge().await;
// debug!("RTC interrupt triggered");
Timer::after(Duration::from_millis(1000)).await; RTCClock { dev: rtc }
//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 { pub async fn get_time(&mut self) -> u64 {
Ok(ts) => { match self.dev.datetime().await {
UTC_TIME.signal(ts); Ok(datetime) => {
info!("Current UTC time: {}", UTC_TIME.wait().await); let utc_time = datetime.and_utc().timestamp() as u64;
utc_time
} }
Err(e) => { Err(e) => {
FEEDBACK_STATE.signal(feedback::FeedbackState::Error); FEEDBACK_STATE.signal(feedback::FeedbackState::Error);
error!("Failed to read RTC datetime: {:?}", e); error!("Failed to read RTC datetime: {:?}", e);
0
} }
} }
} }
@ -94,7 +73,6 @@ pub async fn rtc_config(i2c: I2c<'static, Async>) -> DS3231<I2c<'static, Async>>
}); });
info!("RTC datetime set to: {}", naive_dt); info!("RTC datetime set to: {}", naive_dt);
match rtc.status().await { match rtc.status().await {
Ok(mut status) => { Ok(mut status) => {
status.set_alarm1_flag(false); status.set_alarm1_flag(false);
@ -110,67 +88,9 @@ pub async fn rtc_config(i2c: I2c<'static, Async>) -> DS3231<I2c<'static, Async>>
rtc rtc
} }
pub async fn read_rtc_time<'a>( pub async fn read_rtc_time<'a>(
rtc: &'a mut DS3231<I2c<'static, Async>>, rtc: &'a mut DS3231<I2c<'static, Async>>,
) -> Result<u64, DS3231Error<esp_hal::i2c::master::Error>> { ) -> Result<u64, DS3231Error<esp_hal::i2c::master::Error>> {
let timestamp_result = rtc.datetime().await?; let timestamp_result = rtc.datetime().await?;
Ok(timestamp_result.and_utc().timestamp() as u64) Ok(timestamp_result.and_utc().timestamp() as u64)
} }
// match rtc.datetime().await {
// Ok(datetime) => {
// let utc_time = datetime.and_utc().timestamp() as u64;
// Ok(utc_time)
// }
// Err(e) => {
// FEEDBACK_STATE.signal(feedback::FeedbackState::Error);
// error!("Failed to read RTC datetime: {:?}", 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
/* pub async fn update_rtc_time<'a>(rtc: &'a mut DS3231<I2c<'static, Async>>, datetime: u64) -> Result<(), DS3231Error<esp_hal::i2c::master::Error>> {
match rtc.set_datetime(datetime).await {
info!("RTC datetime updated to: {}", datetime);
Ok(_) => Ok(()),
Err(e) => {
error!("Failed to update RTC datetime: {:?}", e);
Err(e)
}
}
}
*/

View File

@ -1,32 +1,35 @@
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_net::{driver, Stack}; use embassy_net::{Stack, driver};
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::blocking_mutex::Mutex; use embassy_sync::blocking_mutex::Mutex;
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use esp_hal::config; use esp_hal::config;
use esp_hal::gpio::{Input, Pull}; use esp_hal::gpio::{Input, Pull};
use esp_hal::i2c::master::Config; use esp_hal::i2c::master::Config;
use esp_hal::peripherals::{self, GPIO0, GPIO1, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7, GPIO19, GPIO21, GPIO22, GPIO23, I2C0, UART1}; use esp_hal::peripherals::{
self, GPIO0, GPIO1, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7, GPIO19, GPIO21, GPIO22, GPIO23, I2C0,
UART1,
};
use esp_hal::time::Rate; use esp_hal::time::Rate;
use esp_hal::{ use esp_hal::{
Async, Async,
clock::CpuClock, clock::CpuClock,
gpio::{Output, OutputConfig},
i2c::master::I2c,
timer::{systimer::SystemTimer, timg::TimerGroup}, timer::{systimer::SystemTimer, timg::TimerGroup},
uart::Uart, uart::Uart,
i2c::master::I2c,
gpio::{Output, OutputConfig}
}; };
use esp_println::logger::init_logger; use esp_println::logger::init_logger;
use log::{debug, error}; use log::{debug, error};
use crate::init::wifi;
use crate::init::network; use crate::init::network;
use crate::init::wifi;
/************************************************* /*************************************************
* GPIO Pinout Xiao Esp32c6 * GPIO Pinout Xiao Esp32c6
* *
* D0 -> GPIO0 -> Level Shifter OE * D0 -> GPIO0 -> Level Shifter OE
* D1 -> GPIO1 -> Level Shifter A0 -> LED * D1 -> GPIO1 -> Level Shifter A0 -> LED
* D3 -> GPIO21 -> SQW Interrupt RTC * D3 -> GPIO21 -> SQW Interrupt RTC //not in use anymore
* D4 -> GPIO22 -> SDA * D4 -> GPIO22 -> SDA
* D5 -> GPIO23 -> SCL * D5 -> GPIO23 -> SCL
* D7 -> GPIO17 -> Level Shifter A1 -> NFC Reader * D7 -> GPIO17 -> Level Shifter A1 -> NFC Reader
@ -41,9 +44,14 @@ fn panic(_: &core::panic::PanicInfo) -> ! {
esp_bootloader_esp_idf::esp_app_desc!(); esp_bootloader_esp_idf::esp_app_desc!();
pub async fn hardware_init(
spawner: &mut Spawner,
pub async fn hardware_init(spawner: &mut Spawner) -> (Uart<'static, Async>, Stack<'static>, I2c<'static, Async>, GPIO21<'static>, GPIO19<'static>) { ) -> (
Uart<'static, Async>,
Stack<'static>,
I2c<'static, Async>,
GPIO19<'static>,
) {
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
let peripherals = esp_hal::init(config); let peripherals = esp_hal::init(config);
@ -68,19 +76,17 @@ pub async fn hardware_init(spawner: &mut Spawner) -> (Uart<'static, Async>, Stac
let i2c_device = setup_i2c(peripherals.I2C0, peripherals.GPIO22, peripherals.GPIO23); let i2c_device = setup_i2c(peripherals.I2C0, peripherals.GPIO22, peripherals.GPIO23);
//RTC Interrupt pin
let sqw_pin = peripherals.GPIO21;
let buzzer_gpio = peripherals.GPIO19; let buzzer_gpio = peripherals.GPIO19;
debug!("hardware init done"); debug!("hardware init done");
(uart_device, stack, i2c_device, sqw_pin, buzzer_gpio) (uart_device, stack, i2c_device, buzzer_gpio)
} }
// Initialize the level shifter for the NFC reader and LED (output-enable (OE) input is low, all outputs are placed in the high-impedance (Hi-Z) state) // Initialize the level shifter for the NFC reader and LED (output-enable (OE) input is low, all outputs are placed in the high-impedance (Hi-Z) state)
fn init_lvl_shifter(oe_pin: GPIO0<'static>){ fn init_lvl_shifter(oe_pin: GPIO0<'static>) {
let mut oe_lvl_shifter = Output::new(oe_pin, esp_hal::gpio::Level::Low, OutputConfig::default()); let mut oe_lvl_shifter =
Output::new(oe_pin, esp_hal::gpio::Level::Low, OutputConfig::default());
oe_lvl_shifter.set_high(); oe_lvl_shifter.set_high();
} }
@ -125,13 +131,11 @@ pub async fn setup_rtc_iterrupt(sqw_pin: GPIO21<'static>) -> Input<'static> {
} }
pub 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 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); let buzzer = Output::new(buzzer_gpio, esp_hal::gpio::Level::Low, config);
buzzer buzzer
} }
fn setup_spi_led() {}
fn setup_spi_led() {
}

View File

@ -6,15 +6,12 @@
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::{CriticalSectionRawMutex, NoopRawMutex}, blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}, channel::Channel, pubsub::{
pubsub::{
PubSubChannel, Publisher, PubSubChannel, Publisher,
WaitResult::{Lagged, Message}, WaitResult::{Lagged, Message},
}, }, 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;
@ -26,7 +23,6 @@ mod init;
mod store; mod store;
mod webserver; mod webserver;
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();
type TallyChannel = PubSubChannel<NoopRawMutex, TallyID, 8, 2, 1>; type TallyChannel = PubSubChannel<NoopRawMutex, TallyID, 8, 2, 1>;
@ -34,7 +30,7 @@ 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, buzzer_gpio) =
init::hardware::hardware_init(&mut spawner).await; init::hardware::hardware_init(&mut spawner).await;
wait_for_stack_up(stack).await; wait_for_stack_up(stack).await;
@ -47,6 +43,8 @@ async fn main(mut spawner: Spawner) {
let publisher = chan.publisher().unwrap(); let publisher = chan.publisher().unwrap();
let mut rtc = drivers::rtc::RTCClock::new(_i2c).await;
/****************************** Spawning tasks ***********************************/ /****************************** Spawning tasks ***********************************/
debug!("spawing NFC reader task..."); debug!("spawing NFC reader task...");
spawner.must_spawn(drivers::nfc_reader::rfid_reader_task( spawner.must_spawn(drivers::nfc_reader::rfid_reader_task(
@ -54,9 +52,6 @@ async fn main(mut spawner: Spawner) {
publisher, publisher,
)); ));
debug!("spawing 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));
/******************************************************************************/ /******************************************************************************/
@ -67,8 +62,10 @@ async fn main(mut spawner: Spawner) {
FEEDBACK_STATE.signal(feedback::FeedbackState::Startup); FEEDBACK_STATE.signal(feedback::FeedbackState::Startup);
loop { loop {
info!("running in main loop"); rtc.get_time().await;
info!("Current RTC time: {}", rtc.get_time().await);
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 {
// Lagged(_) => debug!("Lagged"), // Lagged(_) => debug!("Lagged"),