#![no_std] #![no_main] #![deny( clippy::mem_forget, reason = "mem::forget is generally not safe to do with esp_hal types, especially those \ holding buffers for the duration of a data transfer." )] use core::fmt::Write; use alloc::string::ToString; use esp_hal::uart::{self, Config, Uart}; use esp_hal::clock::CpuClock; use esp_hal::delay::Delay; use esp_hal::main; use esp_hal::gpio::Event; use esp_hal::gpio::{Input, InputConfig}; use esp_hal::mcpwm::operator::PwmPinConfig; use esp_hal::mcpwm::timer::PwmWorkingMode; use esp_hal::time::Rate; use esp_hal::handler; use core::cell::RefCell; use critical_section::Mutex; use esp_backtrace as _; use esp_hal::time::{Duration, Instant}; use esp_hal::timer::timg::TimerGroup; use rtt_target::rprintln; mod dc_driver; mod peripherals; use dc_driver::afroesc::AfroEsc; use peripherals::nextion::Nextion; use crate::peripherals::ErrCommand; #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { rprintln!("PANIC!"); loop {} } use alloc::format; // static EMERGENCY_BUTTON: Mutex>> = Mutex::new(RefCell::new(None)); extern crate alloc; //target RPM const DEFAULT_TARGET_RPM: u32 = 2000; //in seconds const DEFAULT_SPIN_TIME: u32 = 10; // This creates a default app-descriptor required by the esp-idf bootloader. // For more information see: esp_bootloader_esp_idf::esp_app_desc!(); #[main] fn main() -> ! { // generator version: 1.0.1 rtt_target::rtt_init_print!(); let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let peripherals = esp_hal::init(config); let system = peripherals.SYSTEM; let mut delay = Delay::new(); esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 65536); let clock_config = esp_hal::mcpwm::PeripheralClockConfig::with_frequency(Rate::from_mhz(32)).unwrap(); let mut mcpwm = esp_hal::mcpwm::McPwm::new(peripherals.MCPWM0, clock_config); mcpwm.operator0.set_timer(&mcpwm.timer0); let mut pwm_pin = mcpwm .operator0 .with_pin_a(peripherals.GPIO18, PwmPinConfig::UP_ACTIVE_HIGH); let timer_clock_cfg = clock_config .timer_clock_with_frequency(19_999, PwmWorkingMode::Increase, Rate::from_hz(50)) .unwrap(); mcpwm.timer0.start(timer_clock_cfg); // let mut esc = AfroEsc::new(&mut pwm_pin); // esc.set_timestamp(1000); // delay.delay_millis(3000); // esc.set_duty_percent(10); // delay.delay_millis(3000); //1421 is I think the best, makes calculating the throttle easier // esc.set_timestamp(1055); // delay.delay_millis(3000); //gpio 9 is the button let input_config = InputConfig::default().with_pull(esp_hal::gpio::Pull::Up); use crate::peripherals::Command; //let emergency_button = peripherals.GPIO9; let mut emergency_button = Input::new(peripherals.GPIO9, input_config); critical_section::with(|cs| { emergency_button.listen(Event::FallingEdge); EMERGENCY_BUTTON .borrow_ref_mut(cs) .replace(emergency_button) }); let mut io = esp_hal::gpio::Io::new(peripherals.IO_MUX); io.set_interrupt_handler(handler); let mut uart0 = Uart::new( peripherals.UART0, Config::default() .with_baudrate(115200) .with_data_bits(esp_hal::uart::DataBits::_8) .with_stop_bits(esp_hal::uart::StopBits::_1) .with_parity(esp_hal::uart::Parity::None), ) .unwrap() .with_rx(peripherals.GPIO5) .with_tx(peripherals.GPIO7); let mut display = Nextion::new(&mut uart0); display.send_command(b"page page0"); let mut rpm = DEFAULT_TARGET_RPM; let mut timer = DEFAULT_SPIN_TIME; let mut started = false; loop { if display.read_ready() { match display.read_command() { Ok(Command::CommandSuccess) => { rprintln!("COMMAND SUCCESSFULLY executed"); } Ok(Command::Start) => { rprintln!("START"); started = true; }, Ok(Command::Stop) => { rprintln!("STOP"); started = false; // spincoater.stop(); }, Ok(Command::SetRpm(x)) => { rprintln!("SET_RPM with {}", x); rpm = x; }, Ok(Command::SetTimer(x)) => { rprintln!("SETTING TIMER {}", x); timer = x; }, Ok(Command::SendConfig) => { rprintln!("SEND CONFIG"); let command = format!("rpm.val={}",DEFAULT_TARGET_RPM); display.send_command(command.to_string().as_bytes()); }, Err(ErrCommand::NoValidCmd) => { rprintln!(" NOT A VALID CMD!"); }, Err(ErrCommand::ReadError) =>{ rprintln!("READ FAILED!"); } } // display.send_command(b"page page0"); } if started { // spincoater.armed(); rprintln!("STARTING!") } //display.send_command(b"page page0"); //uart0.write(b"page page0\xff\xff\xff"); } // Example: Ramp from 0% to 50% throttle //the afro esc starts turning at roughly setup gets a PWM at //loop{ // for pulse in 1120..1500 { // rprintln!("pulse:{}",pulse); // pwm_pin.set_timestamp(pulse); // Timer::after_millis(3000).await; // } // Timer::after_millis(1000).await; // // Return to idle // pwm_pin.set_timestamp(1000); // Timer::after_millis(1000).await; // } loop { rprintln!("Hello world!"); delay.delay_millis(3000); } // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.0.0/examples/src/bin } #[handler] // #[ram] fn handler() { critical_section::with(|cs| { let mut binding = EMERGENCY_BUTTON.borrow_ref_mut(cs); let mut button = binding.as_mut().unwrap(); if button.is_interrupt_set() { // do the thing rprintln!("BUTTON1 WAS PRESSED!"); button.clear_interrupt(); return; } }); }