[SOLVED, thanks to Sterretje!] 3 while loops with a button.

Hey guys,

I’m kinda ‘newbie’ to programming and I’m having issues with my code, basically what I want is that I have

  • 3 while loops
  • everytime you press the button it should go to the next while loop
    I have a LED screen, where I first want a welcome message, when you press the button I want to see the temperature (with an if and else loop for hot and cold), and then if you press the button again I want to see the amount of light falling into the sensor!

Problem:

  • Everytime I press the button there’s just not happening a single thing, I would really appreciate some help.

Code:
http://pastebin.com/hY0mQzgf
(Knop = Button)
(warmteSensor = temperatureSensor)
(weinigLicht = notmuchLight)
(blauwLed = blueLed)

Basically what I’m doing now is when the button == HIGH I use the break; to go to the other loop. But it’s just not working.

Thanks!

The code is small enough to include in the post. For those that don’t like the download:

// This code is made by Niels.
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 7);


// variable to hold previous value of the switchpin
const int warmteSensor = A0;     // mean temperatureSensor
const float normalTemp = 20.0;
int blauwLed = 6;
const int lichtSensor = A1; // means lightSensor
int weinigLicht = 135;     // means notmuchLight
int knop = 0;               // means button

// a variable to choose which reply from the crystal ball

void setup()
{
  // set up the number of columns and rows on the LCD
  lcd.begin(16, 2);
  Serial.begin(9600);

  pinMode(warmteSensor, INPUT);
  pinMode(blauwLed, OUTPUT);
  digitalWrite(blauwLed, LOW);
  pinMode(lichtSensor, INPUT);
  pinMode(knop, INPUT);
}

void loop()
{
  // check the status of the switch
  int sensorVal = analogRead(warmteSensor);
  int licht = analogRead(lichtSensor);
  knop = digitalRead(2);
  float voltage = (sensorVal / 1024.0) * 5.0;
  float temperatuur = (voltage - .5) * 100;
  while (1)
  {
    if (knop == LOW)
    {
      lcd.clear();
      lcd.begin(16, 2);
      lcd.print("Niels zijn mooie");
      lcd.setCursor(0, 1);
      lcd.print("weerstation");
      delay(5000);
      lcd.clear();
      lcd.print("Druk op de knop");
      lcd.setCursor(0, 1);
      lcd.print("om te beginnen");
      delay(5000);
    }
    else if (knop == HIGH)
    {
      Serial.print("KNOP WORDT OP GEDRUKT!");
      break;
    }
  }
  while (2)
  {
    if (temperatuur > normalTemp )
    {
      lcd.clear();
      lcd.begin(16, 2);
      lcd.setCursor(1, 0);
      lcd.print("Niels station");
      lcd.setCursor(0, 1);
      lcd.print("Celsius: ");
      lcd.print(temperatuur);
      Serial.println("Het is warm");
      delay(1000);
    }
    if (temperatuur < normalTemp)
    {
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print("Niels station");
      lcd.setCursor(0, 1);
      lcd.print("Celsius: ");
      lcd.print(temperatuur);
      Serial.println("Het is koud");
      delay(1000);
    }
    if (knop == HIGH)
    {
      break;
    }
  }
  while (3)
  {
    if (licht < weinigLicht)
    {
      digitalWrite(blauwLed, HIGH);
      Serial.println("Het is donker!");
      Serial.print(licht);
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print("Het is donker,");
      lcd.setCursor(0, 1);
      lcd.print("licht gaat aan!");
      delay(100);
    }
    if (licht > weinigLicht)
    {
      digitalWrite(blauwLed, LOW);
      Serial.print("Licht, licht blijft uit, waarde: ");
      Serial.print(licht);
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print("Het is licht,");
      lcd.setCursor(0, 1);
      lcd.print("licht blijft uit!");
      delay(100);
      delay(100);
    }
    if (knop == HIGH);
    break;
  }
}

sterretje:
The code is small enough to include in the post. For those that don’t like the download:

// This code is made by Niels.

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 7);

// variable to hold previous value of the switchpin
const int warmteSensor = A0;    // mean temperatureSensor
const float normalTemp = 20.0;
int blauwLed = 6;
const int lichtSensor = A1; // means lightSensor
int weinigLicht = 135;    // means notmuchLight
int knop = 0;              // means button

// a variable to choose which reply from the crystal ball

void setup()
{
  // set up the number of columns and rows on the LCD
  lcd.begin(16, 2);
  Serial.begin(9600);

pinMode(warmteSensor, INPUT);
  pinMode(blauwLed, OUTPUT);
  digitalWrite(blauwLed, LOW);
  pinMode(lichtSensor, INPUT);
  pinMode(knop, INPUT);
}

void loop()
{
  // check the status of the switch
  int sensorVal = analogRead(warmteSensor);
  int licht = analogRead(lichtSensor);
  knop = digitalRead(2);
  float voltage = (sensorVal / 1024.0) * 5.0;
  float temperatuur = (voltage - .5) * 100;
  while (1)
  {
    if (knop == LOW)
    {
      lcd.clear();
      lcd.begin(16, 2);
      lcd.print(“Niels zijn mooie”);
      lcd.setCursor(0, 1);
      lcd.print(“weerstation”);
      delay(5000);
      lcd.clear();
      lcd.print(“Druk op de knop”);
      lcd.setCursor(0, 1);
      lcd.print(“om te beginnen”);
      delay(5000);
    }
    else if (knop == HIGH)
    {
      Serial.print(“KNOP WORDT OP GEDRUKT!”);
      break;
    }
  }
  while (2)
  {
    if (temperatuur > normalTemp )
    {
      lcd.clear();
      lcd.begin(16, 2);
      lcd.setCursor(1, 0);
      lcd.print(“Niels station”);
      lcd.setCursor(0, 1);
      lcd.print("Celsius: ");
      lcd.print(temperatuur);
      Serial.println(“Het is warm”);
      delay(1000);
    }
    if (temperatuur < normalTemp)
    {
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print(“Niels station”);
      lcd.setCursor(0, 1);
      lcd.print("Celsius: ");
      lcd.print(temperatuur);
      Serial.println(“Het is koud”);
      delay(1000);
    }
    if (knop == HIGH)
    {
      break;
    }
  }
  while (3)
  {
    if (licht < weinigLicht)
    {
      digitalWrite(blauwLed, HIGH);
      Serial.println(“Het is donker!”);
      Serial.print(licht);
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print(“Het is donker,”);
      lcd.setCursor(0, 1);
      lcd.print(“licht gaat aan!”);
      delay(100);
    }
    if (licht > weinigLicht)
    {
      digitalWrite(blauwLed, LOW);
      Serial.print("Licht, licht blijft uit, waarde: ");
      Serial.print(licht);
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print(“Het is licht,”);
      lcd.setCursor(0, 1);
      lcd.print(“licht blijft uit!”);
      delay(100);
      delay(100);
    }
    if (knop == HIGH);
    break;
  }
}

Oh sorry I didn’t know to do that :P. Do you know how to fix it though?

First misunderstanding:

...
...
int knop = 0;               // means button
...
...

void setup()
{
  ...
  ...
  pinMode(knop, INPUT);
}

This will set pin 0 to input. But according to your loop you read pin 2 and you should basically set that to input. What saves you here is that the default for a pin is INPUT.

You should have something like

...
...
int knopWaarde = 0;               // buttonValue
const byte knop = 2;
...
...

void setup()
{
  ...
  ...
  pinMode(knop, INPUT);
}

void loop()
{
  knopWaarde = digitalRead(knop);
}

Your problem however is more than likely that you only read the button once. You need to read the button inside the while loops.

This is in general not the correct approach; you actually need a small statemachine and a variable to remember which mode you're in. You also need to check the state-change example that comes with the IDE.

akatchi:
Oh sorry I didn't know to do that :P. Do you know how to fix it though?

If you click the code button, you can see how I used the code tags :wink:

Thanks a lot man! Appreciate your help a lot, I’ll try it now!!

sterretje:
First misunderstanding:

...

...
int knop = 0;              // means button
...
...

void setup()
{
  ...
  ...
  pinMode(knop, INPUT);
}



This will set pin 0 to input. But according to your loop you read pin 2 and you should basically set that to input. What saves you here is that the default for a pin is INPUT.

You should have something like


...
...
int knopWaarde = 0;              // buttonValue
const byte knop = 2;
...
...

void setup()
{
  ...
  ...
  pinMode(knop, INPUT);
}

void loop()
{
  knopWaarde = digitalRead(knop);
}




Your problem however is more than likely that you only read the button once. You need to read the button inside the while loops.

This is in general not the correct approach; you actually need a small statemachine and a variable to remember which mode you're in. You also need to check the state-change example that comes with the IDE.

Hmh when I use that the screen won't show anything, otherwise it means that it won't even go into the first 'while' loop..

Now it's just skipping all the 'while loops'.
Does someone know how to go from 'while' loop to while loop via the button?

Start with the state change example and increment a variable when you detect a change from low to high. Call this variable e.g. 'mode' as it reflects the mode that your program is in. When the variable reaches 3, set it back to 0.

Next part of loop can look like

void loop ()
{
  static byte mode = 0;
  ...
  ...

  switch (mode)
  {
    case 0:
      // display your welcome message
      ...
      ...
      break;
    case 1:
      // display your temperatures
      ...
      ...
      break;
    case 2:
      // display your light readings
      ...
      ...
      break;
  }
}

There are no while loops; loop () takes care of the looping. You shoukd also get rid of the delays; check the blink-without-delay example that also comes with the IDE.

Alright thanks! But how do I make it that it switch to a new case when I press the button?

I gave you the hint to look at the state change example and the blink-without-delay example that came with the IDE. The other example that you might want to look at is the debounce example.

For the debounce example, instead of changing the ledState you can adjust the 'mode' variable. The below is fully based on the debounce example

// constants won't change. They're used here to
const int buttonPin = 2;    // the number of the pushbutton pin

// Variables will change:
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup()
{
  pinMode(buttonPin, INPUT);
}

void loop()
{
  // the mode that our program is in; initialised with 0
  static byte mode = 0;

  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH),  and you've waited
  // long enough since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState)
  {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay)
  {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState)
    {
      buttonState = reading;

      // only change the mode if the new button state is HIGH (so transition from LOW to HIGH)
      if (buttonState == HIGH)
      {
        // next mode
        mode++;
        // set mode back to 0 if needed
        if (mode == 3)
        {
          mode = 0;
        }
      }
    }
  }

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;

  switch (mode)
  {
    case 0:
      // display your welcome message
      displayWelcome();
      break;
    case 1:
      // display your temperatures
      displayTemperatures();
      break;
    case 2:
      // display your light readings
      displayLightReadings();
      break;
  }
}

void displayWelcome()
{
  // display welcome message
}

void displayTemperatures()
{
  // read temperature here
  ...
  ...
  // display it
  ...
  ...
}

void displayLightReadings()
{
  // read light level here
  ...
  ...
  // display it
  ...
  ...
}

Please please please, understand the code.

Note 1:
not tested, I usually use a different approach.
Note 2:
there is no need for any use of while !!

sterretje:
I gave you the hint to look at the state change example and the blink-without-delay example that came with the IDE. The other example that you might want to look at is the debounce example.

For the debounce example, instead of changing the ledState you can adjust the ‘mode’ variable. The below is fully based on the debounce example

// constants won't change. They're used here to

const int buttonPin = 2;    // the number of the pushbutton pin

// Variables will change:
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are long’s because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup()
{
 pinMode(buttonPin, INPUT);
}

void loop()
{
 // the mode that our program is in; initialised with 0
 static byte mode = 0;

// read the state of the switch into a local variable:
 int reading = digitalRead(buttonPin);

// check to see if you just pressed the button
 // (i.e. the input went from LOW to HIGH),  and you’ve waited
 // long enough since the last press to ignore any noise:

// If the switch changed, due to noise or pressing:
 if (reading != lastButtonState)
 {
   // reset the debouncing timer
   lastDebounceTime = millis();
 }

if ((millis() - lastDebounceTime) > debounceDelay)
 {
   // whatever the reading is at, it’s been there for longer
   // than the debounce delay, so take it as the actual current state:

// if the button state has changed:
   if (reading != buttonState)
   {
     buttonState = reading;

// only change the mode if the new button state is HIGH (so transition from LOW to HIGH)
     if (buttonState == HIGH)
     {
       // next mode
       mode++;
       // set mode back to 0 if needed
       if (mode == 3)
       {
         mode = 0;
       }
     }
   }
 }

// save the reading.  Next time through the loop,
 // it’ll be the lastButtonState:
 lastButtonState = reading;

switch (mode)
 {
   case 0:
     // display your welcome message
     displayWelcome();
     break;
   case 1:
     // display your temperatures
     displayTemperatures();
     break;
   case 2:
     // display your light readings
     displayLightReadings();
     break;
 }
}

void displayWelcome()
{
 // display welcome message
}

void displayTemperatures()
{
 // read temperature here
 …
 …
 // display it
 …
 …
}

void displayLightReadings()
{
 // read light level here
 …
 …
 // display it
 …
 …
}




Please please please, understand the code.

Note 1:
not tested, I usually use a different approach.
Note 2:
there is no need for any use of while !!

I’m starting to understand the code! Thanks I’ll try to change the code now as you stated :)!