[Solved] High Switches to Low - I can't see why?

OK, this is a simple garage door opener and I2C Temperature Sensor.

The issue I’m running into is when the Wemos D1 Mini boots, the relay goes into HIGH which is what I have in my Setup.
After I access my Blynk App on my phone and press the (momentum) Button associated with D8 the DOOR_RELAY, the relay itself shutters back a forth a few FAST times between HIGH and LOW then settles on LOW then, everytime I tap the Blynk Apps Momentum Button the relay goes from LOW to HIGH. THAT’S BACKWARDS from the code. I don’t get it, I setup pinMode (OUTPUT) and the digitalWrite(DOOR_RELAY, HIGH) in the SETUP. Nowhere in the code other than the momentum button press, does it tell the relay to go LOW and especially stay LOW. Shouldn’t the momentum button just return it to the digitalWrite state it came from?

include ArduinoOTA.h
include ESP8266WiFi.h
include WiFiClient.h
include BlynkSimpleEsp8266.h
include SPI.h
include DNSServer.h
include SimpleTimer.h
include Wire.h
include LM75A.h

define SERIAL_BAUD 115200
define DEBUG(input) {Serial.print(input);}
define DEBUGln(input) {Serial.println(input);}
define SERIALFLUSH() {Serial.flush();}
else
define DEBUG(input);
define DEBUGln(input);
define SERIALFLUSH();
endif

//*********** Blynk Instructions ****************************
char auth = “";
const char
ssid = "
”;
const char* password = “**********”;

//************************************************************

bool GRcurrent = 1; //logical placeholder - current status of the garage
bool GRprevious = 0; //logical placeholder - previous status of the garage
const char* Open = “GARAGE DOOR IS OPEN”;
const char* Closed = “GARAGE DOOR IS CLOSED”;
int DOOR_RELAY = D5;

LM75A lm75a_sensor;

WidgetLED ledOpen(V6);
WidgetLED ledClosed(V9);
WidgetLCD lcd(V10);

//*****************************************************************************

SimpleTimer Temp;

void setup() {

pinMode(D3, INPUT_PULLUP); // Garage Door Magnetic Sensor
//pinMode(D8, INPUT_PULLUP); // Door Closed Magnetic Sensor (not in use)
pinMode(DOOR_RELAY, OUTPUT);
digitalWrite(DOOR_RELAY, HIGH);

ifdef SERIAL_EN
Serial.begin(SERIAL_BAUD);
endif
WiFi.mode(WIFI_STA);
Blynk.begin(auth, ssid, password);
while (Blynk.connect() == false) {}
// Hostname defaults to esp8266-[ChipID]
ArduinoOTA.setHostname(“garDemo”); // Sometimes restart Arduino IDE before IP Address shows up under Tools>Port
//void setHostname(const char* garDemo101);

Serial.println(“”);
Serial.println(“”);
delay(10);
Serial.println(WiFi.status());
Serial.println(“”);
Serial.println(“”);
Serial.print(“\tAssigned Local IP:\t\t”);
Serial.println(WiFi.localIP());
if (WiFi.status() == WL_CONNECTED) {
Serial.println(“\tWiFi C O N N E C T E D !!!.”);
Serial.println(“”);
Serial.println(“”);
}
else {
Serial.println(“\tWiFi P R O B L E M” );
}

Temp.setInterval (10000, LM75A);

LM75A ();

ArduinoOTA.begin();
}

void garageDoorOpen() {
Blynk.virtualWrite(V9, 0);
Blynk.virtualWrite(V6, 1023);
lcd.clear();
lcd.print(1, 0, " Wendler Home ");
lcd.print(1, 1, “GARAGE OPENED “); // LCD print, column 1, row 1
Serial.println(”\tGARAGE DOOR IS OPEN “);
Blynk.run();
Blynk.virtualWrite(V11, Open);
Blynk.run();
// Blynk.email(”********************”, “GARAGE DOOR OPEN!”, “Garage door has been opened.”);
}

void garageDoorClose() {
Blynk.virtualWrite(V6, 0);
Blynk.virtualWrite(V9, 1023);
lcd.clear();
lcd.print(1, 0, " Wendler Home “);
lcd.print(1, 1, “GARAGE CLOSED”); // LCD print, column 1, row 1
Serial.println(”\tGARAGE DOOR IS CLOSED ");
Blynk.run();
Blynk.virtualWrite(V11, Closed);
Blynk.run();
}

void garageDoor()
{
GRcurrent = digitalRead(D3); // Garage Magnetic
if (GRcurrent != GRprevious) { //only run if there is a status change from previous state
GRprevious = GRcurrent; //reinitialize

if (GRcurrent == LOW)
{
  garageDoorClose();
}
else
{
  garageDoorOpen();
}

}
}

void LM75A ()
{
float temperature_in_degrees = lm75a_sensor.getTemperatureInDegrees();
float t = (LM75A::degreesToFahrenheit(temperature_in_degrees));

if (temperature_in_degrees == INVALID_LM75A_TEMPERATURE) {
Serial.println(“Error while getting temperature”);
} else {
Serial.print(“Temperature: “);
Serial.print(temperature_in_degrees);
Serial.print(” degrees (”);

Serial.print(t);
Serial.println(" fahrenheit)");
char buf[5];
dtostrf(t, 3, 1, buf);
Blynk.virtualWrite(V8, String(buf) + "°F");

}
}

void loop()
{
Blynk.run();
garageDoor();
Temp.run();
Blynk.run();
ArduinoOTA.handle();

}

Do you use any kind of debouncing of the relay? That might help. A simple capacitor would probably be enough.

Instead of directly tying the button in the App to the digital output, you might try using a virtual pin and then in the sketch, watch changes to the virtual pin.

The BLYNK_WRITE() function is called in your sketch when a specified virtual pin is updated from the app. If your momentary button is connected to V1 you could have this:

#include <SimpleTimer.h>
SimpleTimer tripWire;

BLYNK_WRITE(V1) {
  int value = param.asInt();
  if (value==HIGH) { // virtual pin V1 goes HIGH when pressed in the app, goes LOW when released.
    tripActivate();
  }
}

void tripActivate() {
  digitalWrite(D8, LOW);
  tripWire.setTimeout(1000L, tripDeactivate);
}

void tripDeactivate() {
  digitalWrite(LED_INDICATOR, HIGH);
}

void loop() {
  [...other code...]
  tripWire.run();
}

This code fragment also uses the SimpleTimer library, which lets you set a timer that calls a function after some specified delay.

In this way, your app is sending a virtual signal to the microcontroller, which runs a consistent program to trigger the garage door motor – pulling the relay LOW, waiting 1000 microseconds (1 second), and then taking the relay HIGH again.

What you may have been experiencing is that the button in the app goes from LOW to HIGH when pressed, and then HIGH to LOW when released. You appear to expect that the momentary button just toggles the state of the pin from whatever it is, but that’s not how it works.

1 Like

@josecanuc Your code idea worked GREAT! First Time.

I took a look at debounce2 as @Lichtsignaal recommended and that was my next option but HEY, it worked with the BLYNK_WRITE(V1) code so I won’t mess with it.

THANK YOU BOTH - QUICK! GREAT! REPLIES !!!

josecanuc,

I followed your idea/instructions and it WORKED GREAT.

then…

I got the bright idea to tweak it and modify your super simple code. Not a great idea.
I just wanted to make the LCD show the Garage door in motion for a few seconds (a comfort that the door was moving) then revert to the main Void garageDoor();

It’s not working . If it’s in the closed position (magnets touching) then it says closed (that’s right), then when I hit your V1 idea the DigitalWrite value changes perfectly. I wanted it to LCD Quote the text (In Motion) for 9sec then revert to the main void garagedoor(); Your 300ms timeout works great… mine 9000ms does not.

Can you spot why it doesn’t wait 9 sec? The moment I move the magnet, it says OPEN, it’s suppose to wait 9sec then report the position and status of the Digitalread Open or Closed… not immediately.

Thanks in advance!!

BLYNK_WRITE(V1) {
int value = param.asInt();
if (value == HIGH) { // virtual pin V1 goes HIGH when pressed in the app, goes LOW when released.
tripActivate();
}
}

void tripActivate() {
digitalWrite(DOOR_RELAY, LOW);
tripWire.setTimeout(300, tripDeactivate);
tripWire2.setTimeout(9000, inMotion);
lcd.clear();
lcd.print(1, 1, “DOOR IN MOTION”); // LCD print, column 1, row 1
}

void tripDeactivate() {
digitalWrite(DOOR_RELAY, HIGH);
}
void inMotion(){
garageDoor();
}

Is your code still calling garageDoor() in the loop() function?

If so, note that the setTimeout(9000, inMotion) line does not stop the program while it’s waiting 9 seconds – it only says, move past here, and in 9 seconds call inMotion().

josecanuc,

Got it!

That was the part I wasn’t getting. That the line didn’t stop like delay(9000); but executed the setTimeout(9000, inMotion) after 9sec regardless of what else the code is doing.

Thanks for taking time !

Just for educational purposes: On devices that use the ESP8266 chip, using delay() is bad, because it stops the background quasi-operating-system from running, and a watchdog timer for the WiFi part trips and forces the chip to restart. This is because WiFi stations do chit-chat with each other to maintain awareness of connected stations, etc.

The ESP8266 watchdog timer is about 1 second, so if you don’t call yield() or let loop() complete in over a second, the system resets.

Using the SimpleTimer library, or one of the other non-library methods for checking milis() to find out if it’s time yet to branch to some other routine allows your sketch to cause something to happen “later” without stopping to wait (because stopping is bad if you stop for more than 1 second.)

It’s kind of a poor-man’s multithreading and/or an “event-driven” model. You use the Timer triggers to schedule things to happen later, and your code just continues on it’s merry way with other things, until the event triggers.

In your example code you posted most recently, I notice that you created a new SimpleTimer object called tripWire2. That’s not terrible, but be aware that one SimpleTimer object can maintain up to 10 separate timers, so you could just call:

tripWire.setTimeout(300, tripDeactivate);
tripWire.setTimeout(9000, inMotion);

and save a little RAM.

One way you could modify your code to have the “In Motion” message in place is to create a global variable to hold whether you are displaying the “In Motion” message. So, whenever you send “IN MOTION” to the LCD, you also set that variable to 1, and when your timeout runs inMotion(), you reset that variable back to 0. Then, in the code where you send other text to the LCD, you check if that variable is 0 – if it is, then you can update the LCD, otherwise, just skip it. In this way, you can still have garageDoor() in your main loop() function, but garageDoor() knows when it should or should not actually update the LCD based on the switches.

1 Like

josecanuc

HUGE HELP !!!