From d391a7538126a5a05de518d82de9568a07300102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Holmstr=C3=B6m?= <holmstrom.andreas95@gmail.com> Date: Tue, 19 Mar 2024 16:11:08 +0100 Subject: [PATCH] Working on PWM. Problems understanding what set period does. It does not seem to change how often the led blinks --- zoo/examples/pwm_led_example.rs | 158 ++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 zoo/examples/pwm_led_example.rs diff --git a/zoo/examples/pwm_led_example.rs b/zoo/examples/pwm_led_example.rs new file mode 100644 index 0000000..7b2d89e --- /dev/null +++ b/zoo/examples/pwm_led_example.rs @@ -0,0 +1,158 @@ +#![no_main] +#![no_std] +// #![deny(unsafe_code)] +// #![deny(warnings)] + +use { + cortex_m::asm, + embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}, + fugit::{MillisDurationU64, TimerInstantU64}, + hal::{ + pwm::*, + gpio::{Level, Output, Pin, PullDown, PushPull, Input}, + gpiote::*, + // ppi::{self, ConfigurablePpi, Ppi}, + prelude::*, + saadc::*, + clocks::*, + pac::interrupt, + rtc::{Rtc, RtcCompareReg, RtcInterrupt}, + }, + nrf52833_hal as hal, panic_rtt_target as _, + rtt_target::{rprintln, rtt_init_print}, + systick_monotonic::*, +}; + +const TIMER_HZ: u32 = 4; // 4 Hz (250 ms granularity) +const TIME_0: Instant = TimerInstantU64::from_ticks(0); // Constant for time zero + +type SeqBuffer = &'static mut [u16; 48]; +type Led = Pin<Output<PushPull>>; +type Instant = TimerInstantU64<TIMER_HZ>; +type Duration = MillisDurationU64; + +#[rtic::app(device = nrf52833_hal::pac, dispatchers= [TIMER0])] +mod app { + use core::borrow::Borrow; + + use hal::{comp::CompInputPin, gpio::{self, p0::P0_31, Disconnected, Floating}, pac::{PWM0, RTC0}, pwm::PwmSeq}; + + use super::*; + //#[monotonic(binds = RTC0, default = true)] + //type Mono = hal::monotonic::MonotonicTimer<hal::pac::RTC0, 32_768u32>; + #[monotonic(binds = SysTick, default = true)] + type MyMono = Systick<TIMER_HZ>; + + #[shared] + struct Shared { + pwm0: Pwm<PWM0>, + } + + #[local] + struct Local { + } + + #[init(local = [ + BUF0: [u16; 48] = [0u16; 48], + BUF1: [u16; 48] = [0u16; 48], + ])] + fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + rtt_init_print!(); + rprintln!("\n---init---\n"); + + /************************** SECTION: Ports and time *************************/ + let port1 = hal::gpio::p1::Parts::new(cx.device.P1); + let mut mono = Systick::new(cx.core.SYST, 64_000_000); + let port0 = hal::gpio::p0::Parts::new(cx.device.P0); + /****************************************************************************/ + + /******************** SECTION: Buttons, buzzer and led setup ***************/ + let buzzer = port1.p1_09.into_push_pull_output(Level::Low).degrade(); + let led1 = port0.p0_11.into_push_pull_output(Level::Low).degrade(); + /****************************************************************************/ + + /************************** SECTION: PWM Led ********************************/ + let mut pwm0 = Pwm::new(cx.device.PWM0); + pwm0.set_period(1.hz()) + .set_output_pin(Channel::C0, led1) + .set_prescaler(Prescaler::Div128) + .enable_interrupt(PwmEvent::Stopped) + .enable_interrupt(PwmEvent::PwmPeriodEnd) + .enable(); + let max_duty = pwm0.max_duty(); + rprintln!("pmw0 max duty {}", max_duty); + let dutybefore = pwm0.get_duty(Channel::C0); + rprintln!("before {}", dutybefore); + pwm0.set_duty(Channel::C0, max_duty/2); + let dutyafter = pwm0.get_duty(Channel::C0); + rprintln!("after {}", dutyafter); + + + /****************************************************************************/ + let buf0 = cx.local.BUF0; + let buf1 = cx.local.BUF1; + + pwm0.task_start_seq0(); + + + + //stop::spawn_after(2.secs()).unwrap(); + + + (Shared { pwm0 }, Local { }, init::Monotonics(mono)) + } + + #[task(shared = [pwm0])] + fn pwm_stop(mut cx: pwm_stop::Context) { + cx.shared.pwm0.lock(|pwm| { + pwm.stop(); + }); + } + +/* #[task(binds = PWM0, shared = [pwm0])] + fn on_pwm(mut cx: on_pwm::Context) { + cx.shared.pwm0.lock(|pwm| { + if pwm.is_event_triggered(PwmEvent::PwmPeriodEnd) { + toggle_led::spawn_after(1000.millis()).ok(); + } + }); + } */ + + #[task(binds = PWM0, shared = [pwm0])] + fn toggle_led(mut cx: toggle_led::Context) { + cx.shared.pwm0.lock(|pwm| { + if pwm.is_event_triggered(PwmEvent::PwmPeriodEnd) { + let mut led = pwm.clear_output_pin(Channel::C0).unwrap(); + if led.is_set_high().unwrap() { + rprintln!("toggling low"); + match led.set_low() { + Ok(res) => res, + Err(_) => rprintln!("Error with led.set_low() in toggle_led task") + } + } else { + rprintln!("toggling high"); + match led.set_high() { + Ok(res) => res, + Err(_) => rprintln!("Error with led.set_high() in toggle_led task") + } + } + pwm.set_output_pin(Channel::C0, led); + } else { + rprintln!("Other event triggered") + } + }); + } + + + + #[idle] + fn idle(_cx: idle::Context) -> ! { + rprintln!("idle"); + loop{ + //rprintln!("LOOPIN"); + asm::wfi(); + } + } + + +} -- GitLab