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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/**/
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип обработчик
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
    unsigned long interval;
    pDo Do;
    unsigned long past, past1;
    byte counter;
    byte state; /* 0 ждем / 1 подсчет обратно*/
    /*установить в состояние*/
    void stand(byte s) {
      state = s;
      past = mill;
      switch (state) {
        case 0:
          Serial.println("timeBack stop");
          lcd.setCursor(8, 0);
          lcd.print("stop");
          break;
        case 1:
          Serial.println("timeBack start");
          lcd.setCursor(8, 0);
          lcd.print("start");
          past1 = mill;
          counter = 5;
          break;
      }
    }
  public:
    /*конструктор*/
    Cl_timeBack(unsigned long i, pDo Do_): interval(i), Do(Do_) {}
    /*инициализация*/
    void init() {
      stand(0);
    }
    /*работа*/
    void run() {
      if (state == 1 && mill - past1 >= 1000) {
        past1 = mill;
        Serial.println((past - past1 + interval) / 1000);
        lcd.setCursor(8, 0);
        lcd.print("     ");
        lcd.print((past - past1 + interval) / 1000);
      }
      if (state == 1 && mill - past >= interval) stand(0);
    }
    /*запуск подсчета*/
    void start() {
      if (state == 0) stand(1);
    }
    /*сработал датчик движения*/
    void tick() {
      if (state == 0) return;
      counter--;
      lcd.setCursor(6, 1); //<------------------попробуйте сюда
      lcd.print(5 - counter);
      if (counter <= 0) { // если счетчик обнулился
        stand(0);
        Do();// то вызов аварии
      }
    }
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
    byte pin;
    pDo Do;
    bool btn, oldBtn;
  public:
    /*конструктор*/
    Cl_sens(byte p, pDo Do_): pin(p), Do(Do_) {};
    /*инициализация*/
    void init() {
      pinMode(pin, INPUT);
      btn = digitalRead(pin);
    }
    /*работа*/
    void run() {
      oldBtn = btn;
      btn = digitalRead(pin);
      /*если раньше 1, а сейчас 0 то вызовем обработчик*/
      if (oldBtn && !btn) Do();
    }
};
//---Компоновка-----------------------------
const unsigned long time_20s = 20000; //интервал 20 сек
void DoTimeBack() {
  /*здесь отправляем сообщение про проникновение*/
  Serial.println("Alien in the house");
}
Cl_timeBack timeBack(/*интервал*/time_20s,/*обработчик*/&DoTimeBack);
void DoSens() {
  Serial.println("start-tick");
  timeBack.start();
  timeBack.tick();
}
Cl_sens sens(/*пин*/2,/*обработчик*/&DoSens);
//---main-----------------------------
void setup() {
  lcd.clear();
  delay(1);
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Time::>");
  lcd.setCursor(0, 1);
  lcd.print("Tick::>");
  Serial.begin(9600);
  timeBack.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sens.run();
}
/*Скетч использует 4700 байт (15%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 494 байт (24%) динамической памяти, оставляя 1554 байт для локальных переменных. Максимум: 2048 байт.
*/

 

GKV
Offline
Зарегистрирован: 01.10.2013

выводит счет.Как убрать ноль в таймере  и выход сигнала с ардуины (А0) 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

GKV пишет:

выводит счет.Как убрать ноль в таймере  и выход сигнала с ардуины (А0) 

Ну не все мне за вас делать. Посмотрите. Это все же ваш проект, а не мой.

GKV
Offline
Зарегистрирован: 01.10.2013

За то,что помогаете величина благодарности - бесконечная!Дошло.Вроде все работает как надо,завтра попробую подцепить к щиту.Огромное Спасибо!

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну разумеется во внутрь функции обработчика.DoTimeBack() Для этого я и писал /*здесь отправляем сообщение про проникновение*/

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

ВСЕМ НОВИЧКАМ

В этой теме нужно задавать конкретные вопросы ПО КНОПКАМ. Всё остальное: светодиоды, дисплеи, моторчики и т.д. - создавайте отдельную тему и там спрашивайте. Не нужно засирать тему про кнопки всем подряд.

P.S. mag155, у Вас не с кнопками проблема, а с базовыми знаниями по программированию. Начните с раздела "Программирование" в верху сайта. Посмотрите видеоуроки Джереми Блюма, почитайте его книжку. Потом приходите с вопросами.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Клапа, не нагнетай.  

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

DetSimen пишет:

Клапа, не нагнетай.  

с чего бы это?

bwn
Offline
Зарегистрирован: 25.08.2014

Клапауций 298 пишет:

DetSimen пишет:

Клапа, не нагнетай.  

с чего бы это?

Опять торпедируют, а ты нам нужен.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Да. Ты единственный среди нас, как сказали, кто очень добрый, чуткий и отзывчивый к новичкам.  Я аш всплакнул. Жалка будет, када тебя опять на 10 суток за хулиганство закроют. 

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

bwn пишет:

Опять торпедируют, а ты нам нужен.

DetSimen пишет:

Да. Ты единственный среди нас, как сказали, кто очень добрый, чуткий и отзывчивый к новичкам.  Я аш всплакнул. Жалка будет, када тебя опять на 10 суток за хулиганство закроют. 

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

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017
Andrew.vodny
Andrew.vodny аватар
Offline
Зарегистрирован: 02.02.2018

А что насчет сенсорной кнопки TTP223b я хочу написать скетч на 4 кнопки что бы работали как выключатели помогите плиз , где ошибка?

#define BUTTON1_PIN 2
#define RELAY1_PIN 3
#define BUTTON2_PIN 4
#define RELAY2_PIN 5
#define BUTTON3_PIN 6
#define RELAY3_PIN 7
#define BUTTON4_PIN 8
#define RELAY4_PIN 9
boolean blStatus1 = false;                     //логический флаг предыдущего состояния реле включено/выключено. По умолчанию при старте программы выключено
boolean blStatus2 = false;
boolean blStatus3 = false;
boolean blStatus4 = false;
void setup() {
  // инициализируем подключения
  pinMode(BUTTON1_PIN, INPUT);                 //задаем пин 2 как вход кнопки
  pinMode(RELAY1_PIN, OUTPUT);                 //задаем пин 3 как выход на реле
pinMode(BUTTON2_PIN, INPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(BUTTON3_PIN, INPUT);
pinMode(RELAY3_PIN, OUTPUT);
pinMode(BUTTON4_PIN, INPUT);
pinMode(RELAY4_PIN, OUTPUT);
}
void loop() {
  // основная программа. Разовое нажатие на кнопку будет включать или отключать реле без удержания кнопки
    if (digitalRead(BUTTON1_PIN)==HIGH){      //проверяем, нажата ли кнопка (если на 2-м пине есть сигнал)
      blStatus1 = !blStatus1;                 //меняем логический флаг на противоположный от установленного предыдущим нажатием
     digitalWrite(RELAY1_PIN, blStatus1);     //меняем состояние выхода соответственно логическому флагу               
     delay (500);
    }
    if (digitalRead(BUTTON2_PIN)==HIGH){
     blStatus2 = !blStatus2;
     digitalWrite(RELAY2_PIN, blStatus2);
    delay (500);
    }
     if (digitalRead(BUTTON3_PIN)==HIGH){
      digitalWrite(RELAY3_PIN, blStatus3);
      blStatus3 = !blStatus3;
      //delay ();
     }
     if (digitalRead(BUTTON4_PIN)==HIGH){
       digitalWrite(RELAY4_PIN, blStatus4);
       blStatus4 = !blStatus4;
       delay (500); 
     }
     // Serial.println(blStatus);               //выводим состояние реле в серийный порт
     }
     
Andrew.vodny
Andrew.vodny аватар
Offline
Зарегистрирован: 02.02.2018

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

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

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Andrew.vodny пишет:

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

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

Вот Вам для одной кнопки. Остальные я думаю сделаете по аналогии

#define BUTTON1_PIN 2
#define RELAY1_PIN 3
boolean blStatus1 = false;                     //логический флаг предыдущего состояния реле включено/выключено. По умолчанию при старте программы выключено
bool temp_kn1;

void setup() {
  // инициализируем подключения
  pinMode(BUTTON1_PIN, INPUT);                 //задаем пин 2 как вход кнопки
  pinMode(RELAY1_PIN, OUTPUT);                 //задаем пин 3 как выход на реле
}
void loop() {
  // основная программа. Разовое нажатие на кнопку будет включать или отключать реле без удержания кнопки
  if (digitalRead(BUTTON1_PIN) == HIGH && !temp_kn1) {   //проверяем, нажата ли кнопка (если на 2-м пине есть сигнал)
    temp_kn1 = 1;
    blStatus1 = !blStatus1;                 //меняем логический флаг на противоположный от установленного предыдущим нажатием
    digitalWrite(RELAY1_PIN, blStatus1);     //меняем состояние выхода соответственно логическому флагу
    delay (50);
  }
  else if (digitalRead(BUTTON1_PIN) == 0 && temp_kn1)temp_kn1 = 0;


  // Serial.println(blStatus);               //выводим состояние реле в серийный порт
}

 

Andrew.vodny
Andrew.vodny аватар
Offline
Зарегистрирован: 02.02.2018
#define BUTTON2_PIN 2
#define RELAY2_PIN 3
boolean blStatus2 = true;      //логический флаг предыдущего состояния реле включено/выключено. По умолчанию при старте программы выключено
void setup() {
  // инициализируем подключения
  pinMode(BUTTON2_PIN, INPUT);     //задаем пин 2 как вход кнопки
  pinMode(RELAY2_PIN, OUTPUT);     //задаем пин 3 как выход на реле
}
void loop() {
if (digitalRead(BUTTON2_PIN)==HIGH){  //если кнопка нажата 
 blStatus2 = !blStatus2;        // инвертируем значение
 digitalWrite(RELAY2_PIN, blStatus2); // пишем инвертированное значение в порт
 delay (5000);   
    }
}

 вот , дотрагиваюсь до кнопки реле включается , работает 5 сек и выключается , при этом сенсор приходитсья 0,2 сек подержать

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Andrew.vodny пишет:
нажимаю на кнопку реле срабатывает , отжимаю реле выключается.а нужно при нажатие что бы включалось , при повторном нажатие выключалось
Ну если вам нужны "шашечки" то это .

/**/
unsigned long mill;// переменная для millis()
typedef void (*pDo)() ;// тип -функция обработчик
//------Cl_Led----------------------
// класс светодиод
class Cl_Led {
  protected:
    const byte pin;
    byte state; //0 выкл/ 1 вкл
    /*установить в состояние*/
    void stand(byte state_) {
      state = state_;
      switch (state) {
        case 0: // выкл
          digitalWrite(pin, LOW);
          break;
        case 1: // вкл
          digitalWrite(pin, HIGH);
          break;
      }
    }
  public:
    /*конструктор*/
    Cl_Led(byte pin_): pin(pin_) {}
    /*инициализация-вставить в setup()*/
    void init() {
      pinMode(pin, OUTPUT);
      OFF();
    }
    /*работа-вставить в loop()*/
    void run() {
    }
    /*включить*/
    void ON() {
      stand(1);
    }
    /*выключить*/
    void OFF() {
      stand(0);
    }
    /*переключить*/
    void invert() {
      if (state) stand(0);
      else stand(1);
    }
};
//------Cl_Btn----------------------
// класс кнопка
class Cl_Btn {
  protected:
    const byte pin;
    pDo Do;//обработчик
    bool bounce = 0;
    bool btn = 1, oldBtn;
    unsigned long past;
  public:
    /*конструктор*/
    Cl_Btn(byte pin_, pDo Do_): pin(pin_), Do(Do_) {}
    /*инициализация-вставить в setup()*/
    void init() {
      pinMode(pin, INPUT_PULLUP);
    }
    /*работа-вставить в loop()*/
    void run() {
      bool newBtn = digitalRead(pin);
      if (!bounce && newBtn != btn) {
        bounce = 1;
        past = mill;
      }
      if (bounce && mill - past >= 10) {
        bounce = 0 ;
        oldBtn = btn;
        btn = newBtn;
        if (!btn && oldBtn) Do();
      }
    }
};
//-----компоновка----------------------
Cl_Led Led1(/*пин*/13);
Cl_Led Led2(/*пин*/12);
Cl_Led Led3(/*пин*/11);
Cl_Led Led4(/*пин*/10);
void DoBtn1() {
  Led1.invert();
}
void DoBtn2() {
  Led2.invert();
}
void DoBtn3() {
  Led3.invert();
}
void DoBtn4() {
  Led4.invert();
}
Cl_Btn Btn1(/*пин*/2,/*обработчик*/DoBtn1);
Cl_Btn Btn2(/*пин*/3,/*обработчик*/DoBtn2);
Cl_Btn Btn3(/*пин*/4,/*обработчик*/DoBtn3);
Cl_Btn Btn4(/*пин*/5,/*обработчик*/DoBtn4);
//-----main----------------------
void setup() {
  Led1.init();
  Led2.init();
  Led3.init();
  Led4.init();
  Btn1.init();
  Btn2.init();
  Btn3.init();
  Btn4.init();
}
void loop() {
  mill = millis();
  Led1.run();
  Led2.run();
  Led3.run();
  Led4.run();
  Btn1.run();
  Btn2.run();
  Btn3.run();
  Btn4.run();
}

/*Скетч использует 1446 байт (4%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 61 байт (2%) динамической памяти, оставляя 1987 байт для локальных переменных. Максимум: 2048 байт.
*/

А если просто повисеть на форуме. То читайте форум.

bwn
Offline
Зарегистрирован: 25.08.2014

АХТУНГ, прошу всех подписанных и заинтересованных в теме принять участие в опросе и высказать свое мнение по предложениям. Неофитам, не улавливающим разницы между работой с кнопкой и включением реле, просьба не утруждаться.

GKV
Offline
Зарегистрирован: 01.10.2013
Нужно чтоб LED загорался при сигнале от счетчика и гас через 2 сек,на входе 2 остается постоянный уровень HIGH
#include <LiquidCrystal_I2C.h>                           //  Подключаем библиотеку для работы с LCD дисплеем по шине I2C
LiquidCrystal_I2C lcd(0x27,16,2);                        //  Объявляем  объект библиотеки, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2) Если дисплей не отвечает, то измените адрес на 0x3F


int buttonPin = 2;
int LED = 6;


int counterA=0;
int prevValueA=0;

int Perekis = 11;
byte valA; //переменная времени 
byte flagA;
long previousMillisA = 0;

int counterB=0;
int prevValueB=0;

int XLOR = 12;
byte valB; //переменная времени 
byte flagB;
long previousMillisB = 0;


void setup() {
  lcd.begin();
  pinMode(buttonPin, INPUT);
  pinMode(Perekis, OUTPUT);
  pinMode(XLOR, OUTPUT);
  pinMode(LED, OUTPUT);

  

}

void loop() {

boolean bs = digitalRead (buttonPin);

if(bs == HIGH && prevValueA==0) {
  prevValueA=1;
  counterA++;
}

if(bs == LOW) {
  prevValueA=0;
}
 lcd.setCursor(0, 0);
 lcd.print("PEREKIS::>"); 
 lcd.setCursor(12, 0);
 lcd.print("(8) ");
 lcd.setCursor(10, 0);
 lcd.print(counterA);
  
if (counterA<10)
{
  lcd.setCursor(11, 0);
  lcd.print(" "); 
}
if(counterA==8)
{
 counterA=0;
 previousMillisA = millis();
    flagA=1;
    valA=0;
  }
  if(flagA==1)
  {
    digitalWrite(Perekis,HIGH);
    
  }
  if(counterA<=8)
  {

    if (millis() -previousMillisA >1000)
    { 
      previousMillisA = millis();     
      valA++;                       // работает счет,ledPin1  включен 
    
    }  
  }
  if(valA>=2) //кол-во секунд ,при достижении этого значения , ledPin2 выключается
  { 
    digitalWrite(Perekis,LOW);
    flagA=0;
  }

if(bs == HIGH && prevValueB==0) {
  prevValueB=1;
  counterB++;
}

if(bs == LOW) {
  prevValueB=0;
}
 lcd.setCursor(0, 1);
 lcd.print(" XLOR  ::>"); 
 lcd.setCursor(12, 1);
 lcd.print("(10)");
 lcd.setCursor(10, 1);
 lcd.print(counterB);
  
if (counterB<10)
{
  lcd.setCursor(11, 1);
  lcd.print(" "); 
}
if(counterB==10)
{
 counterB=0;
 previousMillisB = millis();
    flagB=1;
    valB=0;
  }
  if(flagB==1)
  {
    digitalWrite(XLOR,HIGH);
    
  }
  if(counterB<=10)
  {

    if (millis() -previousMillisB >1000)
    { 
      previousMillisB = millis();     
      valB++;                       // работает счет,ledPin1  включен 
    
    }  
  }
  if(valB>=2) //кол-во секунд ,при достижении этого значения , ledPin2 выключается
  { 
    digitalWrite(XLOR,LOW);
    flagB=0;
  }  
  if (digitalRead(2) == HIGH) 
  {
  digitalWrite(LED, HIGH);
  }else{
  digitalWrite(LED, LOW);
  }
  
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

/**/
unsigned long mill;
//--------------------------------------
const byte btnPin =/*пин*/2;
bool btn;
const byte ledPin =/*пин*/3;
bool Led;
unsigned long past;
const unsigned long time2sec = 2000;
//-----------main()---------------------------
void setup() {
  pinMode(btnPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, Led = 0);
}
void loop() {
  mill = millis();
  btn = digitalRead(btnPin);
  if (!btn) { /* если кнопка нажата*/
    digitalWrite(ledPin, Led = 1); /*то вкл светодиод*/
    past = mill;
  }
  if (Led & mill - past >= time2sec) {/*если светодиод горит больше 2 сек*/
    digitalWrite(ledPin, Led = 0);/*то выкл*/
  }
}
/*Скетч использует 1084 байт (3%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 19 байт (0%) динамической памяти, оставляя 2029 байт для локальных переменных. Максимум: 2048 байт.
*/

 

b707
Offline
Зарегистрирован: 26.05.2017

чуть поправлю код квона - и

/**/
unsigned long mill;
//--------------------------------------
const byte btnPin =/*пин*/2;
bool btn;
const byte ledPin =/*пин*/3;
bool Led;
unsigned long past;
const unsigned long time2sec = 2000;
//-----------main()---------------------------
void setup() {
  pinMode(btnPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, Led = 0);
}
void loop() {
  mill = millis();
  btn = digitalRead(btnPin);
  if ((!btn)&&(past==0)) { /* если кнопка нажата*/
    digitalWrite(ledPin, Led = 1); /*то вкл светодиод*/
    past = mill;
  }
  if (Led & mill - past >= time2sec) {/*если светодиод горит больше 2 сек*/
    digitalWrite(ledPin, Led = 0);/*то выкл*/
  }
}

мигать не будет. По крайней мере 2 месяца :)

 

GKV
Offline
Зарегистрирован: 01.10.2013

qwone спасибо за код,но чего-то не то.У меня с кнопки HIGH, подтяжка к GND 10K

#include <LiquidCrystal_I2C.h>             
LiquidCrystal_I2C lcd(0x27,16,2);                       

unsigned long mill;
const byte buttonPin = 2;

bool btn;
bool Led;
const byte ledPin = 6;
unsigned long past;
const unsigned long time2sec = 2000;

int counterA=0;
int prevValueA=0;

int Perekis = 11;
byte valA; //переменная времени 
byte flagA;
long previousMillisA = 0;

int counterB=0;
int prevValueB=0;

int XLOR = 12;
byte valB; //переменная времени 
byte flagB;
long previousMillisB = 0;


void setup() {
  lcd.begin();
  pinMode(buttonPin, INPUT);
  pinMode(Perekis, OUTPUT);
  pinMode(XLOR, OUTPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, Led = 0);
  

}

void loop() {

boolean bs = digitalRead (buttonPin);

if(bs == HIGH && prevValueA==0) {
  prevValueA=1;
  counterA++;
}

if(bs == LOW) {
  prevValueA=0;
}
 lcd.setCursor(0, 0);
 lcd.print("PEREKIS::>"); 
 lcd.setCursor(12, 0);
 lcd.print("(8) ");
 lcd.setCursor(10, 0);
 lcd.print(counterA);
  
if (counterA<10)
{
  lcd.setCursor(11, 0);
  lcd.print(" "); 
}
if(counterA==8)
{
 counterA=0;
 previousMillisA = millis();
    flagA=1;
    valA=0;
  }
  if(flagA==1)
  {
    digitalWrite(Perekis,HIGH);
    
  }
  if(counterA<=8)
  {

    if (millis() -previousMillisA >1000)
    { 
      previousMillisA = millis();     
      valA++;                       
    
    }  
  }
  if(valA>=2) 
  { 
    digitalWrite(Perekis,LOW);
    flagA=0;
  }

if(bs == HIGH && prevValueB==0) {
  prevValueB=1;
  counterB++;
}

if(bs == LOW) {
  prevValueB=0;
}
 lcd.setCursor(0, 1);
 lcd.print(" XLOR  ::>"); 
 lcd.setCursor(12, 1);
 lcd.print("(10)");
 lcd.setCursor(10, 1);
 lcd.print(counterB);
  
if (counterB<10)
{
  lcd.setCursor(11, 1);
  lcd.print(" "); 
}
if(counterB==10)
{
 counterB=0;
 previousMillisB = millis();
    flagB=1;
    valB=0;
  }
  if(flagB==1)
  {
    digitalWrite(XLOR,HIGH);
    
  }
  if(counterB<=10)
  {

    if (millis() -previousMillisB >1000)
    { 
      previousMillisB = millis();     
      valB++;                       
    
    }  
  }
  if(valB>=2) 
  { 
    digitalWrite(XLOR,LOW);
    flagB=0;
  }  
 
 mill = millis();
  btn = digitalRead(buttonPin);
  if (!btn) { /* если кнопка нажата*/
    digitalWrite(ledPin, Led = 1); /*то вкл светодиод*/
    past = mill;
  }
  if (Led & mill - past >= time2sec) {/*если светодиод горит больше 2 сек*/
    digitalWrite(ledPin, Led = 0);/*то выкл*/
  }          
   
  
}

 

GKV
Offline
Зарегистрирован: 01.10.2013

b707 переделал к вы написали.Как переделать с подтяжкой к земле ,на кнопке +5в.Сейчас получается ,что ЛЕД загорается только при загрузке скетча

#include <LiquidCrystal_I2C.h>             
LiquidCrystal_I2C lcd(0x27,16,2);                       

unsigned long mill;
const byte buttonPin = 2;

bool btn;
bool Led;
const byte ledPin = 6;
unsigned long past;
const unsigned long time2sec = 2000;

int counterA=0;
int prevValueA=0;

int Perekis = 11;
byte valA; //переменная времени 
byte flagA;
long previousMillisA = 0;

int counterB=0;
int prevValueB=0;

int XLOR = 12;
byte valB; //переменная времени 
byte flagB;
long previousMillisB = 0;


void setup() {
  lcd.begin();
  pinMode(buttonPin, INPUT);
  pinMode(Perekis, OUTPUT);
  pinMode(XLOR, OUTPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, Led = 0);
  digitalWrite(buttonPin, LOW);

}

void loop() {

boolean bs = digitalRead (buttonPin);

if(bs == HIGH && prevValueA==0) {
  prevValueA=1;
  counterA++;
}

if(bs == LOW) {
  prevValueA=0;
}
 lcd.setCursor(0, 0);
 lcd.print("PEREKIS::>"); 
 lcd.setCursor(12, 0);
 lcd.print("(8) ");
 lcd.setCursor(10, 0);
 lcd.print(counterA);
  
if (counterA<10)
{
  lcd.setCursor(11, 0);
  lcd.print(" "); 
}
if(counterA==8)
{
 counterA=0;
 previousMillisA = millis();
    flagA=1;
    valA=0;
  }
  if(flagA==1)
  {
    digitalWrite(Perekis,HIGH);
    
  }
  if(counterA<=8)
  {

    if (millis() -previousMillisA >1000)
    { 
      previousMillisA = millis();     
      valA++;                       
    
    }  
  }
  if(valA>=2) 
  { 
    digitalWrite(Perekis,LOW);
    flagA=0;
  }

if(bs == HIGH && prevValueB==0) {
  prevValueB=1;
  counterB++;
}

if(bs == LOW) {
  prevValueB=0;
}
 lcd.setCursor(0, 1);
 lcd.print(" XLOR  ::>"); 
 lcd.setCursor(12, 1);
 lcd.print("(10)");
 lcd.setCursor(10, 1);
 lcd.print(counterB);
  
if (counterB<10)
{
  lcd.setCursor(11, 1);
  lcd.print(" "); 
}
if(counterB==10)
{
 counterB=0;
 previousMillisB = millis();
    flagB=1;
    valB=0;
  }
  if(flagB==1)
  {
    digitalWrite(XLOR,HIGH);
    
  }
  if(counterB<=10)
  {

    if (millis() -previousMillisB >1000)
    { 
      previousMillisB = millis();     
      valB++;                       
    
    }  
  }
  if(valB>=2) 
  { 
    digitalWrite(XLOR,LOW);
    flagB=0;
  }  
 mill = millis();
  btn = digitalRead(buttonPin);
  if ((!btn)&&(past==0)) { /* если кнопка нажата*/
    digitalWrite(ledPin, Led = 1); /*то вкл светодиод*/
    past = mill;
  }
  if (Led & mill - past >= time2sec) {/*если светодиод горит больше 2 сек*/
    digitalWrite(ledPin, Led = 0);/*то выкл*/
  }
   
  
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Кнопка подключена к питанию. Светодиод горит еще 2 сек как кнопку отпустили

/**/
unsigned long mill;
//--------------------------------------
const byte btnPin =/*пин*/2;/*подтянуть к земле*/
bool btn;
const byte ledPin =/*пин*/3;
bool Led;
unsigned long past;
const unsigned long time2sec = 2000;
//-----------main()---------------------------
void setup() {
  pinMode(btnPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, Led = 0);
}
void loop() {
  mill = millis();
  btn = digitalRead(btnPin);
  if (btn) { /* если кнопка нажата*/
    digitalWrite(ledPin, Led = 1); /*то вкл светодиод*/
    past = mill;
  }
  if (Led & mill - past >= time2sec) {/*если светодиод горит больше 2 сек*/
    digitalWrite(ledPin, Led = 0);/*то выкл*/
  }
}
/*Скетч использует 1084 байт (3%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 19 байт (0%) динамической памяти, оставляя 2029 байт для локальных переменных. Максимум: 2048 байт.
*/

 

GKV
Offline
Зарегистрирован: 01.10.2013

Дело в том,что кнопка на удержании,а ЛЕД должен загореться на 2 сек и погаснут при нажатой кнопке.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Не проверял работу

/**/
unsigned long mill;
typedef void (*pDo)();/* тип обработчик*/
//--------------------------------------
enum  {sLedOFF = 0, sLedON, sLedTimeON};
class Cl_Led {
  protected:
    byte pin;
    byte state;
    unsigned long past, time;
    void stand(byte s) {
      state = s;
      past = mill;
      switch (state) {
        case sLedOFF:
          digitalWrite(pin, LOW);
          break;
        case sLedON:
          digitalWrite(pin, HIGH);
          break;
        case sLedTimeON:
          digitalWrite(pin, HIGH);
          break;
      }
    }
  public:
    /*конструктор*/
    Cl_Led(byte p): pin(p) {}
    void init() {
      pinMode(pin, OUTPUT);
      stand(sLedOFF);
    }
    void run() {
      if (state == sLedTimeON && mill - past >= time) stand(sLedOFF);
    }
    void OFF() {
      stand(sLedOFF);
    }
    void ON() {
      stand(sLedON);
    }
    void ON(unsigned long t) {
      time = t;
      stand(sLedTimeON);
    }
};
//--------------------------------------
// класс кнопка подтянута к земле
class Cl_Btn {
  protected:
    byte pin;
    bool btn,  btnOld;
    pDo DoON, DoOFF;
  public:
    /*конструктор*/
    Cl_Btn(byte p, pDo D1, pDo D2)
      : pin(p), DoON(D1), DoOFF(D2) {
    }
    void init() {
      pinMode(pin, INPUT);
      btn = digitalRead(pin);
    }
    void run() {
      btnOld = btn;
      btn = digitalRead(pin);
      if (btn && !btnOld)  DoON();
      if (!btn && btnOld)  DoOFF();
    }
};
//-------компоновка--------------------------------------
Cl_Led Led(/*пин*/3);
const unsigned long time2sec = 2000;
void DoBtn1() {
  Led.ON(time2sec);/*вкл на 2 сек*/
}
void DoBtn2() {
  Led.OFF();
}
Cl_Btn Btn(/*пин*/2,/*обработчик вкл*/DoBtn1,/*обработчик выкл*/DoBtn2);
//-----------main()---------------------------
void setup() {
  Led.init();
  Btn.init();
}
void loop() {
  mill = millis();
  Led.run();
  Btn.run();
}
/*Скетч использует 1368 байт (4%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 30 байт (1%) динамической памяти, оставляя 2018 байт для локальных переменных. Максимум: 2048 байт.
*/

 

GKV
Offline
Зарегистрирован: 01.10.2013

qwone.Огромное спасибо разобрался,два дня сидел с примерами ничего не получалось.Спасибо опять меня выручили.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Из меня очень паршивый учитель-популизатор Так что изчайте как сможете http://arduino.ru/forum/programmirovanie/pomogite-novichku-ochen-prostoi-proekt-muchayus-3-dnya#comment-325365

Или моя тема http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov

 

JonHappy1
Offline
Зарегистрирован: 11.06.2018

а почему не рассматривается вариант защиты на RS-тиггере? 1 корпус ла3 или тм2 - и 2 кнопки без дребезга. добавим типа ла2 и можем использовать вход преывания.

forfrends
Offline
Зарегистрирован: 24.02.2015

Всем привет! Я сделал небольшое видео как решить проблему дребезга кнопок: https://www.youtube.com/watch?v=4KXKQCDh4X4

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Если в наличие есть не простая тактовая кнопка (SPST), а кнопка с полной группой контактов (SPDT), например

        
Без фиксации          С фиксацией

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

Подключаем кнопку по такой схеме

И всё, забудьте о дребезге навсегда. Если кнопка (SW) не нажата (как на схеме), то на пин подаётся LOW, Если нажата - то HIGH.

Если нужно наоборот (поменять HIGH и LOW местами), то заводим на пин не из этой точки, а из симметричной ей слева (с соединения R1, R2 и коллектора Q1).

Резисторы почти любые от 1k/10k до 1М/10М. Если будете делать высокоомное решение, то старайтесь делать дорожки как можно короче. У меня 1М/10М работало даже не макетке. Больше - не пробовал. Если же наоборот, будете делать низкоомное решение, типа 1k/10k, то можно смело выбросить из схемы конденсаторы (хотя, они там по-любому никому не мешают).

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

В принципе, в природе существуют микросхемы, которые это реализуют (обычно на 4 или 2 кнопки), но для одной кнопки такое решение компактнее (если микросхема в DIP). Да и такое решение как-то "теплее и ламповее" - сразу видно, что и как работает.

За идею спасибо dimax!

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

JonHappy1 пишет:

а почему не рассматривается вариант защиты на RS-тиггере?

Потому, что ты не написал про неё.

Теперь вот, как видишь, рассматривается.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ворота пишет:
такое решение как-то "теплее и ламповее"

Не понял, а где тёплость и ламповость?

Учитесь, блин! На любимой хифилитиками всего мира 12AX7

Как видите, работает!!!

(НА ВСЯКИЙ СЛУЧАЙ: схема является шуткой, в протеусе работает, но повторять не рекоммендуется!)

JonHappy1
Offline
Зарегистрирован: 11.06.2018

примерно такая схемка
количество можно увеличить до 8 (ла3 можно заменить на тм2, ла2 можно заменить на любую с нужным числом входов)
по прерывания ситывается и определяется нажатая кнопка
используя ив1 можно сэкономить входы ардуинки и считывать код нажатой кнопки

sadman41
Offline
Зарегистрирован: 19.10.2016

JonHappy1 пишет:

примерно такая схемка
количество можно увеличить до 8 (ла3 можно заменить на тм2, ла2 можно заменить на любую с нужным числом входов)

Использование советской дискретной логики - это такой челлендж или просто сундук старого радиогубителя вскрыли? PCF8574 8 выходов имеет, есть свой INT выход и некий антидребезг даже. Да и навесить их можно пачкой на одну шину.

Kakmyc
Offline
Зарегистрирован: 15.01.2018
byte key(byte Sb){
static unsigned long start_press=0,pressTime=0;
    static boolean pressFlag=0;
    static byte num=0,_num=0,button=0;
    
button=!digitalRead(Sb);//читаем состояние кнопки
	if(!button){num=0;}//если кнопка отпущена, выдаем результат 0
	if(button&&!pressFlag)//если кнопка нажата и флаг опущен
	{pressTime=millis()-start_press;//считаем время нажатия кнопки
		if(millis()-start_press>=1500){//если нажатие больше 1,5 сек
			pressFlag=1;//поднимаем флаг
            num=2;//значение кнопки 2
            pressTime=0;//сбрасываем длительность нажатия
		}
		}
	if(!button){//если кнопка отпущена
   start_press=millis();//постоянно, при отжатой кнопке, приравниваем начала отсчёта старта нажатия к миллис
        pressFlag=0;//опускаем флаг
        }
    
	if(!button&&!pressFlag){//если кнопка и флаг отпущены
		if(pressTime>50&&pressTime<1500)//а время нажатия больше 50мс, но меньше 2сек
		{pressTime=0;//сбрасываем длительность нажатия
            num=1;}//значение кнопки 1
        }
    _num=num;
        num=0;
	return _num;//возвращаем значение кнопки
}

Вот мой вариант обработчика длинного/короткого нажатия кнопки. Выполнен в виде функции. Работает по факту, то есть одно нажатие один сигнал.

Замечания и критику готов выслушать.

//При одиночном вызове в цикле:
if(key()==1){//что то делаем если короткое нажатие;
}
//Или 
if(key()==2){//что то делаем при длинном нажатии;
}
//Обусловлено сбросом флага после каждого опроса

//Если требуется проверить оба сигнала, делаем так:
int myKey=key();
if(key()==1){//что то делаем, если короткое нажатие;
}
if(key()==2){//что то делаем, если длинное нажатие;
}

Или так:

switch (key()){
case 1: //что то делаем по короткому нажатию
break;
case 2://что то делаем по длинному нажатию
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Kakmyc пишет:
Замечания и критику готов выслушать.

Особо не разбирался, но вот это место смутило.

Kakmyc]</p> <p>[quote=Kakmyc пишет:

	{pressTime=millis()-start_press;//считаем время нажатия кнопки
		if(millis()-start_press>=1500){//если нажатие больше 1,5 сек

Почему в строке 10 не использовать только что вычисленную переменную pressTime? Зачем дважды вычислять одно и тоже?

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Можно и так, но тогда менее понятно, как работает код.

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

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

И только сегодня дошло как сбрасывать флаги внутри функции,до этого переменные были глобальные и сбрасывались в основном цикле, поэтому наверное и выложил.

 

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

Отсрочкой вывода одинарного и изменением значения, если во время отсрочки было ещё одно короткое.

 

В целом , думаю 10 байт(10 потому что одна переменная(button) для облегчения записи, можно убрать), на кнопку для такого , дилетанта, как я , вполне нормальный результат.

 

Код вполне рабочий , использую без малого год, нареканий нет

Green
Offline
Зарегистрирован: 01.10.2015

Ну, за год можно было бы и подшаманить. Мой вариант.

#include "key.h"


uint8_t keyExe()
{
  static uint8_t old_key;
  static uint8_t debounce_timer;
  static bool repeat;

  uint8_t key = get_key();
  if (old_key != key) {
    old_key = key;
    debounce_timer = ms2key(DEBOUNCE_TIME);
    repeat = false;
  }
  if (debounce_timer & !--debounce_timer) {
    #if defined FIRST_REP_TIME && defined NEXT_REP_TIME
    if (key) {
      debounce_timer = ms2key(FIRST_REP_TIME);
      if (repeat) {
        debounce_timer = ms2key(NEXT_REP_TIME);
        return key | 1<<REPEAT_BIT;
      }
      repeat = true;
    }
    #endif
    return key;
  }
  return 0;
}

 

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Выделил кнопки в отдельный класс

class btn//создадим класс кнопок
{public://общие функции
 int key(int pin);
private://личные переменные и функции класса
 unsigned long start_press=0;//переменная времени нажатия кнопки
 unsigned long pressTime=0;//переменная длительности нажатия кнопки
 boolean pressFlag=0;//переменная флага нажатия
//переменные состояния/временного состояния/нажатия кнопки
 byte num=0,_num=0,button=0; 
};

//Объекты кнопок создаём так
btn Btn1;

//Вызываем так:
int MyKey=key(int pin);
//Далее в коде используиспользуем переменную MyKey как состояние кнопки.
//Состояние кнопки действительно один цикл программы
//функция класса Btn(обработчик кнопок)
int btn::key(int Sb){ 
button=!digitalRead(Sb);//читаем состояние кнопки
	if(!button){num=0;}//если кнопка отпущена, выдаем результат 0
	if(button&&!pressFlag)//если кнопка нажата и флаг опущен
	{pressTime=millis()-start_press;//считаем время нажатия кнопки
		if(millis()-start_press>=2000){//если нажатие больше 2 сек
			pressFlag=1;//поднимаем флаг
num=2;//значение кнопки 2
pressTime=0;//сбрасываем длительность нажатия
		}
		}
	if(!button){//если кнопка отпущена
 start_press=millis();//сбрасываем время нажатия
pressFlag=0;//опускаем флаг
}

	if(!button&&!pressFlag){//если кнопка и флаг отпущены
		if(pressTime>50&&pressTime<2000)//а время нажатия больше 50мс, но меньше 2сек
		{pressTime=0;//сбрасываем длительность нажатия
num=1;}//значение кнопки 1
}
_num=num;
num=0;
	return _num;//возвращаем значение кнопки
}

 

Kakmyc
Offline
Зарегистрирован: 15.01.2018
    enum BtnState{
RELEASE,
SHORT,
DOUBLE,
LONG};

class btn//создадим класс кнопок
{public://общие функции
 int key(int pin);
private://личные переменные и функции класса
 uint32_t start_press=0;//переменная времени нажатия кнопки
 uint32_t pressTime=0;//переменная длительности нажатия кнопки
 uint32_t double_press;//переменная времени между нажатиями
 boolean pressFlag=0;//переменная флага нажатия
 int16_t press_one;//переменная количества нажатий
//переменные состояния/временного состояния/нажатия кнопки
 byte num=0,_num=0,button=0; 
};




//функция класса Btn(обработчик кнопок)
int btn::key(int Sb){ 
button=!digitalRead(Sb);//читаем состояние кнопки
	if(!button){num=0;}//если кнопка отпущена, выдаем результат 0
	if(button&&!pressFlag)//если кнопка нажата и флаг опущен
	{pressTime=millis()-start_press;//считаем время нажатия кнопки
		if(pressTime>=1500){//если длительность нажатия больше 1,5 сек
			pressFlag=1;//поднимаем флаг
num=LONG;//значение кнопки long
pressTime=0;//сбрасываем длительность нажатия
		}
		}
	if(!button){//если кнопка отпущена
 start_press=millis();//сбрасываем время нажатия
pressFlag=0;//опускаем флаг
}

	if(!button&&!pressFlag){//если кнопка и флаг отпущены
		if(pressTime>50&&pressTime<1500)//а время нажатия больше 50мс, но меньше 1,5сек
		{press_one++;//увеличиваем счетчик количества нажатий
 if(press_one>2)press_one=2;//ограничиваем значение счетчика
 pressTime=0;//сбрасываем длительность нажатия
 double_press=millis();//запускаем таймер ожидания следующего нажатия
            }
}
if(press_one){//если было короткое нажатие
if(millis()-double_press>=300){//ждем 0,3сек
pressTime=0;//сбрасываем длительность нажатия
num=press_one;//значение кнопки приравниваем к количеству нажатий
press_one=0;//сбрасываем количество нажатий
            }
        }
_num=num;//для одиночного вывода результата, используем временную переменную
num=0;//обнудяем основную переменную значения кнопки
	return _num;//возвращаем значение кнопки
}

btn Btn1;//создадим обьекты кнопок

void setup(){
    Serial.begin(9600);
   pinMode(3,0x2);
}

void loop(){
    int myBtn=Btn1.key(3);
    
    switch (myBtn){
        case RELEASE :
        break;
        case SHORT: Serial.println("short press");break;
        case DOUBLE: Serial.println("double press");break;
        case LONG :Serial.println("long press");
    }
}

Прикрутил к своему обработчику двойное нажатие.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Это всё цифра, представляет интерес обработчик аналоговых кнопок, особенно если подключаем матричную клавиатуру )))

И набросок к ней )))
 

#define LED 13
#define BUTTON_PIN A0
uint16_t data = 0;
uint16_t button,button_0,button_1,button_2,button_3,button_4;
uint8_t cycle = 8;
uint8_t button_sel = 255;
uint8_t flag_button = 0;
uint8_t a_button = 1;
unsigned long led_millis;

void setup() {
Serial.begin(9600);
pinMode(LED,OUTPUT);
digitalWrite(LED,HIGH);
}

/***************** FUNCTION ******************/

void setaRelay(){
  if (flag_button == 1 && millis()-led_millis >=200 && ((button <855) || (button > 900))){ // кнопка отжата
      delay(20);
      flag_button = 0;
  }
}

void readButtons(){
  uint8_t y=0;
  do{
  button_0 = analogRead(BUTTON_PIN);
  button = (button_0 + button_1 + button_2 + button_3 + button_4)/5;
  button_4 = button_3;
  button_3 = button_2;
  button_2 = button_1;
  button_1 = button_0;
  y++;
  } while(y < cycle);
  y = 0;

if (((button >= 35) && (button < 70)) && ((button_1 >= 35) && (button_1 < 70)))   // 1 - button selected
  {
   button_sel = 1;
   flag_button = 1;
  } else
  if (((button >= 75) && (button < 110)) && ((button_1 >= 75) && (button_1 < 110)))   // 2 - button selected    
   {
     button_sel = 2;
     flag_button = 1;
    } else
       if (((button >= 115) && (button < 150)) && ((button_1 >= 115) && (button_1 < 150)))  // 3 - button selected      
        {
       button_sel = 3;
       flag_button = 1;
      } else
       if (((button >= 180) && (button < 220)) && ((button_1 >= 180) && (button_1 < 220)))   // 4 - button selected
        {
         button_sel = 4;
         flag_button = 1;
        } else
        if (((button >= 290) && (button < 330)) && ((button_1 >= 290) && (button_1 < 330)))    // 5 - button selected
           {
           button_sel = 5;
           flag_button = 1;
          } else
          if (((button >= 390) && (button < 450)) && ((button_1 >= 390) && (button_1 < 450)))    // 6 - button selected
             {
             button_sel = 6;
             flag_button = 1;
            } else
            if (((button >= 530) && (button < 580)) && ((button_1 >= 530) && (button_1 < 580)))    // 7 - button selected
               {
               button_sel = 7;
               flag_button = 1;
              } else
              if (((button >= 675) && (button < 720)) && ((button_1 >= 675) && (button_1 < 720)))    // 8 - button selected
                 {
                 button_sel = 8;
                 flag_button = 1;
                } else
                if (((button >= 770) && (button < 810)) && ((button_1 >= 770) && (button_1 < 810)))    // 9 - button selected
                   {
                   button_sel = 9;
                   flag_button = 1;
                 } else
                   if (((button >= 855) && (button < 900)) && (flag_button == 0) &&((button_1 >= 855) && (button_1 < 900)))    // "*" - LED is ON/OFF 
                    {
                    digitalWrite(LED,!digitalRead(LED));
                    led_millis = millis();
                    //Serial.println(button_1);
                    button_sel = 10;
                    flag_button = 1;                    
                    } else
                      if (((button >= 900) && (button < 946)) && ((button_1 >= 900) && (button_1 < 946)))   // 0 - button selected
                      {
                         button_sel = 0;
                         flag_button = 1;
                        } else
                          if (((button >= 946) && (button < 1023)) && ((button_1 >= 946) && (button_1 < 1023))) // # - button selected
                          {
                            button_sel = 11;
                            flag_button = 1;
                          }
} // END readButton



void loop() {
readButtons();
if(flag_button && ((button <855) || (button > 900))){
  flag_button = 0;
  Serial.print("Button - ");
    Serial.println(button_sel);
  }
    delay(200);
    setaRelay();
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

qwone пишет:

Гладко было на бумаге в протеусе, да забыли про овраги приколы . А по ним ходить на нем работать.

Там матрица не просто матрица, матрица с приоритетами однако, можно нажимать по две кнопки, верхняя будет в приоритете и, показания с кнопки не убегают )))

Я даже клавиатурку достал из загашника, хочется в железе посмотреть, плёночная с алиэкспресса

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

qwone пишет:

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

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

#define LED 13
#define BUTTON_PIN A0
uint16_t data = 0;
uint16_t button,button_0,button_1,button_2,button_3,button_4;
uint8_t cycle = 8;
uint8_t button_sel = 255;
uint8_t flag_button = 0;
uint8_t a_button = 1;
unsigned long led_millis;

void setup() {
Serial.begin(9600);
pinMode(LED,OUTPUT);
digitalWrite(LED,HIGH);
}

/***************** FUNCTION ******************/

void setaRelay(){
  if (flag_button == 1 && millis()-led_millis >=200 && button == 0 /* ((button <855) || (button > 900))*/){ // кнопка отжата
      delay(20);
      flag_button = 0;
  }
}

void readButtons(){
  uint8_t y=0;
  do{
  button_0 = analogRead(BUTTON_PIN);
  button = (button_0 + button_1 + button_2 + button_3 + button_4)/5;
  button_4 = button_3;
  button_3 = button_2;
  button_2 = button_1;
  button_1 = button_0;
  y++;
  } while(y < cycle);
  y = 0;

if (((button >= 35) && (button < 70)) && ((button_1 >= 35) && (button_1 < 70)))   // 1 - button selected
  {
   button_sel = 1;
   flag_button = 1;
  } else
  if (((button >= 75) && (button < 110)) && ((button_1 >= 75) && (button_1 < 110)))   // 2 - button selected    
   {
     button_sel = 2;
     flag_button = 1;
    } else
       if (((button >= 115) && (button < 150)) && ((button_1 >= 115) && (button_1 < 150)))  // 3 - button selected      
        {
       button_sel = 3;
       flag_button = 1;
      } else
       if (((button >= 180) && (button < 220)) && ((button_1 >= 180) && (button_1 < 220)))   // 4 - button selected
        {
         button_sel = 4;
         flag_button = 1;
        } else
        if (((button >= 290) && (button < 330)) && ((button_1 >= 290) && (button_1 < 330)))    // 5 - button selected
           {
           button_sel = 5;
           flag_button = 1;
          } else
          if (((button >= 390) && (button < 450)) && ((button_1 >= 390) && (button_1 < 450)))    // 6 - button selected
             {
             button_sel = 6;
             flag_button = 1;
            } else
            if (((button >= 530) && (button < 580)) && ((button_1 >= 530) && (button_1 < 580)))    // 7 - button selected
               {
               button_sel = 7;
               flag_button = 1;
              } else
              if (((button >= 675) && (button < 720)) && ((button_1 >= 675) && (button_1 < 720)))    // 8 - button selected
                 {
                 button_sel = 8;
                 flag_button = 1;
                } else
                if (((button >= 770) && (button < 810)) && ((button_1 >= 770) && (button_1 < 810)))    // 9 - button selected
                   {
                   button_sel = 9;
                   flag_button = 1;
                 } else
                   if (((button >= 855) && (button < 900)) && (flag_button == 0) &&((button_1 >= 855) && (button_1 < 900)))    // "*" - LED is ON/OFF 
                    {
                    digitalWrite(LED,!digitalRead(LED));
                    led_millis = millis();
                    //Serial.println(button_1);
                    button_sel = 10;
                    flag_button = 1;                    
                    } else
                      if (((button >= 900) && (button < 946)) && ((button_1 >= 900) && (button_1 < 946)))   // 0 - button selected
                      {
                         button_sel = 0;
                         flag_button = 1;
                        } else
                          if (((button >= 946) && (button < 1023)) && ((button_1 >= 946) && (button_1 < 1023))) // # - button selected
                          {
                            button_sel = 11;
                            flag_button = 1;
                          }
} // END readButton



void loop() {
readButtons();
if(flag_button && button == 0 /*((button <855) || (button > 900))*/){
  flag_button = 0;
  Serial.print("Button - ");
    Serial.println(button_sel);
  }
   // delay(200);
    setaRelay();
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

bwn да я в курсе сейчас для ua6em выложу код, потом чиканешь. Ну нафига городить такой паровоз под аналоговые кнопки . Вот под LCD Key Shield и никагого гемороя. посто масштабируется и все

/*LCD Key Shield*/
//Cl_analog.h--------------------------------
typedef void (*pDo)() ;// тип -функция обработчик
class Cl_analog {
    const byte pin;
    int  data_next, data, data_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    pDo Do_Right , Do_Up, Do_Down, Do_Left , Do_Select;
    Cl_analog()=delete;
    Cl_analog(byte _pin);
    /**/
    void init();
    void run();
};
//Cl_analog.cpp--------------------------------
Cl_analog::Cl_analog(byte _pin): pin(_pin) {}
void Cl_analog::init() {
  data = analogRead (pin);
  Do_Right = Do_Up = Do_Down = Do_Left = Do_Select = [] {};
}
void Cl_analog::run() {
  data_next = analogRead (pin);
  if (! bounce && data != data_next) { // если прошел фронт изм на выводн
    bounce = 1;                              // выставить флаг
    past = millis();                         // сделать временую засветку
  }
  else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
    bounce = 0;                                // то снять флаг
    data_old = data ;
    data = data_next ;
    if (data_old > 1000) {
      Serial.println(data);
      if (data < 110) Do_Right();
      else if (data < 200) Do_Up();
      else if (data < 400) Do_Down();
      else if (data < 600) Do_Left();
      else if (data < 800) Do_Select() ;
    }
  }
}
Cl_analog Keys(/*пин*/A0);
//---------------Компоновка----------------------------------------------
#include <LiquidCrystal.h>
LiquidCrystal lcd(/*RS*/8,/*Enable*/9,/*DB4*/4,/*DB5*/5,/*DB6*/6,/*DB7*/7);
void lcd_init() {
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("LCD Key Shield");
  lcd.setCursor(0, 1);
  lcd.print("Press Key:None  ");
}
//----------------------------------------
void setup() {
  Serial.begin(9600);
  lcd_init();
  Keys.init();
  Keys.Do_Right = [] {
    lcd.setCursor(10, 1);
    lcd.print ("Right ");
  };
  Keys.Do_Up = [] {
    lcd.setCursor(10, 1);
    lcd.print ("Up    ");
  };
  Keys.Do_Down = [] {
    lcd.setCursor(10, 1);
    lcd.print ("Down  ");
  };
  Keys.Do_Left = [] {
    lcd.setCursor(10, 1);
    lcd.print ("Left  ");
  };
  Keys.Do_Select = [] {
    lcd.setCursor(10, 1);
    lcd.print ("Select");
  };
}
void loop() {
  Keys.run();
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Предложенное аппаратное решение (матрица) интересно тем, что реализуется защита от одновременного нажатия нескольких кнопок, да, теоретически там может быть 4096 состояний, но на выходе имеем практически всего 12 опорных сигналов для детектирования их посредством АЦП, в твоем коде защита реализуется за счёт очень большого окна, в приведённом аппаратном решении - красиво )))

PS аппаратное решение нагуглил, понравилось ;-)
 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

один аналоговый выход. 250р 

https://aliexpress.ru/item/32635207928.html

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

один аналоговый выход. 250р 

https://aliexpress.ru/item/32635207928.html

Отличные кнопки, а если использовать библиотеку Павла, то теоретически можно подключить 21 кнопку )))

bwn
Offline
Зарегистрирован: 25.08.2014

ВСЕМ НЕОФИТАМ, ЖАЖДУЩИМ ЗАДАТЬ ВОПРОС!
ДАННАЯ ТЕМА НЕ ПРЕДНАЗНАЧЕНА ДЛЯ ОБУЧЕНИЯ ВАС ОСНОВАМ ЯЗЫКА И ПРИЕМАМ СОВОКУПЛЕНИЯ ДВУХ И БОЛЕЕ СКЕТЧЕЙ. В ТЕМЕ РАССМАТРИВАЮТСЯ СПОСОБЫ ПОДКЛЮЧЕНИЯ КНОПОК, ПОДАВЛЕНИЕ ДРЕБЕЗГА, ФИКСАЦИЯ СОБЫТИЙ.
ВСЕ ВЫХОДЯЩЕЕ ЗА ОЗНАЧЕННЫЕ РАМКИ К РАБОТЕ С КНОПКАМИ НЕ ОТНОСИТСЯ И ОБСУЖДАЕТСЯ ВО ВНОВЬ СОЗДАННЫХ ИЛИ ПОДХОДЯЩИХ ТЕМАХ.
ОТВЕТЫ НА ОСНОВНЫЕ ВОПРОСЫ, ПО КНОПКАМ, МОЖНО НАЙТИ НА ПЕРВЫХ ПЯТИ СТРАНИЦАХ ТЕМЫ, УЧИТЕСЬ ЧИТАТЬ.

Можете так же ознакомится с "Сагой окнопках".
Для желающих "быстрого" результата "Титановый велосипед".

Если кто то желает добавить свои способы, варианты, описание библиотек, вэлком.

Обзор от Dimax по аппаратному подавлению дребезга.

ЕЩЕ РАЗ ВОПРОШАЮЩИМ: ВСЕ БАНАЛЬНЫЕ ВОПРОСЫ УДАЛЯЮТСЯ БЕЗ ОБСУЖДЕНИЯ.

P/S если кто то считает, что его права нарушены, вэлком в пост.

P/P/S ЕЩЕ РАЗ, КТО ЖЕЛАЕТ ЗАЩИТИТЬ СВОИ ПРАВА И СВОБОДЫ, ССЫЛКА В ПОСТЕ. ТАМ КРОМЕ ХАМСТВА И ПОЛИТОТЫ НИЧЕГО НЕ УБИРАЮ.

bwn
Offline
Зарегистрирован: 25.08.2014

max2007 пишет:

Модератор: Крайнее предупреждение.

Хотим задать вопрос - создаем тему в "Песочнице", задаем свои вопросы.
Почему? Смотрим пост выше.