firmware-base/docs/POT.md

141 lines
4.8 KiB
Markdown

---
title: "POT Component"
description: "Analog potentiometer reader with lightweight digital filtering for ESP32 and other microcontrollers"
keywords: ["potentiometer", "analog", "filter", "ESP32", "Modbus", "component"]
---
# POT
**Path**: [src/components/POT.h](../src/components/POT.h)
**Revision History**: Initial documentation
The POT component provides an analog potentiometer reader with lightweight digital filtering. It's designed for small AVR/ESP32 class MCUs with no dynamic memory allocation and no floating-point operations. The component supports local and remote control modes, making it ideal for industrial applications with Modbus integration.
## REQUIREMENTS
### Hardware
- Analog input pin connected to a potentiometer wiper
- Recommended: RC low-pass filter (using the potentiometer as R and adding a capacitor)
### Software
- Arduino framework
- ArduinoLog library
- Modbus TCP implementation
## FEATURES
- Three damping modes:
- NONE (raw readings)
- MOVING-AVERAGE (box-car filter with O(1) implementation)
- EMA (Exponential Moving Average with 1-pole IIR filter)
- Dead-band implementation to suppress ±1-LSB chatter after scaling
- Scaling from raw ADC values (0-4095 for ESP32) to application values (0-100 by default)
- Local/Remote control modes via Modbus
- Efficient implementation with no dynamic memory allocation
- Configurable sampling interval and filter parameters
## DEPENDENCIES
- [Component](../src/Component.h) - Base component class
- [Arduino](https://www.arduino.cc/reference/en/) - Core Arduino framework
- [ArduinoLog](https://github.com/thijse/Arduino-Log) - Logging functionality
- [ModbusTCP](../src/modbus/ModbusTCP.h) - Modbus TCP implementation
```mermaid
graph TD
POT --> Component
POT --> ArduinoLog
POT --> ModbusTCP
Component --> ArduinoLog
```
## BEHAVIOUR
The POT component reads analog values at a configurable interval, applies filtering based on the selected algorithm, and exposes the value through Modbus registers. It supports two control modes: Local (reading from the physical potentiometer) and Remote (accepting values through Modbus).
```mermaid
stateDiagram-v2
[*] --> Setup
Setup --> Idle
Idle --> ReadAnalog: Sample Interval Elapsed
ReadAnalog --> ApplyFilter
ApplyFilter --> CheckMode
CheckMode --> LocalMode: Mode == Local
CheckMode --> RemoteMode: Mode == Remote
LocalMode --> ApplyDeadband
RemoteMode --> UpdateFromModbus
ApplyDeadband --> ValueChanged
UpdateFromModbus --> ValueChanged
ValueChanged --> NotifyStateChange: Value Changed
ValueChanged --> Idle: No Change
NotifyStateChange --> Idle
```
## TODOS
### PERFORMANCE
- Consider implementing interrupt-based sampling for more precise timing
- Evaluate filter performance with high-frequency noise
- Profile performance impact of different filter algorithms on various platforms
### SECURITY
- Add range validation for Modbus-supplied remote values
- Consider authentication for mode switching between local and remote control
- Implement rate limiting for remote value changes
### COMPLIANCE
- Verify ADC reading methods across different platforms for consistent behavior
- Ensure proper error handling for edge cases (e.g., disconnected potentiometer)
- Document requirements for electrical compliance (input voltage ranges, etc.)
### RECOMMENDATIONS
- Use the hardware RC filter recommendation provided in the component header:
- For 5kΩ potentiometer: Add 1-3.3µF capacitor between wiper and ground
- Adjust capacitor value based on desired cutoff frequency and noise conditions
- Start with the EMA filter for most applications as it provides good smoothing with minimal resources
- For applications requiring precise readings, increase the sampling rate and adjust the filtering parameters
## EXAMPLE
This example shows how to initialize and use a POT component with an ESP32:
```cpp
#ifdef PIN_ANALOG_0
pot_0 = new POT(
this, // owner
PIN_ANALOG_0, // pin
COMPONENT_KEY_ANALOG_0, // id
MB_ANALOG_0, // modbusAddress
POTDampingAlgorithm::DAMPING_EMA // filtering algorithm
);
if (pot_0)
{
components.push_back(pot_0);
Log.infoln(F("POT_0 initialized. Pin:%d, ID:%d, MB:%d"),
PIN_ANALOG_0, COMPONENT_KEY_ANALOG_0, MB_ANALOG_0);
}
else
{
Log.errorln(F("POT_0 initialization failed."));
}
#endif
```
### References
For more information on analog filtering techniques and implementation details, refer to the following resources:
- [ESP32 ADC Documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/adc.html)
- [Digital Filtering Basics](https://www.analog.com/media/en/technical-documentation/dsp-book/dsp_book_Ch8.pdf)
- [Exponential Moving Average (EMA) Overview](https://www.investopedia.com/terms/e/ema.asp)