Making a while-loop timeout

Hi.

I am new to this forum, so bare with me.

For some time now I have been doing a project for my chickencoop.
Evrything works as intended.

But…
I would like to incorporate a timeout function for my “Door Down” and “Door Up” function in case of reed switch failiure or some other fault with the door.

I understand i have to incorporate a millis function in my while-loop, but im having trouble with understanding how to construct the code.

void oppover()//---------------------------------Make door move up-----------------------------
    { 
      while(digitalRead(topSwitchPin)==HIGH)  
      {
        digitalWrite(motorOpp, HIGH);
        digitalWrite(motorNed, LOW);
        analogWrite(fart, 1023);
        Blynk.run();
        if (digitalRead(topSwitchPin)==HIGH && digitalRead(bottomSwitchPin)==HIGH) 
        {
          led.off();
        }
          if (digitalRead(topSwitchPin)==LOW)
        {
          stopp();
        }
      }
   }

All of the code

#define BLYNK_PRINT Serial

#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>


#define fart 2
#define motorNed 16
#define motorOpp 1
#define bottomSwitchPin 14
#define topSwitchPin 12
#define ONE_WIRE_BUS 0

#define BLYNK_Green     "#23C48E"
#define BLYNK_Red       "#D3435C"

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress insideThermometer;
WidgetLED led(V10);
SimpleTimer timer;

void ledwidget() {
  if (digitalRead(bottomSwitchPin)==LOW) {
    led.on();
    led.setColor(BLYNK_Red);
  }

if (digitalRead(topSwitchPin)==LOW) {
    led.on();
    led.setColor(BLYNK_Green);
  }

if (digitalRead(topSwitchPin)==HIGH && digitalRead(bottomSwitchPin)==HIGH) {
    led.off();
  }
}

char auth[] = blablabla
char ssid[] = blablabla
char pass[] = blablabla

void setup(void) {

  Serial.begin(9600);                               // initialize serial port hardware
  Blynk.begin(auth, ssid, pass);
  pinMode(motorOpp, OUTPUT);
  pinMode(motorNed, OUTPUT);
  digitalWrite(motorOpp, LOW);
  digitalWrite(motorNed, LOW);
  pinMode(fart, OUTPUT);
  analogWrite(fart, 0);
  pinMode(bottomSwitchPin, INPUT_PULLUP);                  // set bottom switch pin as input
  pinMode(topSwitchPin, INPUT_PULLUP);                     // set top switch pin as input
  sensors.begin();
  if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0"); 
  Serial.print("Device 0 Address: ");
  printAddress(insideThermometer);
  sensors.setResolution(insideThermometer, 9);
  timer.setInterval(1000L, ledwidget);  
}


void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

void printTemperature(DeviceAddress deviceAddress)
{

  float tempC = sensors.getTempC(deviceAddress);
  Serial.print("Temp C: ");
  Serial.println(tempC);
  Blynk.virtualWrite(V4, tempC+1);
}



BLYNK_WRITE(V1)
{
  int i=param.asInt();
  if (i==1)
  {
    oppover();
  }
  else
  {
    stopp();
  }
}


BLYNK_WRITE(V2)
{
  int i=param.asInt();
  if (i==1)
  {
    nedover();
  }
  else
  {
    stopp();
  }
}

void oppover()
{ 
  while(digitalRead(topSwitchPin)==HIGH)  
  {
    digitalWrite(motorOpp, HIGH);
    digitalWrite(motorNed, LOW);
    analogWrite(fart, 1023);
    Blynk.run();
    if (digitalRead(topSwitchPin)==HIGH && digitalRead(bottomSwitchPin)==HIGH) 
    {
      led.off();
    }
      if (digitalRead(topSwitchPin)==LOW)
    {
      stopp();
    }
  }
}


void nedover()
{
  while(digitalRead(bottomSwitchPin)==HIGH)
  {
    digitalWrite(motorNed, HIGH);
    digitalWrite(motorOpp, LOW);
    analogWrite(fart, 1023);
    Blynk.run();
    if (digitalRead(topSwitchPin)==HIGH && digitalRead(bottomSwitchPin)==HIGH) 
    {
      led.off();
    }
      if (digitalRead(bottomSwitchPin)==LOW)
    {
      stopp();
    }
  }
}


void stopp()
{
   digitalWrite(motorNed, LOW);
   digitalWrite(motorOpp, LOW);
   analogWrite(fart, 0);
}

void loop() {
  
Blynk.run();
timer.run();
sensors.requestTemperatures();
printTemperature(insideThermometer);

}

It may be bad coding, but works as intended.

unsigned long startedWaiting = millis();
while(doorNotClosed && millis() - startedWaiting <= howLongToWait)
{
   // Keep waiting for door to become closed
}

All you need to do is substitute something for doorNotClosed, whether that is a boolean variable or a function call is up to you.

Save the millis() value before the door moves. Then, each time through the while loop check whether the current millis() value minus the start value is greater than the required interval. If so then exit the while loop. If not then go round the while loop again.

Rather than build a timeout into your WHILE loop I suggest you don't use WHILE at all. Just use IF and allow loop() to do the iteration. That way you will only need to call Blynk.run() from loop().

For the timing issue have a look at how millis() is used to manage timing without blocking in Several things at a time. Note how each function runs very briefly and returns to loop() so the next one can be called. And there may be dozens of calls to a function before it is actually time for it to do anything.

...R

The correct way to busy wait for a time is:

while ((long) (millis() - target_time) < 0)
{}

But as has been mentioned busy-waiting isn’t normally a good idea

[ not the cast to a signed type so can compare less than zero, and the subtraction before the compare
so that the wrap-around case is handled correctly ]

I understand that my while-loops are actually delaying my program while nyhet are locked in the loop.

Since the door only will be operrated twice a day and for å very short time each time (Max 10 sec), I did not think of that delay to be a problem for me. The fact that the microcontroller only is intended for the door and 1 temp sensor allso played in.

I am still in the beginner fase of programming, so I apriciate comments on how to gode smarter.

I understand that “howLongToWait” must be declared and sett to desired value earlier on.

Something like this?

void oppover()//---------------------------------Make door move up-----------------------------

    { 
      unsigned long startedWaiting = millis();
      while(digitalRead(topSwitchPin)==HIGH && millis() - startedWaiting <= howLongToWait) 
      {
        digitalWrite(motorOpp, HIGH);
        digitalWrite(motorNed, LOW);
        analogWrite(fart, 1023);
        Blynk.run();
        if (digitalRead(topSwitchPin)==HIGH && digitalRead(bottomSwitchPin)==HIGH) 
        {
          led.off();
        }
          if (digitalRead(topSwitchPin)==LOW)
        {
          stopp();
        }
      }
   }
void oppover()//---------------------------------Make door move up-----------------------------
unsigned long startedWaiting = millis();
    {

NOTHING goes between the ) and the {.

you are testing the value rad on topSwitchPin inside the while-conditional that tests that value... basically up to three times per loop.

why?

PaulS:

void oppover()//---------------------------------Make door move up-----------------------------

unsigned long startedWaiting = millis();
    {



NOTHING goes between the ) and the {.

I know. And noticed that I have done that do i fixed it.

Typing om ny mobile phone and hard to ser what i write.

BulldogLowell: you are testing the value rad on topSwitchPin inside the while-conditional that tests that value... basically up to three times per loop.

why?

I want a Blynk LED to change state while loop runs.

The last test I har to add for the while-loop to stop running and run stopp() function. (It did not do that if i left it out, even though i belived it would so).

tomrudin: I know. And noticed that I have done that do i fixed it.

Typing om ny mobile phone and hard to ser what i write.

Interesting. Maybe give up on posting from yuor ponhe.

PaulS: Interesting. Maybe give up on posting from yuor ponhe.

I'll do! And rather wait until i'm off work.

So much for multitasking

Robin2:
Rather than build a timeout into your WHILE loop I suggest you don’t use WHILE at all. Just use IF and allow loop() to do the iteration. That way you will only need to call Blynk.run() from loop().

For the timing issue have a look at how millis() is used to manage timing without blocking in Several things at a time. Note how each function runs very briefly and returns to loop() so the next one can be called. And there may be dozens of calls to a function before it is actually time for it to do anything.

…R

I did as you sugested.

I removed "while and now use “If” instead.

The timing is now done in the loop and only calls function when parameters are right.

This way i don’t have a delay in my code every time “while” runs either.

Thank you very much for guiding me in the right direction.