Current measurement with ina3221
Signed-off-by: Thomas Klaehn <thomas.klaehn@perinet.io>
This commit is contained in:
@@ -8,7 +8,16 @@
|
|||||||
"WebFetch(domain:docs.rs)",
|
"WebFetch(domain:docs.rs)",
|
||||||
"WebFetch(domain:docs.espressif.com)",
|
"WebFetch(domain:docs.espressif.com)",
|
||||||
"WebFetch(domain:esp32.implrust.com)",
|
"WebFetch(domain:esp32.implrust.com)",
|
||||||
"WebSearch"
|
"WebSearch",
|
||||||
|
"Bash(cargo search:*)",
|
||||||
|
"Bash(find /home/esp/.cargo/registry/src -path */esp-hal-1.0.0/src/i2c/master.rs)",
|
||||||
|
"Bash(cargo add:*)",
|
||||||
|
"Bash(find /home/esp/.cargo/registry/src -path */ohms-*/src/*.rs)",
|
||||||
|
"Bash(find /home/esp/.cargo/registry/src -path */embedded-hal-bus-*/src/i2c*)",
|
||||||
|
"Bash(find /home/esp/.cargo/registry/src -path */axs5106l*/src/*.rs)",
|
||||||
|
"Bash(grep -n \"pub fn read_touch_data\\\\|TouchData\\\\|Coordinates\\\\|finger\\\\|x\\\\|y\\\\|count\" /home/esp/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/axs5106l-0.1.0/src/*.rs)",
|
||||||
|
"Bash(grep -n \"pub fn read_touch_data\\\\|pub fn read_raw\" /home/esp/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/axs5106l-0.1.0/src/*.rs)",
|
||||||
|
"Bash(grep -n \"pub fn micro_volts\\\\|pub fn milli_volts\\\\|pub fn from_micro\\\\|micro_volts\\\\|milli_volts\\\\|-> i32\\\\|-> f32\\\\|-> u32\" /home/esp/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ohms-0.2.0/src/*.rs)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+38
-1
@@ -20,6 +20,17 @@ version = "1.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "axs5106l"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "412c958bcde165622bed3b9d5839efff5def86bd6c8ce5c4c415f714885e3549"
|
||||||
|
dependencies = [
|
||||||
|
"embedded-hal 1.0.0",
|
||||||
|
"heapless 0.9.2",
|
||||||
|
"nb 1.1.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "az"
|
name = "az"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@@ -61,6 +72,12 @@ dependencies = [
|
|||||||
"syn 2.0.117",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.11.0"
|
version = "2.11.0"
|
||||||
@@ -484,7 +501,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "54786287c0a61ca0f78cb0c338a39427551d1be229103b4444591796c579e093"
|
checksum = "54786287c0a61ca0f78cb0c338a39427551d1be229103b4444591796c579e093"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitfield",
|
"bitfield",
|
||||||
"bitflags",
|
"bitflags 2.11.0",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
@@ -668,6 +685,7 @@ dependencies = [
|
|||||||
name = "esp32c6-display"
|
name = "esp32c6-display"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"axs5106l",
|
||||||
"embedded-graphics",
|
"embedded-graphics",
|
||||||
"embedded-hal 1.0.0",
|
"embedded-hal 1.0.0",
|
||||||
"embedded-hal-bus",
|
"embedded-hal-bus",
|
||||||
@@ -676,6 +694,8 @@ dependencies = [
|
|||||||
"esp-bootloader-esp-idf",
|
"esp-bootloader-esp-idf",
|
||||||
"esp-hal",
|
"esp-hal",
|
||||||
"esp-println",
|
"esp-println",
|
||||||
|
"heapless 0.9.2",
|
||||||
|
"ina3221",
|
||||||
"log",
|
"log",
|
||||||
"mipidsi",
|
"mipidsi",
|
||||||
]
|
]
|
||||||
@@ -832,6 +852,17 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ina3221"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7553b95bc4d5b72e4a1e4d945364d83361eac2a5e1d88321cfb3d9281e01d937"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"embedded-hal 1.0.0",
|
||||||
|
"ohms",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.13.0"
|
version = "2.13.0"
|
||||||
@@ -976,6 +1007,12 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ohms"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "71d55b4d2ed96afaf7449a0bbf831c84bcd32e0a35c1ac22edb931decdd855a7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ mipidsi = "0.10"
|
|||||||
|
|
||||||
# 2D graphics primitives and text rendering
|
# 2D graphics primitives and text rendering
|
||||||
embedded-graphics = "0.8"
|
embedded-graphics = "0.8"
|
||||||
|
ina3221 = "0.4.5"
|
||||||
|
axs5106l = "0.1.0"
|
||||||
|
heapless = "0.9"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|||||||
+241
-51
@@ -1,59 +1,206 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
|
use core::cell::RefCell;
|
||||||
|
use core::fmt::Write;
|
||||||
|
use embedded_hal::delay::DelayNs;
|
||||||
|
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
esp_bootloader_esp_idf::esp_app_desc!();
|
esp_bootloader_esp_idf::esp_app_desc!();
|
||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
delay::Delay,
|
delay::Delay,
|
||||||
gpio::{Level, Output, OutputConfig},
|
gpio::{Level, Output, OutputConfig},
|
||||||
|
i2c::master::{Config as I2cConfig, I2c},
|
||||||
main,
|
main,
|
||||||
spi::master::{Config, Spi},
|
spi::master::{Config as SpiConfig, Spi},
|
||||||
time::Rate,
|
time::Rate,
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
|
|
||||||
mod jd9853;
|
use embedded_hal_bus::i2c::RefCellDevice;
|
||||||
|
|
||||||
|
mod jd9853;
|
||||||
use jd9853::JD9853;
|
use jd9853::JD9853;
|
||||||
use mipidsi::{interface::SpiInterface, Builder};
|
use mipidsi::{interface::SpiInterface, Builder};
|
||||||
|
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
mono_font::{ascii::FONT_10X20, MonoTextStyle},
|
mono_font::{
|
||||||
|
ascii::{FONT_6X10, FONT_10X20},
|
||||||
|
MonoTextStyle,
|
||||||
|
},
|
||||||
pixelcolor::Rgb565,
|
pixelcolor::Rgb565,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
primitives::{PrimitiveStyleBuilder, Rectangle},
|
primitives::{Line, PrimitiveStyle, PrimitiveStyleBuilder, Rectangle},
|
||||||
text::Text,
|
text::Text,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: verify pin assignments against your board schematic
|
use ina3221::INA3221;
|
||||||
//
|
use axs5106l::{Axs5106l, Rotation};
|
||||||
// Typical wiring for a 1.47" JD9853 breakout on ESP32-C6:
|
use heapless::String as HString;
|
||||||
//
|
|
||||||
// Display pin │ ESP32-C6 GPIO
|
// --- Hardware constants ------------------------------------------------------
|
||||||
// ─────────────┼───────────────
|
|
||||||
// SCL / SCK │ GPIO6
|
|
||||||
// SDA / MOSI │ GPIO7
|
|
||||||
// CS │ GPIO10
|
|
||||||
// DC │ GPIO4
|
|
||||||
// RST │ GPIO5
|
|
||||||
// BLK / BL │ GPIO22 (set high to enable backlight)
|
|
||||||
//
|
|
||||||
const LCD_W: u16 = 172;
|
const LCD_W: u16 = 172;
|
||||||
const LCD_H: u16 = 320;
|
const LCD_H: u16 = 320;
|
||||||
|
|
||||||
|
// Display pin │ ESP32-C6 GPIO
|
||||||
|
// ─────────────┼───────────────
|
||||||
|
// SCL / SCK │ GPIO1
|
||||||
|
// SDA / MOSI │ GPIO2
|
||||||
|
// CS │ GPIO14
|
||||||
|
// DC │ GPIO15
|
||||||
|
// RST │ GPIO22
|
||||||
|
// BLK / BL │ GPIO23 (set high to enable backlight)
|
||||||
|
//
|
||||||
|
// I2C SDA │ GPIO18
|
||||||
|
// I2C SCL │ GPIO19
|
||||||
|
// Touch RST │ GPIO20
|
||||||
|
//
|
||||||
|
// INA3221 I2C address: 0x40 (A0 = GND)
|
||||||
|
// Shunt resistor: 50 mΩ
|
||||||
|
|
||||||
|
/// Shunt resistor in milliohms.
|
||||||
|
const SHUNT_MOHMS: i32 = 50;
|
||||||
|
|
||||||
|
// --- App types ---------------------------------------------------------------
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
enum AppState {
|
||||||
|
Idle,
|
||||||
|
Measuring,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Default)]
|
||||||
|
struct Measurement {
|
||||||
|
bus_uv: i32, // bus voltage, µV
|
||||||
|
current_ua: i32, // channel current, µA (derived from shunt voltage)
|
||||||
|
power_uw: i32, // power, µW
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Formatting helpers ------------------------------------------------------
|
||||||
|
|
||||||
|
fn fmt_voltage(buf: &mut HString<24>, uv: i32) {
|
||||||
|
let sign = if uv < 0 { "-" } else { "" };
|
||||||
|
let uv = uv.unsigned_abs();
|
||||||
|
write!(buf, "{}{}.{:02} V", sign, uv / 1_000_000, (uv % 1_000_000) / 10_000).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fmt_current(buf: &mut HString<24>, ua: i32) {
|
||||||
|
let sign = if ua < 0 { "-" } else { "" };
|
||||||
|
let ua = ua.unsigned_abs();
|
||||||
|
write!(buf, "{}{}.{} mA", sign, ua / 1000, (ua % 1000) / 100).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fmt_power(buf: &mut HString<24>, uw: i32) {
|
||||||
|
let sign = if uw < 0 { "-" } else { "" };
|
||||||
|
let uw = uw.unsigned_abs();
|
||||||
|
write!(buf, "{}{}.{} mW", sign, uw / 1000, (uw % 1000) / 100).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fmt_duration(buf: &mut HString<24>, secs: u32) {
|
||||||
|
let h = secs / 3600;
|
||||||
|
let m = (secs % 3600) / 60;
|
||||||
|
let s = secs % 60;
|
||||||
|
write!(buf, "{:02}:{:02}:{:02}", h, m, s).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- UI ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn draw_ui<D: DrawTarget<Color = Rgb565>>(display: &mut D, state: AppState, m: &Measurement, elapsed_s: u32) {
|
||||||
|
const BLUE: Rgb565 = Rgb565::new(0, 0, 20);
|
||||||
|
const GREEN: Rgb565 = Rgb565::new(0, 40, 0);
|
||||||
|
const GREY: Rgb565 = Rgb565::new(10, 20, 10);
|
||||||
|
|
||||||
|
display.clear(Rgb565::BLACK).ok();
|
||||||
|
|
||||||
|
// Header bar
|
||||||
|
Rectangle::new(Point::new(0, 0), Size::new(LCD_W as u32, 42))
|
||||||
|
.into_styled(PrimitiveStyleBuilder::new().fill_color(BLUE).build())
|
||||||
|
.draw(display)
|
||||||
|
.ok();
|
||||||
|
Text::new(
|
||||||
|
"POWER MONITOR",
|
||||||
|
Point::new(21, 29),
|
||||||
|
MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE),
|
||||||
|
)
|
||||||
|
.draw(display)
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
// Status line
|
||||||
|
let (status_str, status_color) = if state == AppState::Measuring {
|
||||||
|
("* MEASURING", GREEN)
|
||||||
|
} else {
|
||||||
|
(" STOPPED ", GREY)
|
||||||
|
};
|
||||||
|
Text::new(status_str, Point::new(8, 68), MonoTextStyle::new(&FONT_10X20, status_color))
|
||||||
|
.draw(display)
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
// Divider
|
||||||
|
Line::new(Point::new(0, 78), Point::new(LCD_W as i32 - 1, 78))
|
||||||
|
.into_styled(PrimitiveStyle::with_stroke(GREY, 1))
|
||||||
|
.draw(display)
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
// Labels
|
||||||
|
let label = MonoTextStyle::new(&FONT_6X10, GREY);
|
||||||
|
Text::new("Voltage", Point::new(8, 100), label).draw(display).ok();
|
||||||
|
Text::new("Current", Point::new(8, 160), label).draw(display).ok();
|
||||||
|
Text::new("Power", Point::new(8, 220), label).draw(display).ok();
|
||||||
|
|
||||||
|
// Values
|
||||||
|
let value = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
|
||||||
|
let mut buf: HString<24> = HString::new();
|
||||||
|
|
||||||
|
fmt_voltage(&mut buf, m.bus_uv);
|
||||||
|
Text::new(&buf, Point::new(8, 128), value).draw(display).ok();
|
||||||
|
buf.clear();
|
||||||
|
|
||||||
|
fmt_current(&mut buf, m.current_ua);
|
||||||
|
Text::new(&buf, Point::new(8, 188), value).draw(display).ok();
|
||||||
|
buf.clear();
|
||||||
|
|
||||||
|
fmt_power(&mut buf, m.power_uw);
|
||||||
|
Text::new(&buf, Point::new(8, 248), value).draw(display).ok();
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
Line::new(Point::new(0, 263), Point::new(LCD_W as i32 - 1, 263))
|
||||||
|
.into_styled(PrimitiveStyle::with_stroke(GREY, 1))
|
||||||
|
.draw(display)
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
let mut buf: HString<24> = HString::new();
|
||||||
|
write!(buf, "Runtime: ").ok();
|
||||||
|
fmt_duration(&mut buf, elapsed_s);
|
||||||
|
Text::new(&buf, Point::new(5, 278), MonoTextStyle::new(&FONT_6X10, GREY))
|
||||||
|
.draw(display)
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
Text::new(
|
||||||
|
"tap to start / stop",
|
||||||
|
Point::new(5, 293),
|
||||||
|
MonoTextStyle::new(&FONT_6X10, GREY),
|
||||||
|
)
|
||||||
|
.draw(display)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Entry point -------------------------------------------------------------
|
||||||
|
|
||||||
#[main]
|
#[main]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let peripherals = esp_hal::init(esp_hal::Config::default());
|
let peripherals = esp_hal::init(esp_hal::Config::default());
|
||||||
|
|
||||||
// 72 KB heap for mipidsi internal buffers, alloc, etc.
|
|
||||||
esp_alloc::heap_allocator!(size: 72 * 1024);
|
esp_alloc::heap_allocator!(size: 72 * 1024);
|
||||||
|
|
||||||
println!("ESP32-C6 display demo starting…");
|
println!("Power monitor starting...");
|
||||||
|
|
||||||
// --- SPI bus -----------------------------------------------------------
|
let mut delay = Delay::new();
|
||||||
|
|
||||||
|
// --- SPI / display -------------------------------------------------------
|
||||||
let spi = Spi::new(
|
let spi = Spi::new(
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
Config::default()
|
SpiConfig::default()
|
||||||
.with_frequency(Rate::from_mhz(40))
|
.with_frequency(Rate::from_mhz(40))
|
||||||
.with_mode(esp_hal::spi::Mode::_0),
|
.with_mode(esp_hal::spi::Mode::_0),
|
||||||
)
|
)
|
||||||
@@ -61,50 +208,93 @@ fn main() -> ! {
|
|||||||
.with_sck(peripherals.GPIO1)
|
.with_sck(peripherals.GPIO1)
|
||||||
.with_mosi(peripherals.GPIO2);
|
.with_mosi(peripherals.GPIO2);
|
||||||
|
|
||||||
// Manual chip-select via GPIO
|
let cs = Output::new(peripherals.GPIO14, Level::High, OutputConfig::default());
|
||||||
let cs = Output::new(peripherals.GPIO14, Level::High, OutputConfig::default());
|
|
||||||
|
|
||||||
// Wrap bus + CS into an embedded-hal SpiDevice
|
|
||||||
let spi_device = embedded_hal_bus::spi::ExclusiveDevice::new(spi, cs, Delay::new()).unwrap();
|
let spi_device = embedded_hal_bus::spi::ExclusiveDevice::new(spi, cs, Delay::new()).unwrap();
|
||||||
|
|
||||||
// --- Display -----------------------------------------------------------
|
let dc = Output::new(peripherals.GPIO15, Level::Low, OutputConfig::default());
|
||||||
let dc = Output::new(peripherals.GPIO15, Level::Low, OutputConfig::default());
|
|
||||||
let rst = Output::new(peripherals.GPIO22, Level::High, OutputConfig::default());
|
let rst = Output::new(peripherals.GPIO22, Level::High, OutputConfig::default());
|
||||||
|
|
||||||
// Backlight — drive high to enable
|
|
||||||
let _bl = Output::new(peripherals.GPIO23, Level::High, OutputConfig::default());
|
let _bl = Output::new(peripherals.GPIO23, Level::High, OutputConfig::default());
|
||||||
|
|
||||||
// mipidsi 0.10 requires a small scratch buffer owned by the interface
|
let mut spi_buf = [0u8; 512];
|
||||||
let mut buf = [0u8; 512];
|
let di = SpiInterface::new(spi_device, dc, &mut spi_buf);
|
||||||
let di = SpiInterface::new(spi_device, dc, &mut buf);
|
|
||||||
|
|
||||||
// JD9853 has a 240-wide internal framebuffer; the 172-pixel panel starts at column 34.
|
|
||||||
let mut display = Builder::new(JD9853, di)
|
let mut display = Builder::new(JD9853, di)
|
||||||
.reset_pin(rst)
|
.reset_pin(rst)
|
||||||
.display_size(LCD_W, LCD_H)
|
.display_size(LCD_W, LCD_H)
|
||||||
.display_offset(34, 0)
|
.display_offset(34, 0)
|
||||||
.init(&mut Delay::new())
|
.init(&mut delay)
|
||||||
.expect("display init failed");
|
.expect("display init failed");
|
||||||
|
|
||||||
// --- Drawing -----------------------------------------------------------
|
// --- I2C (shared between INA3221 and AXS5106L) ---------------------------
|
||||||
display.clear(Rgb565::BLACK).unwrap();
|
let i2c = I2c::new(peripherals.I2C0, I2cConfig::default())
|
||||||
|
.expect("I2C init failed")
|
||||||
|
.with_sda(peripherals.GPIO18)
|
||||||
|
.with_scl(peripherals.GPIO19);
|
||||||
|
let i2c_bus = RefCell::new(i2c);
|
||||||
|
|
||||||
// Blue rectangle as background banner
|
// --- INA3221 (channel index 0 = physical CH1, shunt = 50 mΩ) ------------
|
||||||
let bg_style = PrimitiveStyleBuilder::new()
|
let ina = INA3221::new(RefCellDevice::new(&i2c_bus), 0x40);
|
||||||
.fill_color(Rgb565::new(0, 0, 20))
|
|
||||||
.build();
|
|
||||||
Rectangle::new(Point::new(0, 0), Size::new(LCD_W as u32, 40))
|
|
||||||
.into_styled(bg_style)
|
|
||||||
.draw(&mut display)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// White text
|
// --- AXS5106L touch controller -------------------------------------------
|
||||||
let text_style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
|
let touch_rst = Output::new(peripherals.GPIO20, Level::High, OutputConfig::default());
|
||||||
Text::new("ESP32-C6", Point::new(10, 28), text_style)
|
let mut touch = Axs5106l::new(
|
||||||
.draw(&mut display)
|
RefCellDevice::new(&i2c_bus),
|
||||||
.unwrap();
|
touch_rst,
|
||||||
|
LCD_W,
|
||||||
|
LCD_H,
|
||||||
|
Rotation::Rotate0,
|
||||||
|
);
|
||||||
|
touch.init(&mut delay).expect("touch init failed");
|
||||||
|
|
||||||
println!("Display ready.");
|
// --- App state -----------------------------------------------------------
|
||||||
|
let mut state = AppState::Idle;
|
||||||
|
let mut measurement = Measurement::default();
|
||||||
|
let mut was_touched = false;
|
||||||
|
let mut tick: u32 = 0;
|
||||||
|
let mut runtime_loops: u32 = 0; // increments every 10 ms while measuring
|
||||||
|
|
||||||
loop {}
|
draw_ui(&mut display, state, &measurement, 0);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
// Touch: toggle measuring on the leading edge of a tap
|
||||||
|
if let Ok(td) = touch.read_raw_touch_data() {
|
||||||
|
let touched = td.has_touches();
|
||||||
|
if touched && !was_touched {
|
||||||
|
if state == AppState::Idle {
|
||||||
|
state = AppState::Measuring;
|
||||||
|
tick = 50; // trigger first sensor read immediately
|
||||||
|
runtime_loops = 0;
|
||||||
|
} else {
|
||||||
|
state = AppState::Idle;
|
||||||
|
}
|
||||||
|
draw_ui(&mut display, state, &measurement, runtime_loops / 100);
|
||||||
|
}
|
||||||
|
was_touched = touched;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read INA3221 every 500 ms while measuring (10 ms loop × 50 = 500 ms)
|
||||||
|
if state == AppState::Measuring {
|
||||||
|
runtime_loops = runtime_loops.saturating_add(1);
|
||||||
|
tick += 1;
|
||||||
|
if tick >= 50 {
|
||||||
|
tick = 0;
|
||||||
|
match (ina.get_shunt_voltage(0), ina.get_bus_voltage(0)) {
|
||||||
|
(Ok(shunt_v), Ok(bus_v)) => {
|
||||||
|
let bus_uv = bus_v.micro_volts();
|
||||||
|
let shunt_uv = shunt_v.micro_volts();
|
||||||
|
// I (µA) = V_shunt (µV) × 1000 / R_shunt (mΩ)
|
||||||
|
let current_ua = shunt_uv * 1000 / SHUNT_MOHMS;
|
||||||
|
// P (µW) = V_bus (µV) × I (µA) / 1 000 000
|
||||||
|
let power_uw =
|
||||||
|
((bus_uv as i64 * current_ua as i64) / 1_000_000) as i32;
|
||||||
|
measurement = Measurement { bus_uv, current_ua, power_uw };
|
||||||
|
draw_ui(&mut display, state, &measurement, runtime_loops / 100);
|
||||||
|
}
|
||||||
|
_ => println!("INA3221 read error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delay.delay_ms(10u32);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user