Need some logic/syntax help!

Hey guys and gals,

I've been slowly working through some code this morning which is an implementation of the piezo knock pattern sensor, but instead I am using an IR emitter and collector and attempting to measure the gaps between the sensor being blocked, checking those gap intervals against a master key, and either providing a success action or failure action. I have only gotten as far as trying to get the gap values stored properly into an array.

The code works fairly well up to this point except for two problems:

  1. The '6' (last) slot on my array (gapArray) changes with the counter I set up (arrayCounter).
    a. All other array slots populate correctly with the time (in ms) of the gap between one sensor block to the next
    b. The incrementation for arrayCounter is in "gapTimer()" near the bottom of the code
  2. When all 7 slots are filled and I intend for everything to reset back to start (for another entry) the program jumps straight into gapTimer() and not switchTrack().
    a. I have tried resetting timerSwitchA and timerSwitchB back to 0 in the final function without luck

I tried to explain this as best I can. After several hours of trying to debug and trouble shoot, I decided to see if anyone could look at this with a fresh pair of eyes. This could easily be replicated with a simple push button (pin 7) and LED (pin 6) if anyone is willing to physically see what the problem is. Thanks!

int ledPin = 6;
int irPin = 7;
int val = 0;
int val2 = 0;
int gapArray[6];
int arrayCounter = 0;
int timerSwitchA = 0;
int timerSwitchB = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(irPin, INPUT);
}

void loop()
{

  val = digitalRead(7); // Reading value from IR collector
  
  Serial.print(val); // Some serial readouts to verify values
  Serial.print(" ");
  Serial.print(timerSwitchA);
  Serial.print(" ");
  Serial.print(timerSwitchB);
  Serial.print(" A0:");
  Serial.print(gapArray[0]);
  Serial.print(" A1:");
  Serial.print(gapArray[1]);
  Serial.print(" A2:");
  Serial.print(gapArray[2]);
  Serial.print(" A3:");
  Serial.print(gapArray[3]);
  Serial.print(" A4:");
  Serial.print(gapArray[4]);
  Serial.print(" A5:");
  Serial.print(gapArray[5]);
  Serial.print(" A6:");
  Serial.print(gapArray[6]);   
  Serial.print(" AC:");
  Serial.println(arrayCounter);
  
  switchTrack(); //Where the business really starts
  
}

void switchTrack()
  {
   if (arrayCounter == 7) // Used to check pattern after all 7 array slots are filled
  {
   checkPattern();
   timerSwitchA = 0;
   timerSwitchB = 0;
  }
  
   if (val == 1) // If the collector is not receiving IR from emitter			
  {
    digitalWrite(ledPin, HIGH);			
    timerSwitchA = 1;
  } 

  if (timerSwitchA == 1 && val == 0)
  {
    timerSwitchB = 2;
  }

  if (timerSwitchA == 1 && timerSwitchB == 2) // Used to check for when the sensor becomes unblocked to move into gapTimer()
  {
  gapTimer();
  }
}

void gapTimer() {
  digitalWrite(ledPin, LOW);
  
    for (int x = 0; x < 2000; x++) // Counts up to 2 seconds at max for each gap
    {
       val2 = digitalRead(7);  
       Serial.println(x);
       
        if (val2 == 1) // When sensor is blocked again, stores current x value in array slot incremented by arrayCounter
       {
         Serial.print(x);
         Serial.print(" ");
         gapArray[arrayCounter] = x;
         arrayCounter++;
         break; 
       }
   
    timerSwitchA = 0; // Resets 
    timerSwitchB = 0;
  }
}

void checkPattern() { // Will eventually be used to check array values against preprogrammed pattern
  
  timerSwitchA = 0;
  timerSwitchB = 0;
  arrayCounter = 0;
  Serial.print("CHECK PATTERN RAN");
  delay(2000);
  
  for (int y = 0; y < 7; y++) // Used to rest all array values back to 0
  {
    gapArray[y] = 0; 
  }
}

// Used to check pattern after all 7 array slots

The array is declared with 6 elements, zero to five.

1 Like

AWOL:

// Used to check pattern after all 7 array slots

The array is declared with 6 elements, zero to five.

Well this quickly solved one problem. I'm too rusty on arrays and was mistaken in thinking that defining it as '6' meant it stopped at slot 6 (0-6) and was actually 7 slots. Big thanks. :grin:

The issue of the code not resetting properly still exists though.

Well, when you've fixed all the array indices, post your code.

(note to mods: this is virtually unusable.)

Well the only thing I changed was the original definition of the array (from 6 to 7) which corrected my first problem. Nothing else has changed.

And what is virtually unusable?

the program jumps straight into gapTimer() and not switchTrack().

How have you determined this? It looks like the only path into gapTimer() is through switchTrack().

I determined it by watching the serial output from the copious amounts of serial prints I included along the way for debugging. The way in which gapTimer() is invoked within switchTrack() is by having timerSwitchA and timerSwitchB at appropriate values (1 and 2 respectively). This is so that the the gapTimer() is invoked upon release of the button, though I may consider changing that. But, it seems that even though I've tried to redefine timerSwitchA and timerSwitchB to 0 at several times in the code, including when the array is filled and the incremental array counter is reset to 0, upon returning to the void loop() and re-running switchTrack(), it doesn't wait for my input and simply goes to gapTimer().

I guess if I were you, I'd move the serial prints into switchTrack(). That was I definitely see what the values of variables are before gapTimer() gets called.

In your original description you mentioned using a PushButton to simulate the sensor. Is that how you are testing this code now?

Yes, I replaced the IR gate with a push button.

I actually just stumbled upon a work around. I only changed the following code within gapTimer() :

void gapTimer() {
  digitalWrite(ledPin, LOW);
  
    for (int x = 0; x < 500; x++) 
    {
       val2 = digitalRead(7);  
       Serial.println(x);
       
        if (x == 499)
        { 
          digitalWrite(ledPin, HIGH);
          delay(100);
          digitalWrite(ledPin, LOW);
          delay(100);
          digitalWrite(ledPin, HIGH);
          delay(100);
          digitalWrite(ledPin, LOW);
          delay(100);
          digitalWrite(ledPin, HIGH);
          delay(100);
          digitalWrite(ledPin, LOW);
          arrayCounter = 0;
          for (int y = 0; y < 7; y++) // Used to rest all array values back to 0
        {
        gapArray[y] = 0; 
      }
     }
          
        if (val2 == 1) // When sensor is blocked again, stores current x value in array slot incremented by arrayCounter
       {
         Serial.print(x);
         Serial.print(" ");
         gapArray[arrayCounter] = x;
         arrayCounter++;
         break; 
       }
   
    timerSwitchA = 0; // Resets 
    timerSwitchB = 0;
  }
}

This serves to reset the array and counter if there isn't any input for a few seconds (when x reaches 499) and flash the LED a few times to indicate the reset. For some reason when I reset the counter and array in this fashion, it returns back to the start condition and works fine. So, at worst, if an input is received incorrectly, I'll have to wait a few seconds for it to reset. This isn't really what I was wanting, but it seems to work well enough to move forward with checking the intervals against the intended pattern.

I assume then you used an appropriate pull-up (which would invert the pin's input) or pull-down resistor? And a capacitor to handle de-bouncing?

I used a pull down resistor on the button, but no capacitor. I haven't had any issues with de-bouncing in this case.

void gapTimer()
{
    ...
    
        if ( x == 499 )
        {
            ...
            arrayCounter = 0;
            ...
        }
    ...
}

void switchTrack()
{
    if ( arrayCounter == 500 )
    {

    ...

    if ( (1 == timerSwitchA  && (2 == timerSwitchB) )
    {
        gapTimer();
    }
}

As seen above within 'gapTimer' you reset 'arrayCounter' if 'x' is 499, then back at the top of 'switchTrack' is a check for a condition that will never happen!

Lloyd: Not sure what you're referring to. I don't have an if (arrayCounter == 500) within switchTrack, but I do have an if (arrayCounter == 7). The reset for arrayCounter with the x = 499 condition is the work around so that if nothing takes place between when x = 0 and x = 499 then it resets. It doesn't seem to want to do that from my original code when I tried to reset it after running the final check.

The modified code I posted made it work anyways, though not ideally.

Your reset inside of gapTimer():

    timerSwitchA = 0; // Resets 
    timerSwitchB = 0;

Happens inside of the for() loop. Did you mean for that?