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

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 аватар
Онлайн
Зарегистрирован: 25.01.2017

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

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

DetSimen пишет:

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

с чего бы это?

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

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

DetSimen пишет:

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

с чего бы это?

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

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

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

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

bwn пишет:

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

DetSimen пишет:

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

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

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 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;//возвращаем значение кнопки
}

 

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

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

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

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

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

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

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

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

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");
    }
}

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