Комбинация матричной клавиатуры и 7-сегментного дисплея обратного отсчета

Я работаю над квестом для своего университета с помощью Arduino Mega. Последняя часть состоит из 7-сегментного дисплея, представляющего обратный отсчет времени, и участники должны ввести правильное число на матричной клавиатуре, прежде чем оно достигнет нуля.

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

Код, который у меня есть:

char keys[4][4] = 
{
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};

byte rowPins[4] = { 5, 4, 3, 2 };
byte colPins[4] = { 9, 8, 7, 6 };

int pinA = 26; //2
int pinB = 34; //3
int pinC = 31; //4
int pinD = 27; //5
int pinE = 25; //6
int pinF = 28; //7
int pinG = 33; //8
int D1 = 24; //9
int D2 = 30; //10
int D3 = 32; //11
int D4 = 35; //12

Keypad mykeypad = Keypad( makeKeymap(keys), colPins, rowPins, 4, 4);

void setup()
{
Serial.begin(9600);


pinMode(pinA, OUTPUT);     
pinMode(pinB, OUTPUT);     
pinMode(pinC, OUTPUT);     
pinMode(pinD, OUTPUT);     
pinMode(pinE, OUTPUT);     
pinMode(pinF, OUTPUT);     
pinMode(pinG, OUTPUT);   
pinMode(D1, OUTPUT);  //Включаем первую цифру.
pinMode(D2, OUTPUT);  //Включаем вторую цифру.
pinMode(D3, OUTPUT);  //Включаем третью цифру.
pinMode(D4, OUTPUT);  //Включаем четвертую цифру.
}

//
void showTime(){

  digitalWrite(D1, LOW);
  digitalWrite(D2, LOW);
  digitalWrite(D3, LOW);
  digitalWrite(D4, LOW); 

 //3
  digitalWrite(pinA, HIGH);   
  digitalWrite(pinB, HIGH);   
  digitalWrite(pinC, HIGH);   
  digitalWrite(pinD, HIGH);   
  digitalWrite(pinE, LOW);   
  digitalWrite(pinF, LOW);   
  digitalWrite(pinG, HIGH);     
  delay(1000);   

//2
  digitalWrite(pinA, HIGH);   
  digitalWrite(pinB, HIGH);   
  digitalWrite(pinC, LOW);   
  digitalWrite(pinD, HIGH);   
  digitalWrite(pinE, HIGH);   
  digitalWrite(pinF, LOW);   
  digitalWrite(pinG, HIGH);     
  delay(1000); 

  //1
  digitalWrite(pinA, LOW);   
  digitalWrite(pinB, HIGH);   
  digitalWrite(pinC, HIGH);   
  digitalWrite(pinD, LOW);   
  digitalWrite(pinE, LOW);   
  digitalWrite(pinF, LOW);   
  digitalWrite(pinG, LOW);   
  delay(1000); 

  //0
  digitalWrite(pinA, HIGH);   
  digitalWrite(pinB, HIGH);   
  digitalWrite(pinC, HIGH);   
  digitalWrite(pinD, HIGH);   
  digitalWrite(pinE, HIGH);   
  digitalWrite(pinF, HIGH);   
  digitalWrite(pinG, LOW);   
  delay(1000);               

}

//Получает символы с матричной клавиатуры.
void getCode(){
   char key = mykeypad.getKey();
  if(key){
     Serial.print(key);
  }
}

void loop() 
{

  showTime();

}

Есть идеи, как мне получить эту комбинацию? Пытался найти что-то похожее на Thread, но Arduino его не поддерживает.

Заранее спасибо.

, 👍1

Обсуждение

Однако вам не обязательно использовать delay(). Взгляните на несколько примеров того, как настроить действия по времени без использования delay() https://learn.adafruit.com/multi-tasking-the-arduino-part-1/using-millis-for-timing., @jose can u c


2 ответа


0

Используйте примеры «мигания без задержки» в IDE, в которых вы выполняете действие, а затем просто наблюдаете за часами, а остальная часть кода выполняется до тех пор, пока не истечет время. Например, это включает и выключает встроенный светодиод, вы можете добавить к нему показания для чтения с клавиатуры и вывода времени.

unsigned long currentTime;
unsigned long previousTime;
unsigned long elapsedTime;
const byte ledPin = 13;
byte ledState = 0;

void setup(){
pinMode (ledPin, OUTPUT);
previousTime = millis();
}
void loop(){
currentTime = millis();  // фиксируем «время» сейчас
elapsedTme = currentTime - previousTime; // сколько «времени» прошло
if (elapsedTime >= 1000){  // хотя бы одну секунду?
ledState = 1 - ledState; // результат 1,0,1,0,1,0 ...
digitalWrite (ledPin, ledState); // переключение светодиода L
previousTime = currentTime;   // настройка для следующего цикла прохождения
// обновляем для отображения и выводим его
}
// теперь добавляем возможность чтения с клавиатуры
}
,

1

Попробуйте использовать millis(), он возвращает количество миллисекунд, прошедших с тех пор, как плата Arduino начала выполнять текущую программу.

Когда вы запускаете обратный отсчет, вы устанавливаете переменную для времени начала

int millisBegin = millis(); //поместите это в конец вашего setup() {.

Вам также понадобится «граница», чтобы знать, когда прошла одна секунда, поэтому

int millisBorder = 1000; //граница в одну секунду

Каждый раз, когда ваш loop() { запускается заново, вы можете проверить, прошла ли уже одна секунда

int millisNow = millis();
if(millisNow - millisBegin >= millisBorder){} //если прошла одна секунда, выполните {}

Теперь я бы поработал над сегментом, показывающим штуковину. В {} я бы поместил новую переменную, назовем ее counter = 4; //4, потому что я нашел в вашем скетче 3 числа. Каждый раз, когда выполняется if() {}, вы выполняете дополнительные инструкции if () {}, проверяя, какое число отображать следующим.

if (counter == 3)
{
  //показываем номер 3
}

if (counter == 2)
{
  //показываем номер 2
}

if (counter == 1)
{
  //показываем номер 1
}

if (counter == 0)
{
  //показываем номер 0
}
counter = counter - 1;

В конце мы снимаем одну единицу со счетчика, поэтому в следующий раз, когда мы введем if(одна секунда больше) отображаемое число станет меньше

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

После того, как вы сохранили ключ в виде строки, вы можете использовать метод strcmp(); для сравнения строки с решением/ответом strcmp(key,answer);strcmp(key,answer); код>. Если ключ и ответ совпадают, возвращается 1.

if(strcmp(key,answer) == 1)
{
  Serial.println("you made it");
}
,