Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.12.2015, 16:18   #1
zhenek_kreker
Новичок
Джуниор
 
Регистрация: 22.12.2015
Сообщений: 6
По умолчанию Обработка нажатия кнопки в Arduino

Всем привет!
Понимаю что не совсем в тему, но спросить особо негде. Пытаюсь освоить конструктор Arduino. Не гуманитарий, но программировать никогда не умел и не пытался, а тут интересно стало. Небольшая вводная, у Ардуино есть свои нюансы.
В обязательном порядке в программе должны быть предусмотрены две функции: void setup() и void loop(). При запуске контроллера один раз выполняется setup(), потом управление передаётся в loop(), которая выполняется по кругу бесконечно. Есть несколько специфичных функций:
pinMode(pin, INPUT/OUTPUT) - выставляет состояние контакта (они все нумерованы от 0 до 13) на вывод (подача 5 вольт) или вход (считывание 5 вольт).
digitalWrite(pin, STATE) - подаёт или выключает питание 5В на нужном контакте. STATE может быть HIGH или LOW
digitalRead (pin) - считывает подано ли напряжение на контакт. Возвращает значение HIGH или LOW
millis() - возвращает значение в миллисекундах с момента начала работы контроллера, такой внутренний таймер. Переполняется через 2 месяца непрерывной работы.
delay(t) - заморозка работы контроллера на t миллисекунд. При этом состояние удерживается, т.е. если на каком-то пине было 5В, они там останутся. Но вся остальная программа на это время подвисает.
Собрана схема, содержащая кнопку, подключённую к выводу №2 и светодиод к выводу №3. Я написал вот такую программу, в которой предусмотрена функция Blink() для мигания диодом и функция debounce() для устранения дребезга контактов Вот листинг с моими комментариями:
Код:
int GREEN1 = 3; //контакт 3 для светодиода
int BUTTON = 2; //контакт 2 для кнопки
boolean lastButton = LOW; //переменная для хранения последнего состояния кнопки
boolean currentButton = LOW; //переменная для хранения текущего статуса кнопки
int lmode = 0; //переменная для статуса светодиода
int GREEN1_INTERVAL1 = 100; //100 мс для моргания 10 Гц
int GREEN1_INTERVAL2 = 500; //500 мс для моргания 2 Гц
long previousTime = 0;
void setup()
{
  pinMode (GREEN1, OUTPUT); //устанавливаем пин3 как выход
  pinMode (BUTTON, INPUT); //устанавливаем пин2 как вход
  Serial.begin(9600);
}
boolean debounce(boolean last) //функция сглаживания, выдает значения HIGH или LOW
{
  boolean current = digitalRead(BUTTON); //считываем состояние кнопки
  if (last != current) //если не такое, как было
  {
    delay(10); //то ждём 10 мс
    current = digitalRead(BUTTON); //опять считываем состояние кнопки
    Serial.print("current=");
    Serial.println(current);
    return current; //возвращаем состояние
  }
}
void setMode (int mode) //функция для выполнения моргания. void т.к. она ничего не вычисляет
{
  if (mode == 0) //если режим равен 0
  {
    Blink (GREEN1, GREEN1_INTERVAL1); //моргаем на выводе GREEN1 с интервалом GREEN1_INTERVAL1
  }
  if (mode == 1); //если режим равен 1
  {
    Blink (GREEN1, GREEN1_INTERVAL2);
  }
  if (mode == 2); //если режим равен 2
  {
    digitalWrite (GREEN1, LOW); //выключаем питание
  }
}
void Blink (long INTERVAL, int LED_PIN) //функция воспринимает интервал и пин вывода в качетсве входных параметров
{
  long Time = millis(); //записываем время работы контроллера
  if (Time - previousTime > INTERVAL) //если прошло достаточно времени, то
  {
    previousTime = Time; //перезаписываем время
    boolean LED_STATE; //вводим локальную переменную, хранящую состояние диода
    if (LED_STATE == LOW) //если диод выключен
    {
      LED_STATE = HIGH; //то включаем его
    }
    else //а иначе
    {
      LED_STATE = LOW; //опять выключаем
    }
    digitalWrite (LED_PIN, LED_STATE); //тут включаем/выключаем диод.
  }
}
void loop()
{
  currentButton = debounce(lastButton); //подаём функции debounce текущее состояние кнопки, по сути считываем состояние с учётом дребезга
  if (lastButton == HIGH && currentButton == LOW) //если кнопка нажата
  {
    lmode++;    //увеличиваем состояние счётчика режима на 1
  }
  lastButton = currentButton; //запоминаем последнее состояние кнопки
  if (lmode = 3) //если счётчик дошёл до значения 3, которое не предусмотрено в теле функции setMode
    lmode = 0; //то мы его обнуляем
  setMode (lmode); //и передаём значение функции setMode
}
По факту ничего не работает, диод не горит (т.е. питание на выход 3 не подаётся), на кнопку система не реагирует. Я добавил в программу что-то вроде отладчика: строки
Serial.print("current=");
Serial.println(current);
Выводят в COM-порт (его монитор встроен в IDE) значение переменной current. Так вот, при нажатии кнопки выводится current=1, при отпускании тут же current=0. То есть система нажатие обрабатывает, но почему-то сразу же присваивает кнопке статус ВЫКЛ, а по плану он должен циклически меняться.
Понимаю, что это не совсем в тему форума, но на форуме Ардуины помочь не могут
P.S. Электрическая схема выглядит вот так, и она точно рабочая. Простейшие программы на ней выполняются.
zhenek_kreker вне форума Ответить с цитированием
Старый 22.12.2015, 16:40   #2
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Цитата:
boolean LED_STATE; //вводим локальную переменную, хранящую состояние диода
Откуда здесь взялось состояние диода?
У Вас каждый раз новая переменная. Какое значение у нее здесь? Её никто не инициализировал.

Ну и схему лучше нормальную предоставить, а не такой рисунок.
Croessmah вне форума Ответить с цитированием
Старый 22.12.2015, 16:42   #3
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Вечером, как приду с работы, могу подробнее рассмотреть код (Arduino имеем в наличии) )))
Croessmah вне форума Ответить с цитированием
Старый 22.12.2015, 17:09   #4
zhenek_kreker
Новичок
Джуниор
 
Регистрация: 22.12.2015
Сообщений: 6
По умолчанию

Цитата:
Откуда здесь взялось состояние диода?
У Вас каждый раз новая переменная. Какое значение у нее здесь? Её никто не инициализировал.
Эта переменная инициализируется внутри функции:
boolean LED_STATE;
Она ведь и не нужна снаружи, её назначение - принимать значения HIGH/LOW внутри функции Blink, она за её пределами не используется. Наверное, надо ей присвоить какое-то значение, типа вот так:
boolean LED_STATE = LOW;
Но это по-моему неважно. Или я не прав?
Схема вот, но другой программа, кроме Fritzing, у меня всё равно нет.




Цитата:
Вечером, как приду с работы, могу подробнее рассмотреть код (Arduino имеем в наличии) )))
Буду очень признателен. Как бы глупо не звучало, уже сутки почти вожусь.
zhenek_kreker вне форума Ответить с цитированием
Старый 22.12.2015, 17:14   #5
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Вы меня немного не так поняли.
Код:
boolean LED_STATE; //ну вот мы объявили. Какое у нее здесь значение?
    if (LED_STATE == LOW) //ведь здесь мы используем это значение.
Вам нужно инициализировать её, используя текущее состояние светодиода.

Последний раз редактировалось Croessmah; 22.12.2015 в 17:21.
Croessmah вне форума Ответить с цитированием
Старый 22.12.2015, 17:22   #6
zhenek_kreker
Новичок
Джуниор
 
Регистрация: 22.12.2015
Сообщений: 6
По умолчанию

Цитата:
Сообщение от Croessmah Посмотреть сообщение
Вы меня немного не так поняли.
Код:
boolean LED_STATE; //ну вот мы объявили. Какое у нее здесь значение?
    if (LED_STATE == LOW) //ведь здесь мы используем это значение.
Не знаю Одно из двух, либо 0, либо 1. Я не знаю какое значение по умолчанию присваивается. Но это и неважно. Пусть оно было LOW в самом начале программы. Цикл if проверит равно ли оно LOW, это будет правдой, и он изменит его на HIGH, после чего включит диод.
Я пробовал сейчас компилировать с boolean LED_STATE = LOW; и boolean LED_STATE = HIGH;
В первом случае диод быстро-быстро мерцает, но не загорается в полную силу. Субъективно, где-то 10 раз в секунду на 1% интенсивности. Во втором случае вообще не включается, ну или этого не видно.

Последний раз редактировалось zhenek_kreker; 22.12.2015 в 17:25.
zhenek_kreker вне форума Ответить с цитированием
Старый 22.12.2015, 17:25   #7
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Цитата:
после чего включит диод.
После этого при повторном заходе оно опять low и светодиод снова включит :-) а потомеще раз... и еще раз...
Croessmah вне форума Ответить с цитированием
Старый 22.12.2015, 17:31   #8
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Вот еще косяк:
Код:
if (lmode = 3) //оно же не сравнение, а присваивание
Croessmah вне форума Ответить с цитированием
Старый 22.12.2015, 17:32   #9
zhenek_kreker
Новичок
Джуниор
 
Регистрация: 22.12.2015
Сообщений: 6
По умолчанию

Цитата:
Сообщение от Croessmah Посмотреть сообщение
После этого при повторном заходе оно опять low и светодиод снова включит :-) а потомеще раз... и еще раз...
Вы имеет в виду, что светодиод удерживается в включенном/выключенном состоянии только на время выполнения процессором цикла, т.е. очень быстро? А как тогда записать?
P.S. В листинге косяк, функция Blink при вызове из setMode имеет формат:
Код:
Blink (GREEN1, GREEN1_INTERVAL1);
А должен быть наоборот:
Код:
Blink (GREEN1_INTERVAL1, GREEN1);
Но это не помогает, я исправил только что
zhenek_kreker вне форума Ответить с цитированием
Старый 22.12.2015, 17:33   #10
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Со смартфона код плохо видно, но попробуйте сделать LED_STATE статической:
Код:
static boolean LED_STATE  = LOW ;
Croessmah вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Последовательная обработка одинарного и двойного нажатия левой кнопки мышкис KBO Помощь студентам 17 18.11.2015 18:02
Эффект нажатия кнопки -Jack- Общие вопросы Delphi 6 14.03.2014 00:55
Обработка нажатия динамической кнопки Mr_freeman PHP 10 28.11.2011 23:45
Обработка события нажатия кнопки masm Microsoft Office Access 6 22.08.2011 11:21
Обработка нажатия кнопки на форме myprog Microsoft Office Access 8 17.12.2010 22:37