--- title: "AnalogLevelSwitch Component" description: "Analog Level Switch Component for multi-position switch detection via analog input" keywords: ["analog", "level", "switch", "ESP32", "voltage divider", "multi-position"] --- # AnalogLevelSwitch **Path**: [`src/components/AnalogLevelSwitch.h`](../src/components/AnalogLevelSwitch.h) **Revision History**: Initial documentation The AnalogLevelSwitch component interprets an analog voltage as a discrete position or slot. It enables reading an analog input as a multi-position switch by mapping voltage levels to specific slots or positions, with built-in smoothing and debouncing functionality. ## REQUIREMENTS ### Hardware - An analog input pin on the ESP32 - A voltage divider circuit with different resistor values for each switch position - Pull-down resistor (typically 10kΩ) connected to the analog pin ### Software - Arduino framework - ArduinoLog library - ModbusTCP support ## FEATURES - Maps analog voltage readings to discrete positions (slots) - Configurable number of positions/slots (up to 32 positions) - Adjustable ADC step size per slot - Configurable ADC value offset for the first slot - Built-in signal smoothing using moving average or EMA - Debouncing algorithm to prevent spurious readings - Hysteresis to prevent jitter between adjacent positions - Modbus integration for industrial control systems - Customizable reading interval ## DEPENDENCIES - [Component](../src/Component.h) - Base component class - [ModbusTCP](../src/modbus/ModbusTCP.h) - Modbus TCP communication - [ArduinoLog](https://github.com/thijse/Arduino-Log) - Logging functionality ```mermaid graph TD AnalogLevelSwitch --> Component AnalogLevelSwitch --> ModbusTCP AnalogLevelSwitch --> ArduinoLog ``` ## BEHAVIOUR ```mermaid stateDiagram-v2 [*] --> Initialization Initialization --> ReadAnalogValue ReadAnalogValue --> SmoothValue SmoothValue --> DetermineSlot DetermineSlot --> CheckIfChanged CheckIfChanged --> ConfirmChange: Slot different CheckIfChanged --> ReadAnalogValue: Slot same ConfirmChange --> UpdateSlot: Confirmed ConfirmChange --> ReadAnalogValue: Not confirmed UpdateSlot --> NotifyStateChange NotifyStateChange --> ReadAnalogValue ``` ## TODOS ### PERFORMANCE - Consider optimizing the moving average calculation for better performance - Evaluate if the current reading interval is optimal for the application - Investigate using hardware filtering in addition to software smoothing ### SECURITY - Implement range checking for analog readings to prevent unexpected behavior - Add validation for Modbus register access ### COMPLIANCE - Ensure compatibility with industrial standards for analog input processing - Verify noise immunity meets requirements for industrial environments ### RECOMMENDATIONS - Use 1% tolerance resistors in the voltage divider circuit for better accuracy - Ensure the voltage divider resistance values create sufficient separation between positions - Keep the overall equivalent resistance of the voltage divider in the 1kΩ to 100kΩ range - Add appropriate ESD protection for the analog input pin in industrial environments - When using mechanical switches, consider adding hardware debouncing in addition to software debouncing ## EXAMPLE Here's an example of how to initialize and use the AnalogLevelSwitch component: ```cpp #ifdef PIN_ANALOG_LEVEL_SWITCH_0 analogLevelSwitch_0 = new AnalogLevelSwitch( this, // owner PIN_ANALOG_LEVEL_SWITCH_0, // analogPin ALS_0_NUM_LEVELS, // numLevels ALS_0_ADC_STEP, // levelStep ALS_0_ADC_OFFSET, // adcValueOffset ID_ANALOG_LEVEL_SWITCH_0, // id ALS_0_MB_ADDR // modbusAddress ); if (analogLevelSwitch_0) { components.push_back(analogLevelSwitch_0); Log.infoln(F("AnalogLevelSwitch_0 initialized. Pin:%d, Levels:%d, Step:%d, Offset:%d, ID:%d, MB:%d"), PIN_ANALOG_LEVEL_SWITCH_0, ALS_0_NUM_LEVELS, ALS_0_ADC_STEP, ALS_0_ADC_OFFSET, ID_ANALOG_LEVEL_SWITCH_0, ALS_0_MB_ADDR); } else { Log.errorln(F("AnalogLevelSwitch_0 initialization failed.")); } #endif ``` ### References ${DOXYGEN_PLACEHOLDER} ${VENDOR_PLACEHOLDER}