#1 Re: Програмування Arduino » Не работает антидребезг » 2018-10-14 21:27:15

currentState=digitalRead(button);                                     //Считываем состояние кнопки
  if (currentState == 0 && prevState == 1 &&(millis()-debounceTime)>50) //Антидребезг
  {
    prevState=0;
    ++flag;                                                               //Инкрементируем флаг
    if (flag>=3) flag=0;                                                  //Устраняем перегруженость
    prevContact = digitalRead(contact);                                   //Считываем текущее состояние контакта
    debounceTime=millis();                                                //Записываем значение времени для антидребезга
   }
   else if (currentState == 1 && prevState == 0 &&(millis()-debounceTime)>5)  //При отпускании кнопки
   {
    prevState=1;                                                              //меняем предыдущее состояние
   }

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

bool reading = digitalRead (button);
    if (reading != lastButton) lastDebounce = millis();
    if ((millis()-lastDebounce) > debounceDelay)
    {
        if (reading != buttonState)
        {
            buttonState = reading;

            if (buttonState == LOW)
        {
            ++flag;
            if (flag >= 3) flag = 0;
            prevContact = digitalRead (contact);
        }
        }
    }
    lastButton = reading;

И вот с ним то все работает. Но я не могу понять в чем ошибка первого обработчика и почему он у меня все же работал, но после того как я ушел от использования delay в блоке кода отображения чисел на индикаторе то начал проскакивать дребезг.

И куда поцепить конденсатор? Паралельно кнопке?

#5 Re: Програмування Arduino » Не работает антидребезг » 2018-10-13 20:06:15

Я знаю что код - говнище. Это мой первый хоть сколько серьёзный проект. Подскажите по оформлению - нормально ли что 90% кода - это вызов функции "if"?

#6 Програмування Arduino » Не работает антидребезг » 2018-10-13 20:02:30

Kain
відповідей: 14

Здравствуйте.
Такая проблема, делаю таймер с тремя условиями остановки. По внешнему контакту, по истечению времени и по кнопке.
Кнопку я использую и для пуска, и для остановки, и для сброса таймера. Проблема в том что я не могу нормально реализовать антидребезг, часто проскакивает несколько нажатий. Использую внешнюю подтяжку на 5кОм.
Помогите, скажите где ошибка.
Вот скетч

#define secOne 11       //Порт управления младшего розряда индикатора секунд
#define secTwo 10       //Порт управления старшего розряда индикатора секунд
#define minOne 12       //Порт управления молодшим розрядом индикатора минут
#define minTwo 13       //Порт управления старшим розрядом индикатора минут
#define segG 8          //Вывод ручного управления сегментом G
#define segDP 9         //Вивод ручного управления точкой
#define divider A0      //Разделитель разрядов
#define rele A3         //Виход на реле
#define button A1       //Вход для кнопки
#define contact A2      //Вход для контакта

byte numbersArray[]={    //Массив управления портом D для отображения чисел на индикаторе
  0x00,                 //0
  0x9C,                 //1
  0x24,                 //2
  0x0C,                 //3
  0x98,                 //4
  0x48,                 //5
  0x40,                 //6
  0x1C,                 //7
  0x00,                 //8
  0x08                  //9
 };
byte segmentsPos[] = {secOne, secTwo, minOne, minTwo};   //Массив для хранения 
                                                         //виводов управления сегментами
unsigned long prevTime=0;        //Переменная для хранения предыдущего значения millis()
                                 //для подсчета времени
unsigned long debounceTime=0;    //Переменная времени для функции антидребезга контактов
unsigned long delaySegments=0;   //Переменная для задержки отображения индикаторов
byte timeNumbers[5];             //Массив для хранения чисел для отображения
bool currentState = HIGH;        //Нинешнее состояние кнопки
bool prevState = HIGH;           //Предыдущее состояние кнопки
bool prevContact=HIGH;           //Стабильное состояние контакта
byte flag = 0;                   //Флаг работы таймера
byte serviceCounter=0;           //Переменная для перебора значений отображаемых индикатором

void setup()
{
  DDRD=DDRD|B11111100;                  //Конфигурируем порт D на выход
  PORTD=B11111100;                      //Сегменты не горят
  for(byte i=0; i<=3; ++i)              //Конфигурируем
  {                                     //порты
    pinMode(segmentsPos[i], OUTPUT);    //для
    digitalWrite(segmentsPos[i], HIGH); //работы
  }                                     //с
  pinMode(segG, OUTPUT);                //сегментами
  pinMode(segDP, OUTPUT);               //на выход
  pinMode(button, INPUT_PULLUP);     //Вход для кнопки
  pinMode(contact, INPUT_PULLUP);    //Вход для контакта
  digitalWrite(segG, HIGH);          //Сегменты светятся при подаче на них низкого уровня
  digitalWrite(segDP, HIGH);         //поскольку используються индикаторы с общим анодом
}


void loop()
{
  currentState=digitalRead(button);                                     //Считываем состояние кнопки
  if (currentState == 0 && prevState == 1 &&(millis()-debounceTime)>50) //Антидребезг
  {
    prevState=0;
    ++flag;                                                               //Инкрементируем флаг
    if (flag>=3) flag=0;                                                  //Устраняем перегруженость
    prevContact = digitalRead(contact);                                   //Считываем текущее состояние контакта
    debounceTime=millis();                                                //Записываем значение времени для антидребезга
   }
   else if (currentState == 1 && prevState == 0 &&(millis()-debounceTime)>5)  //При отпускании кнопки
   {
    prevState=1;                                                              //меняем предыдущее состояние
   }
   if (digitalRead(contact)!= prevContact) flag=3;                            //Остановка таймера по
                                                                              //изменению состояния
                                                                              //контакта
  if ((millis()-prevTime)>=1000 && flag == 1)                                 //Ожидаем прошествия секунды
  {                                                                           //после запуска таймера
    ++timeNumbers[0];                                                         //Инкрементируем значение секунд
    prevTime=millis();                                                        //Записываем текущее значение millis()
  }
  else if(flag == 0)                                                          //Сброс таймера по флагу 
  {
    for (byte i=0; i<=4; ++i)
    {                                                                         //Можно ли записать значения в массив 
      timeNumbers[i]=0;                                                       //без применения цыкла?
    }
  }
  
  if (timeNumbers[0]==10)                                                     //Проверка перегружености
  {                                                                           //счетчика единиц секунд
    timeNumbers[0]=0;                                                         //Сборс
    ++timeNumbers[1];                                                         //Инкрементирование десяток секунд
  }
  if (timeNumbers[1]==6)                                                      //Проверка перегрузки
  {                                                                           //счетчика десяток секунд
  timeNumbers[1]=0;                                                           //Сброс
  ++timeNumbers[2];                                                           //Инкрементируем значение
  }                                                                           //единиц минут   
  
  if (timeNumbers[2]==10)                                                     //Проверка перегружености
  {                                                                           //Счетчика единиц минут
    timeNumbers[2]=0;                                                         //Сброс
    ++timeNumbers[3];                                                         //Инкрементирование десяток минут
  }
  if (timeNumbers[3]==2 && timeNumbers[2]==5) flag=4;                         //Условие остановки таймера по истечению времени

  if ((millis() - delaySegments)>=2)                                          //Передача значений подпрограмме по
  {                                                                           //работе с индикаторами
    if(serviceCounter >= 4) serviceCounter=0;                                 //Проверка перегружености счетчика
    dispSeg(timeNumbers[serviceCounter], segmentsPos[serviceCounter], 1);     //Передача значений подпрограмме
    ++serviceCounter;                                                         //Инкрементирование счетчика
    delaySegments=millis();                                                   
  }
}
void dispSeg(byte num, byte segNum, bool statDP)                              //Подпрограмма работы с индикатором
 {
  for(byte i=0; i<=3; ++i)                                                    //Гасим индикаторы
  {
    digitalWrite(segmentsPos[i], HIGH);
  }

  if (segNum != 4)                                                            //Функция if - апендицыт,который остался после попыток управления разделителем сегментов 
  {
    PORTD=numbersArray[num];                                                  //Подаем нужный потенциал на сегменты
    if (num == 0 || num == 1 || num == 7)                                     //Ручное управление сегментом G
    {
      digitalWrite(segG, HIGH);
    }
    else
    {
      digitalWrite(segG, LOW);
    }

    digitalWrite(segDP, statDP);                                                //Управление точкой
    digitalWrite(segNum, LOW);                                                  //Зажигаем нужный сегмент
  }
 }

Підвал форуму