improve power calculation

This commit is contained in:
Laila van Reenen 2025-05-05 10:55:02 +02:00
parent a90b1fa6c6
commit aefe383504
Signed by: LailaTheElf
GPG Key ID: 8A3EF0226518C12D
6 changed files with 48 additions and 14 deletions

2
Cargo.lock generated
View File

@ -139,7 +139,7 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]] [[package]]
name = "energyPulseCounter" name = "energyPulseCounter"
version = "1.0.1" version = "1.0.2"
dependencies = [ dependencies = [
"crossbeam", "crossbeam",
"mqtt-client", "mqtt-client",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "energyPulseCounter" name = "energyPulseCounter"
version = "1.0.1" version = "1.0.2"
edition = "2021" edition = "2021"
[dependencies] [dependencies]

7
build.sh Normal file
View File

@ -0,0 +1,7 @@
#!/bin/sh
cross build --target aarch64-unknown-linux-gnu --release
# cargo build --release
cp target/aarch64-unknown-linux-gnu/release/energyPulseCounter energyPulseCounter-aarch64
# cp target/release/energyPulseCounter energyPulseCounter-x86_64

View File

@ -1,8 +1,9 @@
use crossbeam::atomic::AtomicCell; use crossbeam::atomic::AtomicCell;
use std::sync::Arc; use std::sync::Arc;
use rppal::gpio::{Gpio, Trigger}; use rppal::gpio::{Gpio, Trigger};
use std::time::{SystemTime, UNIX_EPOCH};
pub fn pulse_counter(pulses: Arc<AtomicCell<u32>>) { pub fn pulse_counter(pulses: Arc<AtomicCell<u32>>, last_time: Arc<AtomicCell<Option<u128>>>, power: Arc<AtomicCell<f64>>) {
let gpio = Gpio::new().expect("failt to get gpio driver"); let gpio = Gpio::new().expect("failt to get gpio driver");
let mut pulse_gpio = gpio.get(23) let mut pulse_gpio = gpio.get(23)
.expect("failt to get gpio pin") .expect("failt to get gpio pin")
@ -13,7 +14,18 @@ pub fn pulse_counter(pulses: Arc<AtomicCell<u32>>) {
loop { loop {
match pulse_gpio.poll_interrupt(true, None) { match pulse_gpio.poll_interrupt(true, None) {
Ok(_) => { Ok(_) => {
pulses.fetch_add(1); let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis();
let count = pulses.fetch_add(1);
match last_time.swap(Some(now)) {
Some(last) => {
// time between pulses in hours
let time = f64::from(u32::try_from(now - last).unwrap()) / (60.0 * 60.0 * 1000.0);
let watt = 1.0 / time;
let avg = power.load();
power.store(avg + (watt-avg)/f64::from(count));
},
None => {}
}
}, },
Err(_) => panic!("failt to pull interupt") Err(_) => panic!("failt to pull interupt")
} }

View File

@ -5,7 +5,7 @@ use crossbeam::atomic::AtomicCell;
mod publischer; mod publischer;
mod counter; mod counter;
use publischer::PulseTx; use publischer::{PulseTx, Data};
use counter::pulse_counter; use counter::pulse_counter;
#[derive(Deserialize)] #[derive(Deserialize)]
@ -53,22 +53,31 @@ fn main() {
Ok(conf) =>{ Ok(conf) =>{
let pulses: Arc<AtomicCell<u32>> = Arc::new(AtomicCell::new(0)); let pulses: Arc<AtomicCell<u32>> = Arc::new(AtomicCell::new(0));
let last_pulse_time: Arc<AtomicCell<Option<u128>>> = Arc::new(AtomicCell::new(None));
let avg_power: Arc<AtomicCell<f64>> = Arc::new(AtomicCell::new(0.0));
let pulses_counter = pulses.clone(); let pulses_counter = pulses.clone();
let last_pulse_time_counter = last_pulse_time.clone();
let avg_power_counter = avg_power.clone();
let _ = thread::Builder::new() let _ = thread::Builder::new()
.name("counter".to_string()) .name("counter".to_string())
.spawn(move || { .spawn(move || {
pulse_counter(pulses_counter); pulse_counter(pulses_counter, last_pulse_time_counter, avg_power_counter);
}); });
mqtt_client::run::<Arc<AtomicCell<u32>>, PulseTx>( let config: Data = Data {
pulses: pulses.clone(),
avg_power: avg_power.clone(),
};
mqtt_client::run::<Data, PulseTx>(
conf.mqtt.host, conf.mqtt.host,
conf.mqtt.port, conf.mqtt.port,
conf.mqtt.client, conf.mqtt.client,
conf.mqtt.user, conf.mqtt.user,
conf.mqtt.pass, conf.mqtt.pass,
pulses.clone() config
); );
}, },
Err(_) => {} Err(_) => {}

View File

@ -6,9 +6,14 @@ use crossbeam::atomic::AtomicCell;
use mqtt_client::{MqttMessage, Sender, Receiver, QoS}; use mqtt_client::{MqttMessage, Sender, Receiver, QoS};
use mqtt_client::mqtt_client; use mqtt_client::mqtt_client;
pub struct Data {
pub pulses: Arc<AtomicCell<u32>>,
pub avg_power: Arc<AtomicCell<f64>>
}
pub struct PulseTx { pub struct PulseTx {
tx: Sender<mqtt_client::MqttMessage>, tx: Sender<mqtt_client::MqttMessage>,
pulses: Arc<AtomicCell<u32>> pulses: Data
} }
@ -28,7 +33,8 @@ impl PulseTx {
Err(e) => Err(e) =>
println!("ERROR: message_in: clock/time/minute has invalid payload ({:?})", e), println!("ERROR: message_in: clock/time/minute has invalid payload ({:?})", e),
Ok(_) => { Ok(_) => {
let pulses = self.pulses.swap(0); let pulses = self.pulses.pulses.swap(0);
let power = self.pulses.avg_power.swap(0.0);
self.tx({ mqtt_client::MqttMessage { self.tx({ mqtt_client::MqttMessage {
topic: String::from("/kees/energy/metalbox/pulses"), topic: String::from("/kees/energy/metalbox/pulses"),
payload: pulses.to_string(), payload: pulses.to_string(),
@ -37,13 +43,13 @@ impl PulseTx {
}}); }});
self.tx({ mqtt_client::MqttMessage { self.tx({ mqtt_client::MqttMessage {
topic: String::from("/kees/energy/metalbox/watt"), topic: String::from("/kees/energy/metalbox/watt"),
payload: (pulses * 60).to_string(), payload: power.to_string(),
retain: false, retain: false,
qos: mqtt_client::QoS::AtMostOnce, qos: mqtt_client::QoS::AtMostOnce,
}}); }});
self.tx({ mqtt_client::MqttMessage { self.tx({ mqtt_client::MqttMessage {
topic: String::from("/kees/energy/metalbox/data"), topic: String::from("/kees/energy/metalbox/data"),
payload: format!("{{\"pulses\":{pulses},\"watt\":{}}}", pulses * 60), payload: format!("{{\"pulses\":{pulses},\"watt\":{power}}}"),
retain: false, retain: false,
qos: mqtt_client::QoS::AtMostOnce, qos: mqtt_client::QoS::AtMostOnce,
}}); }});
@ -55,8 +61,8 @@ impl PulseTx {
} }
impl mqtt_client::MqttTool<Arc<AtomicCell<u32>>> for PulseTx { impl mqtt_client::MqttTool<Data> for PulseTx {
fn new(client: mqtt_client::Client, tx: Sender<mqtt_client::MqttMessage>, pulses: Arc<AtomicCell<u32>>) -> PulseTx { fn new(client: mqtt_client::Client, tx: Sender<mqtt_client::MqttMessage>, pulses: Data) -> PulseTx {
match client.subscribe("clock/time/minute", QoS::AtMostOnce) { match client.subscribe("clock/time/minute", QoS::AtMostOnce) {
Err(e) => Err(e) =>