Temperature gradient calculation
Temperature Gradient Calculation
The **Temperature Gradient Calculation** module in the Aquarium Control system is responsible for determining the rate of change of the water temperature over time. By calculating the slope (gradient) of the temperature curve, the system can identify trends—such as heating up, cooling down, or stable conditions—more effectively than by looking at instantaneous values alone. This data serves as basis for more sophisticated diagnostics.
Overview
The primary purpose of this module is to provide a reliable trend indicator for the thermal control logic. It helps in:
- **Verifying Actuator Effectiveness**: Confirming that the heater is actually raising the temperature or that the fans are cooling it down.
- **Anomaly Detection**: Identifying rapid temperature spikes or drops that might indicate sensor failure or equipment malfunction.
- **Predictive Control**: Allowing control loops to react to the direction of the temperature change: Providing the basis for PID-control, potentially reducing overshoot - this feature is currently not planned for implementation.
Algorithm
The module employs a **Least Squares Linear Regression** algorithm on a sliding window of historical data points to calculate the gradient. This method is chosen to smooth out sensor noise and quantization errors.
Process
- **Sampling**: The module performs measurement calculation at a configured `sampling_interval`.
- **Data Acquisition**: It retrieves the current water temperature from the central `SensorManager` and captures the current timestamp.
- **Storage**: The data point $(t, T)$ is pushed into a First-In-First-Out (FIFO) buffer (sliding window).
- **Window Management**: If the buffer exceeds the configured `sample_size`, the oldest data point is removed.
- **Calculation**: Once the buffer is full, the gradient $m$ is calculated using the formula:
- <math>m = \frac{N \sum(xy) - \sum x \sum y}{N \sum x^2 - (\sum x)^2}</math>
- Where:
- $N$ is the number of samples.
- $x$ is the time in seconds (normalized relative to the oldest sample to preserve floating-point precision).
- $y$ is the temperature in degrees Celsius.
- **Output**: The resulting slope $m$ (representing °C/second) is updated in a shared memory location protected by a Mutex.
Configuration
The behavior of the gradient calculation is defined in the application's TOML configuration file (typically `/etc/aquarium_control/aquarium_control.toml`) under the `[temperature_gradient]` section.
| Parameter | Type | Description | Constraints |
|---|---|---|---|
| `active` | Boolean | Master switch to enable or disable the calculation logic. | `true` / `false` |
| `execute` | Boolean | Determines if the thread should be spawned (primarily for testing). | `true` / `false` |
| `sampling_interval` | Integer | The time duration (in seconds) between two consecutive temperature samples. | Must be > 0. |
| `sample_size` | Integer | The number of historical data points to keep in the sliding window for regression. | Must be between 2 and 100. |
Example Configuration
<syntaxhighlight lang="toml"> [temperature_gradient] active = true execute = true sampling_interval = 10 # Take a sample every 10 seconds sample_size = 20 # Calculate trend based on the last 20 samples (200 seconds window) </syntaxhighlight>
Architecture and Integration
The Temperature Gradient module is implemented as a standalone thread that runs concurrently with other system components.
Dependencies
- **Input**: It consumes data from the `SensorManager`. Specifically, it reads the `water_temperature` field from the shared `SensorManagerSignals` structure.
- **Output**: It writes the calculated gradient (`f64`) to a shared `Arc<Mutex<f64>>`, which can be read by other components (e.g., logging or safety checks).
- **Lifecycle**: It is managed by the `SignalHandler`. It listens for `Quit` or `Terminate` commands via a dedicated channel to ensure graceful shutdown.
Thread Communication
The module uses Rust's `mpsc` (multi-producer, single-consumer) channels for control signals and `Arc<Mutex<...>>` for data sharing.
Error Handling
The module defines specific error types in `TemperatureGradientError` to handle initialization failures:
- **InvalidSamplingInterval**: Raised if the interval is set to 0.
- **InvalidSampleSize**: Raised if the sample size is outside the allowed range (2-100).
During runtime, the module includes logic to prevent log flooding. If it fails to acquire a lock on the sensor data or the output mutex, it logs the error once and inhibits further identical error logs until a successful operation occurs.