From 94f28e003453181a73a59d936efdd3290fc5f4df Mon Sep 17 00:00:00 2001 From: Robert Schauklies Date: Sat, 7 Mar 2026 20:59:32 +0100 Subject: [PATCH 01/11] We finally have the first iteration of a counter --- spinnyboy_rust/src/bin/main.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/spinnyboy_rust/src/bin/main.rs b/spinnyboy_rust/src/bin/main.rs index 834c2da..8219eef 100644 --- a/spinnyboy_rust/src/bin/main.rs +++ b/spinnyboy_rust/src/bin/main.rs @@ -43,12 +43,16 @@ use crate::dc_driver::dshot; use crate::peripherals::ErrCommand; use esp_hal::rmt::RxChannelConfig; use esp_hal::rmt::RxChannelCreator; + +use esp_hal::timer::timg::TimerGroup; +use esp_hal::timer::OneShotTimer; +use esp_hal::timer::Timer; #[panic_handler] fn panic(panic: &core::panic::PanicInfo) -> ! { rprintln!("{}",panic.message()); let trace = Backtrace::capture(); loop { - // rprintln!("{}",panic.location().unwrap()) + rprintln!("{}",panic.location().unwrap()) } } use alloc::format; @@ -138,8 +142,13 @@ fn main() -> ! { dshot_esc.arm(); let mut rpm = 0; let mut control: f32 = 200.0; - // let timestamp = Instant::now(); - loop { + let mut timg0 = TimerGroup::new(peripherals.TIMG0); + let timer0 = timg0.timer0; + // let now =timer.now(); + //we need the explicit type here! + timer0.load_value(esp_hal::time::Duration::from_secs(10)); + timer0.start(); + while !timer0.is_interrupt_set() { dshot_esc.process(); //let control_val = dc_driver:: //this bad boy needs floats, this will be fun :) @@ -150,7 +159,7 @@ fn main() -> ! { x } None => { - rprintln!("NO RPM!"); + // rprintln!("NO RPM!"); rpm } }; @@ -160,9 +169,10 @@ fn main() -> ! { let timestamp = esp_hal::time::Instant::now().duration_since_epoch().as_millis(); (control, ctx) = controller.compute(ctx, rpm as _, set_point as _, Millis(timestamp), None); let dumped_context = ctx.last_time().expect("LAST TIME!"); - rprintln!("control:{},rpm:{}", control,rpm); + // rprintln!("control:{},rpm:{}", control,rpm); } - + rprintln!("Coating done!"); + dshot_esc.set_throttle(0); // rprintln!("RMT SENT!"); // let mut esc = AfroEsc::new(&mut pwm_pin);; // esc.set_timestamp(1000); From 2d8de20d576b1f60a932f70772c1f6a805f6c0fa Mon Sep 17 00:00:00 2001 From: Robert Schauklies Date: Sat, 7 Mar 2026 21:04:12 +0100 Subject: [PATCH 02/11] slight refactoring, also fuck that --- spinnyboy_rust/src/bin/main.rs | 49 +++++++++++++++++----------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/spinnyboy_rust/src/bin/main.rs b/spinnyboy_rust/src/bin/main.rs index 8219eef..550e0d4 100644 --- a/spinnyboy_rust/src/bin/main.rs +++ b/spinnyboy_rust/src/bin/main.rs @@ -12,18 +12,18 @@ use esp_hal::delay::Delay; use esp_hal::uart::{Config, Uart}; use esp_hal::{gpio, main}; +use core::fmt::Debug; use esp_hal::gpio::{Event, OutputConfig}; use esp_hal::gpio::{Input, InputConfig}; use esp_hal::handler; use esp_hal::rmt::{Rmt, TxChannelConfig, TxChannelCreator}; -use esp_hal::time::{ Instant, Rate}; -use core::fmt::Debug; +use esp_hal::time::{Instant, Rate}; //pid-controller use core::time::Duration; use discrete_pid::pid::PidContext; +use discrete_pid::time::InstantLike; use discrete_pid::time::Millis; use discrete_pid::{pid, time}; -use discrete_pid::time::InstantLike; use core::cell::RefCell; use core::mem::forget; @@ -44,15 +44,15 @@ use crate::peripherals::ErrCommand; use esp_hal::rmt::RxChannelConfig; use esp_hal::rmt::RxChannelCreator; -use esp_hal::timer::timg::TimerGroup; use esp_hal::timer::OneShotTimer; use esp_hal::timer::Timer; +use esp_hal::timer::timg::TimerGroup; #[panic_handler] fn panic(panic: &core::panic::PanicInfo) -> ! { - rprintln!("{}",panic.message()); + rprintln!("{}", panic.message()); let trace = Backtrace::capture(); loop { - rprintln!("{}",panic.location().unwrap()) + rprintln!("{}", panic.location().unwrap()) } } use alloc::format; @@ -82,8 +82,6 @@ impl InstantLike for Time { } } - - #[main] fn main() -> ! { // generator version: 1.0.1 @@ -130,25 +128,26 @@ fn main() -> ! { //PID-Controller let loop_time = Duration::from_micros(10); let cfg = pid::PidConfigBuilder::default() - .kp(3.0) - .ki(1.0).output_limits(100.00, 2040.00) - .sample_time(loop_time) - .filter_tc(0.1) - .build() - .expect("Failed to build a PID configuration"); - let controller = pid::FuncPidController::new(cfg); + .kp(3.0) + .ki(1.0) + .output_limits(100.00, 2040.00) + .sample_time(loop_time) + .filter_tc(0.1) + .build() + .expect("Failed to build a PID configuration"); + let controller = pid::FuncPidController::new(cfg); let mut ctx = PidContext::new(Millis(0), 0.0, 0.0); let set_point = DEFAULT_TARGET_RPM; dshot_esc.arm(); let mut rpm = 0; let mut control: f32 = 200.0; let mut timg0 = TimerGroup::new(peripherals.TIMG0); - let timer0 = timg0.timer0; - // let now =timer.now(); - //we need the explicit type here! - timer0.load_value(esp_hal::time::Duration::from_secs(10)); - timer0.start(); - while !timer0.is_interrupt_set() { + let coat_timer = timg0.timer0; + let _ = coat_timer + .load_value(esp_hal::time::Duration::from_secs(10)) + .expect("TODO: Could not set timer for coating! "); + coat_timer.start(); + while !coat_timer.is_interrupt_set() { dshot_esc.process(); //let control_val = dc_driver:: //this bad boy needs floats, this will be fun :) @@ -165,10 +164,12 @@ fn main() -> ! { }; // rprintln!("RPM:{}",rpm); let last_time = esp_hal::time::Instant::now(); - - let timestamp = esp_hal::time::Instant::now().duration_since_epoch().as_millis(); + + let timestamp = esp_hal::time::Instant::now() + .duration_since_epoch() + .as_millis(); (control, ctx) = controller.compute(ctx, rpm as _, set_point as _, Millis(timestamp), None); - let dumped_context = ctx.last_time().expect("LAST TIME!"); + let dumped_context = ctx.last_time().expect("LAST TIME!"); // rprintln!("control:{},rpm:{}", control,rpm); } rprintln!("Coating done!"); From db90f6dc0c431368b56940680342bdac4b702dd3 Mon Sep 17 00:00:00 2001 From: Robert Schauklies Date: Wed, 11 Mar 2026 21:10:17 +0100 Subject: [PATCH 03/11] put coating logic into the main loop of the display --- spinnyboy_rust/src/bin/main.rs | 79 ++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/spinnyboy_rust/src/bin/main.rs b/spinnyboy_rust/src/bin/main.rs index 550e0d4..edec710 100644 --- a/spinnyboy_rust/src/bin/main.rs +++ b/spinnyboy_rust/src/bin/main.rs @@ -143,38 +143,7 @@ fn main() -> ! { let mut control: f32 = 200.0; let mut timg0 = TimerGroup::new(peripherals.TIMG0); let coat_timer = timg0.timer0; - let _ = coat_timer - .load_value(esp_hal::time::Duration::from_secs(10)) - .expect("TODO: Could not set timer for coating! "); - coat_timer.start(); - while !coat_timer.is_interrupt_set() { - dshot_esc.process(); - //let control_val = dc_driver:: - //this bad boy needs floats, this will be fun :) - dshot_esc.set_throttle(control as _); - rpm = match dshot_esc.get_rpm() { - Some(x) => { - // rprintln!("GOT RPM {}", x); - x - } - None => { - // rprintln!("NO RPM!"); - rpm - } - }; - // rprintln!("RPM:{}",rpm); - let last_time = esp_hal::time::Instant::now(); - - let timestamp = esp_hal::time::Instant::now() - .duration_since_epoch() - .as_millis(); - (control, ctx) = controller.compute(ctx, rpm as _, set_point as _, Millis(timestamp), None); - let dumped_context = ctx.last_time().expect("LAST TIME!"); - // rprintln!("control:{},rpm:{}", control,rpm); - } - rprintln!("Coating done!"); dshot_esc.set_throttle(0); - // rprintln!("RMT SENT!"); // let mut esc = AfroEsc::new(&mut pwm_pin);; // esc.set_timestamp(1000); // delay.delay_millis(3000); @@ -207,7 +176,7 @@ fn main() -> ! { .with_rx(peripherals.GPIO5) .with_tx(peripherals.GPIO7); let mut display = Nextion::new(&mut uart0); - + //we just set it to page0 to be sure display.send_command(b"page page0"); let mut _rpm = DEFAULT_TARGET_RPM; let mut _timer = DEFAULT_SPIN_TIME; @@ -220,6 +189,7 @@ fn main() -> ! { } Ok(Command::Start) => { rprintln!("START"); + display.send_command(b"page page2"); started = true; } Ok(Command::Stop) => { @@ -246,12 +216,55 @@ fn main() -> ! { Err(ErrCommand::ReadError) => { rprintln!("READ FAILED!"); } + _ => { + rprintln!("This should never happen!") + } } // display.send_command(b"page page0"); } if started { + rprintln!("STARTING!"); // spincoater.armed(); - rprintln!("STARTING!") + let _ = coat_timer + .load_value(esp_hal::time::Duration::from_secs(10)) + .expect("TODO: Could not set timer for coating! "); + coat_timer.start(); + while !coat_timer.is_interrupt_set() { + dshot_esc.process(); + //let control_val = dc_driver:: + //this bad boy needs floats, this will be fun :) + dshot_esc.set_throttle(control as _); + rpm = match dshot_esc.get_rpm() { + Some(x) => { + // rprintln!("GOT RPM {}", x); + x + } + None => { + // rprintln!("NO RPM!"); + rpm + } + }; + // rprintln!("RPM:{}",rpm); + let last_time = esp_hal::time::Instant::now(); + + let timestamp = esp_hal::time::Instant::now() + .duration_since_epoch() + .as_millis(); + (control, ctx) = + controller.compute(ctx, rpm as _, set_point as _, Millis(timestamp), None); + let dumped_context = ctx.last_time().expect("LAST TIME!"); + // rprintln!("control:{},rpm:{}", control,rpm); + //first we send the RPM! + let running_rpm = format!("running_rpm.val={}", rpm); + display.send_command(running_rpm.to_string().as_bytes()); + + let counter = format!("counter.val={}", 1234); + display.send_command(counter.to_string().as_bytes()); + } + + rprintln!("COATING done!"); + started = false; + display.send_command(b"page page0"); } } } From 9e842a2a309c3c3ada2d4fb5577ac036080c7c15 Mon Sep 17 00:00:00 2001 From: Robert Schauklies Date: Sat, 14 Mar 2026 16:50:21 +0100 Subject: [PATCH 04/11] some display plumbing --- spinnyboy_rust/src/bin/main.rs | 24 +++++++++++-------- spinnyboy_rust/src/bin/peripherals/nextion.rs | 3 +++ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/spinnyboy_rust/src/bin/main.rs b/spinnyboy_rust/src/bin/main.rs index edec710..e6e8bac 100644 --- a/spinnyboy_rust/src/bin/main.rs +++ b/spinnyboy_rust/src/bin/main.rs @@ -128,8 +128,8 @@ fn main() -> ! { //PID-Controller let loop_time = Duration::from_micros(10); let cfg = pid::PidConfigBuilder::default() - .kp(3.0) - .ki(1.0) + .kp(0.4) + .ki(0.0) .output_limits(100.00, 2040.00) .sample_time(loop_time) .filter_tc(0.1) @@ -138,12 +138,11 @@ fn main() -> ! { let controller = pid::FuncPidController::new(cfg); let mut ctx = PidContext::new(Millis(0), 0.0, 0.0); let set_point = DEFAULT_TARGET_RPM; - dshot_esc.arm(); let mut rpm = 0; let mut control: f32 = 200.0; let mut timg0 = TimerGroup::new(peripherals.TIMG0); let coat_timer = timg0.timer0; - dshot_esc.set_throttle(0); + // shot_esc.set_throttle(0); // let mut esc = AfroEsc::new(&mut pwm_pin);; // esc.set_timestamp(1000); // delay.delay_millis(3000); @@ -224,15 +223,16 @@ fn main() -> ! { } if started { rprintln!("STARTING!"); - // spincoater.armed(); let _ = coat_timer .load_value(esp_hal::time::Duration::from_secs(10)) .expect("TODO: Could not set timer for coating! "); + dshot_esc.arm(); coat_timer.start(); while !coat_timer.is_interrupt_set() { dshot_esc.process(); //let control_val = dc_driver:: //this bad boy needs floats, this will be fun :) + control = 200.00; dshot_esc.set_throttle(control as _); rpm = match dshot_esc.get_rpm() { Some(x) => { @@ -253,13 +253,17 @@ fn main() -> ! { (control, ctx) = controller.compute(ctx, rpm as _, set_point as _, Millis(timestamp), None); let dumped_context = ctx.last_time().expect("LAST TIME!"); - // rprintln!("control:{},rpm:{}", control,rpm); + rprintln!("control:{},rpm:{}", control,rpm); //first we send the RPM! - let running_rpm = format!("running_rpm.val={}", rpm); - display.send_command(running_rpm.to_string().as_bytes()); + if display.write_ready(){ + let running_rpm = format!("running_rpm.val={}", rpm); + display.send_command(running_rpm.to_string().as_bytes()); + } + if display.write_ready(){ + let counter = format!("counter.val={}", 1234); + display.send_command(counter.to_string().as_bytes()); - let counter = format!("counter.val={}", 1234); - display.send_command(counter.to_string().as_bytes()); + } } rprintln!("COATING done!"); diff --git a/spinnyboy_rust/src/bin/peripherals/nextion.rs b/spinnyboy_rust/src/bin/peripherals/nextion.rs index b25ae65..ce11981 100644 --- a/spinnyboy_rust/src/bin/peripherals/nextion.rs +++ b/spinnyboy_rust/src/bin/peripherals/nextion.rs @@ -123,6 +123,9 @@ impl<'a> Nextion<'a> { pub fn read_ready(&mut self) -> bool { self.interface.read_ready() } + pub fn write_ready(&mut self) -> bool { + self.interface.write_ready() + } fn reset(&mut self) { self.state = UartStatemachine::WaitingP; self.idx = 0; From 0e97a15fab532d22a2f53e1e5aa071475ca309d0 Mon Sep 17 00:00:00 2001 From: Robert Schauklies Date: Sat, 14 Mar 2026 18:07:23 +0100 Subject: [PATCH 05/11] just testing with the magic value --- spinnyboy_rust/src/bin/dc_driver/dshot.rs | 2 +- spinnyboy_rust/src/bin/main.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spinnyboy_rust/src/bin/dc_driver/dshot.rs b/spinnyboy_rust/src/bin/dc_driver/dshot.rs index 7249a05..c5e4a97 100644 --- a/spinnyboy_rust/src/bin/dc_driver/dshot.rs +++ b/spinnyboy_rust/src/bin/dc_driver/dshot.rs @@ -323,7 +323,7 @@ impl<'a> DShot<'a> { let erpm = (60 * 1_000_000) / period_ms; let rpm = erpm/XING_EPRO_22_POLES; - self.rpm.set(Some(rpm)) + self.rpm.set(Some((rpm as f32 / 1.7) as _)) } } } diff --git a/spinnyboy_rust/src/bin/main.rs b/spinnyboy_rust/src/bin/main.rs index 834c2da..8905581 100644 --- a/spinnyboy_rust/src/bin/main.rs +++ b/spinnyboy_rust/src/bin/main.rs @@ -126,8 +126,8 @@ fn main() -> ! { //PID-Controller let loop_time = Duration::from_micros(10); let cfg = pid::PidConfigBuilder::default() - .kp(3.0) - .ki(1.0).output_limits(100.00, 2040.00) + .kp(2.0) + .ki(0.1).output_limits(100.00, 2040.00) .sample_time(loop_time) .filter_tc(0.1) .build() @@ -137,7 +137,7 @@ fn main() -> ! { let set_point = DEFAULT_TARGET_RPM; dshot_esc.arm(); let mut rpm = 0; - let mut control: f32 = 200.0; + let mut control: f32 = 600.0; // let timestamp = Instant::now(); loop { dshot_esc.process(); From 14a61d2f84d95d49b6f5517068415a8206581427 Mon Sep 17 00:00:00 2001 From: Robert Schauklies Date: Sat, 14 Mar 2026 18:23:11 +0100 Subject: [PATCH 06/11] magic fafo constant found --- spinnyboy_rust/src/bin/dc_driver/dshot.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spinnyboy_rust/src/bin/dc_driver/dshot.rs b/spinnyboy_rust/src/bin/dc_driver/dshot.rs index c5e4a97..a5dbe53 100644 --- a/spinnyboy_rust/src/bin/dc_driver/dshot.rs +++ b/spinnyboy_rust/src/bin/dc_driver/dshot.rs @@ -16,6 +16,7 @@ fn calculate_crc(frame: u16) -> u16 { IFlight XING-E Pro 2207 2750KV */ const XING_EPRO_22_POLES: u32 = 4; +const XING_EPRO_22_MAGNETS: u32 = 14; #[allow(dead_code)] #[allow(non_camel_case_types)] @@ -322,8 +323,9 @@ impl<'a> DShot<'a> { let period_ms: u32 = (mantissa << exp).into(); let erpm = (60 * 1_000_000) / period_ms; - let rpm = erpm/XING_EPRO_22_POLES; - self.rpm.set(Some((rpm as f32 / 1.7) as _)) + let rpm = erpm/(XING_EPRO_22_MAGNETS/2); + // let rpm = erpm/7; + self.rpm.set(Some((rpm as f32) as _)) } } } From d418da5b12ab0d3e44ab3d537999812ae766147a Mon Sep 17 00:00:00 2001 From: Robert Schauklies Date: Sat, 14 Mar 2026 18:40:32 +0100 Subject: [PATCH 07/11] this should work, we added the magic constant, the pid looks fine is not flaky anymore --- spinnyboy_rust/src/bin/dc_driver/dshot.rs | 4 ++-- spinnyboy_rust/src/bin/main.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spinnyboy_rust/src/bin/dc_driver/dshot.rs b/spinnyboy_rust/src/bin/dc_driver/dshot.rs index 7249a05..d2b65b7 100644 --- a/spinnyboy_rust/src/bin/dc_driver/dshot.rs +++ b/spinnyboy_rust/src/bin/dc_driver/dshot.rs @@ -16,7 +16,7 @@ fn calculate_crc(frame: u16) -> u16 { IFlight XING-E Pro 2207 2750KV */ const XING_EPRO_22_POLES: u32 = 4; - +const XING_EPRO_22_MAGNETS: u32 = 14; #[allow(dead_code)] #[allow(non_camel_case_types)] #[derive(Debug)] @@ -322,7 +322,7 @@ impl<'a> DShot<'a> { let period_ms: u32 = (mantissa << exp).into(); let erpm = (60 * 1_000_000) / period_ms; - let rpm = erpm/XING_EPRO_22_POLES; + let rpm = erpm/(XING_EPRO_22_MAGNETS/2); self.rpm.set(Some(rpm)) } } diff --git a/spinnyboy_rust/src/bin/main.rs b/spinnyboy_rust/src/bin/main.rs index e6e8bac..b2501a2 100644 --- a/spinnyboy_rust/src/bin/main.rs +++ b/spinnyboy_rust/src/bin/main.rs @@ -128,7 +128,7 @@ fn main() -> ! { //PID-Controller let loop_time = Duration::from_micros(10); let cfg = pid::PidConfigBuilder::default() - .kp(0.4) + .kp(2.0) .ki(0.0) .output_limits(100.00, 2040.00) .sample_time(loop_time) From c6db09ac2c27e49f67e48a442f1d79ba2d597332 Mon Sep 17 00:00:00 2001 From: Robert Schauklies Date: Sat, 14 Mar 2026 20:17:49 +0100 Subject: [PATCH 08/11] capped throttle value to sensible values --- spinnyboy_rust/src/bin/main.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/spinnyboy_rust/src/bin/main.rs b/spinnyboy_rust/src/bin/main.rs index b2501a2..5faba26 100644 --- a/spinnyboy_rust/src/bin/main.rs +++ b/spinnyboy_rust/src/bin/main.rs @@ -130,7 +130,7 @@ fn main() -> ! { let cfg = pid::PidConfigBuilder::default() .kp(2.0) .ki(0.0) - .output_limits(100.00, 2040.00) + .output_limits(100.00, 400.00) .sample_time(loop_time) .filter_tc(0.1) .build() @@ -227,6 +227,7 @@ fn main() -> ! { .load_value(esp_hal::time::Duration::from_secs(10)) .expect("TODO: Could not set timer for coating! "); dshot_esc.arm(); + let mut rpm_fail_ctr = 0; coat_timer.start(); while !coat_timer.is_interrupt_set() { dshot_esc.process(); @@ -240,6 +241,7 @@ fn main() -> ! { x } None => { + rpm_fail_ctr+=1; // rprintln!("NO RPM!"); rpm } @@ -256,7 +258,7 @@ fn main() -> ! { rprintln!("control:{},rpm:{}", control,rpm); //first we send the RPM! if display.write_ready(){ - let running_rpm = format!("running_rpm.val={}", rpm); + let running_rpm = format!("rpm.val={}", rpm); display.send_command(running_rpm.to_string().as_bytes()); } if display.write_ready(){ @@ -267,6 +269,7 @@ fn main() -> ! { } rprintln!("COATING done!"); + rprintln!("RPM_READ_FAILS {}",rpm_fail_ctr); started = false; display.send_command(b"page page0"); } From 05b07e5ee30819e606b5b07d21a6b9800db529a6 Mon Sep 17 00:00:00 2001 From: Robert Schauklies Date: Sat, 21 Mar 2026 22:34:11 +0100 Subject: [PATCH 09/11] current working PoC --- spinnyboy_rust/src/bin/main.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/spinnyboy_rust/src/bin/main.rs b/spinnyboy_rust/src/bin/main.rs index 5faba26..2c12095 100644 --- a/spinnyboy_rust/src/bin/main.rs +++ b/spinnyboy_rust/src/bin/main.rs @@ -62,7 +62,7 @@ extern crate alloc; //target RPM const DEFAULT_TARGET_RPM: u32 = 4000; //in seconds -const DEFAULT_SPIN_TIME: u32 = 10; +const DEFAULT_SPIN_TIME: u64 = 10; // This creates a default app-descriptor required by the esp-idf bootloader. // For more information see: esp_bootloader_esp_idf::esp_app_desc!(); @@ -129,7 +129,7 @@ fn main() -> ! { let loop_time = Duration::from_micros(10); let cfg = pid::PidConfigBuilder::default() .kp(2.0) - .ki(0.0) + .ki(0.4) .output_limits(100.00, 400.00) .sample_time(loop_time) .filter_tc(0.1) @@ -137,8 +137,6 @@ fn main() -> ! { .expect("Failed to build a PID configuration"); let controller = pid::FuncPidController::new(cfg); let mut ctx = PidContext::new(Millis(0), 0.0, 0.0); - let set_point = DEFAULT_TARGET_RPM; - let mut rpm = 0; let mut control: f32 = 200.0; let mut timg0 = TimerGroup::new(peripherals.TIMG0); let coat_timer = timg0.timer0; @@ -177,8 +175,8 @@ fn main() -> ! { let mut display = Nextion::new(&mut uart0); //we just set it to page0 to be sure display.send_command(b"page page0"); - let mut _rpm = DEFAULT_TARGET_RPM; - let mut _timer = DEFAULT_SPIN_TIME; + let mut target_rpm = DEFAULT_TARGET_RPM; + let mut timer:u64 = DEFAULT_SPIN_TIME; let mut started = false; loop { if display.read_ready() { @@ -198,11 +196,11 @@ fn main() -> ! { } Ok(Command::SetRpm(x)) => { rprintln!("SET_RPM with {}", x); - _rpm = x; + target_rpm = x; } Ok(Command::SetTimer(x)) => { rprintln!("SETTING TIMER {}", x); - _timer = x; + timer = x as _; } Ok(Command::SendConfig) => { rprintln!("SEND CONFIG"); @@ -224,18 +222,20 @@ fn main() -> ! { if started { rprintln!("STARTING!"); let _ = coat_timer - .load_value(esp_hal::time::Duration::from_secs(10)) + .load_value(esp_hal::time::Duration::from_secs(timer)) .expect("TODO: Could not set timer for coating! "); dshot_esc.arm(); let mut rpm_fail_ctr = 0; + let set_point = target_rpm; coat_timer.start(); + let mut current_rpm = 0; while !coat_timer.is_interrupt_set() { dshot_esc.process(); //let control_val = dc_driver:: //this bad boy needs floats, this will be fun :) control = 200.00; dshot_esc.set_throttle(control as _); - rpm = match dshot_esc.get_rpm() { + current_rpm = match dshot_esc.get_rpm() { Some(x) => { // rprintln!("GOT RPM {}", x); x @@ -243,7 +243,7 @@ fn main() -> ! { None => { rpm_fail_ctr+=1; // rprintln!("NO RPM!"); - rpm + current_rpm } }; // rprintln!("RPM:{}",rpm); @@ -253,12 +253,12 @@ fn main() -> ! { .duration_since_epoch() .as_millis(); (control, ctx) = - controller.compute(ctx, rpm as _, set_point as _, Millis(timestamp), None); + controller.compute(ctx, current_rpm as _, set_point as _, Millis(timestamp), None); let dumped_context = ctx.last_time().expect("LAST TIME!"); - rprintln!("control:{},rpm:{}", control,rpm); + rprintln!("control:{},rpm:{}", control,current_rpm); //first we send the RPM! if display.write_ready(){ - let running_rpm = format!("rpm.val={}", rpm); + let running_rpm = format!("rpm.val={}", current_rpm); display.send_command(running_rpm.to_string().as_bytes()); } if display.write_ready(){ From 8048d48f18a7b0338ad3626470b7da8c9584821d Mon Sep 17 00:00:00 2001 From: Robert Schauklies Date: Mon, 13 Apr 2026 20:05:18 +0200 Subject: [PATCH 10/11] adds the rpm and the timer for the second spinning regime --- spinnyboy_rust/src/bin/main.rs | 33 ++++++++++++++----- spinnyboy_rust/src/bin/peripherals/mod.rs | 2 ++ spinnyboy_rust/src/bin/peripherals/nextion.rs | 8 +++++ 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/spinnyboy_rust/src/bin/main.rs b/spinnyboy_rust/src/bin/main.rs index 2c12095..db46560 100644 --- a/spinnyboy_rust/src/bin/main.rs +++ b/spinnyboy_rust/src/bin/main.rs @@ -63,6 +63,7 @@ extern crate alloc; const DEFAULT_TARGET_RPM: u32 = 4000; //in seconds const DEFAULT_SPIN_TIME: u64 = 10; +const DEFAULT_DRY_SPIN_TIME: u64 = 10; // This creates a default app-descriptor required by the esp-idf bootloader. // For more information see: esp_bootloader_esp_idf::esp_app_desc!(); @@ -176,7 +177,9 @@ fn main() -> ! { //we just set it to page0 to be sure display.send_command(b"page page0"); let mut target_rpm = DEFAULT_TARGET_RPM; - let mut timer:u64 = DEFAULT_SPIN_TIME; + let mut timer: u64 = DEFAULT_SPIN_TIME; + let mut target_dry_rpm = DEFAULT_DRY_SPIN_TIME; + let mut dry_timer: u64 = DEFAULT_SPIN_TIME; let mut started = false; loop { if display.read_ready() { @@ -202,6 +205,14 @@ fn main() -> ! { rprintln!("SETTING TIMER {}", x); timer = x as _; } + Ok(Command::SetRpm2(x)) => { + rprintln!("SET_RPM with {}", x); + target_dry_rpm = x.try_into().expect("Couldn't cast RPM2 to u64"); + } + Ok(Command::SetTimer2(x)) => { + rprintln!("SETTING TIMER {}", x); + dry_timer = x as _; + } Ok(Command::SendConfig) => { rprintln!("SEND CONFIG"); let command = format!("rpm.val={}", DEFAULT_TARGET_RPM); @@ -241,7 +252,7 @@ fn main() -> ! { x } None => { - rpm_fail_ctr+=1; + rpm_fail_ctr += 1; // rprintln!("NO RPM!"); current_rpm } @@ -252,24 +263,28 @@ fn main() -> ! { let timestamp = esp_hal::time::Instant::now() .duration_since_epoch() .as_millis(); - (control, ctx) = - controller.compute(ctx, current_rpm as _, set_point as _, Millis(timestamp), None); + (control, ctx) = controller.compute( + ctx, + current_rpm as _, + set_point as _, + Millis(timestamp), + None, + ); let dumped_context = ctx.last_time().expect("LAST TIME!"); - rprintln!("control:{},rpm:{}", control,current_rpm); + rprintln!("control:{},rpm:{}", control, current_rpm); //first we send the RPM! - if display.write_ready(){ + if display.write_ready() { let running_rpm = format!("rpm.val={}", current_rpm); display.send_command(running_rpm.to_string().as_bytes()); } - if display.write_ready(){ + if display.write_ready() { let counter = format!("counter.val={}", 1234); display.send_command(counter.to_string().as_bytes()); - } } rprintln!("COATING done!"); - rprintln!("RPM_READ_FAILS {}",rpm_fail_ctr); + rprintln!("RPM_READ_FAILS {}", rpm_fail_ctr); started = false; display.send_command(b"page page0"); } diff --git a/spinnyboy_rust/src/bin/peripherals/mod.rs b/spinnyboy_rust/src/bin/peripherals/mod.rs index 5998a6e..4f881e2 100644 --- a/spinnyboy_rust/src/bin/peripherals/mod.rs +++ b/spinnyboy_rust/src/bin/peripherals/mod.rs @@ -7,6 +7,8 @@ pub enum Command { Stop, SendConfig, CommandSuccess, + SetRpm2(u32), + SetTimer2(u32), } #[derive(Debug)] pub enum ErrCommand { diff --git a/spinnyboy_rust/src/bin/peripherals/nextion.rs b/spinnyboy_rust/src/bin/peripherals/nextion.rs index ce11981..d96a6a7 100644 --- a/spinnyboy_rust/src/bin/peripherals/nextion.rs +++ b/spinnyboy_rust/src/bin/peripherals/nextion.rs @@ -116,6 +116,14 @@ impl<'a> Nextion<'a> { Ok(Command::SetTimer(time)) } 05 => Ok(Command::SendConfig), + 06 => { + let rpm = u32::from_le_bytes(buf[1..5].try_into().expect("failed to parse rpm!")); + Ok(Command::SetRpm2(rpm)) + } + 07 => { + let time = u32::from_le_bytes(buf[1..5].try_into().expect("failed to parse rpm!")); + Ok(Command::SetTimer2(time)) + } 00 => Ok(Command::CommandSuccess), _ => Err(ErrCommand::NoValidCmd), } From 1b748dfef0c065087eb8ebec521a3de3cadd17b2 Mon Sep 17 00:00:00 2001 From: Robert Schauklies Date: Mon, 13 Apr 2026 21:16:15 +0200 Subject: [PATCH 11/11] adds the necessary plumbing for https://git.fa-fo.de/fafo/maasier/issues/9 --- spinnyboy_rust/src/bin/main.rs | 15 +++++++++++---- spinnyboy_rust/src/bin/peripherals/mod.rs | 1 + spinnyboy_rust/src/bin/peripherals/nextion.rs | 1 + 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/spinnyboy_rust/src/bin/main.rs b/spinnyboy_rust/src/bin/main.rs index db46560..a1ffa8b 100644 --- a/spinnyboy_rust/src/bin/main.rs +++ b/spinnyboy_rust/src/bin/main.rs @@ -240,6 +240,7 @@ fn main() -> ! { let set_point = target_rpm; coat_timer.start(); let mut current_rpm = 0; + //first round! while !coat_timer.is_interrupt_set() { dshot_esc.process(); //let control_val = dc_driver:: @@ -274,19 +275,25 @@ fn main() -> ! { rprintln!("control:{},rpm:{}", control, current_rpm); //first we send the RPM! if display.write_ready() { - let running_rpm = format!("rpm.val={}", current_rpm); + let running_rpm = format!("rpm1.val={}", current_rpm); display.send_command(running_rpm.to_string().as_bytes()); - } - if display.write_ready() { let counter = format!("counter.val={}", 1234); display.send_command(counter.to_string().as_bytes()); } + if display.read_ready(){ + match display.read_command() { + Ok(Command::DoDryRun) =>{ + break; + }, + _ => {//we don't care about the rest} + } + } } rprintln!("COATING done!"); rprintln!("RPM_READ_FAILS {}", rpm_fail_ctr); started = false; - display.send_command(b"page page0"); + display.send_command(b"page page3"); } } } diff --git a/spinnyboy_rust/src/bin/peripherals/mod.rs b/spinnyboy_rust/src/bin/peripherals/mod.rs index 4f881e2..b410fd4 100644 --- a/spinnyboy_rust/src/bin/peripherals/mod.rs +++ b/spinnyboy_rust/src/bin/peripherals/mod.rs @@ -9,6 +9,7 @@ pub enum Command { CommandSuccess, SetRpm2(u32), SetTimer2(u32), + DoDryRun, } #[derive(Debug)] pub enum ErrCommand { diff --git a/spinnyboy_rust/src/bin/peripherals/nextion.rs b/spinnyboy_rust/src/bin/peripherals/nextion.rs index d96a6a7..73158b9 100644 --- a/spinnyboy_rust/src/bin/peripherals/nextion.rs +++ b/spinnyboy_rust/src/bin/peripherals/nextion.rs @@ -124,6 +124,7 @@ impl<'a> Nextion<'a> { let time = u32::from_le_bytes(buf[1..5].try_into().expect("failed to parse rpm!")); Ok(Command::SetTimer2(time)) } + 08 => Ok(Command::DoDryRun), 00 => Ok(Command::CommandSuccess), _ => Err(ErrCommand::NoValidCmd), }