Заполнение массива символов пробелами

array loop keypad char

Когда я запускаю этот код, мои массивы pin и pinCheck не заполняются результатами keypad.getKey(). Если я напечатаю значение для каждого индекса, результат будет пустым. Насколько я могу судить, я либо не записываю символ в массив, либо неправильно читаю массив, когда приходит время печатать на последовательном мониторе, либо .getKey() работает только в основные или циклические функции.

#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; // количество строк
const byte COLS = 4; // Число столбцов
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}; // распиновка ряда клавиатуры R1 = D8, R2 = D7, R3 = D6, R4 = D5
byte colPins[COLS] = {5, 4, 3, 2};    // распиновка столбцов клавиатуры 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"); //используется для отладки
        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;

  // если их длины разные, возвращаем false
  if (len_a != len_b)
  {
    return false;
  }

  // Проверяем, чтобы все элементы были одинаковыми. если нет, вернуть false
  for (n = 0 ;n < len_a; n++) 
  {
    if (a[n]!= b[n])
    {
      return false;
    }
  }

  //ок, если мы еще не вернулись, они равны :)
  return true;
}

, 👍-1


2 ответа


Лучший ответ:

1

Прежде всего, есть одна важная особенность библиотеки Keypad, которую вы надо понимать: он неблокирующий. Когда вы вызываете keypad.getKey(), он возвращается немедленно и почти всегда возвращает NO_KEY для сигнала что ни одна клавиша не была нажата с момента последней проверки. Если ключ был нажата, keypad.getKey() возвращает эту клавишу, а затем, при следующем вызов, он снова возвращает NO_KEY, так как ни одна клавиша не была нажата с момента последний раз, когда вы проверяли.

Важно понимать, что всякий раз, когда нажимается клавиша, эта клавиша возвращается только один раз с помощью keypad.getKey(). Вы должны успеть не промахнуться это!

Теперь рассмотрим этот цикл:

for (int i = 0; i < 4;)
{
    if (keypad.getKey() == NO_KEY)
    {
        continue;
    }
    pin[i] = keypad.getKey();
    Serial.println(pin[i]);
    i++;
}

Это будет работать очень быстро и почти всегда Оператор continue. При нажатии клавиши keypad.getKey() возвращает значение отличается от NO_KEY (и это значение потеряно), тест внутри if является ложным, и следующий за ним оператор выполняется, а именно:

    pin[i] = keypad.getKey();

Но это другой вызов keypad.getKey(), который возвращает NO_KEY, так что это то, что сохраняется в массиве.

Вот как я бы написал этот цикл:

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]);
}

Обратите внимание, что:

  • Значение, возвращаемое keypad.getKey(), всегда сохраняется в переменная, вы не хотите ее потерять! Когда мы получаем что-то другое чем NO_KEY, сохраняется значение, ранее сохраненное в переменной в массиве.

  • Я переместил i++ на место, чтобы избежать запутанный способ управления циклом.

  • if стал while, потому что мы не хотим переходить к следующую итерацию, пока мы действительно не прочитаем действительный ключ.

  • Цикл выполняет только три итерации, поскольку это длина массив pin, который в противном случае был бы переполнен.

,

0

В дополнение к ответу Эдгара Бонца. Я должен предупредить вас, что ваш код продолжает добавлять позицию, поскольку каждый раз, когда вы проверяете массив, вы увеличиваете значение i. В результате вы заполняете массивы NO_KEY.

Кроме того, ранее у нас была встроенная сигнализация безопасности на Arduino (или мы не должны знать, что вы делаете?). Я должен предупредить вас, что ожидание ввода с клавиатуры означает, что вы не проверяете тампер или тревогу, даже когда она включена, потому что вы застрял внутри функции без цикла, ожидая ввода. Я лично ввел глобальную структуру

struct foo{
   char digits[4];
   byte digit=0;
} pinCode;

Вы можете либо взять экземпляр структуры в качестве параметра своей функции, либо использовать ее для внутреннего использования, потому что она глобальная.

bool addDigit(char button){
  /*здесь мы имеем дело со многими потенциальными входными данными*/

затем вы можете внутри своей функции назначить нажатую кнопку как

pinCode.digits[pinCode.digit]=button;
pinCode.digit++;

если вы передаете экземпляр структуры в качестве указателя, он изменится на

pinCode->digits[pinCode->digit]=button;
pinCode->digit++;

затем вы можете проверить эту функцию, если пароль подтвержден (нажата кнопка OK) и вернуть true.

Пока не достигнут конец пароля, просто верните false. ТАК внутри цикла у вас будет что-то вроде:

key = keypad.getKey();
if(key!=NO_KEY){
   if(addDigit(key)) //Здесь выполняем действие на основе входных данных
}
// Делаем все остальное, что должен делать сигнал тревоги
,