Infinite loop until a condition is met

Hi,

I have Arduino Uno, lcd 16x2 with i2c and a piezo sensor. I'm trying to write a code that will display a short animation of a sleeping face until the sensor is triggered there times which will then move on to a waking up animation.

My approach was to write an if function that will count how many times piezo sensor was triggered (condition was that the threshold must be higher than 30) and then while loop with the condition of reaching the count number of three. Inside the whole loop, I've placed an infinite for loop with the animation.

Tried chat gpt but it was only giving me the code that would repeat the animation each time the sensor was triggered..

It's probably super easy for you but I just can't see the solution.

May i ask for your assistance?

Kind regards,
Daniel

loop() runs continuously, why block,that with an ‘infinite loop’ ?

Better to run loop() continuously doing ‘other’ things, then when the conditions are right - perform your specific action,

Write a sketch that shows the asleep face.
Write a sketch that shows the awake face.
Write a sketch that counts three sensor inputs.
Combine.

Ok, so here's my current code:

#include <LiquidCrystal_I2C.h>

// Define the LCD screen
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Define the piezo sensor on pin A3
const int piezoPin = A3;

// Define the threshold value
const int threshold = 30;

void setup() {
  // Initialize LCD
  lcd.begin();
}

void loop() {
    int Count = 0;
    int sensorValue = analogRead(piezoPin);

    if (sensorValue > threshold) {
      Count++;  
      }

for(Count; Count < 3; Count++){
  lcd.print("    -      -");
  lcd.setCursor(1, 1);
  lcd.print("      . <Zzz)");
  delay(2000);
  lcd.clear();

  lcd.clear();
  lcd.print("    -      -");
  lcd.setCursor(1, 1);
  lcd.print("      C <ZzZzz)");
  delay(2000);
  lcd.clear();
}
      // Optional: Add a delay to avoid immediate re-triggering
      delay(500);

lcd.print("    =      =");
lcd.setCursor(1,1);
 lcd.print("     ----   ");
 delay(1000);
lcd.clear();

 lcd.clear();
 lcd.print("    -      -");
 lcd.setCursor(1,1);
 lcd.print("     ----");
 delay(500);
lcd.clear();

lcd.print("    o      o");
lcd.setCursor(1,1);
 lcd.print("     ----   ");
 delay(2000);
lcd.clear();

lcd.print("   O      O");
lcd.setCursor(1,1);
 lcd.print("    ----   ");
 delay(300);
lcd.clear();

lcd.print(" O      O");
lcd.setCursor(1,1);
 lcd.print("  ----");
 delay(2000);
lcd.clear();

lcd.print("    O      O");
lcd.setCursor(1,1);
 lcd.print("     ----");
 delay(300);
lcd.clear();
lcd.print("      O      O");
lcd.setCursor(1,1);
 lcd.print("       ----");
 delay(300);
lcd.clear();
lcd.print("       O      O");
lcd.setCursor(1,1);
 lcd.print("        ----");
 delay(1000);
lcd.clear();

lcd.print("    O      O");
lcd.setCursor(1,1);
 lcd.print("     ----");
 delay(1000);
lcd.clear();

 lcd.clear();
 lcd.print("    -      -");
 lcd.setCursor(1,1);
 lcd.print("     ----");
 delay(200);
lcd.clear();

lcd.print("    O      O");
lcd.setCursor(1,1);
 lcd.print(" #   ----   #");
 delay(1000);
lcd.clear();

 lcd.clear();
 lcd.print("    ^      ^");
 lcd.setCursor(1,1);
 lcd.print(" #    V     #");
 delay(2000);
lcd.clear();

 lcd.clear();
 lcd.print("    ^      ^");
 lcd.setCursor(1,1);
 lcd.print(" #    c<HELLO!)");
 delay(2000);
lcd.clear();

 lcd.clear();
 lcd.print("    ^      ^");
 lcd.setCursor(1,1);
 lcd.print(" #    V     #");
 delay(2000);
 lcd.clear();

for(;;) {
  // iddle state
 lcd.clear();
 lcd.print("    -      -");
 lcd.setCursor(1,1);
 lcd.print(" #   ----   #");
 delay(300);
lcd.clear();

lcd.print("    O      O");
lcd.setCursor(1,1);
 lcd.print(" #   ----   #");
 delay(3000);
lcd.clear();
}
}

It repeats the sequence in for loop 3 times and then continues to the next part.
Maybe someone smarter will be able to crack it :smiley:

Kind regards,
Daniel

1 Like

Count is a local variable to the loop() function. every time you loop, you'll start at 0 again. so in the best case your if statement

    if (sensorValue > threshold) {
      Count++;  
      }

will get Count to 1

and then your for loop (which uses the same variable)

for(Count; Count < 3; Count++){

will get executed either 3 times if Count was 0 or 2 time if Count was 1.


You need to define better what triggers the animation and not do it all the time, only when needed

bool animationNeedsToRun = checkSensors();

if (animationNeedsToRun) {
   // perform the animation
}

if the animation is long, coding it this way will run the animation without an ability to stop it, esp. if you use delays... depends on what you want to do

1 Like

No maybe about it, there are many here who could crack it easily. That doesn't mean they are smarter than you, just more experienced.

You seem to be asking those "smarter" people to do it for you. They could do that, but most would rather teach a man to fish than simply give a man a fish, for the obvious reason.

Here's even worse news for you. This code will never work the way you want and you need to re-write it. That's because all those loops and delays will mean it misses the important sensor readings almost every time.

At the top of this forum section there is a sticky post containing examples of code that is able to do more than one thing at the same time. That's what your code needs to do: run the animation and monitor the sensor at the same time.

2 Likes

Hello danielnir

You should read and study the coding with "arrays" and "structs".
This will allow you to create scalable and simple code.

Have a nice day and enjoy coding in C++.

1 Like

you may or may not be interested in this

struct Disp {
    const char    *s0;
    const char    *s1;
    unsigned long  msec;
};

Disp a [] = {
    { "    -      -", "      . <Zzz)",       2000 },
    { "    -      -", "      C <ZzZzz)",     2000 },
    { }
};

Disp b [] = {
    { "    =      =",    "     ----   ",     1000 },
    { "    -      -",    "     ----",        500 },
    { "    o      o",    "     ----   ",     2000 },
    { "   O      O",     "    ----   ",      300 },
    { " O      O",       "  ----",           2000 },
    { "    O      O",    "     ----",        300 },
    { "      O      O",  "       ----",      300 },
    { "       O      O", "        ----",     1000 },
    { "    O      O",    "     ----",        1000 },
    { "    -      -",    "     ----",        200 },
    { "    O      O",    " #   ----   #",    1000 },
    { "    ^      ^",    " #    V     #",    2000 },
    { "    ^      ^",    " #    c<HELLO!)",  2000 },
    { "    ^      ^",    " #    V     #",    2000 },
    { }
};

Disp c [] = {
    { "    -      -",    " #   ----   #",    30 },
    { "    O      O",    " #   ----   #",    3000 },
    { }
};

Disp *q = b;
Disp *p = q;;

const byte pinInp = A2;
byte       inpLst;

unsigned long msecPeriod;
unsigned long msecLst;

char s [80];

// -----------------------------------------------------------------------------
void
loop ()
{
    unsigned long msec = millis ();

    if (msec - msecLst >= msecPeriod)  {
        msecLst = msec;

        sprintf (s, "%16s %16s", p->s0, p->s1);
        Serial.println (s);

        p++;
        if (! p->s0)
            p = q;
    
        msecPeriod = p->msec;
    }

    byte inp = digitalRead (pinInp);
    if (inpLst != inp)  {
        inpLst = inp;
        delay (20);

        if (q == a)
            p = q = b;
        else if (q == b)
            p = q = c;
        else if  (q == c)
            p = q = a;
        else
            Serial.println ("error");
    }
}

// -----------------------------------------------------------------------------
void
setup ()
{
    Serial.begin (9600);

    pinMode (pinInp, INPUT_PULLUP);
    inpLst = digitalRead (pinInp);
}
2 Likes

@danielnir - That is a very good animation! : )

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.