init
This commit is contained in:
commit
0f6c9fe97a
13 changed files with 1631 additions and 0 deletions
8
.cargo/config.toml
Normal file
8
.cargo/config.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||||
|
runner = "probe-rs run --chip stm32l431CCUx"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
target = "thumbv7em-none-eabihf"
|
||||||
|
|
||||||
|
[env]
|
||||||
|
DEFMT_LOG = "info"
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
target/
|
1007
Cargo.lock
generated
Normal file
1007
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
80
Cargo.toml
Normal file
80
Cargo.toml
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
[package]
|
||||||
|
edition = "2021"
|
||||||
|
name = "go-tracker"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["malled <malled@flipdot.org>"]
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
defmt = "0.3"
|
||||||
|
defmt-rtt = "0.4"
|
||||||
|
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||||
|
|
||||||
|
embedded-hal = "1.0.0"
|
||||||
|
embedded-hal-async = "1.0.0"
|
||||||
|
embedded-io = "0.6.1"
|
||||||
|
embedded-io-async = "0.6.1"
|
||||||
|
embedded-storage = "0.3.1"
|
||||||
|
|
||||||
|
cortex-m-rt = "0.7.3"
|
||||||
|
|
||||||
|
embassy-executor = { version = "0.6.0", features = [
|
||||||
|
"task-arena-size-8192",
|
||||||
|
"arch-cortex-m",
|
||||||
|
"executor-thread",
|
||||||
|
"defmt",
|
||||||
|
"integrated-timers",
|
||||||
|
"executor-interrupt",
|
||||||
|
] }
|
||||||
|
embassy-sync = { version = "0.6.0" }
|
||||||
|
embassy-time = { version = "0.3.0", features = [
|
||||||
|
"defmt",
|
||||||
|
"defmt-timestamp-uptime",
|
||||||
|
] }
|
||||||
|
|
||||||
|
embassy-net = { version = "0.4.0", features = [
|
||||||
|
"dhcpv4",
|
||||||
|
"tcp",
|
||||||
|
"dns",
|
||||||
|
"defmt",
|
||||||
|
"proto-ipv4",
|
||||||
|
"medium-ip",
|
||||||
|
] }
|
||||||
|
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
|
||||||
|
embassy-stm32 = { version = "0.1.0", features = [
|
||||||
|
"defmt",
|
||||||
|
"stm32l431cc",
|
||||||
|
"unstable-pac",
|
||||||
|
"memory-x",
|
||||||
|
"time-driver-any",
|
||||||
|
] }
|
||||||
|
embassy-net-ppp = { version = "0.1.0", features = ["defmt"] }
|
||||||
|
embassy-futures = "0.1.1"
|
||||||
|
heapless = { version = "0.8.0", features = ["defmt-03"] }
|
||||||
|
static_cell = "2.1.0"
|
||||||
|
rand = { version = "0.8.5", default-features = false }
|
||||||
|
rust-mqtt = { version = "0.3.0", default-features = false, features = [
|
||||||
|
"no_std",
|
||||||
|
] }
|
||||||
|
#minimq = "0.9.0"
|
||||||
|
#embedded-nal = "0.8.0"
|
||||||
|
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
embassy-time = { git = "https://github.com/embassy-rs/embassy", rev = "45cbcb513dc0bbf3e12c102df0db8c15643cc78b" }
|
||||||
|
embassy-time-driver = { git = "https://github.com/embassy-rs/embassy", rev = "45cbcb513dc0bbf3e12c102df0db8c15643cc78b" }
|
||||||
|
embassy-time-queue-driver = { git = "https://github.com/embassy-rs/embassy", rev = "45cbcb513dc0bbf3e12c102df0db8c15643cc78b" }
|
||||||
|
embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "45cbcb513dc0bbf3e12c102df0db8c15643cc78b" }
|
||||||
|
embassy-stm32 = { git = "https://github.com/embassy-rs/embassy", rev = "45cbcb513dc0bbf3e12c102df0db8c15643cc78b" }
|
||||||
|
embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "45cbcb513dc0bbf3e12c102df0db8c15643cc78b" }
|
||||||
|
embassy-net-ppp = { git = "https://github.com/embassy-rs/embassy", rev = "45cbcb513dc0bbf3e12c102df0db8c15643cc78b" }
|
||||||
|
embassy-sync = { git = "https://github.com/embassy-rs/embassy", rev = "45cbcb513dc0bbf3e12c102df0db8c15643cc78b" }
|
||||||
|
embassy-futures = { git = "https://github.com/embassy-rs/embassy", rev = "45cbcb513dc0bbf3e12c102df0db8c15643cc78b" }
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
lto = true
|
||||||
|
opt-level = "s"
|
||||||
|
incremental = false
|
||||||
|
codegen-units = 1
|
||||||
|
# note: debug = true is okay - debuginfo isn't flashed to the device!
|
||||||
|
debug = true
|
44
README.md
Normal file
44
README.md
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
|
||||||
|
# Emerson GO Tracker 1.7 (TXC-TH04) #
|
||||||
|
|
||||||
|
## Parts ##
|
||||||
|
|
||||||
|
| Part Number | Type | Interface |
|
||||||
|
|-------------|------|-----------|
|
||||||
|
| STM32L431CCU | MCU | |
|
||||||
|
| HDC2010 | Humidity and Temperature Sensor | I2C |
|
||||||
|
| TMP112 | Temperature Sensor | I2C |
|
||||||
|
| ????? | Light Sensor | I2C |
|
||||||
|
| Quectel BG95-M5 | GSM + GNSS | UART |
|
||||||
|
| MX25L3233F | Flash | SPI |
|
||||||
|
|
||||||
|
|
||||||
|
| I2C Address | Device | Function |
|
||||||
|
|-------------|--------|----------|
|
||||||
|
| 0x40 | HDC2010 | Humidity and Temperature Sensor |
|
||||||
|
| 0x44 | ????? | Light Sensor? |
|
||||||
|
| 0x48 | TMP112 | Temperature Sensor |
|
||||||
|
|
||||||
|
|
||||||
|
## Light Sensor ##
|
||||||
|
```
|
||||||
|
---------------
|
||||||
|
GND - | 1 6 | - INT (PB9)
|
||||||
|
VCC - | 2 5 | - SDA
|
||||||
|
GND - | 3 4 | - SCL
|
||||||
|
---------------
|
||||||
|
```
|
||||||
|
|
||||||
|
## STM32L431CCU Pinout ##
|
||||||
|
|
||||||
|
| STM Pin | Function | Remark |
|
||||||
|
|---------|---------------|--------|
|
||||||
|
| PA1 | GSM NetKey | - |
|
||||||
|
| PA2 | UART2_TX GSM | - |
|
||||||
|
| PA3 | UART2_RX GSM | - |
|
||||||
|
| PB2 | GSM PWR Enable| - |
|
||||||
|
| PB5 | TMP112 enable | - |
|
||||||
|
| PB6 | I2C1_SCL | - |
|
||||||
|
| PB7 | I2C1_SDA | - |
|
||||||
|
| PB9 | Light INT | not verified |
|
||||||
|
| PB12 | SPI Flash CS | - |
|
35
build.rs
Normal file
35
build.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
//! This build script copies the `memory.x` file from the crate root into
|
||||||
|
//! a directory where the linker can always find it at build time.
|
||||||
|
//! For many projects this is optional, as the linker always searches the
|
||||||
|
//! project root directory -- wherever `Cargo.toml` is. However, if you
|
||||||
|
//! are using a workspace or have a more complicated build setup, this
|
||||||
|
//! build script becomes required. Additionally, by requesting that
|
||||||
|
//! Cargo re-run the build script whenever `memory.x` is changed,
|
||||||
|
//! updating `memory.x` ensures a rebuild of the application with the
|
||||||
|
//! new memory settings.
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Put `memory.x` in our output directory and ensure it's
|
||||||
|
// on the linker search path.
|
||||||
|
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||||
|
File::create(out.join("memory.x"))
|
||||||
|
.unwrap()
|
||||||
|
.write_all(include_bytes!("memory.x"))
|
||||||
|
.unwrap();
|
||||||
|
println!("cargo:rustc-link-search={}", out.display());
|
||||||
|
|
||||||
|
// By default, Cargo will re-run a build script whenever
|
||||||
|
// any file in the project changes. By specifying `memory.x`
|
||||||
|
// here, we ensure the build script is only re-run when
|
||||||
|
// `memory.x` is changed.
|
||||||
|
println!("cargo:rerun-if-changed=memory.x");
|
||||||
|
|
||||||
|
println!("cargo:rustc-link-arg-bins=--nmagic");
|
||||||
|
println!("cargo:rustc-link-arg-bins=-Tlink.x");
|
||||||
|
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
|
||||||
|
}
|
14
memory.x
Normal file
14
memory.x
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
/* NOTE K = KiBi = 1024 bytes */
|
||||||
|
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
|
||||||
|
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* This is where the call stack will be allocated. */
|
||||||
|
/* The stack is of the full descending type. */
|
||||||
|
/* NOTE Do NOT modify `_stack_start` unless you know what you are doing */
|
||||||
|
_stack_start = ORIGIN(RAM) + LENGTH(RAM);
|
10
rust-toolchain.toml
Normal file
10
rust-toolchain.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Before upgrading check that everything is available on all tier1 targets here:
|
||||||
|
# https://rust-lang.github.io/rustup-components-history
|
||||||
|
[toolchain]
|
||||||
|
channel = "stable"
|
||||||
|
components = [ "rustfmt" ]
|
||||||
|
targets = [
|
||||||
|
"thumbv6m-none-eabi",
|
||||||
|
"thumbv7em-none-eabihf",
|
||||||
|
"riscv32imac-unknown-none-elf",
|
||||||
|
]
|
23
src/gnss.rs
Normal file
23
src/gnss.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use defmt::info;
|
||||||
|
use embassy_stm32::{mode::Async, usart::Uart};
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
use heapless::String;
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
pub async fn gnss_task(mut gnss_uart: Uart<'static, Async>) {
|
||||||
|
let mut buf = [0; 90];
|
||||||
|
loop {
|
||||||
|
let rx = gnss_uart.read_until_idle(&mut buf).await;
|
||||||
|
match rx {
|
||||||
|
Ok(rx) => {
|
||||||
|
let buf = core::str::from_utf8(&buf[..rx]).unwrap();
|
||||||
|
info!("RX: {}", buf);
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
info!("Error reading from GNSS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Perform some asynchronous work here
|
||||||
|
Timer::after(Duration::from_secs(1)).await;
|
||||||
|
}
|
||||||
|
}
|
154
src/main.rs
Normal file
154
src/main.rs
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_net::StackResources;
|
||||||
|
use embassy_net_ppp;
|
||||||
|
|
||||||
|
use embassy_stm32::i2c::{self, I2c};
|
||||||
|
use embassy_stm32::rng::{self, Rng};
|
||||||
|
use embassy_stm32::time::Hertz;
|
||||||
|
use embassy_stm32::usart::Config;
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||||
|
use embassy_stm32::{
|
||||||
|
gpio::{Level, Output, Speed},
|
||||||
|
usart::BufferedUart,
|
||||||
|
};
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
|
||||||
|
use net::net_init;
|
||||||
|
use rand::RngCore;
|
||||||
|
|
||||||
|
use static_cell::StaticCell;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
mod gnss;
|
||||||
|
mod mqtt;
|
||||||
|
mod net;
|
||||||
|
mod sensors;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART2 => usart::BufferedInterruptHandler<peripherals::USART2>;
|
||||||
|
USART3 => usart::InterruptHandler<peripherals::USART3>;
|
||||||
|
RNG => rng::InterruptHandler<peripherals::RNG>;
|
||||||
|
I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
|
||||||
|
I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(spawner: Spawner) {
|
||||||
|
let mut stm_config = embassy_stm32::Config::default();
|
||||||
|
{
|
||||||
|
use embassy_stm32::rcc::*;
|
||||||
|
stm_config.rcc.sys = Sysclk::PLL1_R;
|
||||||
|
stm_config.rcc.hsi = false;
|
||||||
|
stm_config.rcc.hse = Some(Hse {
|
||||||
|
freq: embassy_stm32::time::Hertz(12_000_000),
|
||||||
|
mode: HseMode::Oscillator,
|
||||||
|
});
|
||||||
|
stm_config.rcc.pll = Some(Pll {
|
||||||
|
source: PllSource::HSE, // 12 MHz
|
||||||
|
prediv: PllPreDiv::DIV1,
|
||||||
|
|
||||||
|
mul: PllMul::MUL8, // 12 * 8 = 96 MHz
|
||||||
|
divp: None,
|
||||||
|
divq: None,
|
||||||
|
divr: Some(PllRDiv::DIV2), // 96 / 2 = 48 MHz
|
||||||
|
});
|
||||||
|
stm_config.rcc.ls = LsConfig::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
let p = embassy_stm32::init(stm_config);
|
||||||
|
let mut config = Config::default();
|
||||||
|
config.baudrate = 115_200;
|
||||||
|
config.stop_bits = embassy_stm32::usart::StopBits::STOP1;
|
||||||
|
|
||||||
|
defmt::info!("Moin");
|
||||||
|
let mut rng = Rng::new(p.RNG, Irqs);
|
||||||
|
let mut net_key = Output::new(p.PA1, Level::Low, Speed::Low);
|
||||||
|
let mut pwr_en = Output::new(p.PB2, Level::Low, Speed::Low);
|
||||||
|
let mut pwr_tmp = Output::new(p.PB5, Level::Low, Speed::Low);
|
||||||
|
|
||||||
|
// Power on modem
|
||||||
|
pwr_en.set_high();
|
||||||
|
pwr_tmp.set_high();
|
||||||
|
|
||||||
|
static RX_BUF: StaticCell<[u8; 512]> = StaticCell::new();
|
||||||
|
static TX_BUF: StaticCell<[u8; 512]> = StaticCell::new();
|
||||||
|
|
||||||
|
let mut usart_modem = BufferedUart::new(
|
||||||
|
p.USART2,
|
||||||
|
Irqs,
|
||||||
|
p.PA3,
|
||||||
|
p.PA2,
|
||||||
|
RX_BUF.init([0; 512]),
|
||||||
|
TX_BUF.init([0; 512]),
|
||||||
|
config,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// TODO untested
|
||||||
|
let gnss_uart = usart::Uart::new(
|
||||||
|
p.USART3,
|
||||||
|
p.PB11,
|
||||||
|
p.PB10,
|
||||||
|
Irqs,
|
||||||
|
p.DMA1_CH2,
|
||||||
|
p.DMA1_CH3,
|
||||||
|
Config::default(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let i2c = I2c::new(
|
||||||
|
p.I2C1,
|
||||||
|
p.PB6,
|
||||||
|
p.PB7,
|
||||||
|
Irqs,
|
||||||
|
p.DMA1_CH6,
|
||||||
|
p.DMA1_CH7,
|
||||||
|
Hertz(100_000),
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
net_init(&mut net_key, &mut usart_modem).await;
|
||||||
|
|
||||||
|
// spawner.spawn(gnss::gnss_task(gnss_uart)).unwrap();
|
||||||
|
|
||||||
|
static STATE: StaticCell<embassy_net_ppp::State<8, 8>> = StaticCell::new();
|
||||||
|
let state = STATE.init(embassy_net_ppp::State::<8, 8>::new());
|
||||||
|
let (device, runner) = embassy_net_ppp::new(state);
|
||||||
|
// Generate random seed
|
||||||
|
let seed = rng.next_u64();
|
||||||
|
|
||||||
|
// Init network stack
|
||||||
|
static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
|
||||||
|
let (stack, runner_net) = embassy_net::new(
|
||||||
|
device,
|
||||||
|
embassy_net::Config::default(),
|
||||||
|
RESOURCES.init(StackResources::new()),
|
||||||
|
seed,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Launch network task
|
||||||
|
spawner.spawn(net::net_task(runner_net)).unwrap();
|
||||||
|
spawner
|
||||||
|
.spawn(net::ppp_task(stack, runner, usart_modem))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
Timer::after(Duration::from_secs(1)).await;
|
||||||
|
if stack.is_link_up() {
|
||||||
|
info!("Ready");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spawner.spawn(sensors::sensors_task(i2c)).unwrap();
|
||||||
|
spawner.spawn(mqtt::mqtt_task(stack)).unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
Timer::after(Duration::from_secs(1)).await;
|
||||||
|
}
|
||||||
|
}
|
61
src/mqtt.rs
Normal file
61
src/mqtt.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
use defmt::{info, warn};
|
||||||
|
use embassy_net::Stack;
|
||||||
|
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
use rust_mqtt::{
|
||||||
|
client::{client::MqttClient, client_config::ClientConfig},
|
||||||
|
utils::rng_generator::CountingRng,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
pub async fn mqtt_task(stack: Stack<'static>) {
|
||||||
|
info!("Connecting...");
|
||||||
|
let mut rx_buffer = [0; 128];
|
||||||
|
let mut tx_buffer = [0; 128];
|
||||||
|
loop {
|
||||||
|
let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
|
||||||
|
socket.set_timeout(Some(Duration::from_secs(10)));
|
||||||
|
|
||||||
|
let host_addrs = stack
|
||||||
|
.dns_query("test.mosquitto.org", embassy_net::dns::DnsQueryType::A)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let host_addr = host_addrs.iter().next().unwrap();
|
||||||
|
|
||||||
|
if let Err(e) = socket.connect((*host_addr, 1883)).await {
|
||||||
|
warn!("connect error: {:?}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
info!("Connected to {:?}", socket.remote_endpoint());
|
||||||
|
|
||||||
|
let mut config = ClientConfig::new(
|
||||||
|
rust_mqtt::client::client_config::MqttVersion::MQTTv5,
|
||||||
|
CountingRng(20000),
|
||||||
|
);
|
||||||
|
config.add_max_subscribe_qos(rust_mqtt::packet::v5::publish_packet::QualityOfService::QoS1);
|
||||||
|
config.add_client_id("client");
|
||||||
|
// config.add_username(USERNAME);
|
||||||
|
// config.add_password(PASSWORD);
|
||||||
|
config.max_packet_size = 100;
|
||||||
|
let mut recv_buffer = [0; 80];
|
||||||
|
let mut write_buffer = [0; 80];
|
||||||
|
|
||||||
|
let mut client =
|
||||||
|
MqttClient::<_, 5, _>::new(socket, &mut write_buffer, 80, &mut recv_buffer, 80, config);
|
||||||
|
|
||||||
|
client.connect_to_broker().await.unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
client
|
||||||
|
.send_message(
|
||||||
|
"/malled",
|
||||||
|
b"hello2",
|
||||||
|
rust_mqtt::packet::v5::publish_packet::QualityOfService::QoS0,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
Timer::after_millis(2000).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
89
src/net.rs
Normal file
89
src/net.rs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
use defmt::{info, warn};
|
||||||
|
use embassy_net::{ConfigV4, Ipv4Address, Ipv4Cidr, Stack};
|
||||||
|
use embassy_stm32::{gpio::Output, usart::BufferedUart};
|
||||||
|
use embassy_time::Timer;
|
||||||
|
use embedded_io::Write;
|
||||||
|
use embedded_io_async::Read;
|
||||||
|
use heapless::{String, Vec};
|
||||||
|
|
||||||
|
pub async fn net_init(net_key: &mut Output<'static>, usart_modem: &mut BufferedUart<'static>) {
|
||||||
|
// Enable the modem
|
||||||
|
Timer::after_millis(750).await;
|
||||||
|
net_key.set_high();
|
||||||
|
Timer::after_millis(750).await;
|
||||||
|
net_key.set_low();
|
||||||
|
|
||||||
|
let mut rx_buf = String::<128>::new();
|
||||||
|
loop {
|
||||||
|
let mut buf = [0u8; 8];
|
||||||
|
let result = usart_modem.read(&mut buf).await;
|
||||||
|
match result {
|
||||||
|
Ok(size) => {
|
||||||
|
for i in 0..size {
|
||||||
|
rx_buf.push(buf[i] as char).unwrap();
|
||||||
|
}
|
||||||
|
if !rx_buf.contains("\r") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
info!("RX: {}", rx_buf);
|
||||||
|
if rx_buf.contains("CTZV") {
|
||||||
|
// usart_modem.write_all(b"AT+QGPS=1\r").unwrap();
|
||||||
|
usart_modem
|
||||||
|
.write_all(b"AT+CGDCONT=1,\"ip\",\"pinternet.interkom.de\"\r")
|
||||||
|
.unwrap();
|
||||||
|
usart_modem.flush().unwrap();
|
||||||
|
Timer::after_millis(500).await;
|
||||||
|
usart_modem.write_all(b"ATD*99#\r").unwrap();
|
||||||
|
usart_modem.flush().unwrap();
|
||||||
|
Timer::after_millis(500).await;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rx_buf.clear();
|
||||||
|
}
|
||||||
|
Err(_err) => {
|
||||||
|
//Ignore eg. framing errors
|
||||||
|
defmt::error!("Modem RX Error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
pub async fn net_task(
|
||||||
|
mut runner: embassy_net::Runner<'static, embassy_net_ppp::Device<'static>>,
|
||||||
|
) -> ! {
|
||||||
|
info!("Starting Ethernet");
|
||||||
|
runner.run().await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
pub async fn ppp_task(
|
||||||
|
stack: Stack<'static>,
|
||||||
|
mut runner: embassy_net_ppp::Runner<'static>,
|
||||||
|
uart: BufferedUart<'static>,
|
||||||
|
) {
|
||||||
|
let cfg = embassy_net_ppp::Config {
|
||||||
|
username: "foo".as_bytes(),
|
||||||
|
password: "bar".as_bytes(),
|
||||||
|
};
|
||||||
|
info!("Starting PPP");
|
||||||
|
runner
|
||||||
|
.run(uart, cfg, |ipv4| {
|
||||||
|
let Some(addr) = ipv4.address else {
|
||||||
|
warn!("PPP did not provide an IP address.");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let mut dns_servers = Vec::new();
|
||||||
|
for s in ipv4.dns_servers.iter().flatten() {
|
||||||
|
let _ = dns_servers.push(Ipv4Address::from_bytes(&s.0));
|
||||||
|
}
|
||||||
|
let config = ConfigV4::Static(embassy_net::StaticConfigV4 {
|
||||||
|
address: Ipv4Cidr::new(Ipv4Address::from_bytes(&addr.0), 0),
|
||||||
|
gateway: None,
|
||||||
|
dns_servers,
|
||||||
|
});
|
||||||
|
stack.set_config_v4(config);
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
105
src/sensors.rs
Normal file
105
src/sensors.rs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
use defmt::info;
|
||||||
|
use embassy_stm32::i2c::I2c;
|
||||||
|
use embassy_stm32::mode::Async;
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
|
||||||
|
const ADDRESS_TMP112: u8 = 0x48;
|
||||||
|
const ADDRESS_HDC2010: u8 = 0x40;
|
||||||
|
const ADDRESS_LIGHT: u8 = 0x44;
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
pub async fn sensors_task(mut i2c: I2c<'static, Async>) {
|
||||||
|
info!("Sensors task started");
|
||||||
|
Timer::after(Duration::from_secs(1)).await;
|
||||||
|
loop {
|
||||||
|
info!("TMP112 {}", read_temp_tmp112(&mut i2c).await.unwrap());
|
||||||
|
info!("HDC2010 {}", read_temp_hdc2010(&mut i2c).await.unwrap());
|
||||||
|
info!("Light {}", read_light(&mut i2c).await.unwrap());
|
||||||
|
Timer::after(Duration::from_secs(1)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_light(i2c: &mut I2c<'static, Async>) -> Result<i16, embassy_stm32::i2c::Error> {
|
||||||
|
let mut data = [0u8; 2];
|
||||||
|
// let _request = i2c.write(ADDRESS_LIGHT, &[0x7E]).await;
|
||||||
|
Timer::after(Duration::from_millis(50)).await;
|
||||||
|
for i in 1..255 {
|
||||||
|
let resp = i2c.write_read(ADDRESS_LIGHT, &[i], &mut data).await;
|
||||||
|
match resp {
|
||||||
|
Ok(_) => {
|
||||||
|
info!("Addr {:02X} Data: {:02X} {:02X}", i, data[0], data[1],);
|
||||||
|
return Ok(42);
|
||||||
|
}
|
||||||
|
Err(e) => match e {
|
||||||
|
embassy_stm32::i2c::Error::Nack => {
|
||||||
|
info!("NAK");
|
||||||
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
info!("custom err");
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(embassy_stm32::i2c::Error::Timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_temp_hdc2010(
|
||||||
|
i2c: &mut I2c<'static, Async>,
|
||||||
|
) -> Result<i16, embassy_stm32::i2c::Error> {
|
||||||
|
let mut data = [0u8; 4];
|
||||||
|
// let _request = i2c.write(ADDRESS_HUM, &[0x00]).await;
|
||||||
|
Timer::after(Duration::from_millis(50)).await;
|
||||||
|
for _ in 1..10 {
|
||||||
|
let resp = i2c.write_read(ADDRESS_HDC2010, &[0xFC], &mut data).await;
|
||||||
|
match resp {
|
||||||
|
Ok(_) => {
|
||||||
|
info!(
|
||||||
|
"Data: {:02X} {:02X} {:02X} {:02X}",
|
||||||
|
data[0], data[1], data[2], data[3]
|
||||||
|
);
|
||||||
|
return Ok(42);
|
||||||
|
}
|
||||||
|
Err(e) => match e {
|
||||||
|
embassy_stm32::i2c::Error::Nack => {
|
||||||
|
info!("NAK");
|
||||||
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
info!("custom err");
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(embassy_stm32::i2c::Error::Timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_temp_tmp112(i2c: &mut I2c<'static, Async>) -> Result<f32, embassy_stm32::i2c::Error> {
|
||||||
|
let mut data = [0u8; 2];
|
||||||
|
// Timer::after(Duration::from_millis(50)).await;
|
||||||
|
for _ in 1..10 {
|
||||||
|
let resp = i2c.write_read(ADDRESS_TMP112, &[0], &mut data).await;
|
||||||
|
match resp {
|
||||||
|
Ok(_) => {
|
||||||
|
let temp = ((data[0] as u16) << 4) | (data[1] as u16) >> 4;
|
||||||
|
let temp = temp as i16;
|
||||||
|
let temp = temp as f32;
|
||||||
|
let temp = temp * 0.0625;
|
||||||
|
return Ok(temp);
|
||||||
|
}
|
||||||
|
Err(e) => match e {
|
||||||
|
embassy_stm32::i2c::Error::Nack => {
|
||||||
|
info!("NAK");
|
||||||
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
info!("custom err");
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(embassy_stm32::i2c::Error::Timeout)
|
||||||
|
}
|
Loading…
Reference in a new issue