Hi, i want to control my roller blinds with an encoder motor like those that rotate the chain.
I use esp32, 5v encoder motor, mx1508, txs0108e. 3 buttons for up, down and stop, long press on stop enter set limit mode. The issue is that it takes some time from when i brake the motor until it actually stop. I checked the count difference for both direction (up around 116 and down 122) but it can differ from time to time. I tested it on my curtain and its not so accurate. I wonder if there is a better approach to do this? I added my sample code here if someone want to take a look.
#include <OneButton.h>
#include "ESP32Encoder.h"
#include <ESP32MX1508.h>
#define CH1 0
#define CH2 1
#define IN1_PIN 4
#define IN2_PIN 17
#define ENCODER_SIGNAL_A 13
#define ENCODER_SIGNAL_B 14
#define UP_BUTTON_PIN 25
#define STOP_BUTTON_PIN 26
#define DOWN_BUTTON_PIN 27
#define SET_LIMIT_LED 33
OneButton upButton(UP_BUTTON_PIN);
OneButton stopButton(STOP_BUTTON_PIN);
OneButton downButton(DOWN_BUTTON_PIN);
bool isInSetLimitsMode = false;
bool isUpperLimitSet = true;
bool isLowerLimitSet = true;
int numOfStopClicks = 0;
MX1508 motor(IN1_PIN, IN2_PIN, CH1, CH2);
ESP32Encoder encoder;
bool isMotorRunning = false;
bool isGoingUp = false;
long currentEncoderPos = 0;
long upperLimitPos = 0;
long lowerLimitPos = 0;
void tickButtons()
{
stopButton.tick();
upButton.tick();
downButton.tick();
}
void curtainStop()
{
if (isMotorRunning)
{
motor.motorBrake();
delay(1000);
motor.motorStop();
isMotorRunning = false;
}
}
void curtainUp()
{
Serial.println("currentEncoderPos: " + String(currentEncoderPos) + " upperLimitPos: " + String(upperLimitPos));
if (currentEncoderPos < upperLimitPos || !isUpperLimitSet)
{
curtainStop();
motor.motorGo(255);
isMotorRunning = true;
isGoingUp = true;
}
else
{
Serial.println("motor in upper limit");
curtainStop();
}
}
void curtainDown()
{
Serial.println("currentEncoderPos: " + String(currentEncoderPos) + " lowerLimitPos: " + String(lowerLimitPos));
if (currentEncoderPos > lowerLimitPos || !isLowerLimitSet)
{
curtainStop();
motor.motorRev(255);
isMotorRunning = true;
isGoingUp = false;
}
else
{
Serial.println("motor in lower limit");
curtainStop();
}
}
void checkLimits()
{
if (isMotorRunning)
{
currentEncoderPos = encoder.getCount();
if (isGoingUp && currentEncoderPos >= (upperLimitPos - 116) && isUpperLimitSet)
{
Serial.println("Stopping motor at upper limit");
curtainStop();
}
if (!isGoingUp && currentEncoderPos <= (lowerLimitPos + 122) && isLowerLimitSet)
{
Serial.println("Stopping motor at lower limit");
curtainStop();
}
}
}
void curtainGoToPos(int targetPos)
{
targetPos = constrain(targetPos, 0, 100);
long targetEncoderPos = map(targetPos, 0, 100, upperLimitPos, lowerLimitPos);
Serial.println("currentEncoderPos: " + String(currentEncoderPos) + " targetEncoderPos: " + String(targetEncoderPos));
if (currentEncoderPos > targetEncoderPos)
{
targetEncoderPos += 122;
Serial.println("go to pos down: " + String(targetEncoderPos));
curtainDown();
while (currentEncoderPos > targetEncoderPos && isMotorRunning)
{
currentEncoderPos = encoder.getCount();
if (currentEncoderPos <= targetEncoderPos)
{
curtainStop();
break;
}
tickButtons();
}
}
else if (currentEncoderPos < targetEncoderPos)
{
targetEncoderPos -= 116;
Serial.println("go to pos up: " + String(targetEncoderPos));
curtainUp();
while (currentEncoderPos < targetEncoderPos && isMotorRunning)
{
currentEncoderPos = encoder.getCount();
if (currentEncoderPos >= targetEncoderPos)
{
curtainStop();
break;
}
tickButtons();
}
}
delay(1000);
Serial.println("adjsut = " + String(targetEncoderPos - encoder.getCount()));
}
void upButtonHandleClick()
{
Serial.println("clicked up button");
if (isInSetLimitsMode)
{
numOfStopClicks = 0;
}
curtainUp();
}
void downButtonHandleClick()
{
Serial.println("clicked down button");
if (isInSetLimitsMode)
{
numOfStopClicks = 0;
}
curtainDown();
}
void stopButtonHandleClick()
{
Serial.println("clicked stop button");
curtainStop();
if (isInSetLimitsMode)
{
numOfStopClicks++;
if (numOfStopClicks >= 2)
{
if (!isUpperLimitSet)
{
encoder.clearCount();
upperLimitPos = encoder.getCount();
Serial.println("upper limit has been set: " + String(upperLimitPos));
isUpperLimitSet = true;
numOfStopClicks = 0;
digitalWrite(SET_LIMIT_LED, LOW);
delay(1000);
digitalWrite(SET_LIMIT_LED, HIGH);
return;
}
else
{
lowerLimitPos = encoder.getCount();
Serial.println("lower limit has been set: " + String(lowerLimitPos));
isInSetLimitsMode = false;
isLowerLimitSet = true;
numOfStopClicks = 0;
digitalWrite(SET_LIMIT_LED, LOW);
return;
}
}
}
}
void stopButtonHandleLongPress(void *oneButton)
{
Serial.println("long press stop button");
isInSetLimitsMode = !isInSetLimitsMode;
if (isInSetLimitsMode)
{
digitalWrite(SET_LIMIT_LED, HIGH);
isUpperLimitSet = false;
isLowerLimitSet = false;
numOfStopClicks = 0;
}
else
{
digitalWrite(SET_LIMIT_LED, LOW);
}
}
void attachButtons()
{
upButton.attachClick(upButtonHandleClick);
downButton.attachClick(downButtonHandleClick);
stopButton.attachClick(stopButtonHandleClick);
stopButton.attachLongPressStart(stopButtonHandleLongPress, &stopButton);
stopButton.setPressMs(1000);
}
void setup()
{
Serial.begin(115200);
pinMode(SET_LIMIT_LED, OUTPUT);
attachButtons();
ESP32Encoder::useInternalWeakPullResistors = puType::up;
encoder.attachFullQuad(ENCODER_SIGNAL_A, ENCODER_SIGNAL_B);
encoder.clearCount();
}
void loop()
{
tickButtons();
long newEncoderPos = encoder.getCount();
if (newEncoderPos != currentEncoderPos)
{
currentEncoderPos = newEncoderPos;
}
checkLimits();
}