retry wifi connection, show canbus FW version, adjust measurement formular
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user