1
Fork 0

Compare commits

..

No commits in common. "ad82a25329fd9bca3173a09180fc8aa71b63b46f" and "6a285fe7cd39629d9043b3d5a1eb0e831840765f" have entirely different histories.

12 changed files with 241 additions and 626 deletions

View file

@ -1,7 +1,7 @@
//! Data types shared between the northbridge and southbridge for serial communications
#![no_std]
use nalgebra::{SimdPartialOrd, Vector3};
use nalgebra::Vector3;
use serde::{Deserialize, Serialize};
pub const BAUDRATE: u32 = 115200;
@ -20,34 +20,9 @@ pub enum Command {
Disable,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RobotState {
/// forward. clockwise
pub drive: (f32,f32),
/// RGB led brightness
pub underglow: Vector3<u8>,
}
impl RobotState {
/// limit exertion to factor of full output (0 to 1)
pub fn brownout(self, factor: f32) -> Self {
Self {
drive: (
self.drive.0.clamp(-factor, factor),
self.drive.1.clamp(-factor, factor),
),
underglow: self.underglow.simd_min(Vector3::repeat((factor * u8::MAX as f32) as u8))
}
}
/// Safe command to send in uncertian states
pub const fn stopped() -> Self {
Self { drive: (0.0, 0.0), underglow: Vector3::new(100, 0, 0) }
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Response {
pub enabled: bool,
pub sensor_data: Option<SensorData>,
pub uptime_micros: u64,
}
@ -62,6 +37,4 @@ pub enum SensorData {
Magnetometer(Vector3<f32>),
/// V
BusVoltage(f32),
/// C
AmbientTemperature(f32),
}

81
interface/Cargo.lock generated
View file

@ -74,12 +74,6 @@ version = "3.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
[[package]]
name = "bytemuck"
version = "1.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"
[[package]]
name = "byteorder"
version = "1.5.0"
@ -214,7 +208,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.98",
"syn",
]
[[package]]
@ -338,7 +332,6 @@ dependencies = [
"common",
"futures",
"gilrs",
"nalgebra",
"postcard",
"serde",
"tokio",
@ -405,16 +398,6 @@ dependencies = [
"libc",
]
[[package]]
name = "matrixmultiply"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a"
dependencies = [
"autocfg",
"rawpointer",
]
[[package]]
name = "memchr"
version = "2.7.4"
@ -448,8 +431,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20bd243ab3dbb395b39ee730402d2e5405e448c75133ec49cc977762c4cba3d1"
dependencies = [
"approx",
"matrixmultiply",
"nalgebra-macros",
"num-complex",
"num-rational",
"num-traits",
@ -458,17 +439,6 @@ dependencies = [
"typenum",
]
[[package]]
name = "nalgebra-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01fcc0b8149b4632adc89ac3b7b31a12fb6099a0317a4eb2ebff574ef7de7218"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "nix"
version = "0.29.0"
@ -612,12 +582,6 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rawpointer"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
[[package]]
name = "redox_syscall"
version = "0.5.8"
@ -648,15 +612,6 @@ version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]]
name = "safe_arch"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
dependencies = [
"bytemuck",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@ -686,7 +641,7 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.98",
"syn",
]
[[package]]
@ -708,7 +663,6 @@ dependencies = [
"num-complex",
"num-traits",
"paste",
"wide",
]
[[package]]
@ -751,17 +705,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.98"
@ -799,7 +742,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.98",
"syn",
]
[[package]]
@ -854,7 +797,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
"syn 2.0.98",
"syn",
"wasm-bindgen-shared",
]
@ -876,7 +819,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.98",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -900,16 +843,6 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "wide"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41b5576b9a81633f3e8df296ce0063042a73507636cbe956c61133dd7034ab22"
dependencies = [
"bytemuck",
"safe_arch",
]
[[package]]
name = "windows"
version = "0.59.0"
@ -941,7 +874,7 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.98",
"syn",
]
[[package]]
@ -952,7 +885,7 @@ checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.98",
"syn",
]
[[package]]

View file

@ -11,4 +11,3 @@ gilrs = "0.11.0"
futures = "0.3.31"
serde = { version = "1.0.217", features = ["alloc"] }
postcard = { version = "1.0.0", features = ["alloc", "use-std"] }
nalgebra = "0.31.2"

View file

@ -1,10 +1,9 @@
use std::time::Duration;
use anyhow::Context;
use common::{RobotState, SensorData};
use common::Command;
use gilrs::{Axis, Event, Gilrs};
use nalgebra::Vector3;
use tokio::{io::{AsyncReadExt, AsyncWriteExt, BufWriter}, net::{tcp::OwnedReadHalf, TcpStream}, task::JoinHandle, time::{sleep, Instant}};
use tokio::{io::{AsyncWriteExt, BufWriter}, net::TcpStream, time::sleep};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
@ -14,27 +13,20 @@ async fn main() -> anyhow::Result<()> {
let (_, gamepad) = gamepads.gamepads().nth(0).context("no gamepads")?;
let ly = gamepad.axis_code(Axis::LeftStickY).context("no left joystick")?;
let rx = gamepad.axis_code(Axis::RightStickX).context("no right joystick")?;
let lb = gamepad.button_code(gilrs::Button::LeftTrigger).context("no lb")?;
let a = gamepad.button_code(gilrs::Button::South).context("no a")?;
let mut last_a = false;
let server = "pelican.dyn.wpi.edu:3322";
let mut robot = TcpStream::connect(server).await?;
let mut robot = TcpStream::connect("pelican.dyn.wpi.edu:3322").await?;
robot.set_nodelay(true)?;
let (telem, robot_controller) = robot.into_split();
tokio::spawn(print_telem(telem));
let (_telem, robot_controller) = robot.split();
let mut robot_controller = BufWriter::new(robot_controller);
let mut active_gamepad = None;
let mut last_event = Instant::now();
loop {
while let Some(Event { id,..}) = gamepads.next_event() {
active_gamepad = Some(id);
last_event = Instant::now();
}
let Some(gamepad) = active_gamepad else {
@ -43,75 +35,28 @@ async fn main() -> anyhow::Result<()> {
let gamepad = gamepads.gamepad(gamepad);
let values = gamepad.state();
dbg!(values);
let mut ly= values.axis_data(ly).map(|d| d.value()).unwrap_or(0.0);
let mut rx= values.axis_data(rx).map(|d| d.value()).unwrap_or(0.0);
let boost = values.button_data(lb).map(|b| b.is_pressed()).unwrap_or(false);
let a = values.button_data(a).map(|b| b.is_pressed()).unwrap_or(false);
for axis in [&mut rx, &mut ly] {
if axis.abs() < 0.05 {
*axis = 0.0;
}
if !boost {
*axis *= 0.3;
}
}
if !gamepad.is_connected() {
ly = 0.0;
rx = 0.0;
}
let black = Vector3::repeat(0u8);
let green = Vector3::new(254u8, 0, 254);
let color = if a {green} else {black};
let cmd = RobotState {
drive: (ly, rx),
underglow: color,
};
let cmd = Command::Twist(ly, rx);
let encoded = postcard::to_stdvec(&cmd)?;
robot_controller.write_u32(encoded.len() as u32).await?;
robot_controller.write_all(&encoded).await?;
if let Err(e) = robot_controller.flush().await {
println!("flush fail: {e}, reconnecting");
robot = TcpStream::connect(server).await?;
robot.set_nodelay(true)?;
let (telem, robot) = robot.into_split();
tokio::spawn(print_telem(telem));
robot_controller = BufWriter::new(robot);
};
sleep(Duration::from_millis(25)).await;
}
}
async fn print_telem(mut telem: OwnedReadHalf) -> anyhow::Result<()> {
loop {
let len = telem.read_u32().await? as usize;
let mut buf = vec![0; len];
telem.read_exact(&mut buf).await?;
let telem: SensorData = postcard::from_bytes(&buf)?;
match telem {
SensorData::BusVoltage(voltage) => {
println!("voltage: {voltage}");
}
SensorData::AmbientTemperature(temp) => {
println!("pico temp {}", temp * 9./5. + 32.);
}
_ => {}
}
robot_controller.flush().await?;
sleep(Duration::from_micros(3500)).await;
}
}

57
northbridge/Cargo.lock generated
View file

@ -146,62 +146,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]]
name = "crossbeam"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-epoch",
"crossbeam-queue",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "embedded-io"
version = "0.4.0"
@ -499,7 +443,6 @@ version = "0.1.0"
dependencies = [
"anyhow",
"common",
"crossbeam",
"framed",
"futures",
"futures-core",

View file

@ -15,4 +15,3 @@ nalgebra = { version = "0.31.2", default-features=false, features = ["serde-seri
tokio-util = { version = "0.7.13", features = ["codec"] }
futures-core = "0.3.31"
futures = "0.3.31"
crossbeam = "0.8.4"

View file

@ -1,6 +1,3 @@
server := 'pelican.dyn.wpi.edu'
deploy:
cross build --target=armv7-unknown-linux-gnueabihf --release
scp target/armv7-unknown-linux-gnueabihf/release/northbridge cruise@{{server}}:
ssh cruise@{{server}} systemctl --user restart nightstand
scp target/armv7-unknown-linux-gnueabihf/release/northbridge cruise@pelican.dyn.wpi.edu:

View file

@ -1,9 +1,9 @@
use std::result;
use anyhow::{anyhow, Ok};
use common::{Response, RobotState};
use common::{Command, Response};
use framed::{BoxPayload, FRAME_END_SYMBOL};
use tokio_util::{bytes::{Buf, BytesMut}, codec::{Decoder, Encoder}};
use tokio_util::{bytes::BytesMut, codec::{Decoder, Encoder}};
pub struct FramedCodec {
codec: framed::bytes::Codec,
@ -21,40 +21,20 @@ impl Decoder for FramedCodec {
type Error = anyhow::Error;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
println!("len: {}", src.len());
if !src.contains(&0) {
return Ok(None);
}
let terminator_idx = src.iter().position(|b| *b == 0).unwrap();
let (message, remainder) = match postcard::take_from_bytes_cobs(src) {
result::Result::Ok(v) => v,
result::Result::Err(e) => {
println!("telem err: {e}");
// skip to the next terminator and try one more time
src.advance(terminator_idx+1);
if !src.contains(&0) {
println!("incomplete frame");
return Ok(None);
}
match postcard::take_from_bytes_cobs(src) {
result::Result::Ok(v) => v,
result::Result::Err(e) => {
src.clear();
println!("telem err: {e}, cleared");
return Ok(None);
}
}
src.clear();
Err(e)?
}
};
let remainder = remainder.to_vec();
src.clear();
if remainder.len() < 200 { // magic number
src.extend_from_slice(&remainder);
}
Ok(Some(message))
}
@ -71,10 +51,10 @@ impl Encoder<Vec<u8>> for FramedCodec {
}
}
impl Encoder<RobotState> for FramedCodec {
impl Encoder<Command> for FramedCodec {
type Error = anyhow::Error;
fn encode(&mut self, item: RobotState, dst: &mut BytesMut) -> Result<(), Self::Error> {
fn encode(&mut self, item: Command, dst: &mut BytesMut) -> Result<(), Self::Error> {
let data = postcard::to_stdvec(&item)?;
Ok(self.encode(data, dst).map_err(|e| anyhow!("encode fail: {e:?}"))?)
}

View file

@ -1,123 +1,92 @@
#![feature(async_closure)]
use std::{sync::Arc, time::Duration};
use std::time::Duration;
use anyhow::{Context, Result};
use common::{Response, RobotState, SensorData, BAUDRATE};
use crossbeam::queue::ArrayQueue;
use common::{Command, Response, BAUDRATE};
use framed_codec::FramedCodec;
use futures::{FutureExt, SinkExt, StreamExt, TryStreamExt};
use nalgebra::{SimdPartialOrd, SimdValue, Vector3};
use tokio::{io::{AsyncReadExt, AsyncWriteExt}, net::{TcpListener, TcpSocket}, sync::{broadcast::{self, error::RecvError, Receiver, Sender}, watch::{self, channel }, RwLock}, task::JoinHandle, time::{error::Elapsed, sleep, timeout}};
use futures::{SinkExt, StreamExt};
use tokio::{io::AsyncReadExt, net::{TcpListener, TcpSocket}, sync::{broadcast, watch::{self, Sender}}, task::JoinHandle, time::timeout};
use tokio_serial::SerialPortBuilderExt;
use tokio_util::codec::Framed;
mod framed_codec;
#[derive(Default)]
struct RobotInfo {
bus_voltage: f32,
}
#[tokio::main]
async fn main() -> Result<()> {
let mut serial = tokio_serial::new("/dev/ttyAMA0", BAUDRATE).open_native_async()?;
let (sensor_sender, sensor_data) = broadcast::channel(5);
let (sensor_sender, mut sensor_data) = broadcast::channel(5);
serial.set_exclusive(false)?;
let (mut write, mut read) = Framed::new(serial, FramedCodec::new()).split();
let (sender, mut command_receiver) = channel(RobotState::stopped());
let (send, commands) = watch::channel(Command::Stop);
let state = Arc::new(RwLock::new(RobotInfo {
bus_voltage: f32::MAX,
..Default::default()
}));
let _: JoinHandle<Result<()>> = tokio::spawn(async move {
loop {
println!("sensor {:?}", sensor_data.recv().await?);
}
});
tokio::spawn(update_telem(state.clone(), sensor_data.resubscribe()));
let control_telem = sensor_data.resubscribe();
tokio::spawn(async move {
loop {
if let Err(e) = control(sender.clone(), control_telem.resubscribe()).await {
let _ = send.send(Command::Stop);
if let Err(e) = control(send.clone()).await {
println!("controller exited: {e}");
}
}
});
tokio::spawn(async move {
let telem_sender = sensor_sender.clone();
read.for_each( async |telem| {
let Ok(telem) = telem else {return;};
let Some(data) = telem.sensor_data else {return;};
telem_sender.send(data).unwrap();
}).await;
});
println!("starting");
write.send(Command::Enable).await?;
write.flush().await?;
loop {
let _ = timeout(Duration::from_millis(20), command_receiver.changed());
let command = command_receiver.borrow();
let Some(Ok(data)) = read.next().await else {
continue;
};
if data.enabled {
write.send(Command::FeedWatchdog).await?;
write.flush().await?;
println!("sending {command:?}");
} else {
println!("enabled southbridge");
write.send(Command::Enable).await?;
}
write.send(command.clone()).await?;
write.send(Command::Enable).await?;
write.flush().await?;
//dbg!(&data);
if let Some(data) = data.sensor_data {
let _ = sensor_sender.send(data);
}
write.send(dbg!(commands.borrow().clone())).await?;
write.flush().await?;
}
}
async fn control(sender: watch::Sender<RobotState>, mut telem: Receiver<SensorData>) -> Result<()> {
async fn control(sender: Sender<Command>) -> Result<()> {
let listener = TcpListener::bind("0.0.0.0:3322").await?;
let (stream, addr) = listener.accept().await?;
let (mut stream, addr) = listener.accept().await?;
println!("connected to {addr:?}");
let (mut read, mut write) = stream.into_split();
let _: JoinHandle<Result<()>> = tokio::spawn(async move {
loop {
let data = match telem.recv().await {
Ok(it) => it,
Err(RecvError::Lagged(_)) => {continue;},
Err(e) => {Err(e)?},
};
let data = postcard::to_stdvec(&data)?;
write.write_u32(data.len() as u32).await?;
write.write_all(&data).await?;
}
});
loop {
let len = loop {
match timeout(Duration::from_millis(150), read.read_u32()).await {
Ok(it) => { break it?; },
Err(Elapsed) => {
sender.send(RobotState::stopped())?;
continue;
},
};
};
let len = timeout(Duration::from_millis(30), stream.read_u32()).await??;
let mut buf = vec![0; len as usize];
timeout(Duration::from_millis(100), read.read_exact(&mut buf)).await??;
timeout(Duration::from_millis(30), stream.read_exact(&mut buf)).await??;
let cmd: RobotState = postcard::from_bytes(&buf)?;
let cmd: Command = postcard::from_bytes(&buf)?;
println!("recv {cmd:?}");
sender.send(cmd)?;
}
}
async fn update_telem(state: Arc<RwLock<RobotInfo>>, mut telem: Receiver<SensorData>) -> Result<()> {
loop {
let telem = telem.recv().await?;
println!("sensor {telem:?}");
match telem {
SensorData::BusVoltage(voltage) => {
state.write().await.bus_voltage = voltage;
}
_ => {}
}
}
}

267
southbridge/Cargo.lock generated
View file

@ -79,18 +79,18 @@ dependencies = [
[[package]]
name = "bit-set"
version = "0.6.0"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f"
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
dependencies = [
"bit-vec",
]
[[package]]
name = "bit-vec"
version = "0.7.0"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22"
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]]
name = "bitfield"
@ -110,15 +110,6 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "bytemuck"
version = "1.21.0"
@ -193,15 +184,6 @@ dependencies = [
"syn 2.0.96",
]
[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
[[package]]
name = "crc-any"
version = "2.5.0"
@ -229,16 +211,6 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "darling"
version = "0.20.10"
@ -274,15 +246,6 @@ dependencies = [
"syn 2.0.96",
]
[[package]]
name = "dcmimu"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692b1c8923315ac22103c1890512597baf543b95f2eebd66f572ffb1ff8f0170"
dependencies = [
"libm 0.1.4",
]
[[package]]
name = "debug-helper"
version = "0.3.13"
@ -290,14 +253,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e"
[[package]]
name = "digest"
version = "0.10.7"
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "dirs-next"
@ -338,10 +297,10 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "embassy-embedded-hal"
version = "0.3.0"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fea5ef5bed4d3468dfd44f5c9fa4cda8f54c86d4fb4ae683eacf9d39e2ea12"
dependencies = [
"embassy-futures",
"embassy-hal-internal",
"embassy-sync",
"embassy-time",
"embedded-hal 0.2.7",
@ -355,7 +314,8 @@ dependencies = [
[[package]]
name = "embassy-executor"
version = "0.7.0"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90327bcc66333a507f89ecc4e2d911b265c45f5c9bc241f98eee076752d35ac6"
dependencies = [
"cortex-m",
"critical-section",
@ -366,7 +326,8 @@ dependencies = [
[[package]]
name = "embassy-executor-macros"
version = "0.6.2"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3577b1e9446f61381179a330fc5324b01d511624c55f25e3c66c9e3c626dbecf"
dependencies = [
"darling",
"proc-macro2",
@ -377,12 +338,14 @@ dependencies = [
[[package]]
name = "embassy-futures"
version = "0.1.1"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067"
[[package]]
name = "embassy-hal-internal"
version = "0.2.0"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef3bac31ec146321248a169e9c7b5799f1e0b3829c7a9b324cb4600a7438f59"
dependencies = [
"cortex-m",
"critical-section",
@ -392,12 +355,14 @@ dependencies = [
[[package]]
name = "embassy-net-driver"
version = "0.2.0"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d"
[[package]]
name = "embassy-net-driver-channel"
version = "0.3.0"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4818c32afec43e3cae234f324bad9a976c9aa7501022d26ff60a4017a1a006b7"
dependencies = [
"embassy-futures",
"embassy-net-driver",
@ -407,7 +372,8 @@ dependencies = [
[[package]]
name = "embassy-rp"
version = "0.3.0"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cfe90d82ebbfed9de96d9edc6d63b6619c0977b570a3ab1724f76023e72773b"
dependencies = [
"atomic-polyfill",
"cfg-if",
@ -446,7 +412,8 @@ dependencies = [
[[package]]
name = "embassy-sync"
version = "0.6.2"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d2c8cdff05a7a51ba0087489ea44b0b1d97a296ca6b1d6d1a33ea7423d34049"
dependencies = [
"cfg-if",
"critical-section",
@ -459,7 +426,8 @@ dependencies = [
[[package]]
name = "embassy-time"
version = "0.4.0"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f820157f198ada183ad62e0a66f554c610cdcd1a9f27d4b316358103ced7a1f8"
dependencies = [
"cfg-if",
"critical-section",
@ -474,7 +442,8 @@ dependencies = [
[[package]]
name = "embassy-time-driver"
version = "0.2.0"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d45f5d833b6d98bd2aab0c2de70b18bfaa10faf661a1578fd8e5dfb15eb7eba"
dependencies = [
"document-features",
]
@ -482,7 +451,8 @@ dependencies = [
[[package]]
name = "embassy-time-queue-utils"
version = "0.1.0"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc55c748d16908a65b166d09ce976575fb8852cf60ccd06174092b41064d8f83"
dependencies = [
"embassy-executor",
"heapless 0.8.0",
@ -491,7 +461,8 @@ dependencies = [
[[package]]
name = "embassy-usb"
version = "0.4.0"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e651b9b7b47b514e6e6d1940a6e2e300891a2c33641917130643602a0cb6386"
dependencies = [
"embassy-futures",
"embassy-net-driver-channel",
@ -505,12 +476,14 @@ dependencies = [
[[package]]
name = "embassy-usb-driver"
version = "0.1.0"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fc247028eae04174b6635104a35b1ed336aabef4654f5e87a8f32327d231970"
[[package]]
name = "embassy-usb-logger"
version = "0.4.0"
source = "git+https://github.com/embassy-rs/embassy/#0ce6da9706b9d929691c9292c923117fcbc2f9c6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad40e3ec749d83f4b7ab0c0599c9bef0c51a73ce1c1087d8599ff2448d00c2aa"
dependencies = [
"embassy-futures",
"embassy-sync",
@ -671,16 +644,6 @@ dependencies = [
"pin-utils",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.15"
@ -759,6 +722,12 @@ dependencies = [
"stable_deref_trait",
]
[[package]]
name = "hermit-abi"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
[[package]]
name = "ident_case"
version = "1.0.1"
@ -776,52 +745,54 @@ dependencies = [
]
[[package]]
name = "itertools"
version = "0.13.0"
name = "is-terminal"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37"
dependencies = [
"hermit-abi",
"libc",
"windows-sys",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "keccak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654"
dependencies = [
"cpufeatures",
]
[[package]]
name = "lalrpop"
version = "0.21.0"
version = "0.19.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e56f323e2d610628d1f5bdd39168a774674ac7989ed67011963bb3f71edd797"
checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b"
dependencies = [
"ascii-canvas",
"bit-set",
"diff",
"ena",
"is-terminal",
"itertools",
"lalrpop-util",
"petgraph",
"pico-args",
"regex",
"regex-syntax",
"sha3",
"regex-syntax 0.6.29",
"string_cache",
"term",
"tiny-keccak",
"unicode-xid",
"walkdir",
]
[[package]]
name = "lalrpop-util"
version = "0.21.0"
version = "0.19.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "108dc8f5dabad92c65a03523055577d847f5dcc00f3e7d3a68bc4d48e01d8fe1"
checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed"
dependencies = [
"regex-automata",
"regex",
]
[[package]]
@ -830,12 +801,6 @@ version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "libm"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
[[package]]
name = "libm"
version = "0.2.11"
@ -886,7 +851,7 @@ version = "0.1.6"
source = "git+https://git.ank.dev/ank/mpu6050#32604cc16c6a604fd0a4a35bf66bd9df800da18e"
dependencies = [
"embedded-hal 1.0.0",
"libm 0.2.11",
"libm",
"nalgebra",
]
@ -966,22 +931,22 @@ dependencies = [
[[package]]
name = "num_enum"
version = "0.7.3"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179"
checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9"
dependencies = [
"num_enum_derive",
]
[[package]]
name = "num_enum_derive"
version = "0.7.3"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.96",
"syn 1.0.109",
]
[[package]]
@ -1038,12 +1003,6 @@ dependencies = [
"siphasher",
]
[[package]]
name = "pico-args"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@ -1059,7 +1018,8 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pio"
version = "0.2.1"
source = "git+https://github.com/rp-rs/pio-rs?rev=fa586448b0b223217eec8c92c19fe6823dd04cc4#fa586448b0b223217eec8c92c19fe6823dd04cc4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76e09694b50f89f302ed531c1f2a7569f0be5867aee4ab4f8f729bbeec0078e3"
dependencies = [
"arrayvec",
"num_enum",
@ -1069,26 +1029,30 @@ dependencies = [
[[package]]
name = "pio-parser"
version = "0.2.2"
source = "git+https://github.com/rp-rs/pio-rs?rev=fa586448b0b223217eec8c92c19fe6823dd04cc4#fa586448b0b223217eec8c92c19fe6823dd04cc4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77532c2b8279aef98dfc7207ef15298a5a3d6b6cc76ccc8b65913d69f3a8dd6b"
dependencies = [
"lalrpop",
"lalrpop-util",
"pio",
"regex-syntax 0.6.29",
]
[[package]]
name = "pio-proc"
version = "0.2.2"
source = "git+https://github.com/rp-rs/pio-rs?rev=fa586448b0b223217eec8c92c19fe6823dd04cc4#fa586448b0b223217eec8c92c19fe6823dd04cc4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b04dc870fb3a4fd8b3e4ca8c61b53bc8ac4eb78b66805d2b3c2e5c4829e0d7a"
dependencies = [
"codespan-reporting",
"lalrpop-util",
"pio",
"pio-parser",
"proc-macro-error2",
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.96",
"regex-syntax 0.6.29",
"syn 1.0.109",
]
[[package]]
@ -1118,25 +1082,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "proc-macro-error-attr2"
version = "2.0.0"
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.109",
"version_check",
]
[[package]]
name = "proc-macro-error2"
version = "2.0.1"
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
"syn 2.0.96",
"version_check",
]
[[package]]
@ -1198,7 +1164,7 @@ dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
"regex-syntax 0.8.5",
]
[[package]]
@ -1209,9 +1175,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"regex-syntax 0.8.5",
]
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.8.5"
@ -1276,15 +1248,6 @@ version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@ -1338,16 +1301,6 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9"
[[package]]
name = "sha3"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
dependencies = [
"digest",
"keccak",
]
[[package]]
name = "simba"
version = "0.7.3"
@ -1397,7 +1350,6 @@ dependencies = [
"common",
"cortex-m",
"cortex-m-rt",
"dcmimu",
"embassy-executor",
"embassy-rp",
"embassy-sync",
@ -1534,6 +1486,15 @@ dependencies = [
"syn 2.0.96",
]
[[package]]
name = "tiny-keccak"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
dependencies = [
"crunchy",
]
[[package]]
name = "typenum"
version = "1.17.0"
@ -1632,16 +1593,6 @@ dependencies = [
"vcell",
]
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"

View file

@ -25,18 +25,9 @@ log = "0.4"
framed = {git = "https://git.ank.dev/ank/framed-rs", default-features=false, features = ["use_nightly"]}
common = { path = "../common" }
mpu6050 = { git = "https://git.ank.dev/ank/mpu6050" }
dcmimu = "0.2.2"
nalgebra = { version = "0.31.2", default-features=false, features = ["serde-serialize-no-std"] }
serde = { version = "1.0.203", default-features = false, features = ["derive"] }
postcard = "1.0.0"
static_cell = "2.1"
portable-atomic = { version = "1.5", features = ["critical-section"] }
heapless = "0.8"
[patch.crates-io]
# https://github.com/embassy-rs/embassy/pull/3763/
embassy-rp = { git = 'https://github.com/embassy-rs/embassy/' }
embassy-time = { git = 'https://github.com/embassy-rs/embassy/' }
embassy-usb-logger = { git = 'https://github.com/embassy-rs/embassy/' }
embassy-sync = { git = 'https://github.com/embassy-rs/embassy/' }
embassy-executor = { git = 'https://github.com/embassy-rs/embassy/' }

View file

@ -1,16 +1,16 @@
#![no_std]
#![no_main]
use core::{panic::PanicInfo, sync::atomic::{AtomicU16, Ordering}};
use core::{panic::PanicInfo, sync::atomic::Ordering};
use common::{Response, RobotState, SensorData, BAUDRATE};
use common::{Command, Response, SensorData, BAUDRATE};
use embassy_executor::Spawner;
use embassy_rp::{adc::{self, Adc}, bind_interrupts, block::ImageDef, gpio::{Level, Output, Pull}, peripherals::{ADC, ADC_TEMP_SENSOR, PIN_28, UART0, UART1, USB}, pwm::{self, Pwm}, uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, BufferedUartTx, Config}, usb::Driver};
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel, mutex::Mutex, once_lock::OnceLock, pubsub::PubSubChannel, signal::Signal, watch::Watch};
use embassy_rp::{bind_interrupts, block::ImageDef, gpio::{Level, Output}, peripherals::{UART0, UART1, USB}, pwm::{self, Pwm}, uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, BufferedUartTx, Config}, usb::Driver};
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel, once_lock::OnceLock};
use embassy_time::{with_deadline, with_timeout, Duration, Instant, Timer};
use embedded_io_async::{BufRead, Read, Write};
use log::{error, info, trace, warn};
use nalgebra::{clamp, Vector3};
use nalgebra::clamp;
use portable_atomic::AtomicBool;
use static_cell::{ConstStaticCell, StaticCell};
@ -18,27 +18,18 @@ bind_interrupts!(struct Irqs {
I2C1_IRQ => embassy_rp::i2c::InterruptHandler<embassy_rp::peripherals::I2C1>;
USBCTRL_IRQ => embassy_rp::usb::InterruptHandler<USB>;
UART1_IRQ => BufferedInterruptHandler<UART1>;
ADC_IRQ_FIFO => adc::InterruptHandler;
});
pub static COMMANDS: Watch<CriticalSectionRawMutex, (RobotState, Instant), 3> = Watch::new();
pub static COMMANDS: Channel<CriticalSectionRawMutex, Command, 5> = Channel::new();
pub static SENSOR_DATA: Channel<CriticalSectionRawMutex, SensorData, 5> = Channel::new();
pub static BUS_VOLTAGE: AtomicU16 = AtomicU16::new(u16::MAX);
const BUS_ADC_TO_VOLTS: f32 = 251.6763848397;
/// volts
fn bus_voltage() -> f32 {
BUS_VOLTAGE.load(Ordering::Acquire) as f32 / BUS_ADC_TO_VOLTS
}
#[link_section = ".start_block"]
#[used]
pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe();
#[embassy_executor::task]
async fn logger_task(driver: Driver<'static, USB>) {
embassy_usb_logger::run!(2048, log::LevelFilter::Trace, driver);
embassy_usb_logger::run!(1024, log::LevelFilter::Trace, driver);
}
#[panic_handler]
@ -57,7 +48,6 @@ async fn main(spawner: Spawner) {
let driver = Driver::new(p.USB, Irqs);
spawner.spawn(logger_task(driver)).unwrap();
info!("logger enabled");
let mut drive_conf: pwm::Config = Default::default();
drive_conf.divider = 150.into();
@ -67,33 +57,12 @@ async fn main(spawner: Spawner) {
let stopped = drive_conf.clone();
let mut drive_pwm = Pwm::new_output_ab(p.PWM_SLICE0, p.PIN_16, p.PIN_17, stopped.clone());
let disabled_orange = Vector3::new(254, 100, 0);
let enabled_green = Vector3::new(0, 140, 0);
let mut light_conf_rg: pwm::Config = Default::default();
light_conf_rg.divider = 1.into();
light_conf_rg.top = 255;
light_conf_rg.compare_b = 0;
light_conf_rg.compare_a = 0;
let mut light_pwm_rg = Pwm::new_output_ab(p.PWM_SLICE7, p.PIN_14, p.PIN_15, light_conf_rg);
let mut light_conf_b: pwm::Config = Default::default();
light_conf_b.divider = 1.into();
light_conf_b.top = 255;
light_conf_b.compare_b = 0;
let mut light_pwm_b = Pwm::new_output_b(p.PWM_SLICE6, p.PIN_13, light_conf_b);
set_underglow(&mut light_pwm_rg, &mut light_pwm_b, disabled_orange.clone());
Timer::after_secs(13).await; // pi 0 serial ports act strange during the boot process
spawner.spawn(bus_voltage_monitor(p.ADC, p.PIN_28, p.ADC_TEMP_SENSOR)).unwrap();
let config = embassy_rp::i2c::Config::default();
let bus = embassy_rp::i2c::I2c::new_async(p.I2C1, p.PIN_19, p.PIN_18, Irqs, config);
static TX_BUF: ConstStaticCell<[u8; 2048]> = ConstStaticCell::new([0u8;2048]);
static TX_BUF: ConstStaticCell<[u8; 1024]> = ConstStaticCell::new([0u8;1024]);
let tx_buf = TX_BUF.take();
static RX_BUF: ConstStaticCell<[u8; 2048]> = ConstStaticCell::new([0u8;2048]);
static RX_BUF: ConstStaticCell<[u8; 1024]> = ConstStaticCell::new([0u8;1024]);
let rx_buf = RX_BUF.take();
let mut uart_config = Config::default();
@ -104,41 +73,58 @@ async fn main(spawner: Spawner) {
spawner.spawn(decoder(rx)).unwrap();
spawner.spawn(telemetry(tx)).unwrap();
static STARTUP: OnceLock<()> = OnceLock::new();
let watchdog_time = Duration::from_millis(150);
static ENABLED: AtomicBool = AtomicBool::new(false);
spawner.spawn(telemetry(tx, &ENABLED, &STARTUP)).unwrap();
let enabled = &ENABLED;
let mut enable_watchdog = Instant::now();
let enable_watchdog_time = Duration::from_millis(150);
info!("ready");
let mut commands = COMMANDS.receiver().unwrap();
loop {
let motor_update = Timer::after_millis(3);
let (command, time) = commands.get().await;
if time.elapsed() > watchdog_time {
let command = if enabled.load(Ordering::Acquire) {
let Ok(command) = with_deadline(enable_watchdog + enable_watchdog_time, COMMANDS.receive()).await else {
warn!("no message received");
enabled.store(false, Ordering::Release);
continue;
};
command
} else {
// stop all motors
drive_pwm.set_config(&stopped);
set_underglow(&mut light_pwm_rg, &mut light_pwm_b, disabled_orange.clone());
commands.changed().await;
set_underglow(&mut light_pwm_rg, &mut light_pwm_b, enabled_green.clone());
continue;
}
info!("waiting for command");
COMMANDS.receive().await
};
STARTUP.get_or_init(||());
// 100% effort at 9.5v, 0% effort at 7.5v
let brownout = ((bus_voltage()-7.5)/2.0).clamp(0., 1.);
let command = command.clone().brownout(brownout);
match command {
Command::Twist(forward, right) => {
drive_conf.compare_a = calc_speed(-forward - right);
drive_conf.compare_b = calc_speed(forward - right);
drive_pwm.set_config(&drive_conf);
},
Command::Stop => {
drive_pwm.set_config(&stopped);
},
Command::Enable => {
enabled.store(true, Ordering::Release);
enable_watchdog = Instant::now();
},
Command::Disable => {
enabled.store(false, Ordering::Release);
drive_pwm.set_config(&stopped);
},
Command::FeedWatchdog => {
enable_watchdog = Instant::now();
}
c => { error!("{c:?} unimplemented") }
};
// drive motors
let (forward, right) = command.drive;
drive_conf.compare_a = calc_speed(-forward - right);
drive_conf.compare_b = calc_speed(forward - right);
drive_pwm.set_config(&drive_conf);
// underglow
set_underglow(&mut light_pwm_rg, &mut light_pwm_b, command.underglow);
motor_update.await;
info!("Blink");
}
}
@ -146,7 +132,6 @@ async fn main(spawner: Spawner) {
#[embassy_executor::task]
async fn decoder(mut rx: BufferedUartRx<'static, UART1>) {
info!("Reading...");
let sender = COMMANDS.sender();
loop {
let mut len = [0;4];
@ -154,31 +139,30 @@ async fn decoder(mut rx: BufferedUartRx<'static, UART1>) {
let len = u32::from_be_bytes(len) as usize;
let mut buf = [0;1024];
if let Err(e) = rx.read_exact(&mut buf[..len]).await {
trace!("read fail {e:?}");
};
rx.read_exact(&mut buf[..len]).await.unwrap();
let Ok(data) = postcard::from_bytes::<RobotState>(&buf[..len]) else {
let Ok(data) = postcard::from_bytes::<Command>(&buf[..len]) else {
error!("message decode fail");
continue;
};
trace!("received {data:?}");
sender.send((data, Instant::now()));
COMMANDS.send(data).await;
}
}
/// Receive data from channel and send it over UART
#[embassy_executor::task]
async fn telemetry(mut tx: BufferedUartTx<'static, UART1>) {
async fn telemetry(mut tx: BufferedUartTx<'static, UART1>, enabled: &'static AtomicBool, startup: &'static OnceLock<()>) {
info!("Telemetry waiting...");
COMMANDS.receiver().unwrap().get().await;
startup.get().await;
info!("Telemetry started...");
loop {
let data = with_timeout(Duration::from_millis(20), SENSOR_DATA.receive()).await.ok();
let packet = Response {
enabled: enabled.load(Ordering::Acquire),
sensor_data: data,
uptime_micros: Instant::now().as_micros(),
};
@ -191,9 +175,7 @@ async fn telemetry(mut tx: BufferedUartTx<'static, UART1>) {
if let Err(e) = tx.write_all(&serialized).await {
error!("transport error {e:?}");
}
if let Err(e) = tx.flush().await {
error!("flush err {e:?}");
}
tx.flush().await.unwrap();
}
}
@ -206,50 +188,3 @@ fn calc_speed(speed: f32) -> u16 {
(COUNTS_PER_MS * ms) as u16
}
#[embassy_executor::task]
async fn bus_voltage_monitor(adc: ADC, bus: PIN_28, temp: ADC_TEMP_SENSOR) {
let mut adc = Adc::new(adc, Irqs, adc::Config::default());
let mut bus_voltage = adc::Channel::new_pin(bus, Pull::None);
let mut ts = adc::Channel::new_temp_sensor(temp);
// from embassy examples
fn convert_to_celsius(raw_temp: u16) -> f32 {
let temp = 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721;
let sign = if temp < 0.0 { -1.0 } else { 1.0 };
let rounded_temp_x10: i16 = ((temp * 10.0) + 0.5 * sign) as i16;
(rounded_temp_x10 as f32) / 10.0
}
let mut i = 0;
loop {
i += 1;
let level = adc.read(&mut bus_voltage).await.unwrap();
BUS_VOLTAGE.store(level, Ordering::Release);
// empirically calculated against $20 microcenter voltmeter (10k & 33k divider circuit)
let temp = adc.read(&mut ts).await.unwrap();
if i % 10 == 0 { // only send telemetry every 30 milliseconds
SENSOR_DATA.send(SensorData::BusVoltage(level as f32 / BUS_ADC_TO_VOLTS)).await;
SENSOR_DATA.send(SensorData::AmbientTemperature(convert_to_celsius(temp))).await;
}
Timer::after_millis(3).await;
}
}
fn set_underglow(rg: &mut Pwm, b: &mut Pwm, color: Vector3<u8>) {
let mut light_conf_rg: pwm::Config = Default::default();
light_conf_rg.divider = 1.into();
light_conf_rg.top = 255;
light_conf_rg.compare_b = color[1] as u16;
light_conf_rg.compare_a = color[0] as u16;
rg.set_config(&light_conf_rg);
let mut light_conf_b: pwm::Config = Default::default();
light_conf_b.divider = 1.into();
light_conf_b.top = 255;
light_conf_b.compare_b = color[2] as u16;
b.set_config(&light_conf_b);
}