Otput HIGH only while input is HIGH

Hello.

Problem again. I need to enable output 12 (later I'll add more of them) and put custom message on LCD only while input A2 is HIGH. But when I try to do that with following code first my buttons on LCD don't react any more (I'm using Microbot MR007-005.1 LCD Shield), and output doesn't come back to LOW right away, it takes second or two... I used "while" to achieve desired function. Where did I make mistake?
BTW buttons and everything else worked before i added "while" and I need to have Consumption() displayed almost all the time (not while displaying UP time)...

CODE BEFORE ADDING WHILE

#include <LiquidCrystal.h>
#include <StopWatch.h>


LiquidCrystal lcd(7, 6, 5, 4, 3, 2);


StopWatch sw_secs(StopWatch::SECONDS);



int VPin = 12;
int MPin = 8;
int SPin = 7;
int DPG = 4;
int DPD = 2;
int GPin = A2;


void setup() {
  //Welcome message
  lcd.begin(16, 2);
  lcd.setCursor(4, 0);
  lcd.print("SOMETHING");
  delay(1000);
  lcd.setCursor(5, 1);
  lcd.print("SOMETHING");
  delay(2000);

  //My way to blink display
  lcd.clear();
  delay(500);

  lcd.setCursor(5, 1);
  lcd.print("SOMETHING");
  lcd.setCursor(4, 0);
  lcd.print("SOMETHING");
  delay(500);
  lcd.clear();
  delay(500);

  lcd.setCursor(5, 1);
  lcd.print("SOMETHING");
  lcd.setCursor(4, 0);
  lcd.print("SOMETHING");
  delay(500);


  pinMode(VPin, OUTPUT);
  pinMode(MPin, OUTPUT);
  pinMode(SPin, OUTPUT);
  pinMode(DPG, OUTPUT);
  pinMode(DPD, OUTPUT);
  pinMode(GPin, INPUT);
  lcd.clear();

 

  sw_secs.start();


}




void loop()
{
  
    static unsigned long Time;
    if (millis() - Time >= 1000)
    {
      Time += 1000;
      Consumption(); 
    }
  


  
  Buttons();
  Vrijeme();


 




}







void Consumption() {
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("STATUS: ON");
  lcd.setCursor(0, 1);
  lcd.print("Consumption:");
  lcd.setCursor(12, 1);
  lcd.print("kg/h");
  int Potenciometar = A1;
  int Pot1 = 0;
  int Pot2 = 0;
  Pot1 = analogRead(A1) / 10;
  Pot2 = Pot1 / 1.023;
  lcd.setCursor(9, 1);
  lcd.print(Pot2);
}



void Vrijeme() {

}





void Buttons()
{
  int Tipke;
  Tipke = analogRead(0);
  if (Tipke < 50) {
    Consumption;
    lcd.setCursor(0, 0);
    lcd.print("UP                ");
  }

  else if (Tipke < 250) {
    Consumption;
    lcd.setCursor(0, 0);
    lcd.print("DOWN                ");
    
  }

  else if (Tipke < 450) {
    lcd.print("");
    lcd.setCursor(0, 0);
    lcd.print("UP Time:         ");

    int h, m, s;
    s = sw_secs.elapsed();
    m = s / 60;
    h = s / 3600;
    s = s - m * 60;
    m = m - h * 60;

    lcd.setCursor(0, 1);
    lcd.print(h);
    lcd.setCursor(1, 1);
    lcd.print(" hrs                  ");
    lcd.setCursor(6, 1);
    lcd.print(m);
    lcd.setCursor(8, 1);
    lcd.print("min");
    lcd.setCursor(9, 1);
    delay(3000);
  }

  
}

CODE AFTER WHILE

#include <LiquidCrystal.h>
#include <StopWatch.h>


LiquidCrystal lcd(7, 6, 5, 4, 3, 2);


StopWatch sw_secs(StopWatch::SECONDS);



int VPin = 12;
int MPin = 8;
int SPin = 7;
int DPG = 4;
int DPD = 2;
int GPin = A2;


void setup() {
  //Welcome message
  lcd.begin(16, 2);
  lcd.setCursor(4, 0);
  lcd.print("SOMETHING");
  delay(1000);
  lcd.setCursor(5, 1);
  lcd.print("SOMETHING");
  delay(2000);

  //My way to blink display
  lcd.clear();
  delay(500);

  lcd.setCursor(5, 1);
  lcd.print("SOMETHING");
  lcd.setCursor(4, 0);
  lcd.print("SOMETHING");
  delay(500);
  lcd.clear();
  delay(500);

  lcd.setCursor(5, 1);
  lcd.print("SOMETHING");
  lcd.setCursor(4, 0);
  lcd.print("SOMETHING");
  delay(500);


  pinMode(VPin, OUTPUT);
  pinMode(MPin, OUTPUT);
  pinMode(SPin, OUTPUT);
  pinMode(DPG, OUTPUT);
  pinMode(DPD, OUTPUT);
  pinMode(GPin, INPUT);
  lcd.clear();

 

  sw_secs.start();


}




void loop()
{
  
    while (digitalRead(GPin) == LOW) {
    static unsigned long Time;
    if (millis() - Time >= 1000)
    {
      
      Time += 1000;
      Consumption();
    }} 
  
while (digitalRead(GPin) == HIGH); {
  static unsigned long Time;
    if (millis() - Time >= 1000)
    {
      Time += 1000;
      Working(); 
    } 
    digitalWrite(VPin, HIGH);
}
  


  
  Buttons();
  Vrijeme();


 




}







void Consumption() {
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("STATUS: ON");
  lcd.setCursor(0, 1);
  lcd.print("Consumption:");
  lcd.setCursor(12, 1);
  lcd.print("kg/h");
  int Potenciometar = A1;
  int Pot1 = 0;
  int Pot2 = 0;
  Pot1 = analogRead(A1) / 10;
  Pot2 = Pot1 / 1.023;
  lcd.setCursor(9, 1);
  lcd.print(Pot2);
}



void Vrijeme() {

}


void Working() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("STATUS: Working");
  lcd.setCursor(0, 1);
  lcd.print("Consumption:");
  lcd.setCursor(12, 1);
  lcd.print("kg/h");
  int Potenciometar = A1;
  int Pot1 = 0;
  int Pot2 = 0;
  Pot1 = analogRead(A1) / 10;
  Pot2 = Pot1 / 1.023;
  lcd.setCursor(9, 1);
  lcd.print(Pot2);
}


void Buttons()
{
  int Tipke;
  Tipke = analogRead(0);
  if (Tipke < 50) {
    Consumption;
    lcd.setCursor(0, 0);
    lcd.print("UP                ");
  }

  else if (Tipke < 250) {
    Consumption;
    lcd.setCursor(0, 0);
    lcd.print("DOWN                ");
    
  }

  else if (Tipke < 450) {
    lcd.print("");
    lcd.setCursor(0, 0);
    lcd.print("UP Time:         ");

    int h, m, s;
    s = sw_secs.elapsed();
    m = s / 60;
    h = s / 3600;
    s = s - m * 60;
    m = m - h * 60;

    lcd.setCursor(0, 1);
    lcd.print(h);
    lcd.setCursor(1, 1);
    lcd.print(" hrs                  ");
    lcd.setCursor(6, 1);
    lcd.print(m);
    lcd.setCursor(8, 1);
    lcd.print("min");
    lcd.setCursor(9, 1);
    delay(3000);
  }  }

Simple. You messed up the while statement by putting a semicolon after it.

while (digitalRead(GPin) == HIGH); {

Your loop() code is blocky because of the while statements.

The below probably going to take some more work anyway but what you should note is that loop() goes around and around and if you don't write blocking code it will loop in under a millisecond. That is a good thing if you want your code to watch pins that aren't part of blocky little tasks.

In your button code, that 3 second delay at the end needs to go. If you don't want it to print more often than that then that is what if( millis() - start >= wait ) {} is for. Don't make everything else wait too!

void loop()
{
  static unsigned long Time; // declare this once up here
 
  if (digitalRead(GPin) == LOW) 
  {
     if (millis() - Time >= 1000)
    {
     
      Time += 1000;
      Consumption();
    }
  }
  else 
  {
    if (millis() - Time >= 1000)
    {
      Time += 1000;
      Working();
    }
    digitalWrite(VPin, HIGH);
  }

  Buttons();
  Vrijeme();
}

Thank you both, now it's fixed (for now I've just removed delay from Buttons, removed semicolon and instead of while used GoForSmoke's solution).

But still my output remains HIGH even up tu 10 seconds after I've removed +5V from A2 (sometimes it's just 1 second, sometimes it's 5...).

Any idea why is that and how to fix it?

Here is the code as it is now:

#include <LiquidCrystal.h>
#include <StopWatch.h>


LiquidCrystal lcd(7, 6, 5, 4, 3, 2);


StopWatch sw_secs(StopWatch::SECONDS);



int VPin = 12;
int MPin = 8;
int SPin = 7;
int DPG = 4;
int DPD = 2;
int GPin = A2;


void setup() {
  //Welcome message
  lcd.begin(16, 2);
  lcd.setCursor(4, 0);
  lcd.print("SOMETHING");
  delay(1000);
  lcd.setCursor(5, 1);
  lcd.print("SOMETHING");
  delay(2000);

  //My way to blink display
  lcd.clear();
  delay(500);

  lcd.setCursor(5, 1);
  lcd.print("SOMETHING");
  lcd.setCursor(4, 0);
  lcd.print("SOMETHING");
  delay(500);
  lcd.clear();
  delay(500);

  lcd.setCursor(5, 1);
  lcd.print("SOMETHING");
  lcd.setCursor(4, 0);
  lcd.print("SOMETHING");
  delay(500);


  pinMode(VPin, OUTPUT);
  pinMode(MPin, OUTPUT);
  pinMode(SPin, OUTPUT);
  pinMode(DPG, OUTPUT);
  pinMode(DPD, OUTPUT);
  pinMode(GPin, INPUT);
  lcd.clear();

 

  sw_secs.start();


}




void loop()
{

    static unsigned long Time;
    if (digitalRead(GPin) == LOW) {
    
    if (millis() - Time >= 1000)
    {
      
      Time += 1000;
      Consumption();
    }} 
  
else {
  
    if (millis() - Time >= 1000)
    {
      Time += 1000;
      Working(); 
    } 
    digitalWrite(VPin, HIGH);
}
  


  
  Buttons();
  Vrijeme();


 




}







void Consumption() {
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("STATUS: ON");
  lcd.setCursor(0, 1);
  lcd.print("Consumption:");
  lcd.setCursor(12, 1);
  lcd.print("kg/h");
  int Potenciometar = A1;
  int Pot1 = 0;
  int Pot2 = 0;
  Pot1 = analogRead(A1) / 10;
  Pot2 = Pot1 / 1.023;
  lcd.setCursor(9, 1);
  lcd.print(Pot2);
}



void Vrijeme() {

}


void Working() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("STATUS: Working");
  lcd.setCursor(0, 1);
  lcd.print("Consumption:");
  lcd.setCursor(12, 1);
  lcd.print("kg/h");
  int Potenciometar = A1;
  int Pot1 = 0;
  int Pot2 = 0;
  Pot1 = analogRead(A1) / 10;
  Pot2 = Pot1 / 1.023;
  lcd.setCursor(9, 1);
  lcd.print(Pot2);
}


void Buttons()
{
  int Tipke;
  Tipke = analogRead(0);
  if (Tipke < 50) {
    Consumption;
    lcd.setCursor(0, 0);
    lcd.print("UP                ");
  }

  else if (Tipke < 250) {
    Consumption;
    lcd.setCursor(0, 0);
    lcd.print("DOWN                ");
    
  }

  else if (Tipke < 450) {
    lcd.print("");
    lcd.setCursor(0, 0);
    lcd.print("UP Time:         ");

    int h, m, s;
    s = sw_secs.elapsed();
    m = s / 60;
    h = s / 3600;
    s = s - m * 60;
    m = m - h * 60;

    lcd.setCursor(0, 1);
    lcd.print(h);
    lcd.setCursor(1, 1);
    lcd.print(" hrs                  ");
    lcd.setCursor(6, 1);
    lcd.print(m);
    lcd.setCursor(8, 1);
    lcd.print("min");
    lcd.setCursor(9, 1);
  }  }

Delta_G:
When you remove +5V is the pin left connected to anything? If it is not connected to ground but is instead left floating then it might take a while for it to read low.

Just what he says Marko!

I used this in a circuit or two. I fill a wire between a transistor and a pin with 5V charge, lot of electrons. Then I see how many digital reads it takes to drain the charge.

Wire has capacitance, the longer the wire, the more.

If I don't want that then I connect the pin to ground through a 10K or 20K resistor. That is a pull-down.

Connect to power through resistor is a pull-up which AVR has built in 20K to 50K pull ups that you can enable or turn off. A 20K pull up connected to ground can't hurt your chip and it can be grounded through a 10K (smaller) resistor.

THANK YOU both, it works now! Connected 10K resistor between A2 and GND.

Solved?

Want to see a bit more?
Make a global unsigned long named loopCount and at the end of loop() make loopCount++.
Then make a timer to print a line with just loopCount and then zero loopCount.
The goal is to see how fast loop() is running. As long as the number is big, your code will run smooth.

But mostly until you see for yourself it is very hard to grasp how fast that code CAN run.
And you can put the whiles and delay() back in if you want to see a different outcome. :slight_smile:

Thanks for the advice.

Solved but with same problem on the OUTPUT now. Connecting output to GND through 10K resistor didn't solve the problem.

I've tried to enable output on pin 4 (DPG) when I press one of the buttons on LCD shield. And output sometimes remains HIGH after the button is released, sometimes switches to HIGH by itself... And I need it to remain HIGH only while certain button is pressed.

I've tried that in code below but i doesn't seem to work that way.

#include <LiquidCrystal.h>
#include <StopWatch.h>


LiquidCrystal lcd(7, 6, 5, 4, 3, 2);


StopWatch sw_secs(StopWatch::SECONDS);



int VPin = 12;
int MPin = 8;
int SPin = 7;
int DPG = 4;
int DPD = 2;
int GPin = A2;


void setup() {
  //Welcome message
  lcd.begin(16, 2);
  lcd.setCursor(4, 0);
  lcd.print("SOMETHING");
  delay(1000);
  lcd.setCursor(5, 1);
  lcd.print("SOMETHING");
  delay(2000);

  //My way to blink display
  lcd.clear();
  delay(500);

  lcd.setCursor(5, 1);
  lcd.print("SOMETHING");
  lcd.setCursor(4, 0);
  lcd.print("SOMETHING");
  delay(500);
  lcd.clear();
  delay(500);

  lcd.setCursor(5, 1);
  lcd.print("SOMETHING");
  lcd.setCursor(4, 0);
  lcd.print("SOMETHING");
  delay(500);


  pinMode(VPin, OUTPUT);
  pinMode(MPin, OUTPUT);
  pinMode(SPin, OUTPUT);
  pinMode(DPG, OUTPUT);
  pinMode(DPD, OUTPUT);
  pinMode(GPin, INPUT);
  lcd.clear();

 

  sw_secs.start();


}




void loop()
{

    static unsigned long Time;
    if (digitalRead(GPin) == LOW) {
    
    if (millis() - Time >= 1000)
    {
      
      Time += 1000;
      Consumption();
    }} 
  
else {
  
    if (millis() - Time >= 1000)
    {
      Time += 1000;
      Working(); 
    } 
    digitalWrite(VPin, HIGH);
}
  


  
  Buttons();
  Vrijeme();


 




}







void Consumption() {
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("STATUS: ON");
  lcd.setCursor(0, 1);
  lcd.print("Consumption:");
  lcd.setCursor(12, 1);
  lcd.print("kg/h");
  int Potenciometar = A1;
  int Pot1 = 0;
  int Pot2 = 0;
  Pot1 = analogRead(A1) / 10;
  Pot2 = Pot1 / 1.023;
  lcd.setCursor(9, 1);
  lcd.print(Pot2);
}



void Vrijeme() {

}


void Working() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("STATUS: Working");
  lcd.setCursor(0, 1);
  lcd.print("Consumption:");
  lcd.setCursor(12, 1);
  lcd.print("kg/h");
  int Potenciometar = A1;
  int Pot1 = 0;
  int Pot2 = 0;
  Pot1 = analogRead(A1) / 10;
  Pot2 = Pot1 / 1.023;
  lcd.setCursor(9, 1);
  lcd.print(Pot2);
}


void Buttons()
{
  int Tipke;
  Tipke = analogRead(0);
  if (Tipke < 50) {
    Consumption;
    lcd.setCursor(0, 0);
    lcd.print("UP                ");
    digitalWrite(DPG, HIGH);   //Problematic part of code?
  }

  else if (Tipke < 250) {
    Consumption;
    lcd.setCursor(0, 0);
    lcd.print("DOWN                ");
    digitalWrite(DPD, HIGH); //Even tried to place here another line with digitalWrite(DPG, LOW); but it didn't work...
  }

  else if (Tipke < 450) {
    lcd.print("");
    lcd.setCursor(0, 0);
    lcd.print("UP Time:         ");

    int h, m, s;
    s = sw_secs.elapsed();
    m = s / 60;
    h = s / 3600;
    s = s - m * 60;
    m = m - h * 60;

    lcd.setCursor(0, 1);
    lcd.print(h);
    lcd.setCursor(1, 1);
    lcd.print(" hrs                  ");
    lcd.setCursor(6, 1);
    lcd.print(m);
    lcd.setCursor(8, 1);
    lcd.print("min");
    lcd.setCursor(9, 1);
  }  }

Does the LCD shield differentiate between button presses by outputting a different voltage for each button on a single pin or are there separate outputs for each button ?

Is this the LCD board that you have LCD datasheet

This is the one. It uses only one pin, A0.

It uses only one pin, A0.

The code that you posted in reply #8 doesn't read A0, only A2 and even then it uses digitalRead() rather than analogRead().

One, or possibly both, of us is confused. I certainly am.

I thought it reads A0 in this last part of code...

void Buttons()
{
  int Tipke;
  Tipke = analogRead(0);
  if (Tipke < 50) {
    Consumption;
    lcd.setCursor(0, 0);
    lcd.print("UP                ");
    digitalWrite(DPG, HIGH);   //Problematic part of code?
  }

  else if (Tipke < 250) {
    Consumption;
    lcd.setCursor(0, 0);
    lcd.print("DOWN                ");
    digitalWrite(DPD, HIGH); //Even tried to place here another line with digitalWrite(DPG, LOW); but it didn't work...
  }

  else if (Tipke < 450) {
    lcd.print("");
    lcd.setCursor(0, 0);
    lcd.print("UP Time:         ");

    int h, m, s;
    s = sw_secs.elapsed();
    m = s / 60;
    h = s / 3600;
    s = s - m * 60;
    m = m - h * 60;

    lcd.setCursor(0, 1);
    lcd.print(h);
    lcd.setCursor(1, 1);
    lcd.print(" hrs                  ");
    lcd.setCursor(6, 1);
    lcd.print(m);
    lcd.setCursor(8, 1);
    lcd.print("min");
    lcd.setCursor(9, 1);
  }  }

EDIT: Maybe where I've typed Tipke = analogRead(0); should have been Tipke = analogRead(A0); but still result is the same...

My apologies, you are right in that it reads A0. I always use the Ax notation to avoid confusion.

However, when you do this

  Tipke = analogRead(0);
  if (Tipke < 50) {
    Consumption;

What do you think that Consumption; does ?

Well, Consumption; should initialize this:

void Consumption() {
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("STATUS: ON");
  lcd.setCursor(0, 1);
  lcd.print("Consumption:");
  lcd.setCursor(12, 1);
  lcd.print("kg/h");
  int Potenciometar = A1;
  int Pot1 = 0;
  int Pot2 = 0;
  Pot1 = analogRead(A1) / 10;
  Pot2 = Pot1 / 1.023;
  lcd.setCursor(9, 1);
  lcd.print(Pot2);
}

Because I need that to be displayed on LCD and read value from A1 even while button is pressed.
First I've tried with Consumption(); but then when I press buton on LCD shield this reading goes crazy, starts blinking, fading... And I don't know why...

EDIT: I see now that even without that Consumption; it's just a coincidence that display shows what I wanted it to show... Another problem...

Well, Consumption; should initialize this:

You are not CALLING Consumption. If you want to call Consumption, you'd have parentheses:

     Consumption();