improved sensor canbus code
This commit is contained in:
1
Software/CAN_Sensor/Cargo.lock
generated
1
Software/CAN_Sensor/Cargo.lock
generated
@@ -66,6 +66,7 @@ dependencies = [
|
||||
"embedded-can",
|
||||
"heapless",
|
||||
"log",
|
||||
"nb 1.1.0",
|
||||
"panic-halt",
|
||||
"qingke",
|
||||
"qingke-rt",
|
||||
|
||||
@@ -28,6 +28,7 @@ embassy-usb = { version = "0.3.0" }
|
||||
embassy-futures = { version = "0.1.0" }
|
||||
embassy-sync = { version = "0.6.0" }
|
||||
embedded-can = "0.4.1"
|
||||
nb = "1.1"
|
||||
embedded-alloc = { version = "0.6.0", default-features = false, features = ["llff"] }
|
||||
|
||||
# This is okay because we should automatically use whatever ch32-hal uses
|
||||
|
||||
@@ -26,7 +26,6 @@ use {ch32_hal as hal, panic_halt as _};
|
||||
use embedded_alloc::LlffHeap as Heap;
|
||||
use embedded_can::nb::Can as nb_can;
|
||||
|
||||
|
||||
macro_rules! mk_static {
|
||||
($t:ty,$val:expr) => {{
|
||||
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
|
||||
@@ -61,9 +60,50 @@ async fn main(spawner: Spawner) {
|
||||
// Build driver and USB stack using 'static buffers
|
||||
let driver = Driver::new(p.USBD, Irqs, p.PA12, p.PA11);
|
||||
|
||||
|
||||
|
||||
let mut probe_gnd = Flex::new(p.PB1);
|
||||
probe_gnd.set_as_input(Pull::None);
|
||||
|
||||
|
||||
// Create GPIO for 555 Q output (PB0)
|
||||
let q_out = Output::new(p.PB0, Level::Low, Speed::Low);
|
||||
// Built-in LED on PB2 mirrors Q state
|
||||
let mut info = Output::new(p.PB2, Level::Low, Speed::Low);
|
||||
|
||||
// Read configuration switches on PB3..PB7 at startup with floating detection
|
||||
// PB3: Sensor A/B selector (Low=A, High=B)
|
||||
// PB4..PB7: address bits (1,2,4,8)
|
||||
let mut pb3 = Flex::new(p.PB3);
|
||||
let mut pb4 = Flex::new(p.PB4);
|
||||
let mut pb5 = Flex::new(p.PB5);
|
||||
let mut pb6 = Flex::new(p.PB6);
|
||||
let mut pb7 = Flex::new(p.PB7);
|
||||
|
||||
// Validate all config pins; if any is floating, stay in an error loop until fixed
|
||||
// Try read PB3..PB7
|
||||
let res_pb3 = detect_stable_pin(&mut pb3).await;
|
||||
let res_pb4 = detect_stable_pin(&mut pb4).await;
|
||||
let res_pb5 = detect_stable_pin(&mut pb5).await;
|
||||
let res_pb6 = detect_stable_pin(&mut pb6).await;
|
||||
let res_pb7 = detect_stable_pin(&mut pb7).await;
|
||||
|
||||
let slot = if res_pb3.unwrap_or(false) { SensorSlot::B } else { SensorSlot::A };
|
||||
let mut addr: u8 = 0;
|
||||
if res_pb4.unwrap_or(false) { addr |= 1; }
|
||||
if res_pb5.unwrap_or(false) { addr |= 2; }
|
||||
if res_pb6.unwrap_or(false) { addr |= 4; }
|
||||
if res_pb7.unwrap_or(false) { addr |= 8; }
|
||||
let moisture_id = plant_id(MOISTURE_DATA_OFFSET, slot, addr as u16);
|
||||
let identify_id = plant_id(IDENTIFY_CMD_OFFSET, slot, addr as u16);
|
||||
|
||||
let invalid_config = res_pb3.is_none() || res_pb4.is_none() || res_pb5.is_none() || res_pb6.is_none() || res_pb7.is_none();
|
||||
|
||||
let mut config = embassy_usb::Config::new(0xC0DE, 0xCAFE);
|
||||
config.manufacturer = Some("Embassy");
|
||||
config.product = Some("USB-serial example");
|
||||
config.manufacturer = Some("Can Sensor v0.2");
|
||||
let msg = mk_static!(heapless::String<128>, heapless::String::new());;
|
||||
let _ = core::fmt::Write::write_fmt(msg, format_args!("Sensor {:?} plant {}", slot, addr));
|
||||
config.product = Some(msg.as_str());
|
||||
config.serial_number = Some("12345678");
|
||||
config.max_power = 100;
|
||||
config.max_packet_size_0 = 64;
|
||||
@@ -91,29 +131,9 @@ async fn main(spawner: Spawner) {
|
||||
// Build USB device
|
||||
let usb = mk_static!(UsbDevice<Driver<USBD>>, builder.build());
|
||||
|
||||
// Create GPIO for 555 Q output (PB0)
|
||||
let q_out = Output::new(p.PB0, Level::Low, Speed::Low);
|
||||
// Built-in LED on PB2 mirrors Q state
|
||||
let mut info = Output::new(p.PB2, Level::Low, Speed::Low);
|
||||
|
||||
// Read configuration switches on PB3..PB7 at startup with floating detection
|
||||
// PB3: Sensor A/B selector (Low=A, High=B)
|
||||
// PB4..PB7: address bits (1,2,4,8)
|
||||
let mut pb3 = Flex::new(p.PB3);
|
||||
let mut pb4 = Flex::new(p.PB4);
|
||||
let mut pb5 = Flex::new(p.PB5);
|
||||
let mut pb6 = Flex::new(p.PB6);
|
||||
let mut pb7 = Flex::new(p.PB7);
|
||||
|
||||
// Validate all config pins; if any is floating, stay in an error loop until fixed
|
||||
// Try read PB3..PB7
|
||||
let res_pb3 = detect_stable_pin(&mut pb3).await;
|
||||
let res_pb4 = detect_stable_pin(&mut pb4).await;
|
||||
let res_pb5 = detect_stable_pin(&mut pb5).await;
|
||||
let res_pb6 = detect_stable_pin(&mut pb6).await;
|
||||
let res_pb7 = detect_stable_pin(&mut pb7).await;
|
||||
|
||||
if res_pb3.is_none() || res_pb4.is_none() || res_pb5.is_none() || res_pb6.is_none() || res_pb7.is_none() {
|
||||
if invalid_config {
|
||||
// At least one floating: report and blink code for the first one found.
|
||||
let mut msg: heapless::String<128> = heapless::String::new();
|
||||
let code = if res_pb4.is_none() { 1 } else if res_pb5.is_none() { 2 } else if res_pb6.is_none() { 3 } else if res_pb7.is_none() { 4 } else { 5 }; // PB3 -> 5
|
||||
@@ -122,16 +142,10 @@ async fn main(spawner: Spawner) {
|
||||
log(msg);
|
||||
blink_error(&mut info, code).await;
|
||||
};
|
||||
let slot = if res_pb3.unwrap() { SensorSlot::B } else { SensorSlot::A };
|
||||
let mut addr: u8 = 0;
|
||||
if res_pb4.unwrap() { addr |= 1; }
|
||||
if res_pb5.unwrap() { addr |= 2; }
|
||||
if res_pb6.unwrap() { addr |= 4; }
|
||||
if res_pb7.unwrap() { addr |= 8; }
|
||||
|
||||
|
||||
// Log startup configuration and derived CAN IDs
|
||||
let moisture_id = plant_id(MOISTURE_DATA_OFFSET, slot, addr as u16);
|
||||
let identify_id = plant_id(IDENTIFY_CMD_OFFSET, slot, addr as u16);
|
||||
|
||||
{
|
||||
let mut msg: heapless::String<128> = heapless::String::new();
|
||||
let slot_chr = match slot { SensorSlot::A => 'a', SensorSlot::B => 'b' };
|
||||
@@ -161,7 +175,7 @@ async fn main(spawner: Spawner) {
|
||||
spawner.spawn(usb_task(usb)).unwrap();
|
||||
spawner.spawn(usb_writer(class)).unwrap();
|
||||
// move Q output, LED, ADC and analog input into worker task
|
||||
spawner.spawn(worker(q_out, info, adc, ain, can, StandardId::new(moisture_id).unwrap(), StandardId::new(identify_id).unwrap())).unwrap();
|
||||
spawner.spawn(worker(probe_gnd, q_out, info, adc, ain, can, StandardId::new(moisture_id).unwrap(), StandardId::new(identify_id).unwrap())).unwrap();
|
||||
|
||||
// Prevent main from exiting
|
||||
core::future::pending::<()>().await;
|
||||
@@ -195,6 +209,7 @@ async fn blink_error(mut info_led: &mut Output<'static>, code: u8) -> !{
|
||||
|
||||
#[task]
|
||||
async fn worker(
|
||||
mut probe_gnd: Flex<'static>,
|
||||
mut q: Output<'static>,
|
||||
mut info: Output<'static>,
|
||||
mut adc: Adc<'static, hal::peripherals::ADC1>,
|
||||
@@ -215,8 +230,8 @@ async fn worker(
|
||||
.unwrap()
|
||||
.set(identify_id.into(), Default::default());
|
||||
|
||||
can.add_filter(filter);
|
||||
//can.add_filter(CanFilter::accept_all());
|
||||
//can.add_filter(filter);
|
||||
can.add_filter(CanFilter::accept_all());
|
||||
|
||||
loop {
|
||||
// Count rising edges of Q in a 100 ms window
|
||||
@@ -224,6 +239,8 @@ async fn worker(
|
||||
let mut pulses: u32 = 0;
|
||||
let mut last_q = q_high;
|
||||
|
||||
probe_gnd.set_as_output(Speed::Low);
|
||||
probe_gnd.set_low();
|
||||
while Instant::now()
|
||||
.checked_duration_since(start)
|
||||
.unwrap_or(Duration::from_millis(0))
|
||||
@@ -258,6 +275,7 @@ async fn worker(
|
||||
// Yield to allow USB and other tasks to run
|
||||
yield_now().await;
|
||||
}
|
||||
probe_gnd.set_as_input(Pull::None);
|
||||
|
||||
// Compute frequency from 100 ms window
|
||||
let freq_hz = pulses; // pulses per 0.1s => Hz
|
||||
@@ -270,7 +288,7 @@ async fn worker(
|
||||
);
|
||||
log(msg);
|
||||
|
||||
let mut moisture = CanFrame::new(moisture_id, &[freq_hz as u8]).unwrap();
|
||||
let mut moisture = CanFrame::new(moisture_id, &(freq_hz as u16).to_be_bytes()).unwrap();
|
||||
match can.transmit(&mut moisture) {
|
||||
Ok(..) => {
|
||||
let mut msg: heapless::String<128> = heapless::String::new();
|
||||
@@ -278,6 +296,12 @@ async fn worker(
|
||||
log(msg);
|
||||
}
|
||||
Err(err) => {
|
||||
for _ in 0..3 {
|
||||
info.set_high();
|
||||
Timer::after_millis(100).await;
|
||||
info.set_low();
|
||||
Timer::after_millis(100).await;
|
||||
}
|
||||
let mut msg: heapless::String<128> = heapless::String::new();
|
||||
let _ = write!(&mut msg, "err {:?}", err);
|
||||
log(msg);
|
||||
@@ -285,6 +309,15 @@ async fn worker(
|
||||
}
|
||||
|
||||
loop {
|
||||
let mut msg: heapless::String<128> = heapless::String::new();
|
||||
let _ = write!(
|
||||
&mut msg,
|
||||
"Check identity addr received: {:#x} \r\n",
|
||||
identify_id.as_raw()
|
||||
);
|
||||
log(msg);
|
||||
|
||||
|
||||
yield_now().await;
|
||||
match can.receive() {
|
||||
Ok(frame) => match frame.id() {
|
||||
@@ -307,7 +340,8 @@ async fn worker(
|
||||
}
|
||||
Id::Extended(_) => {}
|
||||
},
|
||||
_ => {
|
||||
|
||||
Err(err) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user