Hi guys, I’m in the process of making a motorized linear fader, but I’m having some problems measuring the potentiometer. When I choose a position, the value is varying a lot. To the point of not being useful because when I map from 0 to 100, it varies +2 / -2.
I’ve read and the max I found was that to improve the potentiometer reading, I should use a resistor and a capacitor. But I do not know the values nor the location.
I have not yet decided where I will do the final coding. If it will be in esphome or arduino. I’m undecided with this because I still can’t get the potenciometer to the position I want.
If you can help me, thank you very much. I have a little bit of knowledge, but I do not know electronic components to filter or improve the project.
The points I want in this project are:
- An accessory to connect to Home Assistant.
- An entity input_number from 0 - 100, to receive the measuring of the potentiometer and also to input the level for the motor to go to the selected level.
- Knob Touch.
Dream Features:
- An entity to control the Variable Tactile Feedback on the Linear Slide to feel the levels on the knob. (Ex: 6 will create the virtual “creases” on this levels 0% - 20% - 40% - 60% - 80% - 100% ).
(Ex: 11 will create the virtual “creases” on this levels 0% - 10% - 20% - 30% - 40% - 50% - 60% - 70% - 80% - 90% - 100% ).
The hardware:
- Motorized Slide Linear Potentiometer Touch Sensitive 10k rsa0n11m9
- H-Bridge DC Stepper Motor-Driver Board L9110S
- ESP32 CH340C Type-C
- (Prototyping) Breadboard 830 with Power Supply MB102
- (Not Yet) 4-Digit 7-Segment Display TM1637
Schematic:
The code I have today on the ESPHome:
esphome:
name: slider
friendly_name: Slider
esp32:
board: esp32dev
# framework:
# type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
ota:
password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Slider Fallback Hotspot"
password: !secret wifi_password
captive_portal:
globals:
- id: new_position
type: float
restore_value: no
number:
- platform: template
name: HA Input Percentage
id: ha_input_percentage
min_value: 0
max_value: 100
step: 1
optimistic: true
sensor:
- platform: adc
id: analog_read_fader
pin: A0
name: "Analog Read Fader"
update_interval: 0.005s
accuracy_decimals: 3
attenuation: 11db
# filters:
# - median:
# window_size: 20
# send_every: 1
# - calibrate_linear:
# - 0.14200 -> 0
# - 3.13400 -> 100
- platform: template
name: "Percentage Fader"
id: percentage_fader
lambda: |-
return (id(analog_read_fader).state - 0.142) * (100 - 0) / (3.134 - 0.142) + 0;
update_interval: 0.005s
accuracy_decimals: 0
esp32_touch:
setup_mode: false
binary_sensor:
- platform: esp32_touch
id: touch_fader
name: "Touch Fader"
pin: GPIO33
threshold: 330
output:
- platform: ledc
id: pinA
pin: GPIO22
- platform: ledc
id: pinB
pin: GPIO23
fan:
- platform: hbridge
id: motor_fader
name: "Motor Fader"
pin_a: pinA
pin_b: pinB
decay_mode: slow
The code I have today on the Arduino:
#define FILTER_LEN 5
uint32_t AN_Pot1_Buffer[FILTER_LEN] = {0};
int AN_Pot1_i = 0;
int AN_Pot1_Raw = 0;
int AN_Pot1_Filtered = 0;
// Motor Pins
const int pwmA = 22;
const int pwmB = 23;
bool motor_release_state = false; // to handle motor release
// Fader Pin and Variables
const int fader = A0;
const int touchPin = A5;
int fader_pos = 0;
float filter_amt = 0.75;
float speed = 1.0;
const int touchThreshold = 15;
int baseline;
// float step = 40.92;
// int saved_positions[] = { 230 };
// int current_saved_position = 1 ;
void setup() {
Serial.begin(115200);
Serial.println("!! Initializing .... !!");
delay(1000);
pinMode(touchPin, INPUT);
pinMode (pwmA, OUTPUT);
pinMode (pwmB, OUTPUT);
analogWriteFrequency(100);
analogWrite(pwmA, 0);
analogWrite(pwmB, 0);
baselineTouch();
// for (uint8_t i=0; i< num_buttons; i++){
// buttons[i].attach( button_pins[i], INPUT_PULLUP);
// }
}
int last_fader_pos = fader_pos;
void loop() {
// for (uint8_t i=0; i< num_buttons; i++){
// buttons[i].update();
// if( buttons[i].fell()) {
// current_saved_position = i;
// go_to_position(saved_positions[current_saved_position]);
// }
// }
if( isTouched() ){
Serial.println("Touched");
// motor_release_state = true;
motor_release_state = false;
go_to_position(25);
// delay(1000);
// go_to_position(75);
// delay(1000);
// go_to_position(0);
// delay(1000);
// go_to_position(100);
// analogWrite(pwmA, 0);
// analogWrite(pwmB, 0);
// delay(60);
}
else{
// Serial.println("NOT Touched");
motor_release_state = false;
// go_to_position(saved_positions[current_saved_position]);
}
fader_pos = int( (filter_amt * last_fader_pos) + ( (1.0-filter_amt) * int(analogRead(fader) )) );
// int mappedFader = map(fader_pos, 3, 4095, 0, 100);
// int mappedLast_fader_pos = map(last_fader_pos, 3, 4095, 0, 100);
// Serial.println("-------------------------------------------");
// Serial.print("Fader: ");
// Serial.println(fader_pos);
// Serial.print("Fader Mapped: ");
// Serial.println(mappedFader);
// Serial.print("last_fader_pos: ");
// Serial.println(last_fader_pos);
// Serial.print("last_fader_pos Mapped: ");
// Serial.println(mappedLast_fader_pos);
AN_Pot1_Raw = analogRead(fader);
AN_Pot1_Filtered = readADC_Avg(AN_Pot1_Raw);
int mappedAN_Pot1_Filtered = map(AN_Pot1_Filtered, 0, 4095, 0, 100);
// Serial.print(AN_Pot1_Raw); // Print Raw Reading
// Serial.print(','); // Comma Separator
Serial.print(AN_Pot1_Filtered); // Print Filtered Output
Serial.print(" | "); // Print Filtered Output
Serial.print(mappedAN_Pot1_Filtered); // Print Filtered Output
if (abs(AN_Pot1_Filtered - last_fader_pos) > 1) {
// if (motor_release_state==false){
// go_to_position(saved_positions[current_saved_position]);
// }
last_fader_pos = AN_Pot1_Filtered;
}
Serial.println("");
}
void go_to_position(int new_position_percentage) {
int new_position = map(new_position_percentage, 0, 100, 0, 4095);
// int new_position = new_position_percentage * step;
// int new_position_next = (new_position_percentage + 1) * step;
// new_position = new_position + (step/2);
// if ( new_position > 4095 ) {
// new_position = 4095;
// }
Serial.print("!! new_position: ");
Serial.println(new_position);
int fader_pos_raw = analogRead(fader);
fader_pos = readADC_Avg(fader_pos_raw);
// fader_pos = int(analogRead(fader));
int last_fader = fader_pos;
Serial.print("@@ fader_pos: ");
Serial.println(fader_pos);
// Serial.print("## new_position_next: ");
// Serial.println(new_position_next);
Serial.print("$$ while: ");
Serial.println(abs(fader_pos - new_position));
while (!(abs(fader_pos - new_position) <= 10)) {
// while (new_position <= fader_pos && fader_pos < new_position_next) {
// Serial.print("!! new_position: ");
// Serial.println(new_position);
// Serial.print("%% last_fader: ");
// Serial.println(last_fader);
// Serial.print("@@ fader_pos: ");
// Serial.println(fader_pos);
// Serial.print("## new_position_next: ");
// Serial.println(new_position_next);
Serial.print("Fader Inicio: ");
Serial.println(fader_pos);
Serial.print("$$ Diff: ");
Serial.println(abs(fader_pos - new_position));
Serial.print("$$ WHILE: ");
Serial.println(!(abs(fader_pos - new_position) <= 15));
if ( fader_pos > new_position ) {
// Serial.println("fader_pos MAIOR");
// speed = 2.25 * abs(fader_pos - new_position) / 1024 + 0.2;
// speed = constrain(speed, -1.0, 1.0);
// if (speed > 0.0) {
analogWrite(pwmA, 150);
analogWrite(pwmB, 0);
// delay(30);
// analogWrite(pwmA, 0);
// }
}
if ( fader_pos < new_position ) {
// Serial.println("new_position MAIOR");
// speed = 2.25 * abs(fader_pos - new_position) / 1024 - 0.2;
// speed = constrain(speed, -1.0, 1.0);
// if (speed > 0.0) {
analogWrite(pwmA, 0);
analogWrite(pwmB, 150);
// delay(30);
// analogWrite(pwmB, 0);
// }
}
// delay(200);
// analogWrite(pwmA, 0);
// analogWrite(pwmB, 0);
// delay(50);
last_fader = fader_pos;
fader_pos_raw = analogRead(fader);
fader_pos = readADC_Avg(fader_pos_raw);
// fader_pos = analogRead(fader);
Serial.print("Fader: ");
Serial.println(fader_pos);
if (abs(fader_pos - new_position) <= 10) {
Serial.println("BREAAAK");
analogWrite(pwmA, 0);
analogWrite(pwmB, 0);
}
// Serial.println("-------------------------------------------- ");
}
analogWrite(pwmA, 0);
analogWrite(pwmB, 0);
}
void baselineTouch() {
baseline = touchRead(touchPin);
}
bool isTouched() {
// Serial.print("isTouched(): ");
// Serial.println(readTouch() < baseline - touchThreshold);
// Serial.print("baseline: ");
// Serial.println(baseline);
// Serial.print("touchThreshold: ");
// Serial.println(touchThreshold);
return (readTouch() < baseline - touchThreshold);
}
int readTouch() {
// Serial.print("readTouch(): ");
// Serial.println(touchRead(touchPin));
return touchRead(touchPin);
}
uint32_t readADC_Avg(int ADC_Raw) {
int i = 0;
uint32_t Sum = 0;
AN_Pot1_Buffer[AN_Pot1_i++] = ADC_Raw;
if(AN_Pot1_i == FILTER_LEN)
{
AN_Pot1_i = 0;
}
for(i=0; i<FILTER_LEN; i++)
{
Sum += AN_Pot1_Buffer[i];
}
// Serial.println(Sum/FILTER_LEN);
return (Sum/FILTER_LEN);
}
The readings I got from HA and ESPHome. Period of 5 min. Analog readings from 0.142 to 3.134. The knob was on 75%ish.