--- 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)