FastLED 3.10.8
Loading...
Searching...
No Matches
potentiometer.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/stl/stdint.h"
4#include "fl/stl/function.h"
5#include "fl/stl/shared_ptr.h" // For FASTLED_SHARED_PTR macros
6#include "fl/stl/noexcept.h"
7
8namespace fl {
9
10// Low-level potentiometer class for direct ADC reading without callbacks.
11// This class provides raw hardware access without automatic updates.
13 public:
19
20 // Read raw ADC value (0-1023 for 10-bit, 0-4095 for 12-bit ADC)
21 u16 read() FL_NO_EXCEPT;
22
23 int getPin() const FL_NO_EXCEPT { return mPin; }
24
25 private:
26 int mPin;
27};
28
29// High-level potentiometer class with automatic updates and callback support.
30// This class hooks into FastLED EngineEvents to monitor value changes each frame.
31// Includes hysteresis to prevent noise-induced callback spam.
32// Supports calibration to map raw ADC values to normalized range (0.0-1.0).
34 public:
35 // Constructor
36 // @param pin: Analog pin number
37 // @param hysteresis: Minimum raw ADC change to trigger callbacks (0 = auto: 1% of calibrated range)
38 Potentiometer(int pin, u16 hysteresis = 0) FL_NO_EXCEPT;
39
40 // ========================================================================
41 // Value Accessors
42 // ========================================================================
43
44 // Get raw ADC value (0-1023 for 10-bit, 0-4095 for 12-bit ADC)
45 u16 raw() const FL_NO_EXCEPT { return mCurrentValue; }
46
47 // Get normalized float value (0.0f - 1.0f) based on calibration range
48 // Maps mMinValue -> 0.0f and mMaxValue -> 1.0f
49 // Values outside range are clamped to [0.0, 1.0]
50 float normalized() const FL_NO_EXCEPT;
51
52 // Get fractional 16-bit value (0 - 65535) for high-precision integer math
53 // Based on calibration range (mMinValue -> 0, mMaxValue -> 65535)
54 u16 fractional16() const FL_NO_EXCEPT;
55
56 // Check if value changed this frame (beyond hysteresis threshold)
57 bool hasChanged() const FL_NO_EXCEPT { return mChangedThisFrame; }
58
59 // ========================================================================
60 // Callback Registration
61 // ========================================================================
62
63 // Register callback with Potentiometer reference (can access all value formats)
64 int onChange(fl::function<void(Potentiometer &)> callback) FL_NO_EXCEPT;
65
66 // Register callback with normalized float value (convenience overload)
67 int onChange(fl::function<void(float)> callback) FL_NO_EXCEPT;
68
69 // Remove callback by ID
71 mOnChangeCallbacks.remove(id);
73 }
74
75 // ========================================================================
76 // Configuration
77 // ========================================================================
78
79 // Set hysteresis threshold in raw ADC units (e.g., 10 = must change by 10 ADC counts)
80 void setHysteresis(u16 threshold) FL_NO_EXCEPT { mHysteresis = threshold; }
81
82 // Set hysteresis as percentage of calibrated range (0.0-100.0)
83 // Example: 1.0 = 1% of (mMaxValue - mMinValue)
84 void setHysteresisPercent(float percent) FL_NO_EXCEPT;
85
86 // Get current hysteresis threshold in raw ADC units
87 u16 getHysteresis() const FL_NO_EXCEPT { return mHysteresis; }
88
89 // ========================================================================
90 // Calibration (Range Mapping)
91 // ========================================================================
92
93 // Set the raw ADC range that maps to normalized [0.0, 1.0]
94 // @param min: Raw ADC value that maps to 0.0 (default: 0)
95 // @param max: Raw ADC value that maps to 1.0 (default: ADC max value)
96 // Example: setRange(100, 900) maps 100->0.0, 900->1.0, values outside are clamped
97 void setRange(u16 min, u16 max) FL_NO_EXCEPT;
98
99 // Get the minimum raw value (maps to 0.0 in normalized)
100 u16 getRangeMin() const FL_NO_EXCEPT { return mMinValue; }
101
102 // Get the maximum raw value (maps to 1.0 in normalized)
103 u16 getRangeMax() const FL_NO_EXCEPT { return mMaxValue; }
104
105 // Calibrate to current position as minimum (0.0)
107
108 // Calibrate to current position as maximum (1.0)
110
111 // Reset calibration to full ADC range
116
117 // ========================================================================
118 // Test Helpers (for unit testing only)
119 // ========================================================================
120
121#ifdef FASTLED_UNIT_TEST
122 // Inject a test value directly (bypasses analogRead)
123 // Only available in unit test builds
124 void injectTestValue(u16 value) {
126 // Manually trigger change detection logic
127 u16 diff = (value > mLastValue) ? (value - mLastValue) : (mLastValue - value);
128 mChangedThisFrame = (diff >= mHysteresis);
129 if (mChangedThisFrame) {
131 mOnChangeCallbacks.invoke(*this);
132 float normalized_value = normalized();
133 mOnChangeNormalizedCallbacks.invoke(normalized_value);
134 }
135 }
136#endif
137
138 protected:
143
144 // Update on end frame (before next frame is drawn, matching Button behavior)
145 void onEndFrame() FL_NO_EXCEPT override;
146
147 private:
149 bool added = false;
150 };
151
152 private:
155
156 u16 mCurrentValue = 0; // Current raw ADC value
157 u16 mLastValue = 0; // Last value that triggered callbacks
158 u16 mHysteresis = 0; // Hysteresis threshold in raw ADC units
159 bool mChangedThisFrame = false; // True if changed beyond hysteresis this frame
160
161 // Calibration range: raw ADC values that map to normalized [0.0, 1.0]
162 u16 mMinValue = 0; // Raw value that maps to 0.0 (default: 0)
163 u16 mMaxValue = 0; // Raw value that maps to 1.0 (default: ADC max)
164
165 fl::function_list<void(Potentiometer &)> mOnChangeCallbacks;
166 fl::function_list<void(float)> mOnChangeNormalizedCallbacks;
167
168 // Get ADC resolution (10-bit = 1023, 12-bit = 4095)
169 u16 getAdcMaxValue() const FL_NO_EXCEPT;
170
171 // Calculate default hysteresis (1% of calibrated range)
173};
174
175} // namespace fl
void setHysteresis(u16 threshold) FL_NO_EXCEPT
u16 getRangeMin() const FL_NO_EXCEPT
void calibrateMax() FL_NO_EXCEPT
bool hasChanged() const FL_NO_EXCEPT
void resetCalibration() FL_NO_EXCEPT
int onChange(fl::function< void(Potentiometer &)> callback) FL_NO_EXCEPT
void setRange(u16 min, u16 max) FL_NO_EXCEPT
void calibrateMin() FL_NO_EXCEPT
u16 getAdcMaxValue() const FL_NO_EXCEPT
u16 getRangeMax() const FL_NO_EXCEPT
fl::function_list< void(float)> mOnChangeNormalizedCallbacks
fl::function_list< void(Potentiometer &)> mOnChangeCallbacks
u16 calculateDefaultHysteresis() const FL_NO_EXCEPT
u16 fractional16() const FL_NO_EXCEPT
void setHysteresisPercent(float percent) FL_NO_EXCEPT
u16 raw() const FL_NO_EXCEPT
Potentiometer(int pin, u16 hysteresis=0) FL_NO_EXCEPT
float normalized() const FL_NO_EXCEPT
u16 getHysteresis() const FL_NO_EXCEPT
PotentiometerLowLevel mPot
void removeOnChange(int id) FL_NO_EXCEPT
int getPin() const FL_NO_EXCEPT
PotentiometerLowLevel(const PotentiometerLowLevel &other) FL_NO_EXCEPT=default
PotentiometerLowLevel(PotentiometerLowLevel &&other) FL_NO_EXCEPT=delete
PotentiometerLowLevel & operator=(const PotentiometerLowLevel &other) FL_NO_EXCEPT=delete
PotentiometerLowLevel(int pin) FL_NO_EXCEPT
constexpr common_type_t< T, U > max(T a, U b) FL_NO_EXCEPT
Definition math.h:75
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
constexpr int type_rank< T >::value
FL_DISABLE_WARNING_PUSH U constexpr common_type_t< T, U > min(T a, U b) FL_NO_EXCEPT
Definition math.h:71
Base definition for an LED controller.
Listener(Potentiometer *owner) FL_NO_EXCEPT
void addToEngineEventsOnce() FL_NO_EXCEPT
void onEndFrame() FL_NO_EXCEPT override