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