return ultrasonic data
This commit is contained in:
parent
cc255b77ab
commit
6df844a410
3 changed files with 101 additions and 10 deletions
|
@ -4,6 +4,14 @@ use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Default, Clone)]
|
#[derive(Serialize, Deserialize, Default, Clone)]
|
||||||
pub struct Command {
|
pub struct Command {
|
||||||
|
/// duty cycle, -1.0 - 1.0
|
||||||
pub left: f32,
|
pub left: f32,
|
||||||
|
/// duty cycle, -1.0 - 1.0
|
||||||
pub right: f32,
|
pub right: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, Clone)]
|
||||||
|
pub struct Telemetry {
|
||||||
|
/// inches, front ultrasonic sensor
|
||||||
|
pub distance: f32,
|
||||||
|
}
|
||||||
|
|
|
@ -1,35 +1,52 @@
|
||||||
use std::{io::{BufRead, BufReader}, net::TcpListener, sync::{Arc, Mutex}, thread::sleep, time::Duration};
|
use std::{f32::NAN, io::{BufRead, BufReader, BufWriter, Read, Write}, net::TcpListener, sync::{Arc, Mutex}, thread::sleep, time::Duration};
|
||||||
|
|
||||||
use common::Command;
|
use common::{Command, Telemetry};
|
||||||
use postcard::to_vec_cobs;
|
use postcard::to_vec_cobs;
|
||||||
use heapless::Vec;
|
use heapless::Vec;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut port = serialport::new("/dev/ttyACM0", 115200)
|
let mut port = serialport::new("/dev/ttyACM0", 115200)
|
||||||
|
.timeout(Duration::from_secs(1))
|
||||||
.open().expect("port missing");
|
.open().expect("port missing");
|
||||||
println!("port open");
|
println!("connected over serial");
|
||||||
|
|
||||||
let command: Arc<Mutex<Command>> = Arc::new(Mutex::new(Command { left: 0.0, right: 0.0}));
|
let command: Arc<Mutex<Command>> = Arc::new(Mutex::new(Command { left: 0.0, right: 0.0}));
|
||||||
|
let telemetry: Arc<Mutex<Telemetry>> = Arc::new(Mutex::new(Telemetry { distance: f32::NAN }));
|
||||||
|
|
||||||
{
|
{
|
||||||
let command = command.clone();
|
let command = command.clone();
|
||||||
std::thread::spawn(move || server(command));
|
let telemetry = telemetry.clone();
|
||||||
|
std::thread::spawn(move || server(command,telemetry));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let reader = port.try_clone().unwrap();
|
||||||
|
|
||||||
|
let mut reader = BufReader::new(reader);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let command = command.lock().unwrap().clone();
|
let command = command.lock().unwrap().clone();
|
||||||
let encoded: Vec<u8, 20> = to_vec_cobs(&command).unwrap();
|
let encoded: Vec<u8, 20> = to_vec_cobs(&command).unwrap();
|
||||||
port.write(&encoded).expect("port write fail");
|
port.write(&encoded).expect("port write fail");
|
||||||
println!("sending");
|
println!("sending");
|
||||||
|
|
||||||
|
let mut recv_buf = std::vec::Vec::new();
|
||||||
|
let Ok(len) = reader.read_until(0, &mut recv_buf) else {continue;};
|
||||||
|
if let Ok(telem) = postcard::from_bytes_cobs::<Telemetry>(&mut recv_buf[0..len]) {
|
||||||
|
println!("dist: {}", telem.distance);
|
||||||
|
*telemetry.lock().unwrap() = telem;
|
||||||
|
}
|
||||||
|
|
||||||
sleep(Duration::from_millis(200));
|
sleep(Duration::from_millis(200));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn server(command: Arc<Mutex<Command>>) {
|
fn server(command: Arc<Mutex<Command>>, telemetry: Arc<Mutex<Telemetry>>) {
|
||||||
let listener = TcpListener::bind("0.0.0.0:4242").unwrap();
|
let listener = TcpListener::bind("0.0.0.0:4242").unwrap();
|
||||||
|
|
||||||
while let Ok((stream, _)) = listener.accept() {
|
while let Ok((stream, _)) = listener.accept() {
|
||||||
|
println!("connected over IP");
|
||||||
|
let writer = stream.try_clone().unwrap();
|
||||||
|
let mut writer = BufWriter::new(writer);
|
||||||
let mut reader = BufReader::new(stream);
|
let mut reader = BufReader::new(stream);
|
||||||
|
|
||||||
let mut data_buf = std::vec::Vec::new();
|
let mut data_buf = std::vec::Vec::new();
|
||||||
|
@ -40,6 +57,14 @@ fn server(command: Arc<Mutex<Command>>) {
|
||||||
*command.lock().unwrap() = new_command;
|
*command.lock().unwrap() = new_command;
|
||||||
println!("received");
|
println!("received");
|
||||||
|
|
||||||
|
let telem = telemetry.lock().unwrap().clone();
|
||||||
|
|
||||||
|
if telem.distance == f32::NAN {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
serde_json::to_writer(&mut writer, &telem).unwrap();
|
||||||
|
writer.write(&[b'\n']).unwrap();
|
||||||
|
writer.flush().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#![feature(abi_avr_interrupt)]
|
#![feature(abi_avr_interrupt)]
|
||||||
|
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
|
use core::f32;
|
||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
use arduino_hal::{clock::MHz16, hal::usart::UsartWriter};
|
use arduino_hal::{clock::MHz16, hal::usart::UsartWriter};
|
||||||
|
@ -12,7 +13,7 @@ use arduino_hal::pac::USART0;
|
||||||
use arduino_hal::port::mode::*;
|
use arduino_hal::port::mode::*;
|
||||||
use arduino_hal::prelude::*;
|
use arduino_hal::prelude::*;
|
||||||
use avr_device::interrupt::{self, Mutex};
|
use avr_device::interrupt::{self, Mutex};
|
||||||
use common::Command;
|
use common::{Command, Telemetry};
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
fn shift_out(data_pin: &mut Pin<Output, PB0>, clock_pin: &mut Pin<Output, PD4>, data: &u8) {
|
fn shift_out(data_pin: &mut Pin<Output, PB0>, clock_pin: &mut Pin<Output, PD4>, data: &u8) {
|
||||||
|
@ -43,7 +44,6 @@ fn update_shift_register(
|
||||||
latch_pin.set_high();
|
latch_pin.set_high();
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut UART_TX: MaybeUninit<UsartWriter<USART0, Pin<Input, PD0>, Pin<Output, PD1>, MHz16>> = MaybeUninit::uninit();
|
|
||||||
static mut UART_RX: MaybeUninit<UsartReader<USART0, Pin<Input, PD0>, Pin<Output, PD1>, MHz16>> = MaybeUninit::uninit();
|
static mut UART_RX: MaybeUninit<UsartReader<USART0, Pin<Input, PD0>, Pin<Output, PD1>, MHz16>> = MaybeUninit::uninit();
|
||||||
|
|
||||||
static INPUT_LINE: Mutex<RefCell<[u8; 20]>> = Mutex::new(RefCell::new([0;20]));
|
static INPUT_LINE: Mutex<RefCell<[u8; 20]>> = Mutex::new(RefCell::new([0;20]));
|
||||||
|
@ -51,7 +51,6 @@ static INPUT_LINE: Mutex<RefCell<[u8; 20]>> = Mutex::new(RefCell::new([0;20]));
|
||||||
#[avr_device::interrupt(atmega328p)]
|
#[avr_device::interrupt(atmega328p)]
|
||||||
unsafe fn USART_RX() {
|
unsafe fn USART_RX() {
|
||||||
let rx = &mut *UART_RX.as_mut_ptr();
|
let rx = &mut *UART_RX.as_mut_ptr();
|
||||||
let tx = &mut *UART_TX.as_mut_ptr();
|
|
||||||
|
|
||||||
static mut BUF: [u8; 20] = [0;20];
|
static mut BUF: [u8; 20] = [0;20];
|
||||||
static mut N: usize = 0; // index into line
|
static mut N: usize = 0; // index into line
|
||||||
|
@ -106,6 +105,13 @@ fn main() -> ! {
|
||||||
tc2.ocr2a.write(|w| w.bits(0));
|
tc2.ocr2a.write(|w| w.bits(0));
|
||||||
tc2.ocr2b.write(|w| w.bits(0));
|
tc2.ocr2b.write(|w| w.bits(0));
|
||||||
|
|
||||||
|
let mut trig = pins.a4.into_output();
|
||||||
|
let echo = pins.a5;
|
||||||
|
|
||||||
|
let ultrasonic_timer = dp.TC1;
|
||||||
|
// 4us per tick
|
||||||
|
ultrasonic_timer.tccr1b.write(|w| w.cs1().prescale_64());
|
||||||
|
|
||||||
let mut led = pins.d13.into_output();
|
let mut led = pins.d13.into_output();
|
||||||
|
|
||||||
let mut serial = arduino_hal::default_serial!(dp, pins, 115200);
|
let mut serial = arduino_hal::default_serial!(dp, pins, 115200);
|
||||||
|
@ -117,10 +123,11 @@ fn main() -> ! {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
UART_RX = MaybeUninit::new(rx);
|
UART_RX = MaybeUninit::new(rx);
|
||||||
UART_TX = MaybeUninit::new(tx);
|
|
||||||
avr_device::interrupt::enable();
|
avr_device::interrupt::enable();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut telem = Telemetry { distance: f32::NAN };
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut shift_register = 0;
|
let mut shift_register = 0;
|
||||||
const LEFT_FWD: u8 = 1 << 5; // 1a
|
const LEFT_FWD: u8 = 1 << 5; // 1a
|
||||||
|
@ -156,7 +163,58 @@ fn main() -> ! {
|
||||||
|
|
||||||
update_shift_register(&mut data_pin, &mut latch_pin, &mut clock_pin, &shift_register);
|
update_shift_register(&mut data_pin, &mut latch_pin, &mut clock_pin, &shift_register);
|
||||||
|
|
||||||
arduino_hal::delay_ms(1000);
|
// reset timer
|
||||||
|
ultrasonic_timer.tcnt1.write(|w| w.bits(0));
|
||||||
|
|
||||||
|
// send ultrasonic pulse
|
||||||
|
trig.set_high();
|
||||||
|
arduino_hal::delay_us(10);
|
||||||
|
trig.set_low();
|
||||||
|
|
||||||
|
let mut response = true;
|
||||||
|
|
||||||
|
/// 0.1s/4µs = 25,000
|
||||||
|
const SIGNAL_START_TIMEOUT: u16 = 25000;
|
||||||
|
|
||||||
|
// wait for return signal start
|
||||||
|
while echo.is_low() {
|
||||||
|
if ultrasonic_timer.tcnt1.read().bits() >= SIGNAL_START_TIMEOUT {
|
||||||
|
response = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if response {
|
||||||
|
let remainder = ultrasonic_timer.tcnt1.read().bits();
|
||||||
|
ultrasonic_timer.tcnt1.write(|w| w.bits(0));
|
||||||
|
|
||||||
|
// Wait for the echo to get low again
|
||||||
|
while echo.is_high() {}
|
||||||
|
let counts = ultrasonic_timer.tcnt1.read().bits();
|
||||||
|
let microseconds = counts.saturating_mul(4);
|
||||||
|
|
||||||
|
// inch per 148 microseconds
|
||||||
|
telem.distance = microseconds as f32 / 148.;
|
||||||
|
if microseconds == u16::MAX { telem.distance = f32::NAN };
|
||||||
|
|
||||||
|
// delay for the rest of the return signal timeout if any is left
|
||||||
|
ultrasonic_timer.tcnt1.write(|w| w.bits(SIGNAL_START_TIMEOUT.saturating_sub(remainder + counts)));
|
||||||
|
while ultrasonic_timer.tcnt1.read().bits() <= SIGNAL_START_TIMEOUT {}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
telem.distance = f32::NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buf = [0;20];
|
||||||
|
let encoded = postcard::to_slice_cobs(&telem, &mut buf).unwrap();
|
||||||
|
|
||||||
|
for word in encoded {
|
||||||
|
let _ = tx.write(*word);
|
||||||
|
let _ = tx.flush();
|
||||||
|
arduino_hal::delay_us(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
arduino_hal::delay_ms(250);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue