basic working esp

This commit is contained in:
Daniel Bulant 2026-05-12 14:10:04 +02:00
parent 0475ee343a
commit b5f26fb362
No known key found for this signature in database
5 changed files with 194 additions and 78 deletions

View file

@ -46,7 +46,7 @@ async fn main(_spawner: Spawner) -> ! {
loop { loop {
println!("Scan"); println!("Scan");
let scan_config = ScanConfig::default().with_max(10); let scan_config = ScanConfig::default().with_max(20);
let result = controller.scan_async(&scan_config).await.unwrap(); let result = controller.scan_async(&scan_config).await.unwrap();
for ap in result { for ap in result {
println!("{:?}", ap); println!("{:?}", ap);

View file

@ -3,7 +3,7 @@ use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channe
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use esp_hal::gpio::Input; use esp_hal::gpio::Input;
use esp_hal::i2c::master::{Config, I2c}; use esp_hal::i2c::master::{Config, I2c};
use esp_hal::peripherals::{GPIO4, GPIO5, I2C0}; use esp_hal::peripherals::{GPIO21, GPIO22, I2C0};
use esp_hal::time::Rate; use esp_hal::time::Rate;
use esp_println::println; use esp_println::println;
@ -15,17 +15,20 @@ pub static ANGLE: Mutex<CriticalSectionRawMutex, u16> = Mutex::new(0);
pub struct RotationConfig { pub struct RotationConfig {
pub i2c0: I2C0<'static>, pub i2c0: I2C0<'static>,
pub scl: GPIO5<'static>, pub scl: GPIO22<'static>,
pub sda: GPIO4<'static>, pub sda: GPIO21<'static>,
} }
#[embassy_executor::task] #[embassy_executor::task]
pub async fn rotation_read_task(config: RotationConfig) { pub async fn rotation_read_task(config: RotationConfig) {
let i2c = I2c::new(config.i2c0, Config::default().with_frequency(Rate::from_khz(400))) let i2c = I2c::new(
.unwrap() config.i2c0,
.with_sda(config.sda) Config::default().with_frequency(Rate::from_khz(400)),
.with_scl(config.scl) )
.into_async(); .unwrap()
.with_sda(config.sda)
.with_scl(config.scl)
.into_async();
let mut as5600 = As5600::new(i2c); let mut as5600 = As5600::new(i2c);
loop { loop {
@ -43,14 +46,7 @@ pub async fn rotation_read_task(config: RotationConfig) {
let mut value = wheel.value; let mut value = wheel.value;
let mut accumulated = wheel.accumulated; let mut accumulated = wheel.accumulated;
let precision = crate::WHEEL_PRECISION; let precision = crate::WHEEL_PRECISION;
apply_wheel_delta( apply_wheel_delta(&mut value, min, max, &mut accumulated, diff, precision);
&mut value,
min,
max,
&mut accumulated,
diff,
precision,
);
wheel.value = value; wheel.value = value;
wheel.accumulated = accumulated; wheel.accumulated = accumulated;
} }

View file

@ -8,10 +8,13 @@ use embassy_net::tcp::{TcpReader, TcpWriter};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::mutex::Mutex; use embassy_sync::mutex::Mutex;
use embassy_sync::signal::Signal; use embassy_sync::signal::Signal;
use embassy_time::Timer;
use embedded_io::Write; use embedded_io::Write;
use esp_backtrace as _; use esp_backtrace as _;
use esp_hal::{ use esp_hal::{
gpio::{Input, InputConfig as GpioInputConfig, Pin, Pull}, gpio::{Input, InputConfig as GpioInputConfig, Pin, Pull},
interrupt::software::SoftwareInterruptControl,
timer::timg::TimerGroup,
}; };
use esp_println::println; use esp_println::println;
use owned_str::OwnedStr; use owned_str::OwnedStr;
@ -62,7 +65,8 @@ static WHEEL_VALUE: Mutex<CriticalSectionRawMutex, WheelData> = Mutex::new(Wheel
}); });
#[panic_handler] #[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! { fn panic(info: &core::panic::PanicInfo) -> ! {
println!("PANIC! {:?}", info);
loop {} loop {}
} }
@ -109,7 +113,10 @@ pub async fn tcp_read_loop(mut read: TcpReader<'_>) {
if key == "rangeMin" || key == "rangeMax" { if key == "rangeMin" || key == "rangeMax" {
match q_type { match q_type {
QuestionType::Choice => {} QuestionType::Choice => {}
QuestionType::Numeric { ref mut min, ref mut max } => { QuestionType::Numeric {
ref mut min,
ref mut max,
} => {
if key == "rangeMin" { if key == "rangeMin" {
*min = value.parse().unwrap(); *min = value.parse().unwrap();
future_wheel.min = *min; future_wheel.min = *min;
@ -221,42 +228,98 @@ pub async fn main_loop() {
} }
} }
esp_bootloader_esp_idf::esp_app_desc!();
#[esp_rtos::main] #[esp_rtos::main]
async fn main(spawner: Spawner) -> ! { async fn main(spawner: Spawner) -> ! {
let p = esp_hal::init(esp_hal::Config::default().with_cpu_clock(esp_hal::clock::CpuClock::max())); let p =
esp_hal::init(esp_hal::Config::default().with_cpu_clock(esp_hal::clock::CpuClock::max()));
println!("Booting");
let timg0 = TimerGroup::new(p.TIMG0);
let sw_int = SoftwareInterruptControl::new(p.SW_INTERRUPT);
esp_rtos::start(timg0.timer0, sw_int.software_interrupt0);
esp_alloc::heap_allocator!(size: 64 * 1024); esp_alloc::heap_allocator!(size: 64 * 1024);
let lcd = screen::LcdPins { let lcd = screen::LcdPins {
rs: p.GPIO10, rs: p.GPIO4,
e: p.GPIO11, e: p.GPIO16,
d4: p.GPIO12, d4: p.GPIO17,
d5: p.GPIO13, d5: p.GPIO18,
d6: p.GPIO14, d6: p.GPIO19,
d7: p.GPIO15, d7: p.GPIO23,
}; };
spawner.spawn(screen::lcd_display_task(screen::LcdConfig { pins: lcd }).expect("spawn lcd")); spawner.spawn(screen::lcd_display_task(screen::LcdConfig { pins: lcd }).expect("spawn lcd"));
spawner.spawn(input::rotation_read_task(input::RotationConfig { spawner.spawn(
i2c0: p.I2C0, input::rotation_read_task(input::RotationConfig {
scl: p.GPIO5, i2c0: p.I2C0,
sda: p.GPIO4, scl: p.GPIO22,
}).expect("spawn rotation")); sda: p.GPIO21,
})
.expect("spawn rotation"),
);
spawner.spawn(input::button_task(Input::new(p.GPIO18.degrade(), GpioInputConfig::default().with_pull(Pull::Up)), 1).expect("spawn btn1")); spawner.spawn(
spawner.spawn(input::button_task(Input::new(p.GPIO19.degrade(), GpioInputConfig::default().with_pull(Pull::Up)), 2).expect("spawn btn2")); input::button_task(
spawner.spawn(input::button_task(Input::new(p.GPIO20.degrade(), GpioInputConfig::default().with_pull(Pull::Up)), 3).expect("spawn btn3")); Input::new(
spawner.spawn(input::button_task(Input::new(p.GPIO21.degrade(), GpioInputConfig::default().with_pull(Pull::Up)), 4).expect("spawn btn4")); p.GPIO26.degrade(),
GpioInputConfig::default().with_pull(Pull::Up),
),
1,
)
.expect("spawn btn1"),
);
spawner.spawn(
input::button_task(
Input::new(
p.GPIO25.degrade(),
GpioInputConfig::default().with_pull(Pull::Up),
),
2,
)
.expect("spawn btn2"),
);
spawner.spawn(
input::button_task(
Input::new(
p.GPIO33.degrade(),
GpioInputConfig::default().with_pull(Pull::Up),
),
3,
)
.expect("spawn btn3"),
);
spawner.spawn(
input::button_task(
Input::new(
p.GPIO32.degrade(),
GpioInputConfig::default().with_pull(Pull::Up),
),
4,
)
.expect("spawn btn4"),
);
spawner.spawn(net::network_setup_task(spawner, net::NetworkConfig { spawner.spawn(
wifi: p.WIFI, net::network_setup_task(
wifi_network: WIFI_NETWORK, spawner,
wifi_password: WIFI_PASSWORD, net::NetworkConfig {
target_ip: TARGET_IP, wifi: p.WIFI,
target_port: TARGET_PORT, wifi_network: WIFI_NETWORK,
}).expect("spawn net")); wifi_password: WIFI_PASSWORD,
target_ip: TARGET_IP,
target_port: TARGET_PORT,
},
)
.expect("spawn net"),
);
println!("Init done");
loop { loop {
embassy_time::Timer::after_millis(1000).await; Timer::after_millis(1000).await;
// println!("Looping");
} }
} }

View file

@ -3,13 +3,14 @@ use core::str::FromStr;
use embassy_futures::join::join; use embassy_futures::join::join;
use embassy_net::tcp::TcpSocket; use embassy_net::tcp::TcpSocket;
use embassy_time::Duration; use embassy_time::{Duration, Timer};
use esp_hal::peripherals::WIFI; use esp_hal::peripherals::WIFI;
use esp_hal::rng::Rng; use esp_hal::rng::Rng;
use esp_println::println; use esp_println::println;
use esp_radio::wifi::{scan::ScanConfig, Config, ControllerConfig};
use esp_radio::wifi::sta::StationConfig; use esp_radio::wifi::sta::StationConfig;
use esp_radio::wifi::{Config, ControllerConfig, scan::ScanConfig};
use crate::{WIFI_NETWORK, WIFI_PASSWORD};
use crate::{buffer::wait_for_config, tcp_read_loop, tcp_write_loop}; use crate::{buffer::wait_for_config, tcp_read_loop, tcp_write_loop};
pub struct NetworkConfig<'a> { pub struct NetworkConfig<'a> {
@ -21,12 +22,17 @@ pub struct NetworkConfig<'a> {
} }
#[embassy_executor::task] #[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, esp_radio::wifi::Interface<'static>>) -> ! { async fn net_task(
mut runner: embassy_net::Runner<'static, esp_radio::wifi::Interface<'static>>,
) -> ! {
runner.run().await runner.run().await
} }
#[embassy_executor::task] #[embassy_executor::task]
pub async fn network_setup_task(spawner: embassy_executor::Spawner, config: NetworkConfig<'static>) { pub async fn network_setup_task(
spawner: embassy_executor::Spawner,
config: NetworkConfig<'static>,
) {
let wifi_config = Config::Station( let wifi_config = Config::Station(
StationConfig::default() StationConfig::default()
.with_ssid(config.wifi_network) .with_ssid(config.wifi_network)
@ -41,6 +47,10 @@ pub async fn network_setup_task(spawner: embassy_executor::Spawner, config: Netw
.unwrap(); .unwrap();
println!("Wifi configured and started!"); println!("Wifi configured and started!");
controller
.set_power_saving(esp_radio::wifi::PowerSaveMode::None)
.unwrap();
let wifi_interface = interfaces.station; let wifi_interface = interfaces.station;
let net_config = embassy_net::Config::dhcpv4(Default::default()); let net_config = embassy_net::Config::dhcpv4(Default::default());
let rng = Rng::new(); let rng = Rng::new();
@ -54,28 +64,68 @@ pub async fn network_setup_task(spawner: embassy_executor::Spawner, config: Netw
); );
spawner.spawn(net_task(runner).expect("spawn net task")); spawner.spawn(net_task(runner).expect("spawn net task"));
println!("Scan"); loop {
let scan_config = ScanConfig::default().with_max(10); println!("Scan");
let result = controller.scan_async(&scan_config).await.unwrap(); let scan_config = ScanConfig::default().with_max(10);
for ap in result { let result = controller.scan_async(&scan_config).await.unwrap();
println!("{:?}", ap); for ap in result {
println!(
"- {} (CH {} Strength {})",
ap.ssid.as_str(),
ap.channel,
ap.signal_strength
);
}
println!("Scan ended");
if let Err(e) = controller.set_config(&Config::Station(
StationConfig::default()
// .with_auth_method(esp_radio::wifi::AuthenticationMethod::Wpa2Wpa3Personal)
.with_ssid(WIFI_NETWORK)
.with_password(WIFI_PASSWORD.into()),
)) {
println!("Connection error: {:?}", e);
Timer::after_millis(1000).await;
continue;
}
if let Err(e) = controller.connect_async().await {
println!("Connect error: {:?}", e);
Timer::after_millis(1000).await;
continue;
}
println!("Configured");
stack.wait_config_up().await;
break;
} }
stack.wait_config_up().await; println!("Waiting for DHCP");
let cfg = wait_for_config(stack).await; let cfg = wait_for_config(stack).await;
let local_addr = cfg.address.address(); let local_addr = cfg.address.address();
println!("IP address: {:?}", local_addr); println!("IP address: {:?}", local_addr);
let host_addr = embassy_net::Ipv4Address::from_str(config.target_ip).unwrap(); loop {
let mut rx_buffer = [0; 4096]; let host_addr = embassy_net::Ipv4Address::from_str(config.target_ip).unwrap();
let mut tx_buffer = [0; 4096]; let mut rx_buffer = [0; 4096];
let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); let mut tx_buffer = [0; 4096];
socket.set_timeout(Some(Duration::from_secs(10))); let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
socket.set_keep_alive(Some(Duration::from_secs(1))); socket.set_timeout(Some(Duration::from_secs(10)));
if let Err(e) = socket.connect(SocketAddrV4::new(host_addr, config.target_port)).await { socket.set_keep_alive(Some(Duration::from_secs(1)));
println!("tcp connect error: {:?}", e); if let Err(e) = socket
} .connect(SocketAddrV4::new(host_addr, config.target_port))
.await
{
println!("tcp connect error: {:?}", e);
Timer::after_millis(1000).await;
continue;
}
let (read, write) = socket.split(); let (read, write) = socket.split();
join(tcp_read_loop(read), tcp_write_loop(write)).await; join(tcp_read_loop(read), tcp_write_loop(write)).await;
}
} }

View file

@ -1,19 +1,16 @@
use core::convert::Infallible;
use ag_lcd::LcdDisplay; use ag_lcd::LcdDisplay;
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex, signal::Signal}; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex, signal::Signal};
use embassy_time::{Delay, Timer}; use embassy_time::{Delay, Timer};
use esp_hal::gpio::{Level, Output, OutputConfig}; use esp_hal::gpio::{Level, Output, OutputConfig};
use esp_hal::peripherals::{GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15}; use esp_hal::peripherals::{GPIO4, GPIO16, GPIO17, GPIO18, GPIO19, GPIO23};
use ufmt::uWrite;
pub struct LcdPins { pub struct LcdPins {
pub rs: GPIO10<'static>, pub rs: GPIO4<'static>,
pub e: GPIO11<'static>, pub e: GPIO16<'static>,
pub d4: GPIO12<'static>, pub d4: GPIO17<'static>,
pub d5: GPIO13<'static>, pub d5: GPIO18<'static>,
pub d6: GPIO14<'static>, pub d6: GPIO19<'static>,
pub d7: GPIO15<'static>, pub d7: GPIO23<'static>,
} }
pub struct LcdConfig { pub struct LcdConfig {
@ -32,7 +29,8 @@ pub async fn overwrite_lcd(line1: &str, line2: &str) {
} }
pub fn stack_resources() -> &'static mut embassy_net::StackResources<5> { pub fn stack_resources() -> &'static mut embassy_net::StackResources<5> {
static RESOURCES: static_cell::StaticCell<embassy_net::StackResources<5>> = static_cell::StaticCell::new(); static RESOURCES: static_cell::StaticCell<embassy_net::StackResources<5>> =
static_cell::StaticCell::new();
RESOURCES.init(embassy_net::StackResources::new()) RESOURCES.init(embassy_net::StackResources::new())
} }
@ -53,7 +51,10 @@ impl ScreenBuffer {
} }
pub static SCREEN_BUFFER: Mutex<CriticalSectionRawMutex, ScreenBuffer> = Mutex::new(ScreenBuffer { pub static SCREEN_BUFFER: Mutex<CriticalSectionRawMutex, ScreenBuffer> = Mutex::new(ScreenBuffer {
line1: [0; 16], line1_ptr: 0, line2: [0; 16], line2_ptr: 0, line1: [0; 16],
line1_ptr: 0,
line2: [0; 16],
line2_ptr: 0,
}); });
static LCD_UPDATE: Signal<CriticalSectionRawMutex, ()> = Signal::new(); static LCD_UPDATE: Signal<CriticalSectionRawMutex, ()> = Signal::new();
@ -76,14 +77,20 @@ pub async fn lcd_display_task(config: LcdConfig) {
.with_cursor(ag_lcd::Cursor::On) .with_cursor(ag_lcd::Cursor::On)
.with_lines(ag_lcd::Lines::TwoLines) .with_lines(ag_lcd::Lines::TwoLines)
.build(); .build();
lcd.set_blink(ag_lcd::Blink::Off);
lcd.set_cursor(ag_lcd::Cursor::Off);
loop { loop {
LCD_UPDATE.wait().await; LCD_UPDATE.wait().await;
let buffer = SCREEN_BUFFER.lock().await; let buffer = SCREEN_BUFFER.lock().await;
lcd.clear(); lcd.clear();
for byte in &buffer.line1 { lcd.write(*byte); } for byte in &buffer.line1 {
lcd.write(*byte);
}
lcd.set_position(0, 1); lcd.set_position(0, 1);
for byte in &buffer.line2 { lcd.write(*byte); } for byte in &buffer.line2 {
lcd.write(*byte);
}
Timer::after_millis(20).await; Timer::after_millis(20).await;
} }
} }