"break"ing out of a while-loop

Have a quadrature encoder reading function that I need to break out of if a digitalRead detects a button press.

I have commented out the offending code that kills the function. With it ‘out’, the function works fine. With it ‘in’ the function stops looping back through, I never get a single response to the encoder turning.

I started out with an "if (digitalRead(enterPin) == HIGH) { " instead of the digitalRead / set “y” var… but it was no different.

(gotEnter) is a global variable that I look at when the function exits/returns to determine what to do next…

I’m sure it’s obvious… just not to this newb.

int readEncoder()                                 // "int" variable will be returned
{  
Serial.println("readEncoder()");
  static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_AB = 0;
  int y = 0;
  gotEnter = 0;                                     // reset this to FALSE

for (int x=0; x <= 1; x++) {                        // (exclusive-variable "x") only pay attention to every-other 'event'
  encOut = 0;                                       // and clear encOut when we're skipping it
  while (encOut == 0) {                             // original code - loop until encoder knob is rotated/changed
/*    y=digitalRead(enterPin);                        // test for ENTER button being pressed (close to leading edge checking)
    if (y == 1) {
      gotEnter = 1;                                 // set indicator that we HAVE seen the Enter button go HIGH
Serial.print("gotEnter="); Serial.println(gotEnter);
      break;
*/      
     old_AB <<= 2;                                 // remember previous state
     old_AB |= ( ENC_PORT & 0x03 );                // add current state
     tmpdata = (enc_states[( old_AB & 0x0f )]);
Serial.print("tmpdata="); Serial.println(tmpdata);
     if (tmpdata !=0)
      {                             // if tmpdata is non-zero, do following; else loop back to get a new reading                  
       encOut=tmpdata;              // I do NOT want this to increment the "counter" variable, just give me +1 or -1
      }
    }
  //}
}
Serial.println("readEncoder_exit");
  return (encOut);                  // return a +1 or -1 otherwise, per encoder rotation
}

dang, I’m dum sumtymes…

(this stuff used to be so logical… 30 years ago when my mind was still engulfed in all this)

fixed it…

//------readEncoder-----------------------
                          /* returns only dir of encoder rotation click (-1,1) */
// original code (which works perfect as originally written and used with suitable encoder) from:
//    http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino 
                            
int8_t readEncoder()                           // "int" variable will be returned when all done
{  
int cw = 0;
int ccw = 0;
encOut = 0;
  
int8_t tmpdata;

while (encOut == 0) {
  if (digitalRead(enterPin) == LOW) {      // while encOut=0, loop until encoder knob is rotated/changed
   tmpdata = read_encoderb();                 // calls the function, RAW from reader, not just +1 or -1

    if (tmpdata)  {        

      if (tmpdata == 1)  {                  // value of 1 is a CW encoder (half)click
        cw++;                               // add 1 to my CW clicks counter, and
        if (cw == 2)  {                     // if we've had 2 (half)clicks...
          encOut = 1;                   // we can now set output 
          cw = 0;
          return(encOut);
        }
      }
        
      if (tmpdata == -1)  {                // value of -1 means a CCW encoder (half)click
          ccw++;  
          if (ccw == 2)  {
            encOut = -1;
            ccw = 0;
            return(encOut);
          }
      }
    
    }
    }     
   else {                    // exception to "WHILE", detected enterButton press, do the following
     gotEnter = 1;                    // set indicator that we HAVE seen the Enter button go HIGH
     return (0);           // return a +1 or -1 per encoder detent, except when "enter" button has been pressed
   }
}
}
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
                       /* returns ANY change in encoder state (-1,0,1) */
int8_t read_encoderb()
{  
     static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
     static uint8_t old_AB = 0;

     old_AB <<= 2;                                 // remember previous state
     old_AB |= ( ENC_PORT & 0x03 );                // add current state
     return (enc_states[( old_AB & 0x0f )]);
}
//======================

(ok, THIS is my final ‘fixed’ version… had to split it back apart more like the original code. One of my biggest problems was getting it working with the specific Bourns encoders I already purchased for the project… they output 2 full code sequences per “click”. I had to devise a way to ignore 1/2 of the “events”, which were “direction” codes output from the final Function.)

Again… I’m a freshman here in Arduino-speak… so if you see things I should do a better way, I invite your help!

BTW... the original encoder reading code came from here:

http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino

... it's for QUADRATURE encoders, not Grey code encoders.

ronbot: ... it's for QUADRATURE encoders, not Grey code encoders.

Actually, there is no difference.

A "quadrature" encoder is a Grey Code encoder.

My concern here is that you are using a "while" loop to read an external input which your code itself cannot change. This is an inappropriate use of any sort of loop - it is called "busy waiting" and causes a form of deadlock.

You should be using a code within the main "loop" which reads the encoder, makes some form of decision and moves on. The "decision" will most frequently be to set a status and since you seem to indicate a mechanical encoder (well, you don't, but the article you cite does), part of this decision making involves a debounce routine as well.

If you re-think the procedure in that fashion, no "break out" will be necessary as the separate part of the code (within the master loop as it repeats) which reads your button (is it the encoder press itself?) will simply perform what it needs to do.

so if you see things I should do a better way, I invite your help!

I recommend that you become good friends with Toosl + Auto Format.

Code that bounces
all over the
place is very
hard to
read.

PaulS: I recommend that you become good friends with Toosl + Auto Format.

Toosl?

Toosl?

Yeah. It's right there between Skretch and Hepl.

Carpal Tunnel Syndrome sucks.