user86041: When I run this code, my pin and pinCheck arrays are not being filled with the results of keypad.getKey(). If I print the value at each index, the result is blank. As far as I can tell, I am either not writing a char to the array, I am misreading the array when it comes time to print to the serial monitor, or .getKey() only works in the main or loop functions.
#include <Key.h>
#include <Keypad.h>

void armDisarm(void);
boolean array_cmp(char, char, int, int);

bool isArmed = 0;
char pin[3];
char pinCheck[3];
const byte ROWS = 4; // number of rows
const byte COLS = 4; // number of columns
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'#','0','*','D'}
};

byte rowPins[ROWS] = {9, 8, 7, 6}; // row pinouts of the keypad R1 = D8, R2 = D7, R3 = D6, R4 = D5
byte colPins[COLS] = {5, 4, 3, 2};    // column pinouts of the keypad C1 = D4, C2 = D3, C3 = D2
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
 
void setup()
{
  Serial.begin(9600);
}
 
void loop()
{
  if (isArmed == 1)
  {
    Serial.println("SYSTEM ARMED! ENTER PIN TO DISARM!");
  }
  else 
  {
    Serial.println("SYSTEM DISARMED! ENTER PIN TO ARM!");
  }
  armDisarm();
}

void armDisarm(void)
{
  while(true)
 {
    if (isArmed == 0)
    {
      for (int i = 0; i < 4;)
      {
        if (keypad.getKey() == NO_KEY)
        {
          continue;
        }
        pin[i] = keypad.getKey();
        Serial.println(pin[i]);
        i++;
      }
      isArmed = 1;
      return;
    }
    else if (isArmed == 1)
    {
      for (int j = 0; j < 4;)
      {
        if (keypad.getKey() == NO_KEY)
        {
          continue;
        }
        pinCheck[j] = keypad.getKey();
        Serial.println(pin[j]);
        j++;
      }
      for (int k = 0; k < 4; k++)
      {
        if(pinCheck[k] != pin[k])
        {
          isSame = 0;
          break;
        }
        else
        {
          isSame = 1;
        }
      }

      if (array_cmp(pin, pinCheck, sizeof(pin), sizeof(pinCheck)) == 1)
      {
        Serial.println("same pin"); //used for bebugging
        isArmed = 0;
        return;
      }
      else
      {
        Serial.println("INCORRECT PIN! CLAYMORE ROOMBA DEPLOYED!");
      }
    }
  }
}

boolean array_cmp(char a[sizeof(pin)], char b[sizeof(pinCheck)], int len_a, int len_b)
{
  int n;

  // if their lengths are different, return false
  if (len_a != len_b)
  {
    return false;
  }

  // test each element to be the same. if not, return false
  for (n = 0 ;n < len_a; n++) 
  {
    if (a[n]!= b[n])
    {
      return false;
    }
  }

  //ok, if we have not returned yet, they are equal :)
  return true;
}


user7508: First of all, there is one essential feature of the Keypad library you
have to understand: it is non-blocking. When you call keypad.getKey(),
it returns immediately, and almost always returns NO_KEY to signal
that no key was pressed since the last time you checked. If a key was
pressed, keypad.getKey() returns that key and then, on the next
call, it again returns NO_KEY because no key was pressed since the
last time you checked.
It is important to realize that, whenever a key is pressed, that key is
returned only once by keypad.getKey(). You should manage to not miss
it!
Now consider this loop:
for (int i = 0; i < 4;)
{
    if (keypad.getKey() == NO_KEY)
    {
        continue;
    }
    pin[i] = keypad.getKey();
    Serial.println(pin[i]);
    i++;
}

This will run very fast, and almost always looping through the
continue statement. When a key is pressed, keypad.getKey() returns a
value different from NO_KEY (and this value is lost), the test
within the if is false, and the statement that follows gets executed,
namely:
    pin[i] = keypad.getKey();

But this is another call to keypad.getKey(), which returns NO_KEY,
so this is what gets saved in the array.
This is how I would write that loop:
for (int i = 0; i < 3; i++)
{
    char key = NO_KEY;
    while (key == NO_KEY)
    {
        key = keypad.getKey();
    }
    pin[i] = key;
    Serial.println(pin[i]);
}

Please note that:

The value returned by keypad.getKey() is always saved into a
variable, you do not want to loose it! When we get something other
than NO_KEY, the value previously saved into the variable is stored
in the array.

I moved the i++ where it belongs, in order to avoid that very
confusing way of controlling the loop.

The if has become a while, because we do not want to move to the
next iteration until we have actually read a valid key.

The loop does only three iterations, because this is the length of the
array pin, which we would otherwise overflow.



86041: <p>When I run this code, my <code>pin</code> and <code>pinCheck</code> arrays are not being filled with the results of <code>keypad.getKey()</code>. If I print the value at each index, the result is blank. As far as I can tell, I am either not writing a char to the array, I am misreading the array when it comes time to print to the serial monitor, or <code>.getKey()</code> only works in the main or loop functions.</p>
<pre><code>#include &lt;Key.h&gt;
#include &lt;Keypad.h&gt;

void armDisarm(void);
boolean array_cmp(char, char, int, int);

bool isArmed = 0;
char pin[3];
char pinCheck[3];
const byte ROWS = 4; // number of rows
const byte COLS = 4; // number of columns
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'#','0','*','D'}
};

byte rowPins[ROWS] = {9, 8, 7, 6}; // row pinouts of the keypad R1 = D8, R2 = D7, R3 = D6, R4 = D5
byte colPins[COLS] = {5, 4, 3, 2};    // column pinouts of the keypad C1 = D4, C2 = D3, C3 = D2
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
 
void setup()
{
  Serial.begin(9600);
}
 
void loop()
{
  if (isArmed == 1)
  {
    Serial.println(&quot;SYSTEM ARMED! ENTER PIN TO DISARM!&quot;);
  }
  else 
  {
    Serial.println(&quot;SYSTEM DISARMED! ENTER PIN TO ARM!&quot;);
  }
  armDisarm();
}

void armDisarm(void)
{
  while(true)
 {
    if (isArmed == 0)
    {
      for (int i = 0; i &lt; 4;)
      {
        if (keypad.getKey() == NO_KEY)
        {
          continue;
        }
        pin[i] = keypad.getKey();
        Serial.println(pin[i]);
        i++;
      }
      isArmed = 1;
      return;
    }
    else if (isArmed == 1)
    {
      for (int j = 0; j &lt; 4;)
      {
        if (keypad.getKey() == NO_KEY)
        {
          continue;
        }
        pinCheck[j] = keypad.getKey();
        Serial.println(pin[j]);
        j++;
      }
      for (int k = 0; k &lt; 4; k++)
      {
        if(pinCheck[k] != pin[k])
        {
          isSame = 0;
          break;
        }
        else
        {
          isSame = 1;
        }
      }

      if (array_cmp(pin, pinCheck, sizeof(pin), sizeof(pinCheck)) == 1)
      {
        Serial.println(&quot;same pin&quot;); //used for bebugging
        isArmed = 0;
        return;
      }
      else
      {
        Serial.println(&quot;INCORRECT PIN! CLAYMORE ROOMBA DEPLOYED!&quot;);
      }
    }
  }
}

boolean array_cmp(char a[sizeof(pin)], char b[sizeof(pinCheck)], int len_a, int len_b)
{
  int n;

  // if their lengths are different, return false
  if (len_a != len_b)
  {
    return false;
  }

  // test each element to be the same. if not, return false
  for (n = 0 ;n &lt; len_a; n++) 
  {
    if (a[n]!= b[n])
    {
      return false;
    }
  }

  //ok, if we have not returned yet, they are equal :)
  return true;
}
</code></pre>
 7508: <p>First of all, there is one essential feature of the Keypad library you
have to understand: it is non-blocking. When you call <code>keypad.getKey()</code>,
it returns immediately, and almost always returns <code>NO_KEY</code> to signal
that no key was pressed since the last time you checked. If a key was
pressed, <code>keypad.getKey()</code> returns that key and then, <em>on the next
call</em>, it again returns <code>NO_KEY</code> because no key was pressed <em>since the
last time you checked</em>.</p>
<p>It is important to realize that, whenever a key is pressed, that key is
returned <em>only once</em> by <code>keypad.getKey()</code>. You should manage to not miss
it!</p>
<p>Now consider this loop:</p>
<pre class="lang-cpp prettyprint-override"><code>for (int i = 0; i &lt; 4;)
{
    if (keypad.getKey() == NO_KEY)
    {
        continue;
    }
    pin[i] = keypad.getKey();
    Serial.println(pin[i]);
    i++;
}
</code></pre>
<p>This will run very fast, and almost always looping through the
<code>continue</code> statement. When a key is pressed, <code>keypad.getKey()</code> returns a
value different from <code>NO_KEY</code> (and this value <em>is lost</em>), the test
within the <code>if</code> is false, and the statement that follows gets executed,
namely:</p>
<pre class="lang-cpp prettyprint-override"><code>    pin[i] = keypad.getKey();
</code></pre>
<p>But this is <em>another</em> call to <code>keypad.getKey()</code>, which returns <code>NO_KEY</code>,
so this is what gets saved in the array.</p>
<p>This is how I would write that loop:</p>
<pre class="lang-cpp prettyprint-override"><code>for (int i = 0; i &lt; 3; i++)
{
    char key = NO_KEY;
    while (key == NO_KEY)
    {
        key = keypad.getKey();
    }
    pin[i] = key;
    Serial.println(pin[i]);
}
</code></pre>
<p>Please note that:</p>
<ul>
<li><p>The value returned by <code>keypad.getKey()</code> is <em>always</em> saved into a
variable, you do not want to loose it! When we get something other
than <code>NO_KEY</code>, the value previously saved into the variable is stored
in the array.</p>
</li>
<li><p>I moved the <code>i++</code> where it belongs, in order to avoid that very
confusing way of controlling the loop.</p>
</li>
<li><p>The <code>if</code> has become a <code>while</code>, because we do not want to move to the
next iteration until we have actually read a valid key.</p>
</li>
<li><p>The loop does only three iterations, because this is the length of the
array <code>pin</code>, which we would otherwise overflow.</p>
</li>
</ul>
