Skip to content

Commit

Permalink
added AP mode and cleaned up some areas.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpoisso committed Aug 15, 2024
1 parent 44e465e commit f01c472
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 51 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @jpoisso
12 changes: 12 additions & 0 deletions .github/renovate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended",
"schedule:daily"
],
"labels": [
"dependencies"
],
"automerge": false,
"prConcurrentLimit": 3
}
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ debug = true
opt-level = "z"

[dependencies]
log = { version = "0.4", default-features = false }
esp-idf-svc = { version = "0.49", features = ["default", "pio", "embassy-sync", "critical-section"], default-features = false }
log = { version = "0.4.22", default-features = false }
esp-idf-svc = { version = "0.49.1", features = ["default", "pio", "embassy-sync", "critical-section"], default-features = false }
embedded-svc = { version = "0.28.0", features = ["std"], default-features = false}
anyhow = { version = "1.0.86", features = ["std"], default-features = false}
serde = { version = "1.0.204", features = ["std", "derive"], default-features = false}
serde_json = { version = "1.0.121", features = ["std"], default-features = false}
serde = { version = "1.0.207", features = ["std", "derive"], default-features = false}
serde_json = { version = "1.0.124", features = ["std"], default-features = false}

[build-dependencies]
embuild = "0.32.0"
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ If building on Windows 11, you will probably need to download this driver: https
We'll use `espflash` to push our binaries to the ESP32-S3 board.

```shell
cargo install cargo-generate
cargo install ldproxy
cargo install espup
cargo install espflash
Expand Down
5 changes: 3 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
fn main() {
embuild::espidf::sysenv::output();
println!("cargo:rustc-env=WIFI_SSID=YOUR_SSID");
println!("cargo:rustc-env=WIFI_PASSWORD=YOUR_PASSWORD");
println!("cargo:rustc-env=WIFI_AP_MODE=1"); // Set to anything else for client mode (connects to your netwok)
println!("cargo:rustc-env=WIFI_SSID=WIFI_BOAT_HOTSPOT"); // Replace with your own SSID (AP SSID or Network SSID)
println!("cargo:rustc-env=WIFI_PASSWORD=password"); // Replace with your own password (AP password or Network password)
}
24 changes: 10 additions & 14 deletions src/boat/rudder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,20 @@ use esp_idf_svc::hal::{

pub(crate) struct Rudder<'a> {
servo: Arc<Mutex<LedcDriver<'a>>>,
max_angle: u32,
min_angle: u32,
spread: u32,
}

impl<'a> Rudder<'a> {
pub(crate) fn new(servo: Arc<Mutex<LedcDriver<'a>>>) -> Self {
let max_duty = servo.lock().unwrap().get_max_duty();
let max_angle = max_duty / 8;
let min_angle = max_duty / 40;
let spread = max_angle - min_angle / 180;
Rudder {
servo,
max_angle,
min_angle,
spread,
}
}

Expand All @@ -30,28 +31,23 @@ impl<'a> Rudder<'a> {
}

pub(crate) fn set_angle(&mut self, angle: u32) -> Result<()> {
let duty = self.interpolate(angle);
let duty = angle * self.spread + self.min_angle;
self.servo.lock().unwrap().set_duty(duty)?;
Ok(())
}

fn interpolate(&mut self, angle: u32) -> u32 {
angle * (self.max_angle - self.min_angle) / 180 + self.min_angle
}
}

pub(crate) fn setup_rudder() -> Result<Rudder<'static>> {
let peripherals = Peripherals::take()?;
let servo_driver = LedcTimerDriver::new(
peripherals.ledc.timer1,
&TimerConfig::new()
.frequency(50.Hz())
.resolution(ledc::Resolution::Bits14),
)?;
let servo = Arc::new(Mutex::new(
LedcDriver::new(
peripherals.ledc.channel1,
servo_driver,
LedcTimerDriver::new(
peripherals.ledc.timer1,
&TimerConfig::new()
.frequency(50.Hz())
.resolution(ledc::Resolution::Bits14),
)?,
peripherals.pins.gpio5,
)
.unwrap(),
Expand Down
10 changes: 6 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,24 @@ use std::{thread::sleep, time::Duration};

const WIFI_SSID: &str = env!("WIFI_SSID");
const WIFI_PASSWORD: &str = env!("WIFI_PASSWORD");
const WIFI_AP_MODE: &str = env!("WIFI_AP_MODE");

fn main() -> Result<()> {
// Initialize ESP-IDF system and logging.
esp_idf_svc::sys::link_patches();
esp_idf_svc::log::EspLogger::initialize_default();

info!("connecting to wifi...");
let wifi = wifi::setup_wifi(WIFI_SSID, WIFI_PASSWORD)?;
let wifi = wifi::setup_wifi(WIFI_SSID, WIFI_PASSWORD, WIFI_AP_MODE == "1")?;
sleep(Duration::from_secs(1));
let ip = wifi.sta_netif().get_ip_info()?.ip;
info!("connected to wifi with ip: {ip:?}");

// Create the boat and its components.
let motor = boat::motor::setup_motor()?;
let rudder = boat::rudder::setup_rudder()?;
let boat = boat::Boat { motor, rudder };
let boat = boat::Boat {
motor: boat::motor::setup_motor()?,
rudder: boat::rudder::setup_rudder()?,
};

// Set up http server and keep a reference to it (otherwise it drops out of scope).
let _server = server::setup_server(boat)?;
Expand Down
30 changes: 12 additions & 18 deletions src/server.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
use std::sync::{Arc, Mutex};

use crate::boat::Boat;
use anyhow::Result;
use embedded_svc::http::Headers;
use esp_idf_svc::http::{
server::{EspHttpConnection, EspHttpServer, Request},
Method,
};
use esp_idf_svc::io::Read;

use serde::{Deserialize, Serialize};

use anyhow::Result;

use crate::boat::Boat;
use std::sync::{Arc, Mutex};

#[derive(Debug, Serialize, Deserialize)]
struct BoatInstruction {
Expand All @@ -20,23 +16,21 @@ struct BoatInstruction {
}

pub(crate) fn setup_server(boat: Boat<'static>) -> Result<EspHttpServer<'static>> {
// Wrap the boat instance in an Arc and a Mutex to allow multiple threads to access it
let boat = Arc::new(Mutex::new(boat));

// Server configurations
let configuration = esp_idf_svc::http::server::Configuration {
// Create a new HTTP server with a stack size of 10KB.
let mut server = EspHttpServer::new(&esp_idf_svc::http::server::Configuration {
stack_size: 10240,
..Default::default()
};
})?;

// Wrap the boat instance in an Arc and a Mutex to allow multiple threads to access it
let boat = Arc::new(Mutex::new(boat));

// Boat instruction handler
let mut server = EspHttpServer::new(&configuration)?;
let boat_clone = Arc::clone(&boat);
server.fn_handler::<anyhow::Error, _>("/boat", Method::Post, move |mut request| {
let instruction = extract_boat_instruction(&mut request)?;
let mut boat = boat_clone.lock().unwrap();
boat.motor.set_power(instruction.motor_speed)?;
boat.rudder.set_angle(instruction.rudder_angle)?;
let mut boat_guard = boat.lock().unwrap();
boat_guard.motor.set_power(instruction.motor_speed)?;
boat_guard.rudder.set_angle(instruction.rudder_angle)?;
Ok(())
})?;

Expand Down
32 changes: 24 additions & 8 deletions src/wifi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,44 @@ use esp_idf_svc::{
eventloop::EspSystemEventLoop,
hal::prelude::Peripherals,
nvs::EspDefaultNvsPartition,
wifi::{ClientConfiguration, Configuration, EspWifi},
wifi::{AccessPointConfiguration, AuthMethod, ClientConfiguration, Configuration, EspWifi},
};
use log::info;
use std::{thread::sleep, time::Duration};

pub(crate) fn setup_wifi<'a>(ssid: &'a str, password: &'a str) -> Result<EspWifi<'a>> {
pub(crate) fn setup_wifi<'a>(
ssid: &'a str,
password: &'a str,
is_ap_mode: bool,
) -> Result<EspWifi<'a>> {
let peripherals = Peripherals::take()?;
let sys_loop = EspSystemEventLoop::take()?;
let nvs = EspDefaultNvsPartition::take()?;
let ssid = ssid.try_into().unwrap();
let password = password.try_into().unwrap();
let configuration = Configuration::Client(ClientConfiguration {
ssid,
password,
..Default::default()
});
let configuration = if is_ap_mode {
Configuration::AccessPoint(AccessPointConfiguration {
ssid,
password,
max_connections: 4,
auth_method: AuthMethod::WPA2WPA3Personal,
..Default::default()
})
} else {
Configuration::Client(ClientConfiguration {
ssid,
password,
..Default::default()
})
};

let mut esp_wifi = EspWifi::new(peripherals.modem, sys_loop, Some(nvs))?;
esp_wifi.set_configuration(&configuration)?;

esp_wifi.start()?;
esp_wifi.connect()?;
while !esp_wifi.is_connected()? {
info!("waiting for connected status from wifi endpoint...");
info!("waiting for connection status from wifi driver...");
sleep(Duration::new(1, 0));
}
Ok(esp_wifi)
Expand Down

0 comments on commit f01c472

Please sign in to comment.