Made motor driver independent task
This commit is contained in:
@ -23,6 +23,10 @@ pub enum Commands {
|
|||||||
ButtonTimerExpired,
|
ButtonTimerExpired,
|
||||||
ButtonTimerRestart,
|
ButtonTimerRestart,
|
||||||
ButtonTimerClear,
|
ButtonTimerClear,
|
||||||
|
|
||||||
|
NotifyMotorUp,
|
||||||
|
NotifyMotorDown,
|
||||||
|
NotifyMotorStop,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type CmdType = std::mem::Discriminant<Commands>;
|
pub type CmdType = std::mem::Discriminant<Commands>;
|
||||||
|
|||||||
@ -10,7 +10,6 @@ use log::*; //{trace, debug, info, warn, error}
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use async_executor::Executor;
|
use async_executor::Executor;
|
||||||
use futures_lite::future;
|
use futures_lite::future;
|
||||||
use std::boxed::Box;
|
|
||||||
|
|
||||||
// Debug modules
|
// Debug modules
|
||||||
mod test_console;
|
mod test_console;
|
||||||
@ -38,35 +37,23 @@ fn main() {
|
|||||||
//log::set_max_level(log::LevelFilter::Info);
|
//log::set_max_level(log::LevelFilter::Info);
|
||||||
|
|
||||||
match future::block_on(main_loop()) {
|
match future::block_on(main_loop()) {
|
||||||
Ok(_) => {error!("Exited main loop normally, but this should be impossible.")}
|
Ok(_) => {error!("Exited main loop with no errors, but this should not happen."); panic!();}
|
||||||
Err(e) => {error!("Exited main loop with error {}", e)}
|
Err(e) => {error!("Exited main loop with error {}", e); panic!();}
|
||||||
};
|
};
|
||||||
//TODO: can we restart the microcontroller here?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
async fn test_loop() -> Result<()> {
|
|
||||||
let timer_service = EspTaskTimerService::new()?;
|
|
||||||
|
|
||||||
let mut async_timer = timer_service.timer_async()?;
|
|
||||||
loop {
|
|
||||||
async_timer.after(Duration::from_secs(5)).await?;
|
|
||||||
debug!("Tick ");
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
async fn main_loop() -> Result<()> {
|
async fn main_loop() -> Result<()> {
|
||||||
info!("Entering main loop");
|
info!("Entering main loop");
|
||||||
|
|
||||||
// Create dispatch early so it can outlive most other things
|
// Create dispatch early so it can outlive most other things
|
||||||
let mut dp = dispatch::Dispatch::new();
|
let mut dp = dispatch::Dispatch::new();
|
||||||
|
|
||||||
// Debug Drivers
|
// Debug Drivers (TODO: remove debug)
|
||||||
let motor_driver = Box::new(motor_driver::MotorDriverDebug {});
|
let motor_driver = motor_driver::MotorDriverDebug::new(dp.get_cmd_channel());
|
||||||
|
|
||||||
// Setup of various drivers that need to out-live the executor
|
// Setup of various drivers that need to out-live the executor
|
||||||
let m_chan = motor_controller::Controller::prepare_controller(&mut dp);
|
let m_chan = motor_controller::Controller::prepare_controller(&mut dp);
|
||||||
let mut motor_control = motor_controller::Controller::new(m_chan, dp.get_cmd_channel(), motor_driver);
|
let mut motor_control = motor_controller::Controller::new(m_chan, dp.get_cmd_channel(), motor_driver.get_endpoint());
|
||||||
// Setup callback timers
|
// Setup callback timers
|
||||||
let mut button_timer = MessageTimer::<Commands, Commands>::new_on_dispatch(
|
let mut button_timer = MessageTimer::<Commands, Commands>::new_on_dispatch(
|
||||||
Commands::ButtonTimerRestart,
|
Commands::ButtonTimerRestart,
|
||||||
@ -85,7 +72,7 @@ async fn main_loop() -> Result<()> {
|
|||||||
let executor = Executor::new();
|
let executor = Executor::new();
|
||||||
let mut tasks:Vec<_> = Vec::new();
|
let mut tasks:Vec<_> = Vec::new();
|
||||||
|
|
||||||
//Queue Up debug tasks (TODO: remove)
|
//Queue Up debug tasks (TODO: remove debug)
|
||||||
let cli_endpoint = dp.get_cmd_channel();
|
let cli_endpoint = dp.get_cmd_channel();
|
||||||
tasks.push(executor.spawn(test_console::start_cli(cli_endpoint)));
|
tasks.push(executor.spawn(test_console::start_cli(cli_endpoint)));
|
||||||
//tasks.push(executor.spawn(test_loop()));
|
//tasks.push(executor.spawn(test_loop()));
|
||||||
@ -97,6 +84,7 @@ async fn main_loop() -> Result<()> {
|
|||||||
tasks.push(executor.spawn(button_timer.run()));
|
tasks.push(executor.spawn(button_timer.run()));
|
||||||
tasks.push(executor.spawn(stopping_timer.run()));
|
tasks.push(executor.spawn(stopping_timer.run()));
|
||||||
tasks.push(executor.spawn(ble_server.run()));
|
tasks.push(executor.spawn(ble_server.run()));
|
||||||
|
tasks.push(executor.spawn(motor_driver.run()));
|
||||||
tasks.push(executor.spawn(dp.cmd_loop()));
|
tasks.push(executor.spawn(dp.cmd_loop()));
|
||||||
|
|
||||||
//Once we have all our tasks, await on them all to run them in parallel.
|
//Once we have all our tasks, await on them all to run them in parallel.
|
||||||
@ -108,3 +96,5 @@ async fn main_loop() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: check many of these mut functions to see if they don't need to be.
|
||||||
@ -4,10 +4,10 @@
|
|||||||
use log::*; //{trace, debug, info, warn, error}
|
use log::*; //{trace, debug, info, warn, error}
|
||||||
//use async_channel::Receiver;
|
//use async_channel::Receiver;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use std::boxed::Box;
|
|
||||||
|
|
||||||
use crate::commands::Commands;
|
use crate::commands::Commands;
|
||||||
use crate::motor_driver::MotorDriver;
|
use crate::motor_driver::Commands as MotorCommands;
|
||||||
|
use crate::motor_driver::SendQ as MotorSendQ;
|
||||||
use crate::dispatch::{Dispatch, RecvQ, SendQ};
|
use crate::dispatch::{Dispatch, RecvQ, SendQ};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
@ -23,16 +23,16 @@ pub struct Controller {
|
|||||||
state: ControllerStates,
|
state: ControllerStates,
|
||||||
recv: RecvQ,
|
recv: RecvQ,
|
||||||
send: SendQ,
|
send: SendQ,
|
||||||
driver: Box<dyn MotorDriver>,
|
motor_q: MotorSendQ
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Controller {
|
impl Controller {
|
||||||
pub fn new(recv: RecvQ, send: SendQ, driver: Box<dyn MotorDriver>) -> Controller {
|
pub fn new(recv: RecvQ, send: SendQ, motor_q: MotorSendQ) -> Controller {
|
||||||
Controller {
|
Controller {
|
||||||
state: ControllerStates::Stopping,
|
state: ControllerStates::Stopping,
|
||||||
recv: recv,
|
recv: recv,
|
||||||
send: send,
|
send: send,
|
||||||
driver: driver}
|
motor_q: motor_q}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tell the message dispatch which messages we are interested in receiving, and get
|
/// Tell the message dispatch which messages we are interested in receiving, and get
|
||||||
@ -56,15 +56,15 @@ impl Controller {
|
|||||||
ControllerStates::Stopped => {}
|
ControllerStates::Stopped => {}
|
||||||
ControllerStates::Stopping => {
|
ControllerStates::Stopping => {
|
||||||
self.send.send(Commands::StopTimerRestart).await?;
|
self.send.send(Commands::StopTimerRestart).await?;
|
||||||
self.driver.stop()?;
|
self.motor_q.send(MotorCommands::Stop).await?;
|
||||||
}
|
}
|
||||||
ControllerStates::GoingUp => {
|
ControllerStates::GoingUp => {
|
||||||
self.send.send(Commands::ButtonTimerRestart).await?;
|
self.send.send(Commands::ButtonTimerRestart).await?;
|
||||||
self.driver.start_up()?;
|
self.motor_q.send(MotorCommands::StartUp).await?;
|
||||||
}
|
}
|
||||||
ControllerStates::GoingDown => {
|
ControllerStates::GoingDown => {
|
||||||
self.send.send(Commands::ButtonTimerRestart).await?;
|
self.send.send(Commands::ButtonTimerRestart).await?;
|
||||||
self.driver.start_down()?;
|
self.motor_q.send(MotorCommands::StartDown).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -2,28 +2,85 @@
|
|||||||
|
|
||||||
use log::*; //{trace, debug, info, warn, error}
|
use log::*; //{trace, debug, info, warn, error}
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use async_channel::{unbounded, Receiver, Sender};
|
||||||
|
use std::panic;
|
||||||
|
|
||||||
pub trait MotorDriver: Send + Sync {
|
use crate::dispatch;
|
||||||
fn start_up(&mut self) -> Result<()>;
|
use crate::commands::Commands as Dispatch_Commands;
|
||||||
fn start_down(&mut self) -> Result<()>;
|
|
||||||
fn stop(&mut self) -> Result<()>;
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum Commands {
|
||||||
|
StartUp,
|
||||||
|
StartDown,
|
||||||
|
Stop
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MotorDriverDebug {}
|
pub type SendQ = Sender<Commands>;
|
||||||
|
pub type RecvQ = Receiver<Commands>;
|
||||||
|
|
||||||
impl MotorDriver for MotorDriverDebug {
|
pub struct MotorDriverDebug{
|
||||||
fn start_up(&mut self) -> Result<()> {
|
endpoint: SendQ,
|
||||||
|
recv_q: RecvQ,
|
||||||
|
dispatch: dispatch::SendQ,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Debug / example version of Motor Driver.
|
||||||
|
impl MotorDriverDebug {
|
||||||
|
pub fn new(send_q: dispatch::SendQ) -> Self {
|
||||||
|
let (s,r) = unbounded();
|
||||||
|
MotorDriverDebug {
|
||||||
|
endpoint: s,
|
||||||
|
recv_q: r,
|
||||||
|
dispatch:send_q
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_endpoint(&self) -> SendQ {
|
||||||
|
self.endpoint.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run(&self) -> Result<()> {
|
||||||
|
//TODO: Add error propagation to all loops
|
||||||
|
loop {
|
||||||
|
match self.recv_q.recv().await {
|
||||||
|
Ok(cmd) => {
|
||||||
|
match self.handle_cmd(cmd).await {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Unable to send commands to motor! {:?}", e);
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Unable to receive commands for motor control! {:?}", e);
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_cmd(&self, cmd: Commands) -> Result<()> {
|
||||||
|
match cmd {
|
||||||
|
Commands::StartUp => {self.start_up().await?;Ok(())}
|
||||||
|
Commands::StartDown => {self.start_down().await?;Ok(())}
|
||||||
|
Commands::Stop => {self.stop().await?;Ok(())}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start_up(&self) -> Result<()> {
|
||||||
warn!("Starting motor, direction: Up");
|
warn!("Starting motor, direction: Up");
|
||||||
|
self.dispatch.send(Dispatch_Commands::NotifyMotorUp).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn start_down(&mut self) -> Result<()> {
|
pub async fn start_down(&self) -> Result<()> {
|
||||||
warn!("Starting motor, direction: Down");
|
warn!("Starting motor, direction: Down");
|
||||||
|
self.dispatch.send(Dispatch_Commands::NotifyMotorDown).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn stop(&mut self) ->Result<()> {
|
pub async fn stop(&self) -> Result<()> {
|
||||||
warn!("Stopping motor");
|
warn!("Stopping motor");
|
||||||
|
self.dispatch.send(Dispatch_Commands::NotifyMotorStop).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//unsafe impl Send for MotorDriverDebug {}
|
|
||||||
Reference in New Issue
Block a user