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

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

AVCC должен подключаться к +5В, а не подтягиваться, иначе АЦП не будет работать или будет работать некорректно.

Y.
Offline
Зарегистрирован: 28.11.2014

Моделирую в Proteuse. Что +5В на AVCC напрямую, что через 10k   - все равно ошибка. Больше ничего не подключено. А если pin20 пустая  - работает правильно.

Y.
Offline
Зарегистрирован: 28.11.2014

P.S. Более того, если AVCC замкнуть на землю - работает правильно. Непонятно.

Y.
Offline
Зарегистрирован: 28.11.2014

Да, конечно, такого быть не может. Достал "железный" Arduino, проверил - все работает как положено. Будем проверять модель....     Еще раз спасибо.

Vlad-bodryi
Offline
Зарегистрирован: 12.04.2014

подкажите пожалуйста, как реализовать двойное нажатие кнопки? в моём случае кнопки энкодера.

/*
Для управлением яркостью LED используется энкодер
*/

#define VHOD_SALONNIY_SVET A0             //4 сигнал от штатного блока управления
#define SVET_SALON 13            //1 плюс питания салонного света
#define KNOPKA_SVET A1   //2 кнопка энкодера салонного света 
#define VIHOD_OSTATOCHNOGO_PITANIYA 4  //3 на доводчик стёкол
#define VIHOD_OTKRITO 5                //3 питание салонных приблуд
#define VHOD_ZAKRITO 3                 //3 от ЦЗ
#define VHOD_OTKRITO 2                 //3 от ЦЗ



int val = 0;      //2  сохраняет состояние входного контакта
int old_val = 0;  //2  хранит предыдущее значение "вал"
int state = 0;    //2  0 = LED off в то время как 1 = LED on

int flag=0;                            //3 
unsigned long currentTime_pit;         //3
unsigned long loopTime_pit;            //3

int brightness = 30;             //1  яркость LED, начинаем с половины
int fadeAmount = 1;              //1  шаг изменения яркости LED
unsigned long currentTime_enc;   //1
unsigned long loopTime_enc;      //1
const int pin_A = A2;            //1  pin 22
const int pin_B = A3;            //1  pin 23
unsigned char encoder_A;         //1
unsigned char encoder_B;         //1
unsigned char encoder_A_prev=0;  //1

unsigned long startTime = 0;  //2  когда же мы начнем нажатием?
 
void setup()  
{
  pinMode(KNOPKA_SVET, INPUT);                //2  52 вход кнопки энкодера
  pinMode(VIHOD_OTKRITO, OUTPUT);                         //3
  pinMode(VIHOD_OSTATOCHNOGO_PITANIYA, OUTPUT);           //3
  pinMode(VHOD_SALONNIY_SVET, INPUT);                //4

  pinMode(SVET_SALON, OUTPUT);        //1  устанавливаем как выход
  pinMode(pin_A, INPUT);              //1
  pinMode(pin_B, INPUT);              //1
  digitalWrite(A2, HIGH);             //1  внутренняя подтяжка 10 кОм к +5V
  digitalWrite(A3, HIGH);             //1  внутренняя подтяжка 10 кОм к +5V
  digitalWrite(A1, HIGH);                     //2
  currentTime_enc = millis();         //1
  loopTime_enc = currentTime_enc;     //1
} 
 
void loop()  

{
   val = digitalRead(KNOPKA_SVET);            //2  читать входное значение и сохранить его ням, свежий галочку, если произошел переход
   if ((val == LOW) && (old_val == HIGH))     //2
     {
      state = 1 - state;                      //2   изменить состояние из выключенного состояния во включенное или наоборот
      startTime = millis();                   //2   millis()является Arduino часы она возвращает количество миллисекунд прошло с тех пор совет был сброшен. (эта линия помнит, когда кнопка была нажата в прошлом)
      delay(10);                              //2
     }


  currentTime_enc = millis();                        //1
  if(currentTime_enc >= (loopTime_enc + 5))          //1  проверяем каждые 5мс (200 Гц)
  {
    encoder_A = digitalRead(pin_A);                  //1  считываем состояние выхода А энкодера 
    encoder_B = digitalRead(pin_B);                  //1  считываем состояние выхода А энкодера    
    if((!encoder_A) && (encoder_A_prev))             //1  если состояние изменилось с положительного к нулю
      {
        if(encoder_B)      {if(brightness + fadeAmount <= 255) brightness += fadeAmount;}    //1  выход В в полож. сост., значит вращение по часовой стрелке увеличиваем яркость, не более чем до 255        
      
        else               {if(brightness - fadeAmount >= 1) brightness -= fadeAmount;}      //1  выход В в 0 сост., значит вращение против часовой стрелки уменьшаем яркость, но не ниже 0          
      }   
    encoder_A_prev = encoder_A;       //1  сохраняем значение А для следующего цикла 
     
     old_val = val;                                                   //2  val теперь старый, давайте хранить его
        if ((state == 1&&digitalRead(VIHOD_OTKRITO)==HIGH) || (digitalRead(VIHOD_OTKRITO)==HIGH&&digitalRead(VHOD_SALONNIY_SVET)==HIGH))      {analogWrite(SVET_SALON, brightness);}   //2 //3 //4 включить светодиод на текущем уровне яркости
        else                 {analogWrite(SVET_SALON, 0);}            //2  выключить светодиод
     loopTime_enc = currentTime_enc;          //1  
   }
    if(digitalRead(VHOD_OTKRITO)==HIGH&&digitalRead(VHOD_ZAKRITO)==LOW&&flag==0)       //3  если кнопка нажата и перемення flag равна 0 , то ... 
      { 
       digitalWrite(VIHOD_OTKRITO,HIGH);                           //3
       digitalWrite(VIHOD_OSTATOCHNOGO_PITANIYA,HIGH);             //3
       flag=1;                                                     //3  это нужно для того что бы с каждым нажатием кнопки происходило только одно действие плюс защита от "дребезга"  100% 
       } 
        
      if(digitalRead(VHOD_OTKRITO)==LOW&&digitalRead(VHOD_ZAKRITO)==HIGH&&flag==1)     //3  если кнопка НЕ нажата и переменная flag равна - 1 ,то ... 
     {    
       digitalWrite(VIHOD_OTKRITO,LOW);                            //3
       
       flag=0;                                                     //3 
       state=0;                                                    //3 сбрасываем принудительно салонный свет в выкл. состояние
       loopTime_pit = currentTime_pit;                             //3
      } 
   
     
  currentTime_pit = millis();                                                         //3  считываем время, прошедшее с момента запуска программы
  if(digitalRead(VIHOD_OTKRITO)==LOW && currentTime_pit >= (loopTime_pit + 30000))    //3  сравниваем текущий таймер с переменной loopTime + 1 секунда
     digitalWrite(VIHOD_OSTATOCHNOGO_PITANIYA, digitalRead(VIHOD_OTKRITO));           //3  выключаем остаточное питание через заданный промежуток времени
      
}

 

std
Offline
Зарегистрирован: 05.01.2012

Мои кнопки с диодами, отличают нажимания и удерживания, с градацией по времени сколько держать. Покритикуйте. Диоды перекладиной в сторону кнопок, хвостом в сторону прерывания.

Костыль: делей 10 мс если изменился уровень на прерывании. По нормальному нужен аппаратный подавитель дребезга. Кстати вопрос, как на 74 серии сделать? Конденсатор 0.1 между входом и выходом инвертора не канает, т. к. из-за утечки через входы он слишком быстро заряжается. Такой способ работает только с КМОП.

/*                    +-----------+
    +--/ --+----------| in1       |
    |      |          |           |
    |      +--|<|--+  |           |
    |              |  |           |
    +--/ --+-------|--| in2       |----> out
    |      |       |  |           |
    |      +--|<|--+  | in...     |
    |              |  |           |
    |              +--| D2 (INT0) |
    |                 |...........|
   _|_ gnd                                   */

#define btn1 (4)
#define btn2 (5)
#define btn3 (6)
#define btn4 (7)

#define reprate    (200)    // repeat rate, ms
#define btnsingthr (500)    // hold thresholds, ms
#define btndecthr  (2000)
#define btnhundthr (4500)

/* Keycodes:
  1..4   - press
  11..14 - hold
  21..24 - hold more
  31..34 - hold even more
  0      - no key          */

volatile boolean       bKeyDown=false,
                       bPrevKeyDown=false;
volatile byte          nKey,prevKey;
unsigned long tot_key,last_key;
boolean  bKeyPressing=false;

void setup(){
  pinMode(2,INPUT_PULLUP);     // int0
  pinMode(btn1,INPUT_PULLUP);  // btns
  pinMode(btn2,INPUT_PULLUP);
  pinMode(btn3,INPUT_PULLUP);
  pinMode(btn4,INPUT_PULLUP);
  attachInterrupt(0,kbdFlag,CHANGE);
  Serial.begin(9600);
  last_key=millis();
  nKey=0;
}

void kbdFlag(){
  if(digitalRead(2)){          // rising
    prevKey=nKey;
    nKey=0;
    bKeyDown=false;
  }else{                       // falling
    nKey=0;
    if(!digitalRead(btn1)) nKey=1;
    if(!digitalRead(btn2)) nKey=2;
    if(!digitalRead(btn3)) nKey=3;
    if(!digitalRead(btn4)) nKey=4;
    bKeyDown=true;
  }
}

byte kbdMain(){  
  byte kbdres;
  if(bPrevKeyDown!=bKeyDown){        // ugly hack here
    bPrevKeyDown=bKeyDown;
    delay(10);
  }
  if(!bKeyPressing && bKeyDown){     // press
    if(nKey!=0) tot_key=millis();
    bKeyPressing=true;
    return 0;
  }
  if(bKeyPressing && bKeyDown){      // repeat
    if(millis()-tot_key>=btnhundthr) kbdres=nKey+30;
     else if(millis()-tot_key>=btndecthr) kbdres=nKey+20;
      else if(millis()-tot_key>=btnsingthr) kbdres=nKey+10;
  }
  if(bKeyPressing && !bKeyDown){     // release
    if(millis()-tot_key<btnsingthr) kbdres=prevKey;
     else kbdres=0;
    bKeyPressing=false;
  }
  if(kbdres<10) return kbdres;       // return press code immediately
   else{
    if(millis()-last_key>=reprate){  // return hold code at repeat rate
      last_key=millis();
      return kbdres;
    }
  }
}

void loop(){
  switch(kbdMain()){
    case 1:  Serial.println("P1");break;
    case 2:  Serial.println("P2");break;
    case 3:  Serial.println("P3");break;
    case 4:  Serial.println("P4");break;

    case 11: Serial.println("H1");break;
    case 12: Serial.println("H2");break;
    case 13: Serial.println("H3");break;
    case 14: Serial.println("H4");break;

    case 21: Serial.println("H1+10");break;
    case 22: Serial.println("H2+10");break;
    case 23: Serial.println("H3+10");break;
    case 24: Serial.println("H4+10");break;

    case 31: Serial.println("H1+100");break;
    case 32: Serial.println("H2+100");break;
    case 33: Serial.println("H3+100");break;
    case 34: Serial.println("H4+100");break;
  }
}

 

mummykbf
Offline
Зарегистрирован: 28.03.2014

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

вот вроде бы и пример готовый уже нашел http://jmsarduino.blogspot.ru/2009/05/click-for-press-and-hold-for-b.html

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

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

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

mummykbf пишет:

одним коротким нажатием кнопки включать 1й канал реле, удержанием кнопки - включать 2й канал реле, при этом одиночное нажатие и удержание не должны паразитно влиять друг на друга

Так как про то как хотите выключать реле вы ничего не написали, то предположу, что так же как и включать.

#define BUTTON 2
#define RELE_1 3
#define RELE_2 4

#define DELAY 1000

void setup() 
{     
  pinMode(BUTTON, INPUT);
  digitalWrite(BUTTON, HIGH);  
  pinMode(RELE_1, OUTPUT);
  pinMode(RELE_2, OUTPUT);
}

void loop() 
{
  static uint32_t smillis = 0;
  static bool flag = 0;
  if(!digitalRead(BUTTON)) 
  {
    if(!smillis) smillis = millis();
    if(!flag && millis()-smillis > DELAY)
    {
      digitalWrite(RELE_2, !digitalRead(RELE_2));
      flag = 1;
    }
  }

  if(smillis && digitalRead(BUTTON))
  {
    if(millis()-smillis <= DELAY && millis()-smillis > 50) 
      digitalWrite(RELE_1, !digitalRead(RELE_1));
    smillis = 0;
    flag = 0;
  }
}

Кнопку необходимо подключить так как описано в #16, то есть один контакт кнопки к нужному выводу (в данном примере ко 2-му), а второй контакт к земле (то есть к GND).

Coolerr
Offline
Зарегистрирован: 30.06.2014

Тоже тут голову ломал с задержками от случайных нажатий. Вот что наваял

byte inc=0;//счетчик для удержания
unsigned long oldTime=0;//время удержания
boolean button=0;// переменная состояния кнопки
void setup(){
pinMode(2,INPUT); //вход
pinMode(13,OUTPUT);//выход
digitalWrite(2,HIGH);//подтягиваем к плюсу
}
 void loop(){
  button=digitalRead(2);//опрос кнопки
   if(button==1)inc=0;//если кнопка в исходном счетчик обнуляется
   if(millis()-oldTime>1000){
     if(button==0)inc++; //если кнопка нажата инкрементируем счетчик
      oldTime=millis();
}
  if(inc==2)digitalWrite(13,HIGH);//если счетчик насчитал 2 секунды че-нить запускаем
else{
  digitalWrite(13,LOW);//если не равен тушим.
}
}

Покритикуйте.

 

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

Помогают тем, кто ищет помощи, а тех кто ищет халяву отправляют в тот самый раздел.

Vlad-bodryi
Offline
Зарегистрирован: 12.04.2014

мне лишь нужен пример, чтоб я понял принцип, а как соединить - я уж сам допетрю!

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

а вам выложил для понятия каким мне нужно идти путём...

maksim
Offline
Зарегистрирован: 12.02.2012
#define BUTTON 2

void setup() 
{
  Serial.begin(9600);
  digitalWrite(BUTTON, 1);
}

void loop() 
{
  static bool pushed = 0;
  static uint32_t msec = 0;
  if(!pushed && !digitalRead(BUTTON))
  {
    pushed = 1;
    if(!msec)
    {
      msec = millis();
      Serial.println("1");
    }
    else 
    {
      msec = 0;
      Serial.println("2");
    }
    delay(50);
  }
  if(pushed && digitalRead(BUTTON)) pushed = 0;
  if(msec && millis()-msec > 300) msec = 0;
}

 

koxx
Offline
Зарегистрирован: 26.11.2014

Господа, помогите. Мне надо что-бы цикл шёл по кругу, а он отработает, и останавливается. Где ошибка?

const int button = 2;     
const int led =  11;      
const int leda = 12;


int buttonState = 0;         

void setup() {
  pinMode(led, OUTPUT);  
  pinMode(leda, OUTPUT);  
  pinMode(button, INPUT);    
}

void loop(){
  if(digitalRead(button)==HIGH&&buttonState==0)
  {
  digitalWrite(led, HIGH);   
  delay(60);               
  digitalWrite(led, LOW);    
  delay(60); 
  digitalWrite(led, HIGH);   
  delay(60);               
  digitalWrite(led, LOW);    
  delay(60);               
  digitalWrite(led, HIGH);   
  delay(60);               
  digitalWrite(led, LOW);    
  delay(200);               
  digitalWrite(leda, HIGH);   
  delay(60);               
  digitalWrite(leda, LOW);    
  delay(60); 
  digitalWrite(leda, HIGH);   
  delay(60);               
  digitalWrite(leda, LOW);    
  delay(60); 
  digitalWrite(leda, HIGH);   
  delay(60);               
  digitalWrite(leda, LOW);    
  delay(200); 
  
    buttonState=1;
  }
  if(digitalRead(button)==LOW&&buttonState==1)
  {
    buttonState=0;
  }
  
}
  

 

Coolerr
Offline
Зарегистрирован: 30.06.2014

Ну так все правильно, нажали кнопку выполнилось первое условие пошел цикл кнопка отпущена(LOW) дошел до конца статус=1

проверяет второе условие кнопка(LOW) state(1) выполняем state=0 возврат в начало проверяем условие кнопка(LOW) state=0

условие не выполнилось диоды не мигают.

koxx
Offline
Зарегистрирован: 26.11.2014

Спасибо. Но вот как это исправить? Я только начинаю это дело изучать.

Coolerr
Offline
Зарегистрирован: 30.06.2014

А как дожно работать? Алгоритм?

koxx
Offline
Зарегистрирован: 26.11.2014

Кпопка нажата-отпущена-3 раза моргает первый диод-задержка-3 раза второй диод - задержка - 3 раза 1-ый - задержка - 3 раза 2-ой , и так до бесконечности, пока не будет нажата и отпущена кнопка. Как то так. 

Coolerr
Offline
Зарегистрирован: 30.06.2014

Ну во первых, кнопку лучше подтягивать к плюсу и ловить не HIGH, а LOW. Подтяжка в сетапе digitalWrite(button,HIGH); Если это вся прога то buttonstate нафиг не нужен, а моргание можно запилить в while(1) и в нем условие выхода если нажата кнопка return.

 

koxx
Offline
Зарегистрирован: 26.11.2014

Спасибо. А более простым языком можете объяснить, на пальцах раскидать. Хочу сыну на коляску подсветку поставить, а то вечерами темно. Это первый шаг, потом будут задействованы режимы.

Coolerr
Offline
Зарегистрирован: 30.06.2014

сетап

pinMode(led,OUTPUT);

pinMode(button,INPUT);

digitalWrite(button,HIGH);

луп

если(кнопка==LOW){ 

    while(1){

   мигают светики

       если(кнопка==LOW)return;

}

}

koxx
Offline
Зарегистрирован: 26.11.2014

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

const int button = 2;     
const int led =  11;      
const int leda = 12;


int buttonState = 0;         

void setup() {
  pinMode(led, OUTPUT);  
  pinMode(leda, OUTPUT);  
  pinMode(button, INPUT); 
  digitalWrite(button, LOW);  
}

void loop(){
  if(digitalRead(button)==HIGH)
  while(1) {
  digitalWrite(led, HIGH);   
  delay(60);               
  digitalWrite(led, LOW);    
  delay(60); 
  digitalWrite(led, HIGH);   
  delay(60);               
  digitalWrite(led, LOW);    
  delay(60);               
  digitalWrite(led, HIGH);   
  delay(60);               
  digitalWrite(led, LOW);    
  delay(200);               
  digitalWrite(leda, HIGH);   
  delay(60);               
  digitalWrite(leda, LOW);    
  delay(60); 
  digitalWrite(leda, HIGH);   
  delay(60);               
  digitalWrite(leda, LOW);    
  delay(60); 
  digitalWrite(leda, HIGH);   
  delay(60);               
  digitalWrite(leda, LOW);    
  delay(200); 
  
    
  }
  if(digitalRead(button)==HIGH)return;
  
  
  
}

 

Coolerr
Offline
Зарегистрирован: 30.06.2014

while(1) Это безконечный цикл, посему второй опрос кнопки должен быть внутри него. Ретурн как раз и делает выход из цикла на исходную, а у тебя он за циклом и поэтому никогда не выполнится.

Efremoff
Offline
Зарегистрирован: 11.02.2015

Всем привет. Есть програмка, которая в зависимости от того какая клавиша нажата на клавиатуре - запускает разные фунции. 

что-то вроде такого. Заголовок, сетап-часть и прочее - опускаю за ненадобностью. Импортится Keyboard.h модуль Клава заведена столбцы - на 5-6-7 сам столбец подключен на 8 ногу.  Т.е. для выполнения кейса 'a' - нужно чтобы соеденились 5 и 8 ноги, для 'b' - 6 и 8 и тп.... 


void loop()
{ 
    char key = kpd.getKey();
  if(key)  // Check for a valid key.
  {
    switch (key)
      { 
    case 'a':  
      digitalWrite(13, !digitalRead(13)); //Инвертировать выход 
      break;  //прекратить выполнение программы.
      }
      { 
    case 'b':  
      digitalWrite(14, !digitalRead(14)); //Инвертировать выход 
      break;  //прекратить выполнение программы.
      }
      { 
    case 'c':  
      digitalWrite(15, !digitalRead(15)); //Инвертировать выход 
      break;  //прекратить выполнение программы.
      }
  }
}

Воспрос - как мне заставить чтобы на длинное нажатие клавиши запускалась другая функция? т.е. чтобы при коротком соединении 5 и 8 ноги (case 'a') - я запускал одну функцию (включение/выключение ноги), а если выводы соеденены долго - например через милисикунды можно наполнить переменную какую-то -  

if(millis() - previousMillis  >=  1)                 // начинаем считать время нажатия
        {                                               //
          previousMillis = millis();                    //
          valBut++;                                     // с каждой миллисекундой увеличиваем значение valBut
        }

то чтобы запускалась другая функция (запись в епром или еще что...)?

maksim
Offline
Зарегистрирован: 12.02.2012
Исправления:
void loop()
{ 
  char key = kpd.getKey();
  static char savekey = 0;
  if(key) 
  {
    static uint32_t startmillis = 0;
    if(!startmillis)
    {
      startmillis = millis();
      savekey = key;
    }
    else if(millis()-startmillis > 500)
    {
      startmillis = 0;
      switch (key)
      {
      case 'a':  
        ...     // Делаем, то что надо
        break;  //прекратить выполнение программы.

      case 'b':  
        ...     // Делаем, то что надо
        break;  //прекратить выполнение программы.

      case 'c':  
        ...     // Делаем, то что надо
        break;  //прекратить выполнение программы.
      }
    }
    key = 0;
  }
  else if(startmillis)
  {
    key = savekey;
    startmillis = 0;
  }


  if(key)  // Check for a valid key.
  {
    switch (key)
    { 
    case 'a':  
      digitalWrite(13, !digitalRead(13)); //Инвертировать выход 
      break;  //прекратить выполнение программы.

    case 'b':  
      digitalWrite(14, !digitalRead(14)); //Инвертировать выход 
      break;  //прекратить выполнение программы.

    case 'c':  
      digitalWrite(15, !digitalRead(15)); //Инвертировать выход 
      break;  //прекратить выполнение программы.
    }
  }
}

 

 

Efremoff
Offline
Зарегистрирован: 11.02.2015

ммм, как-то не работает. Точнее работает - но не так как надо. я должен нажимать кнопку быстро несколько раз, чтобы она сработала (т.е. как бы нужно "попасть" в цикл, когда "ждут" инфу от кнопки). Длинное нажатие не производит никаких действий. 

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

Efremoff пишет:

Библиотеку я беру с arduino.cc, она там врое наиболее новая, все остальное с ней работает, что пробовал.

#include <Keypad.h>


Keypad.h
Efremoff пишет:

Импортится Keyboard.h 

 

Efremoff пишет:

Кстати, с какой целью использован uint32_t? почему бы не заюзать обычный long?

Efremoff пишет:

Кажется я нашел одну нестыковку. Переменная startmillis обьявленна внутри цикла. вынес ее а заодно и savekey) в шапку скрипта. вот так:

Efremoff пишет:

Теперь короткое нажатие отрабатывает как надо, но на длинное нажатие - никакой реакции.

Потому, что своими изменениями свели на нет весь алгоритм.

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

Efremoff
Offline
Зарегистрирован: 11.02.2015

Итак. При использовании библиотеки Keypad.h длинное и короткое нажатие отрабатывает корректно с помощью следующего скетча:

#include <Keypad.h>

const byte rows = 1;
const byte cols = 1;
char keys[rows][cols] = {
{'a'}, 
};
byte rowPins[rows] = {5};
byte colPins[cols] = {8};
Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(14, OUTPUT);
}

void loop()
{ 
  char key = kpd.getKey();
  static char savekey = 0;
  static uint32_t startmillis = 0;
  if(kpd.getState() == PRESSED) 
  {
    if(!startmillis)
    {
      startmillis = millis();
      savekey = key;
    }
    else if(millis()-startmillis > 500)
    {
      startmillis = 0;
      switch (savekey)
      {
      case 'a':  
        digitalWrite(14, !digitalRead(14));
        break;  //прекратить выполнение программы.
      }
    }
    key = 0;
  }
  else if(kpd.getState() == RELEASED && startmillis)
    {
    key = savekey;
    startmillis = 0;
  }


  if(key)  // Check for a valid key.
  {
    switch (key)
    { 
    case 'a':  
      digitalWrite(13, !digitalRead(13)); //Инвертировать выход 
      break;  //прекратить выполнение программы.
    }
  }
}

Может кому пригодится. 

Спасибо maksim за активную помощь!

Просьба к модераторам - вытереть промежуточные посты неинформативные. 

 

doka
Offline
Зарегистрирован: 25.10.2014
leshak пишет:

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

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

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

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

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

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

    if(val<min if="" min="val;" val="">max)max=val;
    
    // добавляем замер к среднему
Не работает эта конструкция в IDE???? поясните новичку в чем дело!
maksim
Offline
Зарегистрирован: 12.02.2012
if(val < min) min = val;
if(val > max) max = val;

 

vingor
Offline
Зарегистрирован: 25.05.2014

Ребята подскажите на калякал тут один код но сам понимаю что это фуфло и можно сделать более правильно подскажите в какую сторону копать?

Есть 4 кнопки каждая сидит на отдельной ноге и 4 светодиода. понажатию включается тот светодиод которому соответствует кнопка.

int ch1 = 14; 
int ch2 = 15;
int ch3 = 16;
int ch4 = 17;
void setup()
{
  pinMode(ch1, OUTPUT);
  pinMode(ch2, OUTPUT);
  pinMode(ch3, OUTPUT);
  pinMode(ch4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(2, OUTPUT);
}
 
void loop()
{
 if(digitalRead(5)==HIGH)//если кнопка нажата ...
 {
 digitalWrite(ch1,HIGH);//включаем светодиод
 digitalWrite(ch2,LOW);
 digitalWrite(ch3,LOW);
 digitalWrite(ch4,LOW);
 }
 else if(digitalRead(4)==HIGH)//если кнопка нажата ...
 {
 digitalWrite(ch1,LOW);
 digitalWrite(ch2,HIGH);///включаем светодиод 2
 digitalWrite(ch3,LOW);
 digitalWrite(ch4,LOW);
 }
 else if(digitalRead(3)==HIGH)//если кнопка нажата ...
 {
 digitalWrite(ch1,LOW);
 digitalWrite(ch2,LOW);
 digitalWrite(ch3,HIGH);//включаем светодиод 3
 digitalWrite(ch4,LOW);
 }
  else if(digitalRead(2)==HIGH)//если кнопка нажата ...
 {
 digitalWrite(ch1,LOW);
 digitalWrite(ch2,LOW);
 digitalWrite(ch3,LOW);
 digitalWrite(ch4,HIGH); //включаем светодиод 4
 }
 }

Возникли вопросы:

1 Как сделать что-бы состояние кнопок записывалось в энергонезависимую память? И при сбое питания или перезагрузки загружала с нее состояния светодиодов.

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

Идея такая 1 кнопка включает выключает группу реле, а вернее отрубает питание на группу реле

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

Coolerr
Offline
Зарегистрирован: 30.06.2014

Про память.

http://arduino.ru/Reference/Library/EERPOM/read

http://arduino.ru/Reference/Library/EERPOM/write

Состояния кнопок лучше читать в переменную, а переменную уже сравнивать и записывать в EERPOM, типа 

x=digitalRead(A5);
if(x==HIGH)
каля-маля

EERPOM.write(0,x);

 

vingor
Offline
Зарегистрирован: 25.05.2014

Помогите тогда переключатель на кнопках перевести в удобоваримый код )))

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

Идея такая 1 кнопка включает выключает группу реле, а вернее отрубает питание на группу реле
далее 4 кнопки включает выключает свое реле (одновременно может работать только одно реле). Но при выключении общего питания состояния должны сохранятся до следующего включения.

Неоднозначная ситуация. Если реле были выключены по команде "выключить все", то надо это запоминать, или же при потере/восстановлении питания вернуть все как было до нажатия кнопки "выключить все"?

vingor
Offline
Зарегистрирован: 25.05.2014

1. Если реле были выключены по команде "выключить все", то надо это запоминать, и при включении по этой же кнопки включить именно то реле которое было до выключения.

2. при сбое питания отключили свет так же нужно помнить какое реле было включено последним.

Coolerr
Offline
Зарегистрирован: 30.06.2014

Сам-то что по этому поводу думаешь, предлагай мы поправим если чё.

vingor
Offline
Зарегистрирован: 25.05.2014

Примерная Логика

кнопка on1 нажата 1 раз  - состояние выхода 1 высокое

если состояние выхода 1 высокое тогда

считываем состояние выходов 2,3,4,5 из памяти

если кнопка 2 нажата выход 2 высокий, выходы 3,4,5 низкий

кнопка 3 нажата выход 3 высокий, выходы 2,4,5 низкий

кнопка 4 нажата выход 4 высокий, выходы 2,3,5 низкий

кнопка 5 нажата выход 5 высокий, выходы 2,3,4 низкий

если кнопка от1 нажата еще раз состояние выхода 1 низкий, состояние выходов 2,3,4.5 тоже низкий  

но при включении/выключении, сбое питания надо запоминать состояния выходов 2,3,4,5.

vingor
Offline
Зарегистрирован: 25.05.2014

Coolerr пишет:

Сам-то что по этому поводу думаешь, предлагай мы поправим если чё.

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

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013
// Подключаем библиотеку EEPROM
#include <EEPROM.h>

// Количество элементов (реле и кнопок)
#define ELEMENTS 6

// Назначаем пин для кнопки "выключить все"
#define OFF_BUTTON 10

// Назначаем пины для кнопок
byte buttonPin[ELEMENTS]={
  A2,A3,A4,A5,A6,A7};

// Назначаем пины для реле
byte outPin[ELEMENTS]={
  2,3,4,5,6,7};


void setup()
{
  pinMode(OFF_BUTTON, INPUT_PULLUP);      // конфигурируем пин на вход и используем внутреннюю подтяжку

  for (byte i = 0; i < ELEMENTS; i++)
  {
    pinMode(buttonPin[i], INPUT_PULLUP);  // конфигурируем пины на вход и используем внутреннюю подтяжку
    pinMode(outPin[i], OUTPUT);           // конфигурируем пины на выход
    restorePin(i);                        // восстанавливаем состояние реле
  }
}  // конец setup



void loop()
{
  // читаем состояние кнопки "выключить все"
  boolean stopButton = !digitalRead(OFF_BUTTON);  // инвертировано, т.к. мы используем внутреннюю подтяжку
  if (stopButton)                                 // если кнопка нажата
  {
    allOff();                                     // выключаем все
    delay (20);                                   // примитивный антидребезг
  }

  // читаем состояние остальных кнопок
  for (byte pin = 0; pin < ELEMENTS; pin++)
  {
    boolean state = !digitalRead(buttonPin[pin]); // инвертировано, т.к. мы используем внутреннюю подтяжку
    if (state)                                    // если кнопка нажата
    {
      allOff();                                   // выключаем все
      setPin(pin, state);                         // включаем конкретный реле
      delay (20);                                 // примитивный антидребезг
    } // конец if
  } // конец for

}  // конец loop



// восстанавливаем состояние из EEPROM
void restorePin(byte address)              // входная переменная address - адрес в EEPROM, из которого читаем состояние
{
  byte value = EEPROM.read(100 + address); // читаем из EEPROM состояние реле из ячейки 100 + номер
  // смещение на 100 из-за того, что в первые ячейки EEPROM чаще записывают, они могли уже выработать свой ресурс
  if (value > 1) value = 0;                // если в EEPROM мусор, то реле остается выключенным
  digitalWrite(outPin[address], value);    // восстанавливаем состояние реле
}  // конец restorePin


// Включаем конкретный пин, с записью состояния в EEPROM
void setPin(byte address, byte state)      // входные переменные: address и state - состояние, которое надо установить
{
  EEPROM.write(100 + address, state);      // сохраняем состояние реле в EEPROM
  digitalWrite(outPin[address], state);    // включаем/выключаем реле
}  // конец setPin


// Выключаем все
void allOff()
{
  for (byte pin = 0; pin < ELEMENTS; pin++) 
  {
    setPin(pin, LOW);
  }
}  // конец allOff

 

vingor
Offline
Зарегистрирован: 25.05.2014

вообще не понимаю что тут происходит ((( 

залил код у меня светодиоды просто мигают(((

а при нажатии всех кнопок одновременно получается бегущая строка )))

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

кнопки как подключены?

Про нажатие всех кнопок одновременно в исходных условиях не было ни слова.

vingor
Offline
Зарегистрирован: 25.05.2014

на аналоговые входы A2,A3,A4,A5,A6, на + питания, между + и минусом резистор 10Ком

vingor
Offline
Зарегистрирован: 25.05.2014

Tomasina пишет:

кнопки как подключены?

Про нажатие всех кнопок одновременно в исходных условиях не было ни слова.

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

Vittorio
Offline
Зарегистрирован: 02.02.2015

Если с резистором, то в строках 36 и 46 убери инвертирование (восклицательный знак), там же у Tomasina явно написано про подтяжку.
И в строках 21 и 25 просто INPUT.

vingor
Offline
Зарегистрирован: 25.05.2014

Убрал восклицательный знак теперь просто бегущая строка из светодиодов.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

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

vingor
Offline
Зарегистрирован: 25.05.2014
Исправил вот таким способом

/ Назначаем пины для кнопок
byte buttonPin[ELEMENTS]={
  2,3,4,5,6};

// Назначаем пины для реле
byte outPin[ELEMENTS]={
  A0,A1,A2,A3,A4};

 

немогу понять что это такое

// Назначаем пин для кнопки "выключить все"
#define OFF_BUTTON 10

 

 

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

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

Это и есть еще одна дополнительная кнопка (на пине 10), которая выключает вообще все, независимо от того, что было включено.

vingor
Offline
Зарегистрирован: 25.05.2014

Я прошу прощения в вашем коде разобраться ни как не могу не хватает знаний.

Может меня немного не поняли!

Есть устройство включается/выключается по 1-ой кнопке

И есть еще 4 кнопки выбора режима работы (включения реле) условие - всегда может быть включен один режим (реле) при включении другого режима (реле), другие должны отключатся.

состояние этих режимов надо сохранять в еепром.

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

Как расписали требования к задаче, так она и была сделана :)

Согласитесь, что это отличается от изначального:

Есть 4 кнопки каждая сидит на отдельной ноге и 4 светодиода. понажатию включается тот светодиод которому соответствует кнопка.

Идея такая 1 кнопка включает выключает группу реле, а вернее отрубает питание на группу реле

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

1 Как сделать что-бы состояние кнопок записывалось в энергонезависимую память? И при сбое питания или перезагрузки загружала с нее состояния светодиодов.

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