Limit switch to stop DC motor

Hi,

I've looked all over the web, and what I found makes me think what I have should work, but it doesn't.

My project is to activate a ball valve using D1 Wemos Mini ESP8266 to cut the hot water supply :slight_smile: (4 daugthers and 1 son).

In a nutshell:

  • Valve works when the "limit switches" are not in the sketch. But this is not viable as the ball valve is activated far too long.
  • Valve works for only like 1 seconds if the "limit switches" are used in the sketch. Then it waits for like 10 seconds, and move for another 1 seconds. Repeats until it is in position. But only sometimes. Sometimes it does not work at all.

The long story:

The ball valve has five wires:

  • 2 wires for the 5VDC motor
  • 3 wires to tell the state of the valve (fully opened or fully closed). So one common, and the common is connected internally in the valve to one of the other wires depending if the valve is fully closed or fully opened. Lets call those 3 wires the two "limit switches".

I connected 3.3 V of D1 Wemos to the common wire of the "limit switches". Then the other two wires go to my pins D5 and D6 which are set as inputs.

If I do not use the "limit switches" in my code, it works. I can activate the valve via my internet browser. But the valve is kept activated for like 20-25 seconds, which is far too long. (As a matter of fact, I do not understand why it is only activated 20-25 seconds. To my understanding, if I do not use the "limit switches", the valve should be kept activated by the board.)

The whole sketch that does not use the limit switches is:

//This example will use a static IP to control the switching of a relay. Over LAN using a web browser. 
//A lot of this code have been resued from the example on the ESP8266 Learning Webpage below. 
//http://www.esp8266learning.com/wemos-webserver-example.php

//CODE START 
//1
#include <ESP8266WiFi.h>

// Below you will need to use your own WIFI informaiton.
//2
const char* ssid = "*******"; //WIFI Name, WeMo will only connect to a 2.4GHz network.
const char* password = "*******"; //WIFI Password

//defining the pin and setting up the "server"
//3
int openPin = D1; 
int closePin = D2; 
int valveOpenedPin = D5; 
int valveClosedPin = D6;
WiFiServer server(80);
IPAddress ip(192, 168, 1, 199); // where xx is the desired IP Address
IPAddress gateway(192, 168, 1, 1); // set gateway to match your network
IPAddress subnet(255, 255, 255, 0); // set subnet mask to match your network


// void setup is where we initialize variables, pin modes, start using libraries, etc. 
//The setup function will only run once, after each powerup or reset of the wemos board.
//4
void setup() {
  Serial.begin(115200);
  delay(10);
 

pinMode(openPin, OUTPUT);
pinMode(closePin, OUTPUT);
pinMode(valveOpenedPin, INPUT);
pinMode(valveClosedPin, INPUT);
digitalWrite(openPin, LOW);
digitalWrite(closePin, LOW);
 
  Serial.print(F("Setting static ip to : "));
  Serial.println(ip);
  
  // Connect to WiFi network
  //5
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.config(ip, gateway, subnet); 
  WiFi.begin(ssid, password);
  //Trying to connect it will display dots
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
 
  // Start the server
  server.begin();
  Serial.println("Server started");
 
  // Print the IP address
  Serial.print("Use this URL : ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/"); 
}

//void loop is where you put all your code. it is a funtion that returns nothing and will repeat over and over again
//6
void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
 
  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }
 
  // Read the first line of the request
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();
 
  //Match the request, checking to see what the currect state is
  int value = LOW;
  if (request.indexOf("/relay=ON") != -1) {
    digitalWrite(closePin, LOW);
    digitalWrite(openPin, HIGH);
    value = HIGH;
  } 
  if (request.indexOf("/relay=OFF") != -1){
    digitalWrite(openPin, LOW);
    digitalWrite(closePin, HIGH);
    value = LOW;
  }
  // Return the response, build the html page
  //7
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); //  do not forget this one
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
 
 
  if(value == HIGH) {
    client.print("Il y a de l'eau chaude");  
  } else {
    client.print("L'eau chaude est fermée!!!");
  }
  client.println("


");
  client.println("<a href=\"/relay=ON\">Ouvrir l'eau chaude.</a> 


");
  client.println("<a href=\"/relay=OFF\">Fermer l'eau chaude.</a>
");
  client.println("</html>");
 
  delay(1);
  Serial.println("Client disconnected");
  Serial.println("");
 
}//END

Within this code, the lines that control the valve are:

  if (request.indexOf("/relay=ON") != -1) {
    digitalWrite(closePin, LOW);
    digitalWrite(openPin, HIGH);
    value = HIGH;
  } 
  if (request.indexOf("/relay=OFF") != -1){
    digitalWrite(openPin, LOW);
    digitalWrite(closePin, HIGH);
    value = LOW;
  }

Now, using the "limit switches" I changed the section that control the valve to:

  if (request.indexOf("/relay=ON") != -1) {
    while (digitalRead(valveOpenedPin) == LOW) {
      digitalWrite(closePin, LOW);
      digitalWrite(openPin, HIGH);
    }
      digitalWrite(openPin, LOW);
    value = HIGH;
  }
  if (request.indexOf("/relay=OFF") != -1) {
    while (digitalRead(valveClosedPin) == LOW) {
      digitalWrite(openPin, LOW);
      digitalWrite(closePin, HIGH);
    }
      digitalWrite(closePin, LOW);
    value = LOW;
  }

The way I read my second sketch that incorporates my "limit swithes" is:

  • If I switch the relay ON to open the ball valve,
  • As long as pin D5 (valveOpenedPin) does not receive 3.3 V;
  • The ball valve will be activated through pin D1 (openPin);

The thing is the ball valve is only activated for something like 1 second. A complete cycle of the valve is around 5 seconds.

Could you help me on that please?

Thanks guys!

Hi,
How have you got your limit switches wired?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
Have you got 10K pull down resistors on the digital inputs that the limit switches are connected to?
The pull down resistors ensure the digital input goes LOW when your limit switches are OPEN.

The resistors go from the digital input pin to gnd, one for each input.

Tom.. :slight_smile:

Hi Tom,

Thanks for reaching out to help me!

The "limit switches" are wired as normally opened. And they become closed contacts once the valve is either fully opened or fully closed.

I connected them to the Wemos Mini so they send the 3.3 V as input on pins D5 and D6.

I attached an annotated picture of my breadboard, which I think will give a pretty good idea of my wiring.

No, I do not have pull down 10k resistors. If I understand you correctly, without those 10 K resistors, pins D5 and D6 will see small voltage and see the inputs as HIGH?

I am not too much familiar with this. Should I connect the 10k resistor like this:

D5/D6 on Wemos ----------------/////---------GND
|
|
|
3.3 V from limit switch

Thanks a lot!
Alex

most of us think that on and off is black and white but that's not true when it comes to the arduino inputs.

A tiny amount of voltage with practically zero amps can be seen by a arduino input so we either add a 10k resistor to pull the input low or we program the adruino to add its own internal resistor to pull the input high.

If you have resistors then like tom said add them between the inputs from the switch and negative. That will burn off the floating voltages that are probably tricking the arduino into thinking the switch has been pressed

If you don't have resistors then rewire the switch common to negative (make sure the switch is not sharing any wires with the motor). Next change your inputs to INPUT_PULLUP which turns on the built in resistors on the arduino. (look under learning for examples of the code). next change your code to look for a LOW instead of a high so

while (digitalRead(valveClosedPin) == LOW) {//would become

while (digitalRead(valveClosedPin) == HIGH) {//it would be LOW until switch is made

Hi,

sTaLa:
No, I do not have pull down 10k resistors. If I understand you correctly, without those 10 K resistors, pins D5 and D6 will see small voltage and see the inputs as HIGH?

I am not too much familiar with this. Should I connect the 10k resistor like this:

D5/D6 on Wemos ----------------/////---------GND
|
|
|
3.3 V from limit switch

Thanks a lot!
Alex

Yes that will do the job, one resistor for each input.
OPs image.


Tom... :slight_smile:

Wow! You guys are great! I am pretty sure what you are looking at as a root cause is right!

I tried the pull down resistor, but it did not work. I hooked it up as shown attached.

Then I hooke my Fluke to the Input pins of the Wemos: as soon as I get something more than 5 mV, the valve stops!

So we are on the right track, but my pull down resistors do not work for some reason. Could you have a look at my wiring?

I would really like to figure this wiring out as it goes hand to hand with the I think/code. Otherwise, I will read on the INPUT_PULLUP and give it a shot.

Thanks again!

wiring looks right from what I can see.

I don't understand all the code but im wondering why you changed this line from

if (request.indexOf("/relay=ON") != -1) {//not equal?

to

if (request.indexOf("/relay=ON") == -1) {//equal?

but the relay off didn't change?

might be time to use serial prints inside the while loop to see what the arduino is really doing

also I can not find a wiring diagram for the valve. Any chance the valve wiring is used in a different way?

Most "limit switches" are (or should be) wired normally closed so when the switch is activated it BREAKS the circuit and turns the motor off.

The ! = and the == are just a typo because it was late when I copy pasted my sketch on the forum. They are both ! = in the real code.

I will send out a picture of the wiring this evening.

But I do not really see how to wire the "limit switch" normally closed. What I have are three wires coming from the valve and acting as dry contacts. Contacts are only closed when the valve is either fully closed or fully opened. I have no closed contact during the valve movement :confused:

The only cheap dc ball valve I can find has electronics in the head unit that reverses the valve based on 3 input wires (plus 2 power wires). Can you tell us where you brought your valve or the make and model of the valve?

Sure, here is the link to the valve :3 way Valve CR-05

And the diagram of the wiring:

So I can move the valve using the blue and yellow wires.

And using the Balck, Red and Green wires, I know if the valve is fully closed or fully opened. If the valve is in the middle position, I have no closed contacts between those three wires.

I order to reverse the contact and use the switch so the Micro Controller does not receive 3.3V only once the valve is fully opened, may I could use Pull-Up resistors just like this:

This is probably what you guys meant. I will just have to modify the wiring and code accordingly.

Connect the BLK wire to GND, RED to pin 5 (or 6), GREEN to pin 6 (or 5), in setup(),

pinMode(valveOpenedPin, INPUT_PULLUP);
pinMode(valveClosedPin, INPUT_PULLUP);

The inputs will go LOW when the valve reaches end of travel.

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom... :slight_smile:

I just tried with the pull-up resistor instead of pull-down. And the same thing happens. When I put the fluke on the pins, I can see the voltage droping to around 7mV during movement, so the ball valves stops. When I start the valve back, I read around 3V until it either drops down to around 7-8 mV during travel, or until it reaches destination and I read 0 V.

Below is the code and I attached a picture of my current breadboard wiring. I will work on the CAD drawing, but now it's time to go to sleep in order to be in shape with the kids during the weekend.

Thanks for your help guys!

//This example will use a static IP to control the switching of a relay. Over LAN using a web browser.
//A lot of this code have been resued from the example on the ESP8266 Learning Webpage below.
//http://www.esp8266learning.com/wemos-webserver-example.php

//CODE START
//1
#include <ESP8266WiFi.h>

// Below you will need to use your own WIFI informaiton.
//2
const char* ssid = "Bacterie-verte"; //WIFI Name, WeMo will only connect to a 2.4GHz network.
const char* password = "alakazoo"; //WIFI Password





//defining the pin and setting up the "server"
//3
int openPin = D1;
int closePin = D2;
int valveOpenedPin = D5;
int valveClosedPin = D6;
WiFiServer server(80);
IPAddress ip(192, 168, 1, 199); // where xx is the desired IP Address
IPAddress gateway(192, 168, 1, 1); // set gateway to match your network
IPAddress subnet(255, 255, 255, 0); // set subnet mask to match your network


// void setup is where we initialize variables, pin modes, start using libraries, etc.
//The setup function will only run once, after each powerup or reset of the wemos board.
//4
void setup() {
  Serial.begin(115200);
  delay(10);

  // Reset all the pins
  pinMode(D1, OUTPUT);
  pinMode(D2, OUTPUT);
  pinMode(D3, OUTPUT);
  pinMode(D4, OUTPUT);
  pinMode(D5, OUTPUT);
  pinMode(D6, OUTPUT);
  pinMode(D7, OUTPUT);
  pinMode(D8, OUTPUT);
  digitalWrite(D1, HIGH);
  digitalWrite(D1, LOW);
  digitalWrite(D2, HIGH);
  digitalWrite(D2, LOW);
  digitalWrite(D3, HIGH);
  digitalWrite(D3, LOW);
  digitalWrite(D4, HIGH);
  digitalWrite(D4, LOW);
  digitalWrite(D5, HIGH);
  digitalWrite(D5, LOW);
  digitalWrite(D6, HIGH);
  digitalWrite(D6, LOW);
  digitalWrite(D7, HIGH);
  digitalWrite(D7, LOW);
  digitalWrite(D8, HIGH);
  digitalWrite(D8, LOW);

  pinMode(openPin, OUTPUT);
  pinMode(closePin, OUTPUT);
  pinMode(valveOpenedPin, INPUT_PULLUP);
  pinMode(valveClosedPin, INPUT_PULLUP);
  digitalWrite(openPin, LOW);
  digitalWrite(closePin, LOW);

  Serial.print(F("Setting static ip to : "));
  Serial.println(ip);

  // Connect to WiFi network
  //5
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.config(ip, gateway, subnet);
  WiFi.begin(ssid, password);
  //Trying to connect it will display dots
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.print("Use this URL : ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");
}

//void loop is where you put all your code. it is a funtion that returns nothing and will repeat over and over again
//6
void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while (!client.available()) {
    delay(1);
  }



  // Read the first line of the request
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();

  //Match the request, checking to see what the currect state is
  int value = LOW;
  if (request.indexOf("/relay=ON") != -1) {
    digitalWrite(closePin, LOW);
    digitalWrite(openPin, HIGH);
    delay(1000);
    while (digitalRead(valveOpenedPin) == HIGH) {
      digitalWrite(openPin, HIGH);
    }
    digitalWrite(openPin, LOW);
    value = HIGH;
  }
  if (request.indexOf("/relay=OFF") != -1) {
    digitalWrite(openPin, LOW);
    digitalWrite(closePin, HIGH);
    delay(1000);
    while (digitalRead(valveClosedPin) == HIGH) {
      digitalWrite(closePin, HIGH);
    }
    digitalWrite(closePin, LOW);
    value = LOW;
  }
  // Return the response, build the html page
  //7
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); //  do not forget this one
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");


  if (digitalRead(valveOpenedPin) == HIGH) {
    client.print("Il y a de l'eau chaude.");
  }
  else if (digitalRead(valveClosedPin) == HIGH) {
    client.print("Y A PAS D'EAU CHAUDE!!!");
  } else {
    client.print("La valve est en mouvement");
  }
  client.println("


");
  client.println("<a href=\"/relay=ON\">Ouvrir l'eau chaude.</a> 


");
  client.println("<a href=\"/relay=OFF\">Fermer l'eau chaude.</a>
");
  client.println("</html>");

  delay(1);
  Serial.println("Client disconnected");
  Serial.println("");
  Serial.println(digitalRead(valveOpenedPin));
  Serial.println(digitalRead(valveClosedPin));
}//END

only d3,d4,d8 are able to be used as input pullups according to a quick internet search of the wemos pins so you might have to move things about.

Second you will be looking for a LOW not a HIGH as the pullup is pulling the voltage to 5v with a built in resistor. Only by shorting the pin to negative via the switch (common negative) will the arduino read the pin.

Here's my CAD wiring:

I tried pins D3 and D4 at first, but it did not work at all for some reason. So I went back to D5 and D6.

My understanding is that D3 and D4 have built in resistors to be used as Pull-Up pins. If I want to use D5 and D6 as Pull-Up, I need to add my own 10k resistors. Correct me if I am wrong.

Anyway, alls seems to be working on D5 and D6, expect that I need to activate the button three times to complete the cycle. Whenever the ball valve stops, I can read a voltage drop on my Fluke. I just cannot explain it... I mean, the valve is connected directly to 3.3 V via the 10 k resistor.

Is 10k too much? I read I should use pull-up / pull-down resistors 10 times bigger than the impedance of the pins, which is around 100 Ohms from what I read.

I tried just for fun to apply 3.3 V directly on the Wemos D5/D6 pins, and the valve started to move again, without me doing anything via the IP address...

its time to add some serial prints with in the code especially in the while loop to see what the arduino is seeing.

after reading a little on the net I would be tempted to pull the cap of the top and see how the micro switchs and motor are wired.