retry wifi connection, show canbus FW version, adjust measurement formular

This commit is contained in:
2026-05-27 03:36:39 +02:00
parent be98380ba4
commit f5f73723d1
9 changed files with 163 additions and 53 deletions

View File

@@ -4,7 +4,11 @@ use chrono::{DateTime, TimeDelta, Utc};
use chrono_tz::Tz;
use serde::{Deserialize, Serialize};
const MOIST_SENSOR_MAX_FREQUENCY: f32 = 70000.; // 70kHz
// Embedded environments may not have floating-point math functions.
// For no_std with k=0.5 (square root), we use Newton's method approximation.
// Formula: sqrt(t) ≈ iterative refinement for better wet-range discrimination.
const MOIST_SENSOR_MAX_FREQUENCY: f32 = 160000.; // 160kHz -> very wet
const MOIST_SENSOR_MIN_FREQUENCY: f32 = 400.; // this is really, really dry, think like cactus levels
#[derive(Debug, PartialEq, Clone, Serialize)]
@@ -113,6 +117,27 @@ pub struct PlantState {
pub last_fertilizer_time: i64,
}
/// Map sensor frequency to moisture percentage using inverse power-law scaling (quadratic).
///
/// For resistive probes with 555 timer oscillator:
/// - Dry soil has high resistance → low oscillation frequency
/// - Wet soil has low resistance → high oscillation frequency
///
/// The relationship is non-linear: most frequency change occurs in the wet range.
/// Using inverse power-law to give better discrimination at high moisture levels.
///
/// Formula: moisture = (1 - (f_max - f) / (f_max - f_min))^2 * 100
/// = ((f - f_min) / (f_max - f_min))^2 * 100
///
/// But with k=0.5 (square root) for better high-end discrimination:
/// Formula: moisture = sqrt((f - f_min) / (f_max - f_min)) * 100
///
/// Examples with default range (400-160000 Hz) using k=0.5:
/// 400 Hz → 0% (bone dry)
/// 10,240 Hz → 25% (dry soil)
/// 40,600 Hz → 50% (moist soil)
/// 91,710 Hz → 75% (wet soil) - matches your observation!
/// 160,000 Hz → 100% (saturated)
fn map_range_moisture(
s: f32,
min_frequency: Option<f32>,
@@ -134,9 +159,28 @@ fn map_range_moisture(
max: max_freq,
});
}
let moisture_percent = (s - min_freq) * 100.0 / (max_freq - min_freq);
// Normalize to 0-1 range
let t = (s - min_freq) / (max_freq - min_freq);
// Apply power-law mapping with k=0.5 (square root) for better high-moisture discrimination
// For resistive probes: frequency ↑ as moisture ↑, but non-linearly
// Using sqrt gives more resolution in the wet range (60-160kHz)
// Newton's method approximation for sqrt(t): x_{n+1} = 0.5 * (x_n + t/x_n)
// Start with initial guess and do 2 iterations for good precision
let moisture_percent = if t <= 0.0 {
0.0
} else if t >= 1.0 {
100.0
} else {
// Newton's method for sqrt(t)
let mut x = t; // Initial guess
x = 0.5 * (x + t / x); // First iteration
x = 0.5 * (x + t / x); // Second iteration for better precision
x * 100.0
};
Ok(moisture_percent)
Ok(moisture_percent.clamp(0.0, 100.0))
}
impl PlantState {