Отображение случайного числа для отображения в течение T секунд с помощью Millis() для Dice Roller

Я пишу код для электронного игрального автомата. При нажатии кнопки (A2) код должен отображать случайное число на двухразрядном семисегментном дисплее в течение 20 секунд, а затем отображать пустое изображение.

В настоящее время мой код будет отображать случайное число каждые t секунд, пока кнопка постоянно удерживается. Я хотел бы, чтобы пользователь мог нажать кнопку и отпустить, чтобы код делал свое дело.

На какие примеры мне следует обратить внимание, чтобы добиться этого? Я совсем новичок в коде ардуино.

    #include "SevSeg.h"
SevSeg sevseg; //Создаем экземпляр семисегментного объекта

int displayPeriod = 1000; //задержка нажатия кнопки
unsigned long time_now = 0;

long randNumber;

void setup() {

  pinMode(A2,INPUT);
 randomSeed(analogRead(3));

  byte numDigits = 2;
  byte digitPins[] = {2, 3};
  byte segmentPins[] = {4,5,6,7,8,9,10};
  bool resistorsOnSegments = false; // 'false' означает, что резисторы находятся на цифровых выводах
  byte hardwareConfig = COMMON_CATHODE; // См. README.md для опций
  bool updateWithDelays = false; // Рекомендуется значение по умолчанию false
  bool leadingZeros = false; // Используйте 'true', если хотите сохранить ведущие нули
  bool disableDecPoint = true; // Используйте 'true', если ваша десятичная точка не существует или не связана. Затем вам нужно указать только 7 segmentPins[]

  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
  updateWithDelays, leadingZeros, disableDecPoint);

}

void loop() {


if(digitalRead(A2) == HIGH){

  rollD20();

}

else{

  sevseg.setChars("");
  sevseg.refreshDisplay();
}







}

void rollD20(){

if(millis() >= time_now + displayPeriod){
        time_now += displayPeriod;
        time_now = millis();
        randNumber = random(21); 
        }
        sevseg.setNumber(randNumber);
  sevseg.refreshDisplay();
  }

void testInput(){
sevseg.setNumber(0);
sevseg.refreshDisplay();
}

, 👍-1

Обсуждение

Обратите внимание, что «analogRead(3)» — очень плохой источник энтропии. Время нажатия кнопки с micros() было бы намного лучше., @Edgar Bonet

Почему это плохой источник? Из справочника arduino для функции random(): «Если важно, чтобы последовательность значений, сгенерированных random(), отличалась, при последующих выполнениях скетча используйте randomSeed() для инициализации генератора случайных чисел довольно случайным ввода, например, AnalogRead() для неподключенного вывода». Редактировать: Nvm Я понимаю, почему это плохо., @BobaJFET

ваш код обрабатывает нажатие кнопки, но ничего не делает с отпусканием кнопки... не кодируйте состояние "кнопка нажата", потому что это состояние длится до тех пор, пока кнопка удерживается... код для "перехода между кнопкой отпущена и нажата кнопка`, потому что переход происходит только один раз и может повториться, только если вы отпустите кнопку, @jsotola

@jsotola Да, сейчас я читаю, как это сделать. Я бы хотел, чтобы функция полностью завершила свой код, прежде чем вернуться к основному циклу. С момента написания этого поста в коде появился цикл for, предназначенный для отображения 29 случайных чисел подряд, а затем отображения 30-го числа на дисплее. Кажется, я не понимаю. Какой тип примера я должен искать?, @BobaJFET


2 ответа


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

1

Я бы рекомендовал не изобретать велосипед, и правильное управление кнопками может быть не таким уж тривиальным. Я бы предложил эту библиотеку для решения вашей проблемы.

,

0

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

bool rollingDice = false;

void loop() {


if(digitalRead(A2) == HIGH){
  rollingDice = true;
}
if(rollingDice){
  rollD20();
}
else{
  sevseg.setChars("");
  sevseg.refreshDisplay();
}

А затем в методе rollD20 вам нужно снова установить значение false, когда придет время остановиться:

void rollD20(){
  if(millis() >= time_now + displayPeriod){
        time_now += displayPeriod;
        time_now = millis();
        randNumber = random(21); 
        rollingDice = false;
        }
  sevseg.setNumber(randNumber);
  sevseg.refreshDisplay();
  }
,