EEPROM and mx1508 driver

Hello!
I am currently working on a project with a barrier based on esp8266 nodemcu. The difference is that I have to do it not with a servo, but with a simple gear motor.

image

When the touch button (TTP223) is pressed, the motor should rotate forward for 4 seconds and open the guard. And when you touch it, it should rotate backwards for 1 second and close the fence

That's where I had a problem.
The motor is not as smart as the servo. He does not understand whether to open the fence or close it. If you turn off the device when opening the fence and then turn it on, then when touching the motor tries to open the already open fence.

I want to solve this problem using EEPROM.
That is, when touched, the motor opens the fence and remembers the position (for example, open), and if there is still a touch, the motor closes the fence and clears and adds a new value to the EEPROM (for example, closed)
I think this is how I can solve this problem

Full sketch:

int s1 = D2;
int s2 = D3;
int o1 = D0;
int o2 = D1;
void setup() {
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(o1, OUTPUT);
  pinMode(o2, OUTPUT);
  pinMode(D1, INPUT);
}
void loop() {
  //If the value in the EEPROM is closed
  if (digitalRead(D1) == HIGH) {
    digitalWrite(s1, HIGH);
    delay(4000);
    digitalWrite(s1, LOW);
  }
  //If the value in the EEPROM is open
  if (digitalRead(D1) == HIGH) {
    digitalWrite(s2, HIGH);
    delay(1000);
    digitalWrite(s2, LOW);

  }
}

Please help me solve this problem

Hello muhammedjan

Take view to gain the knowledge.

1 Like

Is it possible to write a word in EEPROM?

int s1 = D2;
int s2 = D3;
int o1 = D0;
int o2 = D1;
#include <EEPROM.h>
char buffer[100];
char valueOnEeprom[100];
void setup() {
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(o1, OUTPUT);
  pinMode(o2, OUTPUT);
  pinMode(D1, INPUT);
}
void loop() {
  //If the value in the EEPROM is open
  if (digitalRead(D1) == HIGH) {
    digitalWrite(s1, HIGH);
    delay(4000);
    digitalWrite(s1, LOW);
    //Write the word "close" in the EEPROM
  }
  //If the value in the EEPROM is close
  if (digitalRead(D1) == HIGH) {
    digitalWrite(s2, HIGH);
    delay(1000);
    digitalWrite(s2, LOW);
    //Write the word "open" in the EEPROM
  }
}

Didn´t you read and study how to use an EEPROM, did you?

1 Like

Yes, I have read and used EEPROM before for other purposes. Then I wrote down the numbers.
But now, at this moment, I don't understand how to write down a word, and then compare it and do something.

Isn't that what limit switches are for?

With limit switches for the up and down positions, you would know whether the barrier was up, down or somewhere in between.

That's not going to work reliably. What if the boom is e.g. half open. Do you still want to turn for 4 seconds. See reply #6 by @markd833 .

Don't use words, just use numbers like 0 for closed and 1 for open.

A post was split to a new topic: Arduino + PID + Valve?

On your advice, I'm testing it now. But there were some problems. I use limit switch

Here is the full code:

int s1 = D2;
int s2 = D3;
#include <ezButton.h>
ezButton limitSwitch(D4);
ezButton limitSwitch2(D1);
void setup() {
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(D5, INPUT);
  limitSwitch.setDebounceTime(50);
  limitSwitch2.setDebounceTime(50);

  /*
    limitSwitch.loop();
    int state = limitSwitch.getState();
    if (state == LOW) {                             //The motor turns and stops when button 1 is pressed
     digitalWrite(s1, LOW);
     Serial.println("asd1");
    } else {
     digitalWrite(s1, HIGH);
    }
    break;
  */
}

void loop() {
  limitSwitch.loop(); // MUST call the loop() function first
  int state = limitSwitch.getState();
  int statee = limitSwitch2.getState();

  if (digitalRead(D5) == 0) { //if there is a touch

    //if (state == LOW){  The first button is activated
    //digitalWrite(s2, HIGH); turn the motor back
    //if (statee == LOW){
    //{digitalWrite(s2, LOW);} Turn until the button 2 is activated

    // if (statee == LOW){ and if the second button is activated
    // digitalWrite(s1, HIGH); turn the motor back
    // if (state == LOW){digitalWrite(s1, LOW);} Twist until 1 button is activated

  }
}

Try enabling the internal pullup resistor on the pin with the microswitch.

Note that you may need to use an external pullup resistor - maybe 1K - if you have issues using the internal pullups.

Your switch is connected to D7 in the picture but your code isn't looking at that pin.

I mean, everything works for me.
I can't construct the correct algorithm.

Here I want to turn the motor back until it touches the button 1

It works for me, but after releasing the button, the motor starts turning again.

void setup() {
/*
    limitSwitch.loop();
    int state = limitSwitch.getState();
    if (state == LOW) {                             //The motor turns and stops when button 1 is pressed
     digitalWrite(s1, LOW);
     Serial.println("asd1");
    } else {
     digitalWrite(s1, HIGH);
    }
    break;
  */
}

The limit switch shouldn't really make the motor change direction. The job of the limit switch in this scenario is to let the software know that an object (in this case the barrier) has reached a predetermined position.

Your project may benefit from a simple state machine such that:

State 0: UNKNOWN - the barrier is not fully up or fully down (usually at power on)
State 1: DOWN - the down limit switch is activated
State 2: GOING_UP - barrier is moving up & waiting for up limit switch to activate
State 3: UP - the up limit switch is activated
State 4: GOING_DOWN - barrier is moving down & waiting for the down limit switch to activate.

You can achieve this with a simple switch statement.

Your touch button will then perform a different function depending on which state your barrier is in.

In state 1, touching the button moves the barrier to state 2 where you activate the motor to raise the barrier. In state 3, touching the button moves the barrier to state 4 where you activate the motor to lower the barrier.

In state 2, you look for the up limit switch and when it is activated, you stop the motor and move to state 3. Similarly in state 4, you look for the down limit switch and when it is activated, you stop the motor and move to state 1.

1 Like

Thank you for the detailed information!
Difficulties and questions appeared during the execution.
The previously agreed 5 position of the button are all inside the switch case?
I mean, the state is UNKNOWN, shouldn't it be in setup?


 switch (var) {
    case 1:
      if (state == HIGH && statee == HIGH)
      {
        digitalWrite(s2, HIGH);
      }
      break;
  }

Am I going the right way?

Ok, here's a bit of untested code that I quickly put together that should demonstrate the use of a simple state machine. You will need to tweek it for your specific limit switch and touch switch connections and insert your code that activates your motor.

enum barrierStates {
  UNKNOWN,
  DOWN,
  GOING_UP,
  UP,
  GOING_DOWN
};

enum barrierStates barrierState;

const uint8_t upLimitSwitchPin = 4;    // UNO pin 4
const uint8_t downLimitSwitchPin = 5;  // UNO pin 5
const uint8_t touchSwitchPin = 6;      // UNO Pin 6

uint8_t upLimitSwitch;
uint8_t downLimitSwitch;
uint8_t touchSwitch;
uint8_t prevTouchSwitch;

void setup() {
  Serial.begin(9600);
  pinMode( upLimitSwitchPin, INPUT_PULLUP );
  pinMode( downLimitSwitchPin, INPUT_PULLUP );
  pinMode( touchSwitchPin, INPUT_PULLUP );

  delay(100);
  touchSwitch = digitalRead( touchSwitchPin );
  prevTouchSwitch = touchSwitch;
  
  // a HIGH here means the limit switch is open
  upLimitSwitch = digitalRead( upLimitSwitchPin );
  downLimitSwitch = digitalRead( downLimitSwitchPin );
  
  // determine the initial barrier position
  if ( upLimitSwitch == LOW && downLimitSwitch == LOW ){
    Serial.println(F("ERROR - both limit switches activated"));
    while(1);
  }
  else if ( upLimitSwitch == HIGH && downLimitSwitch == HIGH ){
    barrierState = UNKNOWN;
    Serial.println(F("BARRIER POSITION UNKNOWN"));
  }
  else if ( upLimitSwitch == LOW ) {
    Serial.println(F("BARRIER UP"));
    barrierState = UP;
  }
  else {
    Serial.println(F("BARRIER DOWN"));
    barrierState = DOWN;
  }
}

void loop() {
  // assume HIGH = switch touched
  touchSwitch = digitalRead( touchSwitchPin );

  switch ( barrierState ) {
    case UNKNOWN:
      // INSERT YOUR CODE TO ACTIVATE MOTOR TO MAKE BARRIER GO UP
      upLimitSwitch = digitalRead( upLimitSwitchPin );
      if ( upLimitSwitch == LOW ) {
        // INSERT YOUR CODE TO STOP MOTOR
        Serial.println(F("BARRIER UP"));
        barrierState = UP;
      }
      break;
      
    case DOWN:
      if (( touchSwitch != prevTouchSwitch ) && ( touchSwitch == HIGH ) ) {
        // INSERT YOUR CODE TO ACTIVATE MOTOR TO MAKE BARRIER GO UP
        Serial.println(F("BARRIER GOING UP"));
        barrierState = GOING_UP;
      }
      break;
      
    case GOING_UP:
      upLimitSwitch = digitalRead( upLimitSwitchPin );
      if ( upLimitSwitch == LOW ) {
        // INSERT YOUR CODE TO STOP MOTOR
        Serial.println(F("BARRIER UP"));
        barrierState = UP;
      }
      break;
      
    case UP:
      if (( touchSwitch != prevTouchSwitch ) && ( touchSwitch == HIGH ) ) {
        // INSERT YOUR CODE TO ACTIVATE MOTOR TO MAKE BARRIER GO DOWN
        Serial.println(F("BARRIER GOING DOWN"));
        barrierState = GOING_DOWN;
      }
      break;
      
    case GOING_DOWN:
      downLimitSwitch = digitalRead( downLimitSwitchPin );
      if ( downLimitSwitch == LOW ) {
        // INSERT YOUR CODE TO STOP MOTOR
        Serial.println(F("BARRIER DOWN"));
        barrierState = DOWN;
      }
      break;
  }
  prevTouchSwitch = touchSwitch;
}
1 Like

Thank you very much! With your help, it worked)

I have one question. What to do if, in the process of closing or opening, the barrier rests against an object and this does not allow the process to be completed. How can I set a timer for 5 seconds in this case?
That is, after 5 seconds, it does not return to the specified button, the touch touch allows itself to be pressed again.
For example: pressed the touch the barrier opens and he cannot fully open the object rests. After 5 seconds, if you press touch, it is back

Generally I guess you would have either sensors on the barrier or a way of monitoring the motor current to detect that the barrier has come into contact with another object. You would probably want to know quicker than 5 seconds that the barrier has hit an object, otherwise you risk damaging that object and/or burning out the motor.

You could then either simply stop the barrier where it is or get it to reverse its direction.

You could add 2 new states: GOING_UP_OBJECT_IN_WAY and GOING_DOWN_OBJECT_IN_WAY.

When you are in GOING_UP and you detect an object in the way, you enter the GOING_UP_OBJECT_IN_WAY state. Here you decide what to do next, how long to wait etc. Same for GOING_DOWN.

1 Like

Thanks!
But in my case, the barrier sometimes has to collide with an object. And the engine should not stop and turn on until the end. :grin:
And if the barrier does not return to the button within 5 seconds after opening, the touch touch allows you to press again on your own.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.