Для блока питания необходимо будет сделать панель управления состоящую из блока кнопок. Если просто подвести через кнопку питание через сопротивление, то получим:

  1. дребезг при нажатии - когда нпаряжение на ножке контроллера меняется не один раз а много раз 0-5В-0-5В-0-5В... обусловлен дребез несовершенством механизма самой кнопки
  2. отсуствие инерционности, случайные нажатия и отпускания заставят контроллер выполнять какие-то действия, а хотелось бы инерционности. например дать возможность нажимать кнопку не более раз в 0.1 секунды. Подобные проблемы хорошо описаны в видеоуроке на сайте Амперки Только в видеоуроке упрощенный рассчет и разрядка не верная, т.к конденсатор при замыкании кнопки буде чень быстро разряжаться через сопротивление кнопки.

Можно на програмном уровне сделать искуственную задержку на 0.1 секнду, как описанно здесь

#define BUTTON_PIN  3
#define LED_PIN     13

boolean buttonWasUp = true;  // была ли кнопка отпущена?
boolean ledEnabled = false;  // включен ли свет?

void setup()
{
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop()
{
  // определить момент «клика» несколько сложнее, чем факт того,
  // что кнопка сейчас просто нажата. Для определения клика мы
  // сначала понимаем, отпущена ли кнопка прямо сейчас...
  boolean buttonIsUp = digitalRead(BUTTON_PIN);

  // ...если «кнопка была отпущена и (&&) не отпущена сейчас»...
  if (buttonWasUp && !buttonIsUp) {
    // ...может это «клик», а может и ложный сигнал (дребезг),
    // возникающий в момент замыкания/размыкания пластин кнопки,
    // поэтому даём кнопке полностью «успокоиться»...
    delay(10);
    // ...и считываем сигнал снова
    buttonIsUp = digitalRead(BUTTON_PIN);
    if (!buttonIsUp) {  // если она всё ещё нажата...
      // ...это клик! Переворачиваем сигнал светодиода
      ledEnabled = !ledEnabled;
      digitalWrite(LED_PIN, ledEnabled);
    }
  }

  // запоминаем последнее состояние кнопки для новой итерации
  buttonWasUp = buttonIsUp;
}

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

Для этого необходимо:

  1. кнопка
  2. 74HC14 или инвертирующий триггер Шмитта (на него можно аж 6 кнопок навесить). Что это такое?
  3. резисторы 100К и 47К
  4. емкость 1мкФ

Вот схема: Схема подавления дребезга

Так она выглядит на макетной плате:

Схема подавления дребезга Схема подавления дребезга

А теперь немного математики

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

Экспериментально установил, что гестерезис у триггера шмитта на отметках 2Вольта при ниспадающем фронте и 2.5В при возрастающем. Вот доказательство:

пороги срабатывания триггера шмитта

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

Ситуация 1

переход от 5В к 2В, т.е ниспадающий фронт и время разрядки емкости до 2В от 5В должно быть 0.1 секунды. Vпит=5В верхний уровень, Vтриггера_нисп=2В напряжение срабатывания триггера при ниспадающем фронте, требуемре время t=0.1 секунды. Когда происходит разрядка - когда кнопка нажата, тогда через цепочку C1-R2-кнопка-земля утекает накопленный емкостью заряд. И разряжается он по формуле:

Vискомое=Vначальное*exp(-t/(R2*C1))

где Vискомое это напряжение при котором срабатывает триггер, а Vначальное - это напряжение питания Vтриггера_нисп/Vпит=exp(-t/(R2*C1))

ln(Vтриггера_нисп/Vпит)=-t/(R2*C2)

откуда получаем:

R2=-(t/(ln(Vтриггера_нисп/Vпит)*C1))=-(0.1c/(ln(2В/5В)*0.000001Ф))=109135 примерно 100К

Ситуация 2

переход от 0В к 2.5В, когда триггер срабатывает уже по восходящему фронту. Емкость в этот момент заряжается через источник питания-R1-R2-C1-земля. И за 0.1 секнуды должна набрать заряд 2.5 вольта от 0В.

Формула зарядки:

Vискомое=Vпит*(1-exp(-t/(R*C1))), где R=R1+R2

Vискомое=2.5В, Vпит как и ранее 5В, t=0.1 секунды емкость C1 неизменна. преобразуем формулу: Vискомое/Vпит=1-exp(-t/(R*C1))

1-Vискомое/Vпит=exp(-t/(R*C1))

ln(1-Vискомое/Vпит)=-t/(R*C1)

R=-t/(C1*ln(1-Vискомое/Vпит))=-0.1/(0.000001*ln(1-2.5/5))=144269 примерно 147К.

Т.к R2 мы уже знаем, высчитаем R1=R-R2=147К-100К=47К.

А теперь практический пример:

Разряд

это время разрядки, видно что длилось оно до срабатывания 66милли секунд. Из-за погрешностей при выборе сопротивления, но меня такой интервал устраивает.

Заряд

а вот зарядка ровно легла на рассчетный период = 100милли секунд.

И вот пример частого нажатия кнопки:

Шумы

Как видно - триггер сработал один раз, шумов не видно.

Красный график осциллографа показывает, какой сигнал будет на контроллере при нажатии и отпускании кнопки.

Добавить комментарий

Blog Comments powered by Disqus.

Следующая запись Предыдущая запись