Water Valve Project: Adding Blynk control to previously written code

Thanks Pete. I’ll have to draw up a diagram when I’m at the computer again, Short story, if I can get blynk to open and close my valve via the relay and display virtual LEDs when its open or closed I’d be happy. Later, I can try to do some upgrades like adding physical LEDs to illuminate along with the virtual ones. I might also add a manual momentary Dpdt switch as a second option to open and close the valve manually and add Alexa control as a third option. Of the valves 5 wires, yellow and blue (when connected to 24vDC) will open and close the valve depending on the polarity.

The other three (Black, Red and green) are a part of a switch inside the valve. Black will either connect to green once the valve reaches its full open position or black to red when it reaches its full closed position.

That’s why I connected the board’s 3.3v pin to the valve’s black wire, the valves red wire to pin (18) and green wire pin (17) on the esp32. I figured if either one of these pins gets 3.3v, it confirms the valve has reached it’s full open or closed position. The internal switch does not make this connection until it does.

Normally when using a manual switch and physical LED’s, black would connect directly to the ‘+’ side of the LED power supply and then red or green would connect to one leg of the red or green LED. The other leg of the LEDs would go directly to ‘-’ side of the LEDs power supply. Each only illuminating when the switch connects the black wire to either the green or red wire and competing the circuit to the LEDs. Hopefully that makes sense.

Okay, that explanation would have been useful before :grinning:

So, the way to go is to connect the black wire to either GND, and the green and red wires to GPIO pins. You can then poll these GPIOs to see if they are LOW (circuit to GND completed).
The GPIOs will need to have pinMode declarations in void setup, and these should use the INPUT_PULLUP modifier to ensure that they are HIGH by default and don’t float at an intermediate voltage.

You can poll the GPIOs with a timer that calls a function which reads the values of the GPIOs. The timer frequency will depend on how quickly you need to know that the circuit is made, but somewhere around 100ms will probably be okay.

Pete.

OK, so its sounds like I don’t have to connect the 3.3v pin thru the switch to the GPIOs as connecting GND thru the switch to the GPIOs will still be able to read they are connected or disconnected from the GND pin ? Just curious, any particular reason using ground vs the 3.3v connection ? 100 ms should be fine, The valve takes like 6 seconds or so to open or close as it is … so that’s lightning fast

Correct.
The advantage of doing it this way is that you can use INPUT_PULLUP, as the NodeMCU doesn’t have an INPUT_PULLDOWN modifier, so you’d need to use physical 10k pulldown resistors.

Pete.

Hi Guys, I got the valve to open/close using virtual pins, so now I’m onto the virtual LED widget. I’ve added code I’ve come up with here, but, getting an error during verification…
“exit status 1 - expected unqualified-id before ‘{’ token”
on top of that, I can’t be sure what I wrote will even work … was not sure how to poll via the timer function Pete mentioned


#define relay 16
#define openPositionGPIO 17
#define closedPositionGPIO 18
#define vRelayBtn V1
#define v_openLED V2
#define v_closedLED V3

{
  if (openPositionGPIO == HIGH) {
    Blynk.virtualWrite(v_openLED,255);
  } if (closedPositionGPIO == HIGH);
    Blynk.virtualWrite(v_closedLED,255);
  } else {
    Blynk.virtualWrite(v_openLED,0);
    Blynk.virtualWrite(v_closedLED,0);
  }
}

void setup()
{
  // Debug console
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  {
    pinMode(relay,OUTPUT);
    pinMode(openPositionGPIO,INPUT_PULLUP);
    pinMode(closedPositionGPIO,INPUT_PULLUP);
  }
}
BLYNK_WRITE(vRelayBtn){
    if (param.asInt()){       
        digitalWrite(relay, HIGH);
    } else {
        digitalWrite(relay, LOW);
    }
}
void loop()
{
  Blynk.run();
}

This is the piece of code that your compiler is complaining about, and there are quite a few things wrong with it.
I’m assuming that it is meant to be a function, and in that case it needs to be given a name, so that the compiler recognises it as a function, and it can be called from within the rest of your code. As it’s meant to control you LEDs, lets call it control_LEDs, like this…

void control_LEDs()
{
  // your code in here...
}

Your piece of function code has a mis-matched number of opening and closing curly brackets, which the compiler won’t like.
In addition, one of your 'ifstatements isn't written correctly as it has a semicolon after theifcomparison, and no curly brackets around the action to be taken if theif` statement evaluates as true.

Also, to find the current state of a GPIO, it’s necessary to do a digitalRead on the pin, so this:

won’t do what you are wanting it to.

I’m also not sure that the logic of your if / else statements will actually do what you are expecting.

It’s much easier to see at a glance what your code is meant to be doing if you are sensible about where you position your opening and closing curly brackets, and uses indents appropriately.

In addition to this, you also have some curly brackets scattered around your void setup which shouldn’t be there.

This is what I think your code should look like, with the addition of a timer to call your new control_LEDs function every 100ms…

#define relay 16
#define openPositionGPIO 17
#define closedPositionGPIO 18
#define vRelayBtn V1
#define v_openLED V2
#define v_closedLED V3

BlynkTimer timer;

void control_LEDs()
{
  if (digitalRead(openPositionGPIO) == HIGH)
  {
    Blynk.virtualWrite(v_openLED,255);
  }
  else
  {
    Blynk.virtualWrite(v_openLED,0);    
  }


  if (digitalRead(closedPositionGPIO) == HIGH)
  {
    Blynk.virtualWrite(v_closedLED,255);
  }
  else
  {
    Blynk.virtualWrite(v_closedLED,0);
  }
}


void setup()
{
  // Debug console
  Serial.begin(9600);

  pinMode(relay,OUTPUT);
  pinMode(openPositionGPIO,INPUT_PULLUP);
  pinMode(closedPositionGPIO,INPUT_PULLUP);

  timer.setInterval(100,control_LEDs);

  Blynk.begin(auth, ssid, pass);
}


BLYNK_WRITE(vRelayBtn)
{
  if (param.asInt())
  {       
    digitalWrite(relay, HIGH);
  }
  else
  {
    digitalWrite(relay, LOW);
  }
}


void loop()
{
  timer.run();
  Blynk.run();
}

If you’re having trouble sleeping and fancy a little light bedtime reading, then this will tell you all you ever wanted to know (and much, much more) about timers…

Pete.

@Blink_tynker I’ve just edited the code in my last post to fix the error that I mentioned here:

which I forgot to do earlier.

Pete.

Eureka Pete! Thanks for the code lesson … that update worked, the appropriate virtual LEDs are on when it’s either open or closed and both are on when the valve is changing state … which I guess is a good indicator that it’s either moving or stuck. Now that I have this working, I’m looking at updating the code to include the addition of physical LEDs. Seems like I would just add the new #defines for open & closed additional lines plus the new pinModes

'# define realLEDOpen = xx // what ever pin I connect the LED to & GND
'# define realLEDClosed = xx // what ever pin I connect the LED to & GND
pinMode(realLEDOpen,OUTPUT) // add under void setup
pinMode(realLEDOpen,OUTPUT) // add under void setup

then right below the ‘Blynk.virtualWrite’ lines, add new digital write lines to turn the physical LEDs on

if (digitalRead(openPositionGPIO) == HIGH)
  {
    Blynk.virtualWrite(v_openLED,255);
    digitalWrite (realLEDOpen,HIGH); //new lines to turn on open Real LED on when valve is open
  }
  else
  {
    Blynk.virtualWrite(v_openLED,0);
    digitalWrite(realLEDOpen, LOW); // new lines to turn off open Real LED off when valve is closed    
  }

and then duplicate this for the closed LED

I don’t have any LEDs at the moment, can’t actually test this … but it looks like GPIO21 and GPIO22 can be used for each LED. Any suggestions on an LED kit to use, I found this kit on Amazon seems like it has what I need, I guess I just need to match the correct resistor with the Red and Green LEDs

The code looks good!

As far as the LEDs are concerned, I’d prefer to have LED that a proper specification for their voltage, current consumption, brightness etc, to allow you to accurately calculate the value of the series resistor.
The kit you linked to doesn’t even say what size the LEDs are.

Pete.

Hi Guys, I’m tweaking my setup a little and have a few questions. I going to add a DPDT bypass switch between my relay and the valve. This switch will toggle the source of power to the valve from either the valve relay when it’s in the up position or from a second DPDT switch (wired to reverse polarity) when it in the down position. This way I have a backup switch if the ESP32 and/or relay ever fail and I need to open and close it with a manaul switch.
I’ve also decided to upgrade my current water heater wifi setup from the current wifi on/off switch and app, to a second relay connected to the ESP32 and turning it on and off fith a second virtual button in Blynk … this will also have switch to toggle the activation source for the contactor that powers the Water Heater (Up: Relay controls contactor, middle power off, Down: Switch powers contactor) I’ve added in the new code and have no errors.

My Question:
My current set up is for the ESP32 to illuminate physical LEDs via separate GPIO outputs and virtual LEDs in Blynk when another set of GPIO INPUT pins sense a GND signal from either the red or green valve wires. However, if I’m in manual mode and the ESP32 and relay(s) are down, there would be no physical LED illumination on site as the ESP32 (the LED power source) would be down. Looking for some ideas to Illuminate the physical LEDs from a separate source – maybe the 24vDC valve power + resistors – and still have the ability to illuminate virtual LEDs when the system is online (ESP32, relay and Blynk)
Do I just read power off of the separate LED power source on a GPIO same as the ground read and add a resistor in between ?

.
For the water heater, I just want a physical LED indicator, so I can add an LED + resistors to work with 120v which will tell me if power is flowing to the contactor or not. I do have a question on this, if I have a 2v, 20mA LED, it appears that a 6.2KΩ resistor is required. I have smaller and larger ones, but the closest to 6.2K I have are 5.1K and 10K. Do I just combine a 100Ω, 1KΩ and 5.1KΩ in series to get the 6.2k ?

Thanks, Jack

I’ll answer the last question first…
Yes, you can add resistors in series to make the value you want, or just go for the next higher value.
However - LEDs are DC devices and powering them from mains AC won’t give a very satisfactory result. The LED will only be receiving forward voltage half of the time (because the AC reverses polarity at a frequency of 60Hz in the US, 50Hz in the civilised world). This means that your LED will appear dimmer than expected, and will have a reverse voltage applied to it for 50% of the time, which isn’t conducive to a long life for the LED. You can probably buy LEDs that are designed for 120v mains, which include a bridge rectifier circuit and built-in resistor.

Back to the first question - I think I understand what you’re asking, and I’d recommend using an option isolator between the 24v supply and the GPIO pins of the NodeMCU. This lowers the risk of a component failure resulting in a fried ESP32, and will also help eliminate electrical noise from the 24v valves.

Pete.

Thanks, Pete. Yes, they do. I’ve already looked and found them, then thought I could use existing LEDs, but it sounds like it’s a better Idea to just get the ready made ones.

Not familiar with this, can you provide me with some more information on what this is or a link to one.
Thanks, Jack

Is option isolator the same as an optocoupler ?

Sorry, my spell check butchered what should have been “Opto Isolator”.
Yes, sometimes referred to as an optocoupler.

Basically an LED and a phototransistor in a package which provides electrical isolation between two circuits.

Pete.

Ok I did some reading on these, looks like I need two of them, – one for each LED?
I do have 12-24vDC LEDs, so additional resistors should not be required to power them
If I were to use the Sharp PC817, I would connect (although I’m not sure if I need to add any resistors on the 24vDC side and/or on the ESP32 side of the octo coupler connection)

Optocoupler #1 (Open)

  • Valve’s Black wire to 24vDC ‘-’
  • 24vDC ‘+’ to ‘+’ side of Green LED and PC817 pin 1 (anode)
  • Valve’s Green wire to ‘-’ side of Green LED and PC817 pin 2 (diode)
  • ESP32 GND to PC817 pin 3 emitter
  • PC817 pin 4 collector to my GPIO 17 which will illuminate virtual LED when open

Optocoupler #2 (Closed)

  • Valve’s Black wire to 24vDC ‘-’
  • 24vDC ‘+’ to ‘+’ side of Red LED and PC817 pin 1 (anode)
  • Valve’s Red wire to ‘-’ side of Red LED and PC817 pin 2 (diode)
  • ESP32 GND to PC817 pin 3 emitter
  • PC817 pin 4 collector to my GPIO 18 which will illuminate virtual LED when closed

Hi Pete, looks like this is the connection I need to make … does this look right ?
Two PC817s, for each connect to1,2,3 have the same connection with #4 going to GPIO 17 for the open vLED and the other #4 going to GPIO 18 for the closed vLED
Thanks, Jack

Do you mean pin #4 of the PC817, or do you mean pin #3 ?

Pete.

oops my mistake … it’s as written (Schematic was wrong) Pin 3 to GND and pin 4 to the GPIOs …
updated the schematic

I thought pin #4 was supposed to be GND?

Pete.

This where I’m a getting little confused when reading, I’ve seen it written both ways but this way seemed to fit what I was attempting to do.

  1. Anode - ‘+’ 24vDC
  2. Diode - ‘-’ 24vDC
  3. Emitter - ESP32 GND
  4. Collector - GPIO 17 or 18

Although I’m making the assumption that this will essentially work as a switch for me, when the diode has ‘-’ power applied (via the valves internal open/close switch) and the pc817 LED is on, a connection is made between the Emitter and collector …essentially connecting the ESP32’s ground to the appropriate GPIO pin, where my code will read it and illuminate the appropriate vLED… Or maybe I have that completely wrong