Stumped Again

In my continuing quest to build a valve control device for water drop
photography I am once again battling C++. this time it is program
logic. I have the following code that is supposed to allow me
to change the number of drops that I am going to release.

The outloop does what it is supposed to do based on the number
of drops I select. What happens is when I enter the main loop
I can select 1, 2 or 3 drops by pushing the up and down keys on
the DFRobot LCD shield. I have logic in the loop to force no
more than 3 drops or less than 1 drop. That works.

What fails is the call to the outloop. When the outloop runs
it outputs pulses that Ii can see on the board LED. When the outloop
completes it does not go back to the top of the main loop. It appears
to be running over and over with getting back to the while (key != 4) statement.

I put a couple of diagnostic counters in the program to try and help me diagnose
the failure. loopcount increments very fast while doing the drop select logic
which is what I would expect. loopcount1 is doing nothing when I am selecting
drops, also expected results. When I push the select button (Key = 4) that changes.
loopcount stops incrementing and loopcount1 increments each time the outloop runs.

My code is obviously flawed because I do not understand returning from the outloop and what is
wrong with my code that it does NOT go to the while (key != 4) statement when I return from
outloop.

Thanks in advance for any and all help!!!

RWW

Here is the code:

#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

char msgs[5][15] = {
  "Right Key OK ",   // Value = 0
  "Up Key OK    ",   // Value = 1
  "Down Key OK  ",   // Value = 2
  "Left Key OK  ",   // Value = 3
  "Select Key OK" }; // Value = 4

int  adc_key_val[5] ={
  30, 150, 360, 535, 760 };

int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;

int DropCount = 2;       // default Starting point
int pulseWidth0 = 1000;  //Valve ON Time  (Drop Size)
int pulseWidth1 = 1000;  //Valve ON Time  (Drop Size)
int pulseWidth2 = 1000;  //Valve ON Time  (Drop Size)
int pulseSep0 = 300;    // Drop Seperation time  (Time Between Drops), valve off time
int pulseSep1 = 350;    // Drop Seperation time  (Time Between Drops), valve off time
int pulseSep2 = 400;    // Drop Seperation time  (Time Between Drops), valve off time
int sensorValue =0;
int reading = 0;
int backLight = 10;
int selectPin = 6;
int valveControl =11;    // Output pin to turn valve ON & OFF
int ledpin = 13;

int loopcount = 0;
int loopcount1 = 0;

void setup() 
{ 
  pinMode(13, OUTPUT);  //we'll use the debug LED to output a heartbeat
  pinMode(11,OUTPUT);
  pinMode(10,OUTPUT);
  lcd.begin(16,2);
  //optionally, now set up our application-specific display settings, overriding whatever the lcd did in lcd.init()
  digitalWrite(13, LOW);    // Turn OFF board LED
  digitalWrite(backLight,HIGH); // Turn ON LCD Backlight
  lcd.clear();
 
    lcd.print("Drop Count");
    lcd.setCursor(13,0);
    lcd.print(DropCount);
    lcd.setCursor(13,0);
    //lcd.cursor();   //Turn on the cursor
}

void loop() 
{
  while (key != 4)
  {
  adc_key_in = analogRead(0);    // read the value from the sensor  
       loopcount = loopcount++; 
       lcd.setCursor(0,1);
       lcd.print(loopcount);
       lcd.setCursor(8,1);
       lcd.print(loopcount1);
  //digitalWrite(13, HIGH);  
  key = get_key(adc_key_in);    // convert into key press
  if (key != oldkey) // if keypress is detected
  {
    delay(50);      // wait for debounce time
    adc_key_in = analogRead(0);    // read the value from the sensor  
    key = get_key(adc_key_in);    // convert into key press
    if (key != oldkey)             
    {           
      oldkey = key;
      if (key >=0)
      {  
          lcd.setCursor(13, 0);  //line=1, pos 13
          lcd.setCursor(0,1);
          lcd.print("             ");  // erase error message   
          lcd.setCursor(0,0);
          lcd.print("Drop Count");
          lcd.setCursor(13,0);
          lcd.print(DropCount);
          lcd.setCursor(13,0);
        }
          if (key == 1)
          {
          DropCount = DropCount++;
          if (DropCount == 4)

          { 
            DropCount = 3;
            lcd.setCursor(0,1);
            lcd.print("Max Drops = 3");
            lcd.setCursor(13,0);
          }

          lcd.print(DropCount);
          lcd.setCursor(13,0);
        }

        else if (key == 2)
        {
          lcd.setCursor(13, 0);  //line=1, pos 13
          DropCount = DropCount--;
          lcd.print(DropCount);
          lcd.setCursor(13,0);
          if (DropCount == 0)
          { 
            DropCount = 1;
            lcd.setCursor(0,1);
            lcd.print("Min Drops = 1");
            lcd.setCursor(13,0);
          }
          lcd.print(DropCount);
          lcd.setCursor(13,0);
        }
       }
      }    
     }
       outloop();
         delay(500);
         lcd.setCursor(13,0);
         lcd.print(DropCount);

       }

// Convert ADC value to key number

int get_key(unsigned int input)
     {   
  int k;
  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {  
      return k;  
    }
  }
  if (k >= NUM_KEYS)
    k = -1;     // No valid key pressed
  return k;
}

void outloop()
      
     { 
       loopcount1 = loopcount1++;
       lcd.setCursor(8,1);
       lcd.print(loopcount1);
       lcd.setCursor(0,1);
       lcd.print(loopcount);
       if (DropCount == 1)
             {
               digitalWrite(backLight,LOW);  //Backlight OFF
               
               digitalWrite(13,HIGH);
               digitalWrite(valveControl,LOW);   //Valve ON
               delay (pulseWidth0);
               digitalWrite(valveControl,HIGH);
               digitalWrite(13,LOW);
               delay(2000);                     //  Make sure Camera is done 
               digitalWrite(backLight,HIGH);   //Backlight ON
             }
  
       else if (DropCount == 2)
             {
               digitalWrite(backLight,LOW);    //Backlight OFF
               
               digitalWrite(13,HIGH);
               digitalWrite(valveControl,LOW);   //Valve ON
               delay (pulseWidth0);
               digitalWrite(valveControl,HIGH);  //Valve OFF
               digitalWrite(13,LOW);
               
               delay(pulseSep0);
               
               digitalWrite(13,HIGH);
               digitalWrite(valveControl,LOW);   //Valve ON
               delay (pulseWidth1);
               digitalWrite(valveControl,HIGH);  //Valve OFF
               digitalWrite(13,LOW);
               delay(2000);                       //  Make sure Camera is done 
               digitalWrite(backLight,HIGH);    //Backlight ON
            }
     
        else if (DropCount == 3)
         
              {
                 digitalWrite(backLight,LOW);   //Backlight OFF
                 
                 digitalWrite(13,HIGH);
                 digitalWrite(valveControl,LOW);   //Valve ON
                 delay (pulseWidth0);
                 digitalWrite(valveControl,HIGH);  //Valve OFF
                 digitalWrite(13,LOW);
                 
                 delay(pulseSep0);
                 
                 digitalWrite(13,HIGH);
                 digitalWrite(valveControl,LOW);    //Valve ON
                 delay (pulseWidth1);
                 digitalWrite(valveControl,HIGH);   //Valve OFF
                 digitalWrite(13,LOW);
                 
                 delay(pulseSep1);
                 
                 digitalWrite(13,HIGH);
                 digitalWrite(valveControl,LOW);   //Valve ON
                 delay (pulseWidth2);
                 digitalWrite(valveControl,HIGH);  //Valve OFF
                 digitalWrite(13,LOW);
                 delay(2000);                       //  Make sure Camera is done 
                 digitalWrite(backLight,HIGH);   //Backlight ON
                 return;
           }
             
}
  loopcount1 = loopcount1++;

Did you mean to do that?

or did you just meanloopcount1++;

The return at the end of "outloop" looks to me to be redundant.

Judging by the amount of common code in "outloop", it looks to me like it would be better written as switch/case with fall-throughs.

AWOL,

The loopcount = loopcount++ was meant to increment loopcount by one as a diagnostic tool for me. It has no other function in the code. based on your comment I am assuming the syntax for this statement is incorrect and I will change it.

As to the redundant return I put that there hoping to fix the outloop coming back to the main loop in the wrong spot. The sketch did the same thing with or without the return.

As for the case switch I wanted to keep my outloop simple by using 'if else' and 'while' statements. So much for that convoluted thinking....

Where I seem to be getting tripped up is the return from the outloop. Can you shed any insight as to what you think might be causing the routine to comeback to the main loop in the wrong spot?

Can you shed any insight as to what you think might be causing the routine to comeback to the main loop in the wrong spot?

A function will return to immediately after the point it was called, so if it is returning to the wrong place, it suggests the call was at the wrong place.

based on your comment I am assuming the syntax for this statement is incorrect and I will change it.

There is nothing at all wrong with the syntax. Had there been, the compiler would have complained.

AWOL,

Ok, a function returns to immediately after it was called. I did not know that. Now to figure out where to put the call so it does execute when the select button is pushed and goes back to the while != 4 statement.

void loop() { while (key != 4) // stay here and set up the number of drops // this is where I would expect the call to return

{ statement 1; // determine if up is pushed and add one to drop count statement 2; // determine if down is pushed and subtract one from drop count statement 3; // determine if min/max settings are violated } // this curly brace ends the while loop, correct? outloop(); // the select button has been pushed key is = 4, control the valve } // this curly brace ends the loop, correct?

void outloop() // control the valve { do stuff }

in the above statements where will the call return to?

void loop() 
{
  while (key != 4)
  {
    // blah blah
  }
  outloop();

// <--- when you return from outloop it comes to here
 
  delay(500);
  lcd.setCursor(13,0);
  lcd.print(DropCount);

}

where will the call return to?

It returns to directly after where you called it, as AWOL said. Don’t start thinking it will magically jump to somewhere else. The point I put the arrow at.

So I modified the code by getting rid of the ‘while’ statement
and adding an ‘else if’ statement to check for the select button
and that now works.

I suspect that I was getting tripped up by curly braces.

Now to incorporate code that asks for drop size and duration based on
the number of drops selected. This is really going to get hairy now!!!

RWW

#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

/*
 Right        Value = 0
 Up           Value = 1
 Down         Value = 2
 Left         Value = 3
 Select       Value = 4
 */
int  adc_key_val[5] ={
  30, 150, 360, 535, 760 };

int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;

int DropCount = 2;       // default Starting point
int pulseWidth0 = 1000;  //Valve ON Time  (Drop Size)
int pulseWidth1 = 1000;  //Valve ON Time  (Drop Size)
int pulseWidth2 = 1000;  //Valve ON Time  (Drop Size)
int pulseSep0 = 300;    // Drop Seperation time  (Time Between Drops), valve off time
int pulseSep1 = 350;    // Drop Seperation time  (Time Between Drops), valve off time
int pulseSep2 = 400;    // Drop Seperation time  (Time Between Drops), valve off time
int sensorValue =0;
int reading = 0;
int backLight = 10;
int selectPin = 6;
int valveControl =11;    // Output pin to turn valve ON & OFF
int ledpin = 13;

int loopcount = 0;
int loopcount1 = 0;

void setup() 
{ 
  pinMode(13, OUTPUT);  //we'll use the debug LED to output a heartbeat
  pinMode(11,OUTPUT);
  pinMode(10,OUTPUT);
  lcd.begin(16,2);
  //optionally, now set up our application-specific display settings, overriding whatever the lcd did in lcd.init()
  digitalWrite(13, LOW);    // Turn OFF board LED
  digitalWrite(backLight,HIGH); // Turn ON LCD Backlight
  lcd.clear();

  lcd.print("Drop Count");
  lcd.setCursor(13,0);
  lcd.print(DropCount);
  lcd.setCursor(13,0);
  //lcd.cursor();   //Turn on the cursor
}

void loop() 
{

    adc_key_in = analogRead(0);    // read the value from the sensor  
  
    key = get_key(adc_key_in);    // convert into key press
    if (key != oldkey) // if keypress is detected
    {
      delay(50);      // wait for debounce time
      adc_key_in = analogRead(0);    // read the value from the sensor  
      key = get_key(adc_key_in);    // convert into key press
      if (key != oldkey)             
      {           
        oldkey = key;
        if (key >=0)
        {  
          lcd.setCursor(13, 0);  //line=1, pos 13
          lcd.setCursor(0,1);
          lcd.print("             ");  // erase error message   
          lcd.setCursor(0,0);
          lcd.print("Drop Count");
          lcd.setCursor(13,0);
          lcd.print(DropCount);
          lcd.setCursor(13,0);
        }
        if (key == 1)
        {
          DropCount = DropCount++;
          if (DropCount == 4)

          { 
            DropCount = 3;
            lcd.setCursor(0,1);
            lcd.print("Max Drops = 3");
            lcd.setCursor(13,0);
          }

          lcd.print(DropCount);
          lcd.setCursor(13,0);
        }

        else if (key == 2)
        {
          lcd.setCursor(13, 0);  //line=1, pos 13
          DropCount = DropCount--;
          lcd.print(DropCount);
          lcd.setCursor(13,0);
          if (DropCount == 0)
          { 
            DropCount = 1;
            lcd.setCursor(0,1);
            lcd.print("Min Drops = 1");
            lcd.setCursor(13,0);
          }
          lcd.print(DropCount);
          lcd.setCursor(13,0);
        }
        else if (key == 4)
        { outloop();
          delay(500);
          lcd.setCursor(13,0);
          lcd.print(DropCount);
        }
      }
    }    
  }
  
  


// Convert ADC value to key number

int get_key(unsigned int input)
{   
  int k;
  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {  
      return k;  
    }
  }
  if (k >= NUM_KEYS)
    k = -1;     // No valid key pressed
  return k;
}

void outloop()

{ 

  if (DropCount == 1)                        //  Output 1 drop
 
  {
    digitalWrite(backLight,LOW);      //Backlight OFF

    digitalWrite(13,HIGH);
    digitalWrite(valveControl,LOW);   //Valve ON
    delay (pulseWidth0);
    digitalWrite(valveControl,HIGH);
    digitalWrite(13,LOW);
    delay(2000);                     //  Make sure Camera is done 
    digitalWrite(backLight,HIGH);   //Backlight ON
  }

  else if (DropCount == 2)
  {
    digitalWrite(backLight,LOW);    //Backlight OFF

    digitalWrite(13,HIGH);
    digitalWrite(valveControl,LOW);   //Valve ON
    delay (pulseWidth0);
    digitalWrite(valveControl,HIGH);  //Valve OFF
    digitalWrite(13,LOW);

    delay(pulseSep0);

    digitalWrite(13,HIGH);
    digitalWrite(valveControl,LOW);   //Valve ON
    delay (pulseWidth1);
    digitalWrite(valveControl,HIGH);  //Valve OFF
    digitalWrite(13,LOW);
    delay(2000);                      //Make sure Camera is done 
    digitalWrite(backLight,HIGH);     //Backlight ON
  }

  else if (DropCount == 3)                 //  Output 3 drops

  {
    digitalWrite(backLight,LOW);     //Backlight OFF

    digitalWrite(13,HIGH);
    digitalWrite(valveControl,LOW);   //Valve ON
    delay (pulseWidth0);
    digitalWrite(valveControl,HIGH);  //Valve OFF
    digitalWrite(13,LOW);

    delay(pulseSep0);

    digitalWrite(13,HIGH);
    digitalWrite(valveControl,LOW);    //Valve ON
    delay (pulseWidth1);
    digitalWrite(valveControl,HIGH);   //Valve OFF
    digitalWrite(13,LOW);

    delay(pulseSep1);

    digitalWrite(13,HIGH);
    digitalWrite(valveControl,LOW);   //Valve ON
    delay (pulseWidth2);
    digitalWrite(valveControl,HIGH);  //Valve OFF
    digitalWrite(13,LOW);
    delay(2000);                      //  Make sure Camera is done 
    digitalWrite(backLight,HIGH);     //Backlight ON

  }             
}