Skip to content
Snippets Groups Projects
Commit e118b151 authored by Benjamin Koch's avatar Benjamin Koch
Browse files

start adding ADC

parent 93554290
No related branches found
No related tags found
No related merge requests found
......@@ -2,10 +2,13 @@
#![no_main]
#![feature(type_alias_impl_trait)]
use core::sync::atomic::{AtomicU16, AtomicU32, Ordering};
use defmt::*;
use embassy_executor::Spawner;
//use embassy_futures::join::join;
use embassy_futures::select::*;
use embassy_rp::adc::{self, Adc};
use embassy_rp::peripherals::*;
use embassy_time::{Duration, Timer};
use embassy_rp::gpio::{Input, Level, Output, Pull, Flex};
......@@ -76,6 +79,46 @@ async fn uart_task(this: RS485<ModbusServer<ModBusRegs<'static>>>) {
this.run_task().await;
}
struct AdcData {
current1: AtomicU16,
current2: AtomicU16,
analog_in1_raw: AtomicU16,
analog_in1_millivolt: AtomicU16,
vcc: AtomicU16,
}
fn convert_to_celsius(raw_temp: u16) -> f32 {
// According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet
27.0 - (raw_temp as f32 * 3.0522 / 4096.0 - 0.706) / 0.001721 as f32
}
#[embassy_executor::task]
async fn adc_task(shared_data: &'static AdcData, adc: ADC, en_measure_current: Output<'static, PIN_3>,
mut analog_in1: PIN_26, mut current2: PIN_27, mut current1: PIN_28, mut measure_vcc: PIN_29) {
let irq = interrupt::take!(ADC_IRQ_FIFO);
let mut adc = Adc::new(adc, irq, adc::Config::default());
loop {
let level = adc.read(&mut analog_in1).await;
shared_data.analog_in1_raw.store(level, Ordering::Release);
let value = 3.05*level as f32/4096. * (10.+2.*5.1)/5.1;
shared_data.analog_in1_millivolt.store((value * 1000.) as u16, Ordering::Release);
info!("ADC analog_in1: {} -> {}", level, value);
let level = adc.read(&mut current2).await;
info!("ADC current2: {}", level);
let level = adc.read(&mut current1).await;
info!("ADC current1: {}", level);
let level = adc.read(&mut measure_vcc).await;
let vcc = 3.05 * level as f32 / 4096. * (100. + 10.)/10.;
info!("ADC measure_vcc: {} -> {}", level, vcc);
let temp = adc.read_temperature().await;
info!("Temp: {} -> {} degrees", temp, convert_to_celsius(temp));
Timer::after(Duration::from_secs(1)).await;
}
}
struct ModBusRegs<'a> {
led_g: Output<'a, PIN_5>,
button_boot2: Input<'a, PIN_11>,
......@@ -83,6 +126,7 @@ struct ModBusRegs<'a> {
reed4: Input<'a, PIN_20>,
reed2: Input<'a, PIN_21>,
reed1: Input<'a, PIN_22>,
adc_data: &'a AdcData,
}
impl<'a> ModbusRegisters for ModBusRegs<'a> {
......@@ -105,10 +149,12 @@ impl<'a> ModbusRegisters for ModBusRegs<'a> {
}
fn read_input_register(self: &mut Self, addr: u16) -> Result<u16, ModbusErrorCode> {
if addr == 2 {
return Ok(42)
match addr {
0 => Ok(42),
1 => Ok(self.adc_data.analog_in1_raw.load(Ordering::Relaxed)),
2 => Ok(self.adc_data.analog_in1_millivolt.load(Ordering::Relaxed)),
_ => Err(ModbusErrorCode::IllegalDataAddress)
}
Err(ModbusErrorCode::IllegalDataAddress)
}
fn write_coil(self: &mut Self, addr: u16, value: bool) -> Result<(), ModbusErrorCode> {
......@@ -134,7 +180,7 @@ async fn main(spawner: Spawner) {
//let LED_W = p.PIN_2;
let _ws2812_display = p.PIN_2;
//let LED_Y = p.PIN_3;
let mut _en_measure_current = Output::new(p.PIN_3, Level::Low);
let en_measure_current = Output::new(p.PIN_3, Level::Low);
let mut led_b = Output::new(p.PIN_4, Level::Low);
let led_g = Output::new(p.PIN_5, Level::Low);
let led_r = p.PIN_6;
......@@ -157,16 +203,22 @@ async fn main(spawner: Spawner) {
let _matrix_in3 = Input::new(p.PIN_23, Pull::Up);
let _digout1 = p.PIN_24;
let _digout2 = p.PIN_25;
let _analog_in1 = p.PIN_26;
let _current2 = p.PIN_27;
let _current1 = p.PIN_28;
let _measure_vcc = p.PIN_29;
let analog_in1 = p.PIN_26;
let current2 = p.PIN_27;
let current1 = p.PIN_28;
let measure_vcc = p.PIN_29;
let i2c_irq = interrupt::take!(I2C0_IRQ);
let mut i2c_config = i2c::Config::default();
i2c_config.frequency = 400_000;
unwrap!(spawner.spawn(i2c_task(p.I2C0, scl, sda, i2c_irq, i2c_config)));
static ADC_DATA: AdcData = AdcData {
current1: AtomicU16::new(0), current2: AtomicU16::new(0), analog_in1_raw: AtomicU16::new(0),
analog_in1_millivolt: AtomicU16::new(0), vcc: AtomicU16::new(0)
};
unwrap!(spawner.spawn(adc_task(&ADC_DATA, p.ADC, en_measure_current, analog_in1, current2, current1, measure_vcc)));
// use 19200 baud in 8E1 mode - not great but it's the Modbus default
let mut uart_config = uart::Config::default();
uart_config.baudrate = 19200;
......@@ -178,6 +230,7 @@ async fn main(spawner: Spawner) {
led_g,
button_boot2,
reed1, reed2, reed3, reed4,
adc_data: &ADC_DATA,
}),
);
unwrap!(spawner.spawn(uart_task(rs485)));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment