Перейти к содержанию

Управление кнопкой, функция pulseIn.


Рекомендуемые сообщения

Не могу понять как сделать управлением кнопкой. Реализую вход в меню программирования готового устройства на базе ардуино. Код взят с сайта амперка для ознакомления и прототипирования на бред-борде. Необходимо считать время нажатой кнопки и если оно находиться в определенном пределе по времени то моргнуть светодиодом 4 раза, если нет то просто зажечь светодиод. Пытался использовать функцию millis(), но столкнулся с трудностями понимания её работы. Прошу сильно не пинать, только осваиваю данную платформу. 

#define BUTTON_PIN  8
#define LED_PIN     13
unsigned long level;
 
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;
      level = pulseIn(digitalRead(BUTTON_PIN), HIGH);
      if (level >=5000 || level <=10000)
      {
        digitalWrite(LED_PIN, HIGH);
        delay(500);
        digitalWrite(LED_PIN, LOW);
        delay(500);
        digitalWrite(LED_PIN, HIGH);
        delay(500);
        digitalWrite(LED_PIN, LOW);
        delay(500);
        digitalWrite(LED_PIN, HIGH);
        delay(500);
        digitalWrite(LED_PIN, LOW);
        delay(500);
        digitalWrite(LED_PIN, HIGH);
        delay(500);
        digitalWrite(LED_PIN, LOW);
        delay(500);
      }
      else
      {
        digitalWrite(LED_PIN, HIGH);
        delay(500);
      }
      //digitalWrite(LED_PIN, ledEnabled);
    }
  }
 
  // запоминаем последнее состояние кнопки для новой итерации
  buttonWasUp = buttonIsUp;

  
}

 

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Привет.

Строка  level = pulseIn(digitalRead(BUTTON_PIN), HIGH);

Должно быть  level = pulseIn(BUTTON_PIN, HIGH);

И еще level  в пределах от 5000 мкс до 10000 мкс. это в пределах от 5 до 10 секунд. Палец устанет давить!!!

и вроде по умолчанию можно до 1 секунды. Без умолчания можно до 180 секунд.

Но тогда должно быть  level = pulseIn(BUTTON_PIN, HIGH,30000); //поставил ограничение  30 секунд

Изменено пользователем Сергей_Харьков
Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Какие длинные микросекунды, однако. Может от 5 до 10 милисекунд? http://arduino.ru/Reference/PulseIn

 

48 минут назад, Сергей_Харьков сказал:

И еще level  в пределах от 5000 мкс до 10000 мкс. это в пределах от 5 до 10 секунд. 

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Виноват, после праздников перепутал

миллисекунды с микросекундами. ( 0.005 с и 0.01 с, Тогда слишком быстро, фиг успеешь попасть)

Тогда просто   level = pulseIn(BUTTON_PIN, HIGH);

Изменено пользователем Сергей_Харьков
Ссылка на комментарий
Поделиться на другие сайты

  • 3 недели спустя...

А так ли важно определить именно  момент клика? Частота ардуино довольно большая и мне кажется, что определения того, что кнопка сейчас нажата вполне достаточно. Если будет известно, что в предыдущей итерации кнопка была не нажата, а в текущей итерации нажата, то погрешности там будут миллисекунды (если конечно код не очень большой с кучей delay()). Писал я как-то код для модуля джойстика с кнопкой

/* Код предназначен для джойстика и кнопки. Выпоняет следующий алгоритм: при нажатии кнопки и удержании ее в течении 2 секунд, открывается прим данных с джойстика.
 *  Если перемещение джойстика прекращается и не начинается в течении 5 секунд, то прием данных закрывается и программа ожидает следующего нажатия на кнопку.
 */

int axis_X = A0; // Ось Х
int axis_Y = A1; // Ось Y
int button = 2; // Кнопка

int vaule_X = 0; //Текущее значение оси Х
int vaule_Y = 0; //Текущее значение оси Y
int vaule_XP; //Предыдущее значение оси Х
int vaule_YP; //Предыдущее значение оси Y

unsigned long timeout = 10000000; // таймаут функции 10 сек
unsigned long TIME = 0;
unsigned long n_time = 2000000; // условное время начала према данных (мкс)
int k_time = 5000; // условное время закрытия приема (мс)

int nT = 0; // Переменные для отсчитывания времени бездействия
int kT = 0;

int condition_1 = 0; //условие начала приема данных
int condition_2 = 0; //условие, определяющее бездействие

void setup() {
  Serial.begin(9600); //настройка КОМ - порта
  pinMode(axis_X, INPUT); // оси и кнопка это входы
  pinMode(axis_Y, INPUT);
  pinMode(button, INPUT);
  Serial.println("Hello"); //Здрасьте

}

void loop() {
  if ((digitalRead(button) == LOW) && (condition_1 == 0)) // если кнопка нажата и прием данных закрыт
    {
      TIME = pulseIn(button, LOW, timeout); // время, которое кнопка была нажата

      if (TIME >= n_time) // если время нажатия больше или равно двум секундам
        {
          condition_1 = 1; // тогда условию 1 присваиваем единичку
          TIME = 0; //обнуляем времячко
          Serial.println("Data reception is open"); //пишем, что открыт прием данных
        }
    }

  if (condition_1 == 1) //если условие 1 единичка, то принимаем данные
    {
      vaule_XP = vaule_X; // данные в предыдущей итерации
      vaule_YP = vaule_Y;
      vaule_X = map(analogRead(axis_X), 0, 1023, -10, 10); //данные в текущей итерации
      vaule_Y = map(analogRead(axis_Y), 0, 1023, -10, 10);
      Serial.print("X: "); //пишем данные в КОМ
      Serial.print(vaule_X);
      Serial.print(" | Y: ");
      Serial.println(vaule_Y);

      delay(500); // ждем просто так

      if ((vaule_X == vaule_XP) && (vaule_Y == vaule_YP)) //если данные в предыдущей итерации и в текущей совпадают, значит изменения не произошло, значит бездействуем
        {
          if (condition_2 == 0) // если условие 2 нолик, то это значит, что бездействие началось только что
            {
              nT = millis(); // запоминаем время начала бездействия
              condition_2 = 1; // условию 2 присваиваем единичку, чтобы время nT не перезаписвалось с каждой новой итерацией
            }

          if (condition_2 == 1) //если условие 2 единичка, значит бездействие уже идет
            {
              kT = millis(); // текущее время

              if (kT - nT >= k_time) // если бездействие длилось 5 секунд
                {
                  condition_2 = 0; //заканчиваем бездействие
                  condition_1 = 0; //закрываем прием данных
                  Serial.println("Data reception is close"); //пишем, что прием данных закрыт
                }
            }
        }

      else { condition_2 = 0;} //если значения поменялись, присваиваем условию 2 нолик и в следующий раз ожидание бездействия начнется сначала
    }

}

 

Ссылка на комментарий
Поделиться на другие сайты

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

1. Делаем функцию button_is_pressed(), которая вернет 1, если кнопка нажата, и 0 в противном случае. Эта функция занимается тем, что подавляет дребезг (выше вы уже это делали).
2. А теперь заводим переменную-счетчик и делаем цикл "пока кнопка нажата - инкремент счетчика и задержка в 10 мс".
3. После выхода из цикла смотрим на счетчик: его значение будет равно длительности удержания кнопки в нажатом состоянии в десятимиллисекундных интервалах. Ну и соответственно, принимаем решение, что надо сделать если счетчик большой или маленький.

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

Ссылка на комментарий
Поделиться на другие сайты

while(1)

{

delay_ms(10);

oldButton= Button;

Button= PINX.Y;

if(!oldButton && !Button && (counter < 255)) ++counter;

if(!oldButton && Button)

{

if(counter > N) {}; // кнопка была нажатой долго

else {}; // кнопка удерживалась недолго

counter= 0;

}

}

 

Я не раздаю удочки. Я продаю рыбу.

Ссылка на комментарий
Поделиться на другие сайты

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

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

Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, ARV сказал:

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

1. Делаем функцию button_is_pressed(), которая вернет 1, если кнопка нажата, и 0 в противном случае. Эта функция занимается тем, что подавляет дребезг (выше вы уже это делали).
2. А теперь заводим переменную-счетчик и делаем цикл "пока кнопка нажата - инкремент счетчика и задержка в 10 мс".
3. После выхода из цикла смотрим на счетчик: его значение будет равно длительности удержания кнопки в нажатом состоянии в десятимиллисекундных интервалах. Ну и соответственно, принимаем решение, что надо сделать если счетчик большой или маленький.

А зачем так изголяться если можно использовать pulseIn(). Просто делаем условие: если кнопка нажата, считаем время, которое держится сигнал.

Ссылка на комментарий
Поделиться на другие сайты

Только что, Vladislav G. сказал:

А зачем так изголяться

Я описал абстрактный алгоритм - я не знаток ардуино и их "стандартных" функций. Общий алгоритм все равно будет правильным независимо от частностей...

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

Ссылка на комментарий
Поделиться на другие сайты

9 часов назад, ARV сказал:

я бы сделал

Само собой. Я привел только алгоритм в общем виде, не готовый код.

Я не раздаю удочки. Я продаю рыбу.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...