Работа с кнопками. В помощь новичку.

ATkRnr
Offline
Зарегистрирован: 22.10.2013
Я как новичек примного благодарен nestandart , за столь подробно расписанный пример с коментариями.
А то, пока поймешь что по чем в этих кодах, пока найдешь литературу и еще надо в ней найти то что интересует, вобщем времени удет только на поиски не одну неделю. А еще ведь надо все переварить и усвоить. А тут все расписано коментариями в самом коде, да еще в статье описано.
ЕЩЕ раз СПАСИБО!!!!!
ps\\  по больше бы таких примеров
 

 

next-999
Offline
Зарегистрирован: 30.09.2013

Ребята помогите с кодом

Зажимаем кнопку 3 сек, светодиод моргает 3 раза по каналу 12, после того как он поморгал загорается светодиод по каналу 11 и 10, если сделать кракое нажатие кнопки, то 11 и 10 гаснут, загорается 9 и 8, затем если снова нажать кратко, загорается снова 11 и 10 и тд. Если зажать снова кнопку на 3 сек. все светодиоды гаснут кроме 12, 12 моргает 3 раза и выключается.

готов заплатить за код

 

Monsel
Offline
Зарегистрирован: 27.10.2013

leshak пишет:
По поводу аналоговых кнопок награфоманил в блоге

Леший в мире Ардуины: Читаем аналоговые кнопки. Часть 1

Раздел "железная составляющая" - в принципе описывает то же самое что и nestandart в сообщении #1 . Причем, как мне кажется у него более внятно "разжеванно". Но может и мое кто-нибудь поймет :).

Остальное - альтернатива подходу приведенному maksim в сообщении #5 .

помогите понять синтаксическую конструкцию выражения (вложенный if ) из вашей программы:

//ищем максимум/минимум

    if(val<min if="" min="val;" val="">max)max=val;
    
    // добавляем замер к среднему
nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

next-999 пишите в почту ,помогу. heruvim219@mail.ru

Есть вопросы по алгоритму. Требуется более детальное пояснение.

Андрей01
Offline
Зарегистрирован: 04.11.2013
#include <Servo.h>

Servo servo_gor;// создаём объект для контроля сервы

int val;//
void setup()  
{  
   servo_gor.attach(9);// подключаем серву к пину 9      
   pinMode(10, INPUT);   //объявляем 10 пин как вход    
}
void loop()                       
{
   val = digitalRead(10);    // узнаём состояние кнопки
  if(val)                    // тоже самое что (val == HIGN)  // если 10 пин замкнут
     {
     servo_gor.writeMicroseconds(2000);
   delay(2000);
 servo_gor.writeMicroseconds(2150);
   delay(2000);
     }               // делаем какуюто каманду
  if(!val)                   // тоже что и val==LOW           // если 10 пин не замкнут
     {
     servo_gor.writeMicroseconds(2188);
   delay(1500);
     servo_gor.writeMicroseconds(2000);
   delay(2000);
   }               // делаем другую каманду
}

Доброго времени суток, подскажите правильно ли я написал програмку? У меня не ругается на программу а вот в железе смогу пока сделать чють попоже, ориентие конец недели. А так надо управлять программным кодом при нажатии или отпускании кнопки (кнопок).

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

maksim пишет:

Одно из решений "аналоговой клавиатуры", которое можно подредактировать и под вашу схему:

#define NUM_KEYS 5
int  adc_key_val[NUM_KEYS] = {30, 150, 360, 535, 760};

void setup()
{
  Serial.begin(9600);
}

void loop() 
{
  int key = get_key(A0);
  if(key) Serial.println(key, DEC);
}

int get_key(int key_pin)
{
  int input = analogRead(key_pin);
  int k;
  for(k = 0; k < NUM_KEYS; k++) 
    if(input < adc_key_val[k]) 
      return k + 1;     
  return 0;
}

данный код написан под эту схему

как видите количество кнопок задается параметром NUM_KEYS,
а "диапазоны" акуратненько "лежат" в массиве adc_key_val[].

 

Уважаемый Максим. Я собрал схему. запустл Ваш скетч и скетч из примера на analogRead, и видно, что значения без нажатия кнопок скачут вверх от 0 до 1023 и обратно от 1023 до 0 с разным шагом. Так и должно быть?

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Так быть не должно. При отпущеных кнопках на входе будет 1023. Ищите ошибку в сборке. Обратите особое внимание на R2.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

nestandart пишет:

Так быть не должно. При отпущеных кнопках на входе будет 1023. Ищите ошибку в сборке. Обратите особое внимание на R2.

 

пересмотрю схему.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

ingener.solovyev пишет:

nestandart пишет:

Так быть не должно. При отпущеных кнопках на входе будет 1023. Ищите ошибку в сборке. Обратите особое внимание на R2.

 

пересмотрю схему.

 

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

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Впишите  delay(100);  в строку 12.

Можно и кондер. 0.1 - 10мкф между входом и землей.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

nestandart пишет:

Впишите  delay(100);  в строку 12.

Можно и кондер. 0.1 - 10мкф между входом и землей.

входом вы называете сигнальный провод на A0?

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Да. Проще говоря поставьте кондер между +5  и GND.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Правла с кондером вы получите некоторую энерциальность в работе ( зависит от емкости кондера). Если это не критично то ставьте кондер.

maksim
Offline
Зарегистрирован: 12.02.2012

Не ставьте конденсатор - так вы только сделаете хуже. Вы и ловите эти "соседние кнопки" только по той причине что на линии не мгновенно устанавливается нужное напряжение.

byte get_key(int key_pin)
{
  if(analogRead(key_pin) < adc_key_val[NUM_KEYS-1])
  {
    byte k[3];
    for(byte i = 0; i < 3; i++)
    {
      delay(10);
      k[i] = 0;
      for(byte j = 0; j < NUM_KEYS; j++)
      { 
        if(analogRead(key_pin) < adc_key_val[j]) 
        {
          k[i] = j + 1;
          break;
        }
      }
    }
    if((k[0] > 0) && (k[0] == k[1]) && (k[0] == k[2]) && (k[1] == k[2])) return k[0];
  }
  return 0;
}

 

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

maksim пишет:

Не ставьте конденсатор - так вы только сделаете хуже. Вы и ловите эти "соседние кнопки" только по той причине что на линии не мгновенно устанавливается нужное напряжение.

byte get_key(int key_pin)
{
  if(analogRead(key_pin) < adc_key_val[NUM_KEYS-1])
  {
    byte k[3];
    for(byte i = 0; i < 3; i++)
    {
      delay(10);
      k[i] = 0;
      for(byte j = 0; j < NUM_KEYS; j++)
      { 
        if(analogRead(key_pin) < adc_key_val[j]) 
        {
          k[i] = j + 1;
          break;
        }
      }
    }
    if((k[0] > 0) && (k[0] == k[1]) && (k[0] == k[2]) && (k[1] == k[2])) return k[0];
  }
  return 0;
}

 

 

Я Вам благодарен, но могли бы Вы, мне, недалекому человеку, сказать куда вставить эту часть кода?

maksim
Offline
Зарегистрирован: 12.02.2012
#define NUM_KEYS 5
int  adc_key_val[NUM_KEYS] = {30, 150, 360, 535, 760};

void setup()
{
  Serial.begin(9600);
}

void loop() 
{
  int key = get_key(A0);
  if(key) Serial.println(key, DEC);
}

byte get_key(int key_pin)
{
  if(analogRead(key_pin) < adc_key_val[NUM_KEYS-1])
  {
    byte k[3];
    for(byte i = 0; i < 3; i++)
    {
      delay(10);
      k[i] = 0;
      for(byte j = 0; j < NUM_KEYS; j++)
      { 
        if(analogRead(key_pin) < adc_key_val[j]) 
        {
          k[i] = j + 1;
          break;
        }
      }
    }
    if((k[0] > 0) && (k[0] == k[1]) && (k[0] == k[2]) && (k[1] == k[2])) return k[0];
  }
  return 0;
}

 

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

maksim пишет:

#define NUM_KEYS 5
int  adc_key_val[NUM_KEYS] = {30, 150, 360, 535, 760};

void setup()
{
  Serial.begin(9600);
}

void loop() 
{
  int key = get_key(A0);
  if(key) Serial.println(key, DEC);
}

byte get_key(int key_pin)
{
  if(analogRead(key_pin) < adc_key_val[NUM_KEYS-1])
  {
    byte k[3];
    for(byte i = 0; i < 3; i++)
    {
      delay(10);
      k[i] = 0;
      for(byte j = 0; j < NUM_KEYS; j++)
      { 
        if(analogRead(key_pin) < adc_key_val[j]) 
        {
          k[i] = j + 1;
          break;
        }
      }
    }
    if((k[0] > 0) && (k[0] == k[1]) && (k[0] == k[2]) && (k[1] == k[2])) return k[0];
  }
  return 0;
}

 

 

Максим, а могли бы Вы на этом примере показать, как упаковать это чудо в отдельную библиотеку?

Пример с сайта  (Morse) не совсем понятен для данного случая. 

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

максим, и у меня просьба - прокомментируйте свой код, что-то непонятно как оно работает (ну я тут недавно в C++ ...)

kaznachej
Offline
Зарегистрирован: 21.01.2012

Здравствуйте, форумчане! Помогите с моей проблемкой.

Нужно при кратковременном нажатии кнопки "+" (или "-") увеличивать (уменьшать) число на единицу. При удержании этой кнопки нужно увеличивать (уменьшать) число на единицу в полсекунды. При удержании дольше 5 сек, добавлять (или отнимать) десятки с такой же частотой, А при удержании дольше 10 сек увеличивать (уменьшать) сотни этого числа раз в полсекунды.

Вот часть моего кода для обработки кнопок:

if (digitalRead(pin_plus)==HIGH&&flag_plus==0){        //
    n_ust++; lcd.clear(); flag_plus=1; }               // обрабатываем кнопку          
    if (digitalRead(pin_plus)==LOW&&flag_plus==1){     // +
    flag_plus=0;}                                      // количества витков
    
    if (digitalRead(pin_plus)==HIGH){
      if ((millis()-previousMillis)>100){
       previousMillis=millis();
       n_ust++; lcd.clear();
      } 
    }
                  
    
    
    if (digitalRead(pin_min)==HIGH&&flag_min==0){           //
    n_ust--; lcd.clear(); flag_min=1;}                      // обрабатываем кнопку          
    if (digitalRead(pin_min)==LOW&&flag_min==1){            // -
    flag_min=0;}                                            // количества витков
    
    if (digitalRead(pin_min)==HIGH){
      if ((millis()-previousMillis)>100){
       previousMillis=millis();
       n_ust--; lcd.clear();
      } 
    }

нужная переменная n_ust.

vvadim
Offline
Зарегистрирован: 23.05.2012

Попробовал  так

  if (buttonLeftState==HIGH) {
    currentMillis = millis();
    if(currentMillis - previousMillis < 5000) {
      previousMillis = currentMillis; 
      val-= 1;
      if(val <= 0) {
        val = 0;
      }
    }
    else if(currentMillis - previousMillis > 5000) {
      previousMillis = currentMillis; 
      val-= 10;
      if(val <= 0) {
        val = 0;
      }
    }
  }

отнимает только по единице. Как заставить десятки отнимать?

kaznachej
Offline
Зарегистрирован: 21.01.2012

Решил свою проблему. Толькопривязку взял не ко времени, а к числу. Вот моя программа для намоточного станка, может кому будет нужна\полезна:

/*
//////////////////////////////////////// 
///Счетчик витков намоточного станка.///
////////////////////////////////////////
Отображает на ЖК (8 символов, 2 строки) дисплее заданное и 
реальное количество витков.
При достижении заданного количества витков, выдает цифровой 
сигнал на клемму OUT и сигнализирует звуком.
Счетчик имеет 4 кнопки управления: сброс; +; -; прог.
В режиме счета кнопки + и - не работают, кнопка сброс - 
сбрасывает в 0 реальные показания витков, кнопка прог - 
переводит счетчик в режим установки заданного количества витков.
В этом режиме кнопки + и - увеличиват или уменьшают это значение,
кнопка сброс - сбрасывает устанавливаемые показания в 0,
кнопка прог - возвращает устройство в режим счета. При этом 
происходит запоминание заданного количества витков в
энергонезависимой памяти устройства
  

  
  Схема подключения:
 * LCD RS пин к цифр. выходу 11
 * LCD Enable пин к цифр. выходу 10
 * LCD R/W к Общему
 * LCD VO пин (пин 3) к ШИМ-выходу 9
 * LCD D4 пин к цифр. выходу 8
 * LCD D5 пин к цифр. выходу 5
 * LCD D6 пин к цифр. выходу 7
 * LCD D7 пин к цифр. выходу 6

 зуммер пин 12
 контраст пин 9
 кнопка сброс пин 14
 кнопка + пин 15
 кнопка - пин 16
 кнопка прог пин 17
 вых синг пин 18
 ик излучатель пин 19
 ик приемник пин 4

 */

 #include <EEPROM.h>
 #include <LiquidCrystal.h>

LiquidCrystal lcd(11, 10, 8, 5, 7, 6);

word n_real=0;
word n_ust=0;

int pin_res=14;
int pin_plus=15;
int pin_min=16;
int pin_prog=17;

int pin_Zum=12;
int pin_signal=18;
int pin_ik_out=19;
int pin_ik_in=4;

boolean flag_res=0;
boolean flag_plus=0;
boolean flag_min=0;
boolean flag_prog=0;

boolean flag_schet=0;

boolean regim=0;

long previousMillis=0;

word prew_n_ust=0;

long i=0;



void setup() {
  
  pinMode(9, OUTPUT); 
  analogWrite(9, 70);           // устанавливаем ШИМ выход контрастности 
  lcd.begin(8, 2);              // устанавливаем кол-во столбцов и строк
  

pinMode(pin_res, INPUT);
pinMode(pin_plus, INPUT);
pinMode(pin_min, INPUT);
pinMode(pin_prog, INPUT);

pinMode(pin_signal, OUTPUT);
pinMode(pin_ik_out, OUTPUT);
pinMode(pin_ik_in, INPUT);

 tone(pin_Zum, 2000, 70);
 delay(150);
 tone(pin_Zum, 3000, 85);
 delay(150);
 tone(pin_Zum, 4000, 100);

 n_ust=word(EEPROM.read(0), EEPROM.read(1));
}

void loop() {
  
  if (digitalRead(pin_prog)==HIGH&&flag_prog==0){              // меняем режимы:
    regim=!regim; flag_prog=1; lcd.clear();}                   // программирования (при 1) и  
  if (digitalRead(pin_prog)==LOW&&flag_prog==1){               // счета (при 0)
   flag_prog=0;}
  
  
  if (regim==0){                        // считаем витки
  
    if (digitalRead(pin_res)==HIGH&&flag_res==0){          //
    delay(50); n_real=0; flag_res=1; lcd.clear();}         // обрабатываем кнопку          
    if (digitalRead(pin_res)==LOW&&flag_res==1){           // сброс
    flag_res=0;}                                           // реального количества витков
    
    digitalWrite(pin_ik_out, HIGH);                      // включаем ИК излучатель
                                                         //
    if (digitalRead(pin_ik_in)==LOW&&flag_schet==0){     // ведем счет
    n_real++;              flag_schet=1;}                // витков          
    if (digitalRead(pin_ik_in)==HIGH&&flag_schet==1){    // 
    flag_schet=0;}                                       // 
    
    if (n_real==n_ust){                           // при достижении
                                                  // заданного количества
      lcd.clear();                                // витков
      digitalWrite(pin_signal, HIGH);             // сбрасываем счетчик,
      delay(50);                                  // выдаем выходной сигнал, 
      digitalWrite(pin_signal, LOW);              // пикаем
      if (n_real!=0)tone(pin_Zum, 2000, 300);     // и
      n_real=0;                                   //
      delay(100); }                               // ждем переезда
    
    lcd.setCursor(0, 0);               // выводим на дисплей
    lcd.print(n_real);                 // показания счетчика
    lcd.setCursor(0, 1);               // и заданного 
    lcd.print(n_ust);                  // количества витков
    
  }
  
  
  if (regim==1){                    // настраиваем количество витков
    
 //   n_real=0;
 int pause=250;
    
    digitalWrite(pin_ik_out, LOW);               // выключаем ИК излучатель
    
    if (digitalRead(pin_res)==HIGH&&flag_res==0){           //
    n_ust=0; lcd.clear(); flag_res=1;}                     // обрабатываем кнопку          
    if (digitalRead(pin_res)==LOW&&flag_res==1){           // сброс
    flag_res=0;}                                           // заданного количества витков
    
    if (digitalRead(pin_plus)==HIGH&&flag_plus==0){        //
     lcd.clear(); flag_plus=1; prew_n_ust=n_ust;}          // обрабатываем кнопку          
    if (digitalRead(pin_plus)==LOW&&flag_plus==1){         // +
    flag_plus=0;}                                          // количества витков
    
    if (digitalRead(pin_plus)==HIGH){
      if (((n_ust-prew_n_ust)<15)&&((millis()-previousMillis)>pause)){
        n_ust++; previousMillis=millis(); lcd.clear();}
      else if (((n_ust-prew_n_ust)<220)&&((millis()-previousMillis)>pause)){
        n_ust=n_ust+10; previousMillis=millis(); lcd.clear();}
      else if (((n_ust-prew_n_ust)<2620)&&((millis()-previousMillis)>pause)){
        n_ust=n_ust+100; previousMillis=millis(); lcd.clear();}
      else if (((n_ust-prew_n_ust)<65500)&&((millis()-previousMillis)>pause)){
        n_ust=n_ust+1000; previousMillis=millis(); lcd.clear();} 
    }
                  
                  
  if (digitalRead(pin_min)==HIGH&&flag_min==0){         //
  lcd.clear(); flag_min=1; prew_n_ust=n_ust;}           // обрабатываем кнопку          
  if (digitalRead(pin_min)==LOW&&flag_min==1){          // -
  flag_min=0;}                                          // количества витков
    
  if (digitalRead(pin_min)==HIGH){
    if (((prew_n_ust-n_ust)<15)&&((millis()-previousMillis)>pause)){
      n_ust--; previousMillis=millis(); lcd.clear();}
    else if (((prew_n_ust-n_ust)<220)&&((millis()-previousMillis)>pause)){
      n_ust=n_ust-10; previousMillis=millis(); lcd.clear();}
    else if (((prew_n_ust-n_ust)<2620)&&((millis()-previousMillis)>pause)){
      n_ust=n_ust-100; previousMillis=millis(); lcd.clear();}
    else if (((prew_n_ust-n_ust)<65500)&&((millis()-previousMillis)>pause)){
      n_ust=n_ust-1000; previousMillis=millis(); lcd.clear();} 
   }
    
    EEPROM.write(0, highByte(n_ust));      // записываем значение в память
    EEPROM.write(1, lowByte(n_ust));       //
    
    lcd.setCursor(0, 0);               // выводим на дисплей
    lcd.print(n_real);                 // показания счетчика
    lcd.setCursor(0, 1);               // и заданного 
    lcd.print(n_ust);                  // количества витков
    lcd.setCursor(7, 1);               // выводим букву Р 
    lcd.print("P");                    // в режиме программирования
  }
  
  
}  // конец loop

 

 

vvadim
Offline
Зарегистрирован: 23.05.2012

Попробовал сделать привязку к числу. Работает. Только мне не совсем удобно.

 Нужен такой алгоритм: 

- нажимаю или удерживаю до 5 сек - +- единицы 

- удерживаю более 5 сек -  +- десятки

- отпускаю (таймер обнулился) и опять нажимаю - +- единицы 


if (buttonRightState==HIGH ) {
  currentMillis = millis();
  if((currentMillis - previousMillis) < 5000) {
    val +=  1;
    if(val >= 1000) {
      val = 1000;
    }
  }
  else if((currentMillis - previousMillis) > 5000) {
    val += 10;
    if(val >= 1000) {
      val = 1000;
    }
  }
}
if (buttonRightState==LOW ) {
  previousMillis = currentMillis;
}

Десятки после 5 сек не хотят прибавляться    

step962
Offline
Зарегистрирован: 23.05.2011

Чтобы заработало, как задумано, необходимо анализировать не только СОСТОЯНИЯ, но и СОБЫТИЯ.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

Объясните, как эти кнопки работают:

maksim
Offline
Зарегистрирован: 12.02.2012

Это матричная клавиатура, погуглите. Только вот использовать ее для 4-х кнопок неразумно.

demon969
Offline
Зарегистрирован: 24.04.2012

 

 

Возможно ли отследить одновременное нажатие двух кнопок, при выше приведенной схеме?

Клапауций
Offline
Зарегистрирован: 10.02.2013

demon969 пишет:

Возможно ли отследить одновременное нажатие двух кнопок, при выше приведенной схеме?

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

Kish
Offline
Зарегистрирован: 18.01.2014

Приветствую.

Тоже начал работать с тактовой кнопкой. Воспользовался библиотекой Bounce версии 2. Вот код:

#define BUTTON_ENTER 13
Bounce buttonEnter = Bounce();

void setup()
{
  pinMode(BUTTON_ENTER, INPUT);
  buttonEnter.attach(BUTTON_ENTER);
  buttonEnter.interval(5);
}

void loop()
{
  switch(mainMenu)
  {
    case(1):

    break;

    case(2):

    break;

    case(3):
    display_lcd(0,0,"Ololo");
    delay (1000);
    lcd.clear();
    mainMenu = 0;
    break;

  default:
     if (buttonEnter.update())
    {
      if (buttonEnter.read() == HIGH) {
         mainMenu = 3;
       }
    }
    break;
  }
}

Подключил, как видите по коду, к 13 пину, на котором сидит и светодиод, расположенный по дефолту на плате Ардуино Уно. Кнопка подключена по этой схеме: http://arduino.ru/tutorials/button через резистор на 10 кОм. При нажатии на кнопку, светодиод, который расположен на плате загорается сразу, а вот надпись на экране появляется, примерно, через 2 секунды удержания кнопки. Хотелось бы, чтобы надпись появлялась быстрее. Что я делаю не так?

Спасибо.

codex
Offline
Зарегистрирован: 26.01.2014

Уважаемые форума!

По коду: если светло - на выходах 22 и 23 LOW and HIGH соответственно, темно - наоборот. 

Есть такая проблема, как к этому коду прикрутить две кнопки (в моём случае это концевики) так, чтобы при нажатии одной из кнопок на двух этих выходах одновременно  появилисть либо LOW, либо HIGH (уровень не  принципиален), но есть маленькое но!!! допустим одна из кнопок (Up) будет нажата (концевик), при условии - светло, как заставить при этом работать программу если условие поменяется на - темно ?

int analogPin = 0; // здесь фоторезистор
int loadPin_22 = 22; // здесь нагрузка
int loadPin_23 = 23; // здесь нагрузка
int val = 0; // переменная для хранения значения входного напряжения
int button_1 = 42; // номер входа кнопка Up
int button_2 = 43; // номер входа кнопка Down

 void setup()
{
  pinMode(analogPin, INPUT);
  pinMode(button_1, INPUT);
  pinMode(button_2, INPUT);
  pinMode(loadPin_22, OUTPUT);
  pinMode(loadPin_23, OUTPUT);
  digitalWrite(loadPin_22, LOW);
  digitalWrite(loadPin_23, LOW);
}
 
 void loop(){
   val = analogRead(analogPin); // считываем значение с фоторезистора
   static uint32_t millis_prev, millis_off; //2 переменные для хранения меток времени
     if (val <= 400) // тут подбираем под освещенность
       {
         if(millis()-millis_prev >= 5000) // проверяем что уровень держится >= 5 cек.
       {
        digitalWrite(loadPin_22, HIGH);
        digitalWrite(loadPin_23, LOW);
        millis_off = millis();
       } 
}
     else
  {
        millis_prev = millis();
        if(millis()-millis_off >= 5000)
       {
        digitalWrite(loadPin_22, LOW);  
        digitalWrite(loadPin_23, HIGH); 
       } 
}
}

P.S. Искренне прошу помощи, в поиск не посылать, много переварил, но воз так и стоит.

С ув. codex

chaytan
Offline
Зарегистрирован: 02.02.2012

nestandart пишет:

 Достаточно немного изменить включение резисторов и кнопки можно будет отслеживать и две и три и все сразу.

а об этом способе можно немного поподробнее.

в настоящий момент в реализуемом проэкте востребована такая возможность.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Способ считывания нескольких кнопок (нажатых комбинаций) описан в первом посте.

chaytan
Offline
Зарегистрирован: 02.02.2012

nestandart пишет:

Способ считывания нескольких кнопок (нажатых комбинаций) описан в первом посте.

интерес представляет способ максимально возможного уменьшения кол-ва проводов от кнопок...

 

Клапауций
Offline
Зарегистрирован: 10.02.2013

chaytan пишет:

интерес представляет способ максимально возможного уменьшения кол-ва проводов от кнопок...

менее двух проводов никак не получается - многие пробовали, но упёрлись в жестокую реальность.

но, впечатляет, что к аналоговому пину можно подключить 1024 кнопки - лешак явил сию истину народу, была большая радость.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

В первом посте представлен способ подключения двух кнопок к пину АЦП по двум проводам.

1024 это вы конечно загнули.

Учитывая погрешности измерений и "Шум в эфире" не больше 100 кнопок.

Клапауций
Offline
Зарегистрирован: 10.02.2013

nestandart пишет:

В первом посте представлен способ подключения двух кнопок к пину АЦП по двум проводам.

ок - наблюдаю ступенчатый резистор на три положения.

почему это настойчиво называется "способом увеличения количества кнопок по одному проводу" - не ясно.

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

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Можно конечно и потенциометр подключить. Но он неудобен тем что для того чтобы установить его в какое либо положение нужно проскакать по предыдущим.

 

>>почему это настойчиво называется "способом увеличения количества кнопок по одному проводу" - не ясно.<<

По форме это именно увеличение количества кнопок.

По содержанию - потенциометр.

 

 

Клапауций
Offline
Зарегистрирован: 10.02.2013

nestandart пишет:

Можно конечно и потенциометр подключить. Но он неудобен тем что для того чтобы установить его в какое либо положение нужно проскакать по предыдущим.

кнопки не решают проблемы практической невозможности мгновенной телепортации значения напряжения от 0 до, допустим 3,5В, минуя промежуточные значения - по любому значение напряжения будет повышаться от 0 до 3,5В, включая все кнопки в этом диапазоне.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Вы это серьезно ?!

Ну тогда можно и про скорость движения электронов поговорить.

О каких промежуточных значениях вы говорите ? Скорость переключения от 0 до нужного напряжения определяется рскоростью распространения электрического поля в проводе.

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

А теперь посмотрите ( в справочных материалах) сколько времени занимает опрос пина АЦП. 

Клапауций
Offline
Зарегистрирован: 10.02.2013

nestandart пишет:

О каких промежуточных значениях вы говорите ? Скорость переключения от 0 до нужного напряжения определяется рскоростью распространения электрического поля в проводе.

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

Chubaka
Offline
Зарегистрирован: 28.01.2014

Здравствуйте. Подскажите пожалуйста.

Есть резистивные кнопки. Подключены к аналоговому пину. Ардуино в качестве HID клавиатуры.

Сейчас у меня при нажатии на кнопку отправляется только одно значение. Работает отлично, как и надо при одиночном нажатии.

Не могу понять как сделать чтобы при одиночном нажатии отправлялось одно действиие а при удержании другое. Например кнопка "следующий трек". При одиночном нажатии отправляла Remote.next() (следующий трек), а при удержании постоянно отправляла Remote.forward() (перемотка).

Вот какой скетч сейчас.

int buttonPin=6; //пин для резистивных кнопок
int data;
int flag=0;

void setup()
{
 Keyboard.begin();
 Serial.begin(9600);
}

void loop()
{
 data=analogRead(buttonPin); //читаем значение нажатой кнопки
 Serial.println(data); //для определения кодов нажатых кнопок на мониторе порта
  
//кнопка громкости +
   if (data>=210 && data<=232 && flag==0)  // нажата кнопка
  {
   Remote.increase();
   Remote.clear();
   flag=1;
  }

//кнопка громкости -
   if (data>=460 && data<=488 && flag==0)  // нажата кнопка
  {
   Remote.decrease();
   Remote.clear();
   flag=1;
  }

//кнопка следующий трек
   if (data==0 && flag==0)  // нажата кнопка
  {
   Remote.next();
   Remote.clear();
   flag=1;
  }
  
//кнопка предидущий трек
   if (data>=76 && data<=92 && flag==0)  // нажата кнопка
  {
   Remote.previous();
   Remote.clear();
   flag=1;
  }
  
//кнопка приглушения звука
   if (data>=565 && data<=594 && flag==0)  // нажата кнопка
  {
   Remote.mute();
   Remote.clear();
   flag=1;
  }
  
//не нажата не одна из кнопок
   if (data>=950 && data<=960 && flag==1)
  {
   flag=0;
  }
}

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Делаете таймер , который при нажатии на кнопку  начинает отсчет времени и присваивает это значение переменной. При отпущеной кнопке переменная обнуляется. 

А потом отслеживаете значение переменной. Если время нажатия превысило пороговое значение - удержание кнопки. Если нет (обнулилось)  - короткое нажатие.

Chubaka
Offline
Зарегистрирован: 28.01.2014

nestandart пишет:

Делаете таймер , который при нажатии на кнопку  начинает отсчет времени и присваивает это значение переменной. При отпущеной кнопке переменная обнуляется. 

А потом отслеживаете значение переменной. Если время нажатия превысило пороговое значение - удержание кнопки. Если нет (обнулилось)  - короткое нажатие.

Спасибо!!! Почти всё получилось. Вот только при нажатии и удержании кнопки "следующий трек", сначало переключается трек а потом начинается перемотка. Т.е. выполняется и условие строки 063 и условие строки 070. С другими кнопками аналогичная ситуация. А как сделать что бы при удержании не выполнялось условие 063?


int buttonPin=6; //пин для резистивных кнопок
int data;
int flag=0;
long previousMillis = 0; 
int val=0; 


void setup()
{
 Keyboard.begin();
 Serial.begin(9600);
}

void loop()
{
 data=analogRead(buttonPin); //читаем значение нажатой кнопки
 Serial.println(data); //для определения кодов нажатых кнопок на мониторе порта
 
   if (data<=900) //если нажата любая из кнопок начинается отсчёт
  { 
      if (millis() -previousMillis >40)    
     { 
      previousMillis = millis();     
      val++; 
     } 
  } 
   else 
  { 
   val=0; 
  }
     
//кнопка громкости +
   if (data>=210 && data<=232 && flag==0 && val>=1 && val<=3)  //одиночное нажатие
  {
   Remote.increase(); //прибавить громкость на ед.
   Remote.clear();
   flag=1;
   val=0;
  }
   else if (data>=210 && data<=232 && val>=4)  // удержание
  {
   Remote.increase(); //прибавлять громкость до отпускания
   Remote.clear();
   val=0;
  }

//кнопка громкости -
   if (data>=460 && data<=488 && flag==0 && val>=1 && val<=3)  //одиночное нажатие
  {
   Remote.decrease(); //убавить громкость на ед.
   Remote.clear();
   flag=1;
   val=0;
  }
   else if (data>=460 && data<=488 && val>=4)  //удержание
  {
   Remote.decrease(); //убавлять громкость до отпускания
   Remote.clear();
   val=0;
  }

//кнопка следующий трек
   if (data==0 && flag==0 && val>=1 && val<=5)  //одиночное нажатие
  {
   Remote.next(); //следующий трек
   Remote.clear();
   flag=1;
   val=0;
  }
   else if (data==0 && val>=6)  //удержание
  {
   Remote.forward(); //перемотка вперёд
   Remote.clear();
   val=0;
  }
  
//кнопка предидущий трек
   if (data>=76 && data<=92 && flag==0 && val>=1 && val<=5)  //одиночное нажатие
  {
   Remote.previous(); //предидущий трек
   Remote.clear();
   flag=1;
   val=0;
  }
   else if (data>=76 && data<=92 && val>=6)  //удержание
  {
   Remote.rewind(); //перемотка назад
   Remote.clear();
   val=0;
  }
  
//кнопка приглушения звука
   if (data>=565 && data<=594 && flag==0)  //нажата кнопка
  {
   Remote.mute();
   Remote.clear();
   flag=1;
  }
  
//не нажата не одна из кнопок
   if (data>=950 && data<=960 && flag==1)
  {
   flag=0;
  }
}

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

 

В программу особо не вчитывался , но ...

Переделайте все конструкции if else if на просто if ( лучше вообще откажитесь от оператора else).  Возможно у вас конфликт по условиям if  else.

Примерно так.
//кнопка следующий трек
	   if (data==0 && flag==0 && val>=1 && val<=5)  //одиночное нажатие
	  {
	   Remote.next(); //следующий трек
	   Remote.clear();
	   flag=1;
	   val=0;
	  }
               if (data==0 && val>=6)  //удержание
	  {
	   Remote.forward(); //перемотка вперёд
	   Remote.clear();
	   val=0;
	  }
	   

И еще. Как вариант , перенесите скобку из строки 25 в самый низ.

Ход таймера маловат (40мс). Получается чтобы сработало одиночное нажатие нужно удерживать кнопку не более 120мс (неудобно).

Оптимальное время для одиночного нажатия 500-1000мс.

 

Я бы сделал отдельный таймер для каждой кнопки. 

 

kriss
Offline
Зарегистрирован: 24.01.2014

 

Прошу  программистов помочь в  очень простой для вас, практической задаче для уменьшения простоя лифта. Сегодня  лифты  напичканы электроникой, а элмеханик не всегда может локализовать неисправность – то ли электроника глючит (тогда жди пока наладчик приедет – бывает долго. Это я и есть)  или   в  шахте непорядок. У меня   есть самодельный стенд для полной проверки, собрал его на жесткой логике. Вот хочу для механиков собрать такую приблуду, чтобы меня  меньше дергали – старенький я и сами меньше в шахте ползали.

Для начала информация:

В шахте лифта и на кабине расположены  шунты, а на кабине -герконовые датчики. Основных датчиков три:  VN, TO и   VV.    (Дал им имена  для   скетча).                                                                                     По последовательности появления   этих сигналов ,   главный контроллер лифта определяет направление движения,  местоположение кабины и обеспечивает точную остановку в  датчике ТО.

                  VN -  TO -   VV    -вниз           VV -  TO -   VN    -вверх

Задача  :  собрать с помощью Ардуино эмулятор  движения кабины лифта для проверки  главного контроллера  в части работы узла местоположения кабины.   Датчики – это три светодиода VN, TO и   VV, подключенные к выходам 50,51 и 52    Они должны поочередно засвечиваться в зависимости от заданного направления.

Направление задают две кнопки  , подключенные на выходы 30 и 31.

 Собрал схемку – 3 светодиода с резисторами и две кнопки кподключил к МЕГА 2560, загрузил  свой примитивный скетч – последовательность работает,  но неправильно.  Просьба помочь  по двум вопросам: 

1. при снятии сигнала на входе, цикл продолжается , а нужна немедленная остановка.   И если он остановился, в момент, когда на выходе пина «1», то  выход должен остаться в этом состоянии (запомнить эту «1»).??

2. Другой цикл движения не знаю как вставить. ?

  // определяю назначение  выходов и входов

  int VN  =  51;   //датчик замедления вниз ( светодиод+резистор)

  int TO  =  50;   // датчик точной остановки

  int VV  =  52;   // датчик замедления вверх

  int pinN = 31;   // команда на включение привода кабины вниз          ( кнопка и резистор  дотяжки 15ком)                                                               

  int pinV = 30;   // команда на включение привода кабины вверх

  int valN=0 ; 

  int valV=0;

   void setup() {

   pinMode(VN , OUTPUT);

   pinMode(TO , OUTPUT);

   pinMode(VV , OUTPUT);   

   pinMode(pinN, INPUT);

   pinMode(pinV, INPUT);       

}

   void loop(){

   valN = digitalRead(pinN);

   valV = digitalRead(pinV);

  if (val == 1)                          //  поехали  вверх, поочередно включаем светодиоды. имитируем вход -выход шунта из датчика.  (потом эти выходы будут подключены ко входам проверяемого контроллера)

  {        

     digitalWrite(VN, 1);

     delay (2000);

     digitalWrite(VN, 0);

     digitalWrite(TO, 1);

     delay (2000);

     digitalWrite(TO, 0);       //понимаю, что это примитивно., но не знаю других способов, без delay

     digitalWrite(VV, 1);

     delay (2000);

     digitalWrite(VV, 0);  

  } else  {    

    digitalWrite(VN, 0);  // ЭТО ВЕРОЯТНО ЛИШНЕЕ?

    digitalWrite(TO, 0);

    digitalWrite(VV, 0);

  }}

 

второй цикл  хотел, но не знаю куда вставить        

******************************************

if (valV == 1)            //вниз  {        

     digitalWrite(VV, 1);     

     delay (2000);

     digitalWrite(VV, 0);

     digitalWrite(TO, 1);

     delay (2000);

     digitalWrite(TO, 0);

     digitalWrite(VN, 1);

     delay (2000);

     digitalWrite(VN, 0);

  

 

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

не в эту тему ;)

maksim
Offline
Зарегистрирован: 12.02.2012

Мега для таких целей ох как жирновато....

// определяю назначение  выходов и входов
#define VN    51   //датчик замедления вниз ( светодиод+резистор)
#define TO    50   // датчик точной остановки
#define VV    52   // датчик замедления вверх
#define pinN  31   // команда на включение привода кабины вниз          ( кнопка и резистор  дотяжки 15ком)                                                               
#define pinV  30   // команда на включение привода кабины вверх

byte state = 1; 

void setup() 
{
  pinMode(VN, OUTPUT);
  pinMode(TO, OUTPUT);
  pinMode(VV, OUTPUT);   
}

void loop()
{
  if(digitalRead(pinV))
  {
    state++;
    if(state == 4) state = 1;
    State(state);
  }
  
  if(digitalRead(pinN))
  {
    state--;
    if(state == 0) state = 3;
    State(state);
  }
}

void State(byte state)
{
  if(state == 1) digitalWrite(VV, 1); else digitalWrite(VV, 0); 
  if(state == 2) digitalWrite(TO, 1); else digitalWrite(TO, 0); 
  if(state == 3) digitalWrite(VN, 1); else digitalWrite(VN, 0);  
  delay (2000);
}

 

kriss
Offline
Зарегистрирован: 24.01.2014

 МАКСИМ! Спасибо большое - сразу заработало.  мне нужно время изучить,  как ВЫ сделали.

У меня просто  уже есть мега от внука- подарил  ему на день рождения - получилось себе. Своим механикам, если  все получится, дам схему  на что-нить подешевле.  

Это ведь начало задачи.    Буду  потом искат прогу для  подсчета  количества остановок по этим трем импульсам и вывода №этажа на семисегментный двустрочный индикатор.      Может сразу мне и подскажите где  посмотреть пример?

Заранее благодарю.

maksim
Offline
Зарегистрирован: 12.02.2012

kriss пишет:

где  посмотреть пример?

Нигде.

kriss
Offline
Зарегистрирован: 24.01.2014

Подскажите, пожалуйста, как выбирать тему? где можно подробнее об правилах этого форума узнать?

maksim
Offline
Зарегистрирован: 12.02.2012

Не надо выбирать, создайте новую. Создать новую тему