After spending hours of searching I’m finally ready to give up and ask for help.
I can’t find how to use the variable voltage given out by a potentiometer to tell ESPHome the position of a valve (or even cover).
Here’s the device I’m trying to control:
I have a motorised two position valve that is rotated with a simple DC motor through a wormdrive gearbox. There is a potentiometer connected to the valve’s rotating core. When you apply 12v the core rotates until it hits the end of motion and stalls. The potentiometer outputs 0.5v at this point. When you apply the reverse voltage, the core rotates until it stops and gives out 4.8v.
Every example and help page I’ve found so far only documents how to use some form of binary end stop switch to detect the end position of either a cover or valve. How can I use an analogue voltage given out by a potentiometer to determine the position?
Once I get it sorted I’ll post the full code here for others, as I don’t think there’s a single example of this on the internet yet.
With ADC component ? You’ll have to modify input voltage a bit, though. ESP accepts up to 3.3V if i’m not mistaken, while you have 4.8V, so a resistor voltage divider in between and you’re done.
Better than that, I’ll just supply the potentiometer with 3.3v from the ESP instead of the current 5v
And yeah I found the ADC component in my searching, but I can’t work out how to integrate it into either a cover or valve integration. Could you give me some help? It doesn’t need to be 100% functional code, just a rough example should help me on my way.
Can anyone give me an example of how that code would look? Even just example code blocks pasted together in the right order might be enough to set me on my journey.
At the moment I’m struggling to work out how to get the various parts to talk to eachother.
#measure the voltage
sensor:
- platform: adc
pin: GPIOXX
name: "potentiometer"
id: potentiometer
- platform: adc
sensor: potentiometer
name: “valve percent”
unit_of_measurement: “%”
filters:
- calibrate_linear:
- 0.5 -> 0.00
- 3.1 -> 100.00
#binary sensor is open or closed based on threshold value
binary_sensor:
- platform: analog_threshold
name: "valve"
id: valve
sensor_id: potentiometer
threshold: 2.5
valve:
- platform: template
name: "Valve"
lambda: |-
if (id(valve).state) =1 {
return VALVE_OPEN;
} else {
return VALVE_CLOSED;
}
And I am looking for any suggestion and improvement, because I am looking for the same kind of solution, but not sure the code above is correct.
Will it show as a valve?
There are a few different ways to skin the cat. Technically you could skip the whole copy sensor and processing all together, but practically with ADC you probably need it.
Awesome! Thank you for that. And any hints on getting this template to turn the valve via a LN298 motor driver?
In case it helps, this is the Arduino sketch I’m currently using to control the valve with the motor driver. You press one button and it opens, you press another button and it closes.
// Define the motor control pins
#define MOTOR_PIN1 9 // Motor driver input 1
#define MOTOR_PIN2 10 // Motor driver input 2
#define MOTOR_PWM 11 // Motor PWM (speed control)
// Define the button pins
#define BUTTON_PIN1 2 // Button 1 (Position 1)
#define BUTTON_PIN2 3 // Button 2 (Position 2)
// Define the potentiometer pin
#define POT_PIN A0 // Potentiometer to read valve position
// Define the target potentiometer values for the two positions
#define POSITION1 50 // Potentiometer value for position 1 (adjust as needed)
#define POSITION2 930 // Potentiometer value for position 2 (adjust as needed)
//910 is perfect spot for middle outlet flow
//850 is point that end connection is sealed
//113 is when middle is unsealed
int currentPos = 0; // Current position of the potentiometer
int targetPos = 0; // Target position based on button input
bool moving = false; // Motor movement state
void setup() {
// Initialize motor pins
pinMode(MOTOR_PIN1, OUTPUT);
pinMode(MOTOR_PIN2, OUTPUT);
pinMode(MOTOR_PWM, OUTPUT);
// Initialize button pins
pinMode(BUTTON_PIN1, INPUT_PULLUP); // Using internal pull-up resistors
pinMode(BUTTON_PIN2, INPUT_PULLUP);
// Start serial communication for debugging
Serial.begin(9600);
}
void loop() {
// Read the current potentiometer value
currentPos = analogRead(POT_PIN);
Serial.print("Current Position: ");
Serial.println(currentPos);
// Read button states
if (digitalRead(BUTTON_PIN1) == LOW) {
targetPos = POSITION1;
moving = true;
Serial.print("button one pressed");
}
if (digitalRead(BUTTON_PIN2) == LOW) {
targetPos = POSITION2;
moving = true;
Serial.print("button two pressed");
}
// Move the motor to the target position
if (moving) {
moveToPosition(targetPos);
}
}
// Function to move motor to target position
void moveToPosition(int target) {
int error = target - currentPos; // Calculate the error
// If error is small enough, stop moving
if (abs(error) < 20) {
stopMotor();
moving = false;
Serial.println("Position reached!");
} else {
// If target is greater than current, rotate motor forward
if (error > 0) {
digitalWrite(MOTOR_PIN1, HIGH);
digitalWrite(MOTOR_PIN2, LOW);
analogWrite(MOTOR_PWM, 255); // Full speed (adjust as needed)
Serial.println("motor forwards");
}
// If target is less than current, rotate motor backward
else {
digitalWrite(MOTOR_PIN1, LOW);
digitalWrite(MOTOR_PIN2, HIGH);
analogWrite(MOTOR_PWM, 255); // Full speed (adjust as needed)
Serial.println("motor backwards");
}
}
}
// Function to stop the motor
void stopMotor() {
analogWrite(MOTOR_PWM, 0); // Stop motor
digitalWrite(MOTOR_PIN1, LOW);
digitalWrite(MOTOR_PIN2, LOW);
}