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

Kolaha
Offline
Зарегистрирован: 29.12.2016

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

unsigned long Time=0;

void setup() {
  pinMode(13, OUTPUT);
  pinMode(12, INPUT);
  digitalWrite(12, HIGH); 
}

void loop() {
  if (!Time&&!digitalRead(12)) Time=millis();
  if (digitalRead(12)) Time=0;
  if (Time&&(millis()-Time >5000)&&!digitalRead(12)) {
    digitalWrite(13,!digitalRead(13));
    Time=0;
  }
}

 

deftvk
Offline
Зарегистрирован: 27.05.2016

А вот статья с теоретическими раскладками, расчетами, вариантами подключения нескольких кнопок к одному аналоговому входу Arduino - http://codius.ru/articles/221. Там же механизм отслеживания нажатий по фронту, по спаду. Как раз для новичков все разжевано.

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

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

/*
Принцип кода: короткое нажатие на кнопку 1 вкл авторотации сервы
              короткое нажатие на кнопку 2 выкл авторотации сервы
              длиное нажатие на кнопку 1 медленный поворот направо до упора
              длиное нажатие на кнопку 2 медленный поворот налево до упора
#2 Серва  упр. выв -> 9    (servo_pin)
               +5В -> +5В
               GND -> GND
#3       кнопка  1 -> 2 (btn1_pin) Влево  0 нажата /1 нет
#4       кнопка  2 -> 3 (btn2_pin) Вправо 0 нажата /1 нет
*/
// #2
#include <Servo.h>
Servo servo;
const int servo_pin = 9   ;// нога сервы
const int angle_min = 0   ;// 0   угол сервы
const int angle_max = 180 ;// 180 угол сервы
int angle = angle_min     ;// angle_min..angle_max угол сервы
const int angle_step = 2  ;// шаг поворота сервы
bool auto_rotation   = 0  ;// автоповорот 1 -включен / 0 -выключен
bool dir = 0                ; // направление вращение автоповорота   0 -влево / 1 -вправо
// #3
// короткое нажатие автоповорот вкл
const int btn1_pin = 2; // вывод кнопки
bool btn1, btn1_old; // значение на кнопке без дребезга, тоже но стар значение
bool bounce_btn1 = 0; // антидребезговый флаг
const uint32_t const_time_btn1 = 200  ; // константа длительности нажатия ниже короткое нажатие выше длиное,миллисек
// #4
// короткое нажатие автоповорот выкл
const int btn2_pin = 3; // вывод кнопки
bool btn2, btn2_old; // значение на кнопке без дребезга, тоже но стар значение
bool bounce_btn2 = 0; // антидребезговый флаг
const uint32_t const_time_btn2 = 200  ; // константа длительности нажатия ниже короткое нажатие выше длиное,миллисек
void setup() {
  // #2
  servo.attach(servo_pin)       ; // подключить серву
  servo.write(angle);           ; // серву установить на нужный угол
  // #3
  pinMode(btn1_pin, INPUT_PULLUP); // подключить кнопку 1 с подтяжкой
  btn1 = digitalRead(btn1_pin);
  // #4
  pinMode(btn2_pin, INPUT_PULLUP); // подключить кнопку 1 с подтяжкой
  btn2 = digitalRead(btn2_pin);

}

void loop() {
  //#2  200 миллисекунд вычислит. поток 2
  static uint32_t past_2  = 0 ;
  static uint32_t past1_3 = 0 ; // перенесена из потока #3 время начало нажатия кнопки 1
  static uint32_t past1_4 = 0 ; // перенесена из потока #4 время начало нажатия кнопки 2
  if (millis() - past_2 >= 100) {
    past_2 = millis() ;
    if (! btn1 &&  millis() - past1_3 > const_time_btn1  && btn2) { // если долго нажата кнопка 1, а кнопка 2 отпущена
      dir = 1;
      auto_rotation = 0;
      angle += angle_step;
      if (angle > angle_max) {
        angle -= angle_step;
      }
      servo.write(angle);
    }
    if (btn1 && ! btn2 &&  millis() - past1_4 > const_time_btn2 ) { // если долго нажата кнопка 2, а кнопка 1 отпущена
      dir = 0;
      auto_rotation = 0;
      angle -= angle_step;
      if (angle < angle_min) {
        angle += angle_step;
      }
      servo.write(angle);
    }
    if (auto_rotation) { // если автоповорот включен
      if (dir) {  // если вращение направо
        angle += angle_step;
        if (angle + angle_step > angle_max)
          dir = 0;
      }
      else {      // если вращение налево
        angle -= angle_step;
        if ( angle - angle_step < angle_min) {
          dir = 1;
        }
      }
      servo.write(angle);
    }
  }
  // #3
  static uint32_t past_3 = 0 ;
  if (! bounce_btn1 && btn1 != digitalRead(btn1_pin)) { // если прошел фронт изм на выводн
    bounce_btn1 = 1;                                 // выставить флаг
    past_3 = millis();                          // сделать временую засветку
  }
  else if ( bounce_btn1 && millis() - past_3 >= 40 ) { // если прошло антидребезговое время
    bounce_btn1 = 0;      // то снять флаг
    btn1_old = btn1;
    btn1 = digitalRead(btn1_pin) ; // прочитать реальное значение на выводе
    if (btn1_old && ! btn1) {      // если обнаружилось что это было нажатие
      past1_3 = millis();
    }
    if (! btn1_old && btn1 && millis() - past1_3 < const_time_btn1)  //если это было короткое отжатие кнопки 1
      auto_rotation = 1; // выключить авторотацию;
  }
  // #4
  static uint32_t past_4 = 0 ;
  if (! bounce_btn2 && btn2 != digitalRead(btn2_pin)) { // если прошел фронт изм на выводн
    bounce_btn2 = 2;                                 // выставить флаг
    past_4 = millis();                          // сделать временую засветку
  }
  else if ( bounce_btn2 && millis() - past_4 >= 40 ) { // если прошло антидребезговое время
    bounce_btn2 = 0;      // то снять флаг
    btn2_old = btn2;
    btn2 = digitalRead(btn2_pin) ; // прочитать реальное значение на выводе
    if (btn2_old && ! btn2) {      // если обнаружилось что это было нажатие
      past1_4 = millis(); // зафиксировать время начала нажатия
    }
    if (! btn2_old && btn2 && millis() - past1_4 < const_time_btn2 ) //если это было короткое отжатие кнопки 2
      auto_rotation = 0; // выключить авторотацию;
  }
}

 

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

digitalWrite(13,analogRead(14));

u_37df9e9851cdd1f9422b498a1528ceea_800.g

Meren
Offline
Зарегистрирован: 15.01.2017

Доброго утра всем!

Уважаемые , помогите с кодом, пожалуйста , не сочтите ленивым!

Есть ардуинка уно + модуль реле 4шт. + две нефиксируемой кнопки.

Первая кнопка при нажатии может включить и отключить реле, вторая кнопка при нажатии может только отключать реле.

П.С. реле используется только одно.

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

Ну задача очень простая вот скетч в папке https://yadi.sk/d/oYJVN7jO397Xyf

А вот код главной части. Тем более и проблема с дребезгом решена 

/* to_Meren.ino
  #1 реле     ->2
  #2 кнопка 1 ->3
  #3 кнопка 2 ->4
*/
//#1 реле
#include "Cl_relay.h"
#define RELAY1_PIN 2
Cl_relay Relay1(RELAY1_PIN, 0); // (пин,логика) /создать по времени отключ реле на пине 2
//#2 кнопка 1
#include "Cl_press_btn.h"
#define BTN1_PIN 3
Cl_press_btn Btn1(BTN1_PIN); // создать кнопку на пине 3
void func_1(void) {
  Relay1.invert();
}
//#3 кнопка 2
#define BTN2_PIN 4
Cl_press_btn Btn2(BTN2_PIN); // создать кнопку на пине 4
void func_2(void) {
  Relay1.OFF();
}
void setup() {
  //#1 реле
  Relay1.setup();
  //#2 кнопка 1
  Btn1.setup();
  //#3 кнопка 2
  Btn2.setup();
}

void loop() {
  //#1 реле
  Relay1.loop();
  //#2 кнопка 1
  Btn1.loop(& func_1);
  //#3 кнопка 2
  Btn2.loop(& func_2);

}

 

Meren
Offline
Зарегистрирован: 15.01.2017

Благодарю!

Пины 2,3,4 - это цыфровые выходы на ардуино ?

точнее пин 2 - цыфровой выход на реле 

пин 3 и 4 цыфровой выход, но в данном случае  они являются цыфровыми входами для кнопок. Так ? 

 

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

Ну да. В примере 2 это цифровой выход. А 3,4 цифровой вход. Конечно  вы можете прописать свои.Расматривайте этот скетч, как средство очень быстро написать программу для кнопок и реле. 

Скачай архив с яндекс диска и распакуй. Это и есть полная программа.

Meren
Offline
Зарегистрирован: 15.01.2017

Скетч проверен, и залит.

А что делать с внешними подтягивающими резисторами для кнопок? выходит что они здесь не нужны ?

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

Нет, не нужны. Я прописал их в программе. Вот только кнопки подсоединять вывод и земля. Реле и так и так.

Cl_relay Relay1(RELAY1_PIN, 0);  // <-- только в одном случае 0, в другом 1 и все.

 

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

Этот класс очень поможет обладателям  Nextion и аналогичным устройствам Полный скетч здесь  https://yadi.sk/d/8m8Un8ZV3G8KBs

Головной выкладываю 

/*Class_Serial_strbtn.ino 
  принцип кода: Написать правильное слово и выполнится нужное действие
*/
#include "Cl_Serial_str_btn.h"
String command_1 = "up";
String command_2 = "down";
String command_3 = "left";
String command_4 = "right";
String command_5 = "select";
void Do_1() {
  Serial.println("Press Do_up");
};
void Do_2() {
  Serial.println("Press Do_down");
};
void Do_3() {
  Serial.println("Press Do_left");
};
void Do_4() {
  Serial.println("Press Do_right");
};
void Do_5() {
  Serial.println("Press Do_select");
};
Cl_Serial_str_btn Serial_str_btn(& command_1, &command_2, &command_3, &command_4, &command_5,
                                 & Do_1, &Do_2, &Do_3, &Do_4, &Do_5);
void setup() {
  Serial.begin(9600);
  Serial_str_btn.setup();
}

void loop() {
  Serial_str_btn.loop();
}

 

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

внезапно кому интересно будет - матрица на одном аналоговом пине

http://www.avr-asm-tutorial.net/avr_en/keypad/keyboard.html

adc-matrix.gif

Las42
Offline
Зарегистрирован: 25.05.2017

Здравствуйте а прошу помощи как новечок в ардуино!делаю планшет в машину nexus7, подключил  arduino micro к инкодеру для управления громкостью а можно ли ещё к этой же ардуино подключить кнопки на руле и задать им функции?

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

Я не претендую на открые нового. выкладываю для однокомление . Скетч рабочий.Пакет здесь https://yadi.sk/d/7BoOge953JWQux

Головной файл 

/* HelloWorld.ino 
  LCD1602  I2C(0x27/0x3F) <== Wire
  LCD2004  I2C(0x3F/0x27) <== Wire
*/
#include <Wire.h>
#include "CL_Lcd_I2C.h"
//-----------------class Cl_sys---------------------------
class Cl_sys {
    CL_Lcd_I2C *Start_Lcd_I2C = NULL;
  public:
    Cl_sys() {}
    void Plug(CL_Lcd_I2C * obj) {
      obj->pnt = Start_Lcd_I2C;
      Start_Lcd_I2C = obj;
    }
    void setup() {
      Start_Lcd_I2C->setup();
    }
    void loop() {
      Start_Lcd_I2C->loop();
    }
} Sys;
//--------------------------------------------
CL_Lcd_I2C lcd (0x27, 16, 2) ; // 0x3F/0x27
CL_Lcd_I2C lcd1(0x3F, 20, 4) ; // 0x3F/0x27

void setup() {
  Sys.Plug(&lcd);
  Sys.Plug(&lcd1);

  Sys.setup();
  // Отправка сообщения в LCD и LCD1
  lcd.print("   Hello, world!");
  lcd.setCursor(0, 1);
  lcd.print("Arduino LCD I2C 2017");

  lcd1.print("   Hello, world!");
  lcd1.setCursor(0, 1);
  lcd1.print("Arduino LCD I2C 2017");
}

void loop() {
  Sys.loop();
}

 

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

Есть такая программа https://geekelectronics.org/arduino/podklyuchenie-lcd-keypad-shield-k-arduino.html

Но мне она не очень нравится поэтому предлагаю свой аналог. Пакет здесь https://yadi.sk/d/-WBXfL8W3JX5Qw

/* Class_Lcd.ino
*/
#include "CL_Lcd.h"
//--------------------class Cl_an_btn5------------------------
class Cl_an_btn5 {
    byte pin ; // нога аналог клавиатуры
    void (*Do_right)(), (*Do_up)(), (*Do_down)(), (*Do_left)(), (*Do_select)();
    byte read() {
      const int Right  =  60; // ниже = нажата кнопка  Right
      const int Up     = 200; // ниже = нажата кнопка  Up
      const int Down   = 400; // ниже = нажата кнопка  Down
      const int Left   = 600; // ниже = нажата кнопка  Left
      const int Select = 800; // ниже = нажата кнопка  Select
      static int a ;
      a = analogRead(pin);
      if (a < Right) return 1;
      else if (a < Up) return 2;
      else if (a < Down) return 3;
      else if (a < Left) return 4;
      else if (a < Select) return 5;
      else return 0;
    }
    byte abtn, abtn_old; // старый и новый номер нажатой клавиши
    bool bounce_abtn = 0; // антидребезговый флаг
    uint32_t past = 0 ; // временной отчет
  public:
    // указатель на следующий элемент
    Cl_an_btn5 *pnt = NULL;
    // конструктор
    Cl_an_btn5(byte _pin, void (* _Do_right)(), void (* _Do_up)(), void (* _Do_down)(), void (* _Do_left)(), void (* _Do_select)()):
      pin(_pin), Do_right(_Do_right), Do_up( _Do_up), Do_down(_Do_down), Do_left(_Do_left), Do_select(_Do_select) {}
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      abtn = read() ; // прочитать реальное значение на выводе
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (! bounce_abtn && abtn != read()) { // если прошел фронт изм на выводн
        bounce_abtn = 1;                     // выставить флаг
        past = millis();                     // сделать временую засветку
      }
      else if ( bounce_abtn && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce_abtn = 0;      // то снять флаг
        abtn_old = abtn ;
        abtn = read() ; // прочитать реальное значение на выводе
        if (abtn_old == 0) {
          if (abtn == 1) Do_right()  ;
          if (abtn == 2) Do_up()     ;
          if (abtn == 3) Do_down()   ;
          if (abtn == 4) Do_left()   ;
          if (abtn == 5) Do_select() ;
        }
      }
    }
};
//-----------------class Cl_sys---------------------------
class Cl_sys {
    CL_Lcd *Start_Lcd = NULL;
    Cl_an_btn5 *Start_an_btn5 = NULL;
  public:
    Cl_sys() {}
    void Plug(CL_Lcd * obj) {
      obj->pnt = Start_Lcd;
      Start_Lcd = obj;
    }
    void Plug(Cl_an_btn5 * obj) {
      obj->pnt = Start_an_btn5;
      Start_an_btn5 = obj;
    }
    void setup() {
      Start_Lcd->setup();
      Start_an_btn5->setup();
    }
    void loop() {
      Start_Lcd->loop();
      Start_an_btn5->loop();
    }
} Sys;
//--------------------------------------------------------------------------
// создать lcd 16x2
CL_Lcd lcd(16, 2);
void Do_right () {
  lcd.setCursor(10, 1);
  lcd.print ("Right ");
}
void Do_up    () {
  lcd.setCursor(10, 1);
  lcd.print ("Up    ");
}
void Do_down  () {

  lcd.setCursor(10, 1);
  lcd.print ("Down  ");
}
void Do_left  () {
  lcd.setCursor(10, 1);
  lcd.print ("Left  ");
}
void Do_select() {
  lcd.setCursor(10, 1);
  lcd.print ("Select");
}
Cl_an_btn5 A_Btn(A0, Do_right, Do_up, Do_down, Do_left , Do_select);

void setup() {
  Sys.Plug(&lcd);
  // (RS=8,Enable=9,D4=4,D5=5,D6=6,D7=7,R/W=GND,VSS=GND,VCC==5V, lcd(пин3)на подстроичник)
  lcd.connect(8, 9, 4, 5, 6, 7); // ставьте до Sys.setup();
  Sys.Plug(&A_Btn);
  Sys.setup();
  lcd.setCursor(0, 0);
  lcd.print("LCD Key Shield");
  lcd.setCursor(0, 1);
  lcd.print("Press Key:");
}

void loop() {
  Sys.loop();
}

 

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

Вот еще мой аналог переделаный из этого. http://zelectro.cc/nokia5110_module_arduino

Мой пакет https://yadi.sk/d/JOWvYoXj3JXWMF головной файл 

/* Class_PCD8544.ino
  Serial clock out (SCLK)   --> pin 3
  Serial data out (DIN)     --> pin 4
  Data/Command select (D/C) --> pin 5
  LCD chip select (CS)      --> pin 6
  LCD reset (RST)           --> pin 7
*/
#include "Adafruit_GFX.h"
#include "Cl_PCD8544.h"
const static unsigned char PROGMEM logoBmp[] = {
  B11111111, B11111111, B10000000,
  B11111111, B11111111, B10000000,
  B11111111, B11111111, B10000000,
  B11111100, B00000011, B10000000,
  B11111000, B00000001, B10000000,
  B11111100, B00000011, B10000000,
  B11111111, B11000011, B10000000,
  B11111111, B10000111, B10000000,
  B11111111, B10001111, B10000000,
  B11111111, B00001111, B10000000,
  B11111110, B00011111, B10000000,
  B11111110, B00011111, B10000000,
  B11111100, B00111111, B10000000,
  B11111100, B01111111, B10000000,
  B11111000, B00000011, B10000000,
  B11111000, B00000001, B10000000
};
//--------------------class Cl_AAA------------------------
class Cl_AAA {
    uint32_t time;
    uint32_t past = 0;
    void (*Do)();
  public:
    // указатель на следующий элемент
    Cl_AAA *pnt = NULL;
    // конструктор
    Cl_AAA(uint32_t _time, void (*_Do)()): time(_time), Do(_Do) {}
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (millis() - past > time) {
        past = millis();
        Do();
      }
    }
};
//-----------------class Cl_sys---------------------------
class Cl_sys {
    Cl_PCD8544 *Start_PCD8544 = NULL;
    Cl_AAA *StartAAA = NULL;
  public:
    Cl_sys() {}
    void Plug(Cl_PCD8544 * obj) {
      obj->pnt = Start_PCD8544;
      Start_PCD8544 = obj;
    }
    void Plug(Cl_AAA * obj) {
      obj->pnt = StartAAA;
      StartAAA = obj;
    }
    void setup() {
      Start_PCD8544->setup();
      StartAAA     ->setup();
    }
    void loop() {
      Start_PCD8544->loop();
      StartAAA     ->loop();
    }
} Sys;
//--------------------------------------------------------------------------
Cl_PCD8544 display = Cl_PCD8544(3, 4, 5, 6, 7); // подключить модуль Nokia5110
void Do_step() {
  static byte var = 0;
  ++var;
  switch (var) {
    case 1: display.clearDisplay(); // Очищаем дисплей
      Serial.println(var);
      break;
    case 2: // Рисуем несколько пикселей (точек)
      Serial.println(var);
      display.drawPixel(0, 0, BLACK);
      display.drawPixel(1, 1, BLACK);
      display.drawPixel(2, 2, WHITE); // Посередине белый пиксель
      display.drawPixel(3, 3, BLACK);
      display.drawPixel(4, 4, BLACK);
      display.display();
      break;
    case 3: display.clearDisplay();
      Serial.println(var);
      break;
    case 4:// Рисуем диагональ
      Serial.println(var);
      display.drawLine(0, LCDHEIGHT - 1, LCDWIDTH, 0, BLACK); // x0, y0, x1, y1, color
      break;
    case 5: display.clearDisplay();
      break;
    case 6: // Для рисования вертикальных и горизонтальных линий лучше использовать
      //   более быстрые функции
      display.drawFastVLine(LCDWIDTH / 2, 0, LCDHEIGHT, BLACK); // x, y, h, color
      display.drawFastHLine(0, LCDHEIGHT / 2, LCDWIDTH, BLACK); //x, y, w, color
      break;
    case 7: display.clearDisplay();
      break;
    case 8:// Рисуем прямоугольник
      display.drawRect(LCDWIDTH / 4, LCDHEIGHT / 4, LCDWIDTH / 2, LCDHEIGHT / 2, BLACK); // x, y, w, h, color
      break;
    case 9: display.clearDisplay();
      break;
    case 10: // Рисуем закрашенный прямоугольник
      display.fillRect(LCDWIDTH / 4, LCDHEIGHT / 4, LCDWIDTH / 2, LCDHEIGHT / 2, BLACK); // x, y, w, h, color
      break;
    case 11: display.clearDisplay();
      break;
    case 12: display.fillScreen(BLACK); // Закрашиваем весь дисплей
      break;
    case 13: display.clearDisplay();
      break;
    case 14:      // Рисуем окружность
      display.drawCircle(LCDWIDTH / 2, LCDHEIGHT / 2, LCDHEIGHT / 2, BLACK); // x, y, r, color
      break;
    case 15: display.clearDisplay();
      break;
    case 16:      // Рисуем закрашенную окружность
      display.fillCircle(LCDWIDTH / 2, LCDHEIGHT / 2, LCDHEIGHT / 2, BLACK); // x, y, r, color
      break;
    case 17: display.clearDisplay();
      break;
    case 18:  // Рисуем треугольник
      display.drawTriangle(LCDWIDTH / 4, LCDHEIGHT / 4, 3 * LCDWIDTH / 4, LCDHEIGHT / 4, LCDWIDTH / 2, 3 * LCDHEIGHT / 4, BLACK); // x0, y0, x1, y1, x2, y2, color
      break;
    case 19: display.clearDisplay();
      break;
    case 20: // Рисуем закрашенный треугольник
      display.fillTriangle(LCDWIDTH / 4, LCDHEIGHT / 4, 3 * LCDWIDTH / 4, LCDHEIGHT / 4, LCDWIDTH / 2, 3 * LCDHEIGHT / 4, BLACK); // x0, y0, x1, y1, x2, y2, color
      break;
    case 21: display.clearDisplay();
      break;
    case 22: // Рисуем прямоугольник с закругленными углами
      display.drawRoundRect(LCDWIDTH / 4, LCDHEIGHT / 4, LCDWIDTH / 2, LCDHEIGHT / 2, 10, BLACK); // x, y, w, h, r, color
      break;
    case 23: display.clearDisplay();
      break;
    case 24: // Рисуем закрашенный прямоугольник с закругленными углами
      display.fillRoundRect(LCDWIDTH / 4, LCDHEIGHT / 4, LCDWIDTH / 2, LCDHEIGHT / 2, 10, BLACK); // x, y, w, h, r, colordisplay.display();
      break;
    case 25: display.clearDisplay();
      break;
    case 26:  // Рисуем заранее подготовленное лого
      //         Подготовлен массив из 16 пар байтов
      //         каждый байт состоит из 8 битов, соответсвенно
      //         получаем матрицу 16х16 битов, 1-черный цвет, 0-белый цвет
      display.drawBitmap(LCDWIDTH / 2 - 8, LCDHEIGHT / 2 - 8, logoBmp, 24, 16, BLACK); // x, y, logo, w, h, color
      break;
    case 27: display.clearDisplay();
      break;
    default:
      var = 0;
      display.print("Zelectro"); // Выведем текст
  }
  display.display();
}
const uint32_t time_1s = 1000;// время 1 сек
Cl_AAA AAA(time_1s, Do_step); // подключить модуль AAA_1

void setup() {
  Serial.begin(9600);
  Sys.Plug(&display);
  Sys.Plug(&AAA);
  Sys.setup(); // команды к дисплею полжны быть после setup()
  display.setContrast(60);      // Устанавливаем контраст
  display.setTextColor(BLACK);  // Устанавливаем цвет текста
  display.setTextSize(1);       // Устанавливаем размер текста
  display.clearDisplay();       // Очищаем дисплей
  display.display();
}

void loop() {
  Sys.loop();
}

 

mihvlad
Offline
Зарегистрирован: 27.06.2017

Добрый вечер!

Не поможите с написанием кода, нужна простая функция:

есть две кнопки ТТР223 + Arduino + двух канальное реле, нужно при нажатии на кнопку 1 реле срабатывает на 3 сек.  при нажатии на кнопку 2 срабатывает 2 реле на 3 сек., должна быть возможность работать одновременно.

Кроме решения с delay ни чего сделать не могу!

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

mihvlad пишет:

Кроме решения с delay ни чего сделать не могу!

Читать тоже не умеете? Тут на форуме есть чудесная тема, с оригинальным названием: "Блинк без делей"

mihvlad
Offline
Зарегистрирован: 27.06.2017

Спасибо прочитал, попробывал, но это не тот вариант, здесь при нажатии происходит включение при еще нажатии выключение, а мне надо при нажатии включение на несколько секунд (одновибратор).



const int Rele =  9;      // номер пина, подключенного к реле
// Variables will change:
int ReleState = LOW;             // этой переменной устанавливаем состояние реле 
long previousMillis = 0;        // храним время последнего переключения реле

long interval = 1000;           // интервал между включение/выключением реле (1 секунда)

void setup() {
  // задаем режим выхода для порта, подключенного к реле
  pinMode(Rele, OUTPUT);     
  pinMode(8,INPUT); 
  digitalWrite(9,1);
}

void loop()
{
    if (digitalRead(8) == HIGH){
    
    unsigned long currentMillis = millis();
 
  //проверяем не прошел ли нужный интервал, если прошел то
  if(currentMillis - previousMillis > interval) {
    // сохраняем время последнего переключения
    previousMillis = currentMillis;  

    // если реле не вкл, то включаем, и наоборот
    if (ReleState == LOW)
      ReleState = HIGH;
    else
      ReleState = LOW;

    // устанавливаем состояния выхода, чтобы включить или выключить реле
    digitalWrite(Rele, ReleState);
  }

  }
  }

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/* Cl_Mech_BTN.ino
  (Светодиод+R=1кОм)    ардуина
  пин 1 <==> пин 12
  пин 2 <==> GND
    (Светодиод+R=1кОм)    ардуина
  пин 1 <==> пин 11
  пин 2 <==> GND
  кнопка1    ардуина
  пин 1 <==> пин 2 программная подтяжка
  пин 2 <==> GND
    кнопка2    ардуина
  пин 1 <==> пин 3 программная подтяжка
  пин 2 <==> GND
*/
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//----------------Cl_LED------------------------------------------------------------
class Cl_LED {
    byte pin; // нога для подключения светодиода
    bool inv; // 0 светодиод горит при 1/ 1 светодиод горит при 0
    bool stat_ON = 0, led = 0;
    uint32_t time = 500, past = 0;
  public:
    //указатель на следующий компонент
    Cl_LED *pnt_LED;
    //конструктор
    Cl_LED(Cl_Sys *Sys, byte _pin, bool _inv);
    // setup()
    void setup() {
      pinMode(pin, OUTPUT);// подключить светодиод
      led = 0;
      digitalWrite(pin, led ^ inv) ; // погасить светодиод
    }
    // loop()
    void loop() {
      if (stat_ON && millis() - past >= time)OFF();
    }
    // включить светодиод
    void ON() {
      stat_ON = 0;
      led = 1;
      digitalWrite(pin, led ^ inv) ; // зажечь светодиод
    }
    // включить светодиод на время
    void ON( uint32_t _time) {
      time = _time;
      stat_ON = 1;
      past = millis();
      led = 1;
      digitalWrite(pin, led ^ inv) ; // зажечь светодиод
    }
    // выключить светодиод
    void OFF() {
      stat_ON = 0;
      led = 0;
      digitalWrite(pin, led ^ inv) ; // погасить светодиод
    }
};
//----------------Cl_Mech_BTN------------------------------------------------------------
// класс на механич кнопку подкл к кнопке Ардуины.
class Cl_Mech_BTN {
    byte pin; // номер ноги на кнопке
    void (* Do)();// указатель на обработчик
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    //указатель на следующий компонент
    Cl_Mech_BTN *pnt_Mech_BTN;
    //конструктор
    Cl_Mech_BTN(Cl_Sys *Sys, byte _pin, void (* _Do)());
    void setup() {
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    void loop () {
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ;                   // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do();
      }
    }
};
//----------------Cl_Sys------------------------------------------------------------
class Cl_Sys {
  public:
    // указатели на блоки однотипных классов в системе
    Cl_LED * Start_LED = NULL;
    Cl_Mech_BTN * Start_Mech_BTN = NULL;
    void setup() {
      for (Cl_LED *i = Start_LED; i != NULL; i = i->pnt_LED) i->setup();
      for (Cl_Mech_BTN *i = Start_Mech_BTN; i != NULL; i = i->pnt_Mech_BTN) i->setup();
    }
    void loop () {
      for (Cl_LED *i = Start_LED; i != NULL; i = i->pnt_LED) i->loop ();
      for (Cl_Mech_BTN *i = Start_Mech_BTN; i != NULL; i = i->pnt_Mech_BTN)  i->loop ();
    }
};
//-----------------конструкторы классов вход в систему-------------------------------
Cl_LED::Cl_LED(Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv) {
  pnt_LED = Sys->Start_LED;
  Sys->Start_LED = this;
}
Cl_Mech_BTN::Cl_Mech_BTN(Cl_Sys *Sys, byte _pin, void (* _Do)()): pin(_pin), Do(_Do) {
  pnt_Mech_BTN = Sys->Start_Mech_BTN;
  Sys->Start_Mech_BTN = this;
}
//------------------компоновка-------------------------------------------------------
Cl_Sys *Sys = new Cl_Sys();
Cl_LED *LED1 = new Cl_LED(Sys,/*пин*/12,/*инверсия*/0);// создать светодиод LED1
Cl_LED *LED2 = new Cl_LED(Sys,/*пин*/11,/*инверсия*/0);// создать светодиод LED2
void Do_BTN1() {
  LED1->ON(3000);
}
void Do_BTN2() {
  LED2->ON(3000);
}
Cl_Mech_BTN *BTN1 = new Cl_Mech_BTN(Sys,/*пин*/2,/*обработчик*/Do_BTN1);// создать кнопку BTN1
Cl_Mech_BTN *BTN2 = new Cl_Mech_BTN(Sys,/*пин*/3,/*обработчик*/Do_BTN2);// создать кнопку BTN2
//------------------ main()----------------------------------------------------------
void setup() {
  Sys->setup();
}

void loop() {
  Sys->loop();
}

 

mihvlad
Offline
Зарегистрирован: 27.06.2017

Спасибо большое!

Все работает, правда что-бы понять этот код мне нужно еще учиться и учиться! Я думал такая задача решается более простым способом!!!

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

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

mihvlad
Offline
Зарегистрирован: 27.06.2017

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

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

mihvlad пишет:

Добрый вечер!

Не поможите с написанием кода, нужна простая функция:

есть две кнопки ТТР223 + Arduino + двух канальное реле, нужно при нажатии на кнопку 1 реле срабатывает на 3 сек.  при нажатии на кнопку 2 срабатывает 2 реле на 3 сек., должна быть возможность работать одновременно.

Кроме решения с delay ни чего сделать не могу!

Если по простому то то можно так.(Кнопка считается включеной если подать МИНУС)

#define kn1 3
#define kn2 4
#define rele1 5
#define rele2 6
int interval1 = 3000;
unsigned long time_rele1;
unsigned long time_rele2;

void setup() {
  pinMode(kn1, INPUT_PULLUP);
  pinMode(kn2, INPUT_PULLUP);
  pinMode(rele1, OUTPUT);
  pinMode(rele2, OUTPUT);
  //Serial.begin(9600);
}

void loop() {
  if (digitalRead(kn1) == LOW) {
  time_rele1 = millis();
  }
  if (millis() - time_rele1 <= interval1) {
  digitalWrite(rele1, HIGH);
  }
  else digitalWrite(rele1, LOW);

    if (digitalRead(kn2) == LOW) {
    time_rele2 = millis();
    }
  if (millis() - time_rele2 <= interval1) {
  digitalWrite(rele2, HIGH);
  }
  else digitalWrite(rele2, LOW);
  }

 

mihvlad
Offline
Зарегистрирован: 27.06.2017

Спасибо!

Работает,вот с этим я могу разобраться:)

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

Доброго времени суток.Написал скетч на основе примеров.Все вроде работает,но чувствую что-то не так.Суть задачи:при нажатии и удержании кнопки,запускается таймер на 2сек.По окончании 2сек выход отключается,но кнопка остается нажатой.При следующем нажатии цикл должен повториться.Огромная просьба проверить на ошибки.Вот код:

#define ledPin1 A0  //Реле 1 - управление
 
byte valA; //переменная времени 
byte flagA;
long previousMillisA = 0;
 
void setup()    
 
  pinMode(ledPin1, OUTPUT); //иниц выхода
 
void loop() 
 
  //**************************первый таймер **********************************
if(digitalRead(2)==HIGH)//если кнопка нажата ... 
  { 
    flagA=1;
  }
  if(flagA==1)
  {
 
    if (millis() -previousMillisA >1000) 
    { 
      previousMillisA = millis();     
      valA++;                      
      digitalWrite(ledPin1,HIGH); 
    } 
  } 
 
  if(valA>=2) //кол-во секунд((millis() -previousMillisA >1000) 
  { 
    digitalWrite(ledPin1,LOW);
}
  if(digitalRead(2)==LOW)
  { 
    flagA=0;
    digitalWrite(ledPin1,LOW);
    valA=0;
  } 
 
}
vvadim
Offline
Зарегистрирован: 23.05.2012

а вставить код по нормальному тяжко)))

GKV
Offline
Зарегистрирован: 01.10.2013
#define ledPin1 A0  //Реле 1 - управление

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

void setup()    
{ 

  pinMode(ledPin1, OUTPUT); //иниц выхода

} 
void loop() 

{ 
  //**************************первый таймер **********************************
 if(digitalRead(2)==HIGH)//если кнопка нажата ... 
  { 
    flagA=1;
  }
  if(flagA==1)
  {

    if (millis() -previousMillisA >1000) 
    { 
      previousMillisA = millis();     
      valA++;                       // работает счет,ledPin1  выключен 
      digitalWrite(ledPin1,HIGH); 
    } 
  } 

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


  }
  if(digitalRead(2)==LOW)//если кнопка не нажата ... 
  { 
    flagA=0;
    digitalWrite(ledPin1,LOW); //выключаем ledPin1 
    valA=0;//обнуляем переменную
     
  } 

}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
 pinMode(ledPin1, OUTPUT); //иниц выхода <--- это вижу для светодиода.
/*А вот где это для кнопки , не наблюдаю
*/

 

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

del

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

Вот кнопка (она так работает),скетч рабочий,но берут смутные сомнения,что что-то не так.

if(digitalRead(2)==HIGH)//если кнопка нажата ...

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

Вот вся конструкция.Таймеров должно быть восемь.

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

GKV пишет:

Вот кнопка (она так работает),скетч рабочий,но берут смутные сомнения,что что-то не так.

if(digitalRead(2)==HIGH)//если кнопка нажата ...

И что вы мне хотите этим сказать. Я к примеру давно не пишу, как втюхивают нам "нормы программирования в Ардуине", потому что меня давно взяли "смутные сомнения". Но стойкому народу "новичков Ардуины" мой код тяжкий, потому что перебороть свои смутные сомнения проще, чем начать поглубже изучать язык Си и программирование в целом. 

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

qwone пишет:

GKV пишет:

Вот кнопка (она так работает),скетч рабочий,но берут смутные сомнения,что что-то не так.

if(digitalRead(2)==HIGH)//если кнопка нажата ...

И что вы мне хотите этим сказать. Я к примеру давно не пишу, как втюхивают нам "нормы программирования в Ардуине", потому что меня давно взяли "смутные сомнения". Но стойкому народу "новичков Ардуины" мой код тяжкий, потому что перебороть свои смутные сомнения проще, чем начать поглубже изучать язык Си и программирование в целом. 

Так есть в коде ошибка?

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

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

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

Выше написал,но не суть.

При появлении +5в на входе D2 должен включиться выход А0 и отключиться через 2сек независимо от того,что на входе D2 присутствует +5в.

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

Если вам нужен рабочий , именно работающий код без глюков то возьмите этот #1150

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

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

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

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

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

//
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//----------------Cl_LED------------------------------------------------------------
class Cl_LED {
    byte pin; // нога для подключения светодиода
    bool inv; // 0 светодиод горит при 1/ 1 светодиод горит при 0
    bool stat_ON = 0, led = 0;
    uint32_t time = 500, past = 0;
  public:
    //указатель на следующий компонент
    Cl_LED *pnt_LED;
    //конструктор
    Cl_LED(Cl_Sys *Sys, byte _pin, bool _inv);
    // setup()
    void setup() {
      pinMode(pin, OUTPUT);// подключить светодиод
      led = 0;
      digitalWrite(pin, led ^ inv) ; // погасить светодиод
    }
    // loop()
    void loop() {
      if (stat_ON && millis() - past >= time)OFF();
    }
    // включить светодиод
    void ON() {
      stat_ON = 0;
      led = 1;
      digitalWrite(pin, led ^ inv) ; // зажечь светодиод
    }
    // включить светодиод на время
    void ON( uint32_t _time) {
      time = _time;
      stat_ON = 1;
      past = millis();
      led = 1;
      digitalWrite(pin, led ^ inv) ; // зажечь светодиод
    }
    // выключить светодиод
    void OFF() {
      stat_ON = 0;
      led = 0;
      digitalWrite(pin, led ^ inv) ; // погасить светодиод
    }
};
//----------------Cl_Mech_BTN------------------------------------------------------------
// класс на механич кнопку подкл к кнопке Ардуины.
class Cl_Mech_BTN {
    byte pin; // номер ноги на кнопке
    void (* Do)();// указатель на обработчик
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    //указатель на следующий компонент
    Cl_Mech_BTN *pnt_Mech_BTN;
    //конструктор
    Cl_Mech_BTN(Cl_Sys *Sys, byte _pin, void (* _Do)());
    void setup() {
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    void loop () {
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ;                   // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do();
      }
    }
};
//----------------Cl_Sys------------------------------------------------------------
class Cl_Sys {
  public:
    // указатели на блоки однотипных классов в системе
    Cl_LED * Start_LED = NULL;
    Cl_Mech_BTN * Start_Mech_BTN = NULL;
    void setup() {
      for (Cl_LED *i = Start_LED; i != NULL; i = i->pnt_LED) i->setup();
      for (Cl_Mech_BTN *i = Start_Mech_BTN; i != NULL; i = i->pnt_Mech_BTN) i->setup();
    }
    void loop () {
      for (Cl_LED *i = Start_LED; i != NULL; i = i->pnt_LED) i->loop ();
      for (Cl_Mech_BTN *i = Start_Mech_BTN; i != NULL; i = i->pnt_Mech_BTN)  i->loop ();
    }
};
//-----------------конструкторы классов вход в систему-------------------------------
Cl_LED::Cl_LED(Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv) {
  pnt_LED = Sys->Start_LED;
  Sys->Start_LED = this;
}
Cl_Mech_BTN::Cl_Mech_BTN(Cl_Sys *Sys, byte _pin, void (* _Do)()): pin(_pin), Do(_Do) {
  pnt_Mech_BTN = Sys->Start_Mech_BTN;
  Sys->Start_Mech_BTN = this;
}
//------------------компоновка-------------------------------------------------------
Cl_Sys *Sys = new Cl_Sys();
Cl_LED *LED1 = new Cl_LED(Sys,/*пин*/13,/*инверсия*/0);// создать светодиод LED1
Cl_LED *LED2 = new Cl_LED(Sys,/*пин*/12,/*инверсия*/0);// создать светодиод LED2
Cl_LED *LED3 = new Cl_LED(Sys,/*пин*/11,/*инверсия*/0);// создать светодиод LED3
Cl_LED *LED4 = new Cl_LED(Sys,/*пин*/10,/*инверсия*/0);// создать светодиод LED4
Cl_LED *LED5 = new Cl_LED(Sys,/*пин*/9,/*инверсия*/0);// создать светодиод LED5
Cl_LED *LED6 = new Cl_LED(Sys,/*пин*/8,/*инверсия*/0);// создать светодиод LED6
void Do_BTN1() {
  LED1->ON(2000);
}
void Do_BTN2() {
  LED2->ON(2000);
}
void Do_BTN3() {
  LED3->ON(2000);
}
void Do_BTN4() {
  LED4->ON(2000);
}
void Do_BTN5() {
  LED5->ON(2000);
}
void Do_BTN6() {
  LED6->ON(2000);
}
Cl_Mech_BTN *BTN1 = new Cl_Mech_BTN(Sys,/*пин*/2,/*обработчик*/Do_BTN1);// создать кнопку BTN1
Cl_Mech_BTN *BTN2 = new Cl_Mech_BTN(Sys,/*пин*/3,/*обработчик*/Do_BTN2);// создать кнопку BTN2
Cl_Mech_BTN *BTN3 = new Cl_Mech_BTN(Sys,/*пин*/4,/*обработчик*/Do_BTN3);// создать кнопку BTN3
Cl_Mech_BTN *BTN4 = new Cl_Mech_BTN(Sys,/*пин*/5,/*обработчик*/Do_BTN4);// создать кнопку BTN4
Cl_Mech_BTN *BTN5 = new Cl_Mech_BTN(Sys,/*пин*/6,/*обработчик*/Do_BTN5);// создать кнопку BTN5
Cl_Mech_BTN *BTN6 = new Cl_Mech_BTN(Sys,/*пин*/7,/*обработчик*/Do_BTN6);// создать кнопку BTN6
//------------------ main()----------------------------------------------------------
void setup() {
  Sys->setup();
}

void loop() {
  Sys->loop();
}

 

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

Залил ваш скетч,подходить под логику,но при отпускании кнопки выход опять включается.Как убрать это?

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

подключение земля-кнопка - вывод ?

Cl_LED *LED1 = new Cl_LED(Sys,/*пин*/13,/*инверсия*/0);// создать светодиод LED1
// инверсия  0/1 это как подключен светодиод на землю или питание.

 

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

Все кнопки Подключены через подтягивающий резистор на GND 10kOm

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

там програмное подтягивание на +5В. Ну если ваши резисторы подтягивают к питанию, то можно оставить. А зачем делать подтяжку на землю?

Код с подтяжкой на землю

// Скетч расчитан на кнопки с подтяжкой резисторов 10к на землю

class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//----------------Cl_LED------------------------------------------------------------
class Cl_LED {
    byte pin; // нога для подключения светодиода
    bool inv; // 0 светодиод горит при 1/ 1 светодиод горит при 0
    bool stat_ON = 0, led = 0;
    uint32_t time = 500, past = 0;
  public:
    //указатель на следующий компонент
    Cl_LED *pnt_LED;
    //конструктор
    Cl_LED(Cl_Sys *Sys, byte _pin, bool _inv);
    // setup()
    void setup() {
      pinMode(pin, OUTPUT);// подключить светодиод
      led = 0;
      digitalWrite(pin, led ^ inv) ; // погасить светодиод
    }
    // loop()
    void loop() {
      if (stat_ON && millis() - past >= time)OFF();
    }
    // включить светодиод
    void ON() {
      stat_ON = 0;
      led = 1;
      digitalWrite(pin, led ^ inv) ; // зажечь светодиод
    }
    // включить светодиод на время
    void ON( uint32_t _time) {
      time = _time;
      stat_ON = 1;
      past = millis();
      led = 1;
      digitalWrite(pin, led ^ inv) ; // зажечь светодиод
    }
    // выключить светодиод
    void OFF() {
      stat_ON = 0;
      led = 0;
      digitalWrite(pin, led ^ inv) ; // погасить светодиод
    }
};
//----------------Cl_Mech_BTN------------------------------------------------------------
// класс на механич кнопку подкл к кнопке Ардуины.
class Cl_Mech_BTN {
    byte pin; // номер ноги на кнопке
    void (* Do)();// указатель на обработчик
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    //указатель на следующий компонент
    Cl_Mech_BTN *pnt_Mech_BTN;
    //конструктор
    Cl_Mech_BTN(Cl_Sys *Sys, byte _pin, void (* _Do)());
    void setup() {
      pinMode(pin, INPUT);// подключить кнопку 
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    void loop () {
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ;                   // прочитать реальное значение на выводе
        if (!btn_old && btn) Do();
      }
    }
};
//----------------Cl_Sys------------------------------------------------------------
class Cl_Sys {
  public:
    // указатели на блоки однотипных классов в системе
    Cl_LED * Start_LED = NULL;
    Cl_Mech_BTN * Start_Mech_BTN = NULL;
    void setup() {
      for (Cl_LED *i = Start_LED; i != NULL; i = i->pnt_LED) i->setup();
      for (Cl_Mech_BTN *i = Start_Mech_BTN; i != NULL; i = i->pnt_Mech_BTN) i->setup();
    }
    void loop () {
      for (Cl_LED *i = Start_LED; i != NULL; i = i->pnt_LED) i->loop ();
      for (Cl_Mech_BTN *i = Start_Mech_BTN; i != NULL; i = i->pnt_Mech_BTN)  i->loop ();
    }
};
//-----------------конструкторы классов вход в систему-------------------------------
Cl_LED::Cl_LED(Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv) {
  pnt_LED = Sys->Start_LED;
  Sys->Start_LED = this;
}
Cl_Mech_BTN::Cl_Mech_BTN(Cl_Sys *Sys, byte _pin, void (* _Do)()): pin(_pin), Do(_Do) {
  pnt_Mech_BTN = Sys->Start_Mech_BTN;
  Sys->Start_Mech_BTN = this;
}
//------------------компоновка-------------------------------------------------------
Cl_Sys *Sys = new Cl_Sys();
Cl_LED *LED1 = new Cl_LED(Sys,/*пин*/13,/*инверсия*/0);// создать светодиод LED1
Cl_LED *LED2 = new Cl_LED(Sys,/*пин*/12,/*инверсия*/0);// создать светодиод LED2
Cl_LED *LED3 = new Cl_LED(Sys,/*пин*/11,/*инверсия*/0);// создать светодиод LED3
Cl_LED *LED4 = new Cl_LED(Sys,/*пин*/10,/*инверсия*/0);// создать светодиод LED4
Cl_LED *LED5 = new Cl_LED(Sys,/*пин*/9,/*инверсия*/0);// создать светодиод LED5
Cl_LED *LED6 = new Cl_LED(Sys,/*пин*/8,/*инверсия*/0);// создать светодиод LED6
void Do_BTN1() {
  LED1->ON(2000);
}
void Do_BTN2() {
  LED2->ON(2000);
}
void Do_BTN3() {
  LED3->ON(2000);
}
void Do_BTN4() {
  LED4->ON(2000);
}
void Do_BTN5() {
  LED5->ON(2000);
}
void Do_BTN6() {
  LED6->ON(2000);
}
Cl_Mech_BTN *BTN1 = new Cl_Mech_BTN(Sys,/*пин*/2,/*обработчик*/Do_BTN1);// создать кнопку BTN1
Cl_Mech_BTN *BTN2 = new Cl_Mech_BTN(Sys,/*пин*/3,/*обработчик*/Do_BTN2);// создать кнопку BTN2
Cl_Mech_BTN *BTN3 = new Cl_Mech_BTN(Sys,/*пин*/4,/*обработчик*/Do_BTN3);// создать кнопку BTN3
Cl_Mech_BTN *BTN4 = new Cl_Mech_BTN(Sys,/*пин*/5,/*обработчик*/Do_BTN4);// создать кнопку BTN4
Cl_Mech_BTN *BTN5 = new Cl_Mech_BTN(Sys,/*пин*/6,/*обработчик*/Do_BTN5);// создать кнопку BTN5
Cl_Mech_BTN *BTN6 = new Cl_Mech_BTN(Sys,/*пин*/7,/*обработчик*/Do_BTN6);// создать кнопку BTN6
//------------------ main()----------------------------------------------------------
void setup() {
  Sys->setup();
}

void loop() {
  Sys->loop();
}

 

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

Огромное спасибо!Все работает как надо.Добавил еще две кнопки и два выхода.Делаю эту штуку для удаленного управления вкл\откл кондиционеров в кол-ве 4шт.Подпаиваюсь к кнопке on/off дистанц.пульта.получается Им

// Скетч расчитан на кнопки с подтяжкой резисторов 10к на землю

class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//----------------Cl_LED------------------------------------------------------------
class Cl_LED {
    byte pin; // нога для подключения светодиода
    bool inv; // 0 светодиод горит при 1/ 1 светодиод горит при 0
    bool stat_ON = 0, led = 0;
    uint32_t time = 500, past = 0;
  public:
    //указатель на следующий компонент
    Cl_LED *pnt_LED;
    //конструктор
    Cl_LED(Cl_Sys *Sys, byte _pin, bool _inv);
    // setup()
    void setup() {
      pinMode(pin, OUTPUT);// подключить светодиод
      led = 0;
      digitalWrite(pin, led ^ inv) ; // погасить светодиод
    }
    // loop()
    void loop() {
      if (stat_ON && millis() - past >= time)OFF();
    }
    // включить светодиод
    void ON() {
      stat_ON = 0;
      led = 1;
      digitalWrite(pin, led ^ inv) ; // зажечь светодиод
    }
    // включить светодиод на время
    void ON( uint32_t _time) {
      time = _time;
      stat_ON = 1;
      past = millis();
      led = 1;
      digitalWrite(pin, led ^ inv) ; // зажечь светодиод
    }
    // выключить светодиод
    void OFF() {
      stat_ON = 0;
      led = 0;
      digitalWrite(pin, led ^ inv) ; // погасить светодиод
    }
};
//----------------Cl_Mech_BTN------------------------------------------------------------
// класс на механич кнопку подкл к кнопке Ардуины.
class Cl_Mech_BTN {
    byte pin; // номер ноги на кнопке
    void (* Do)();// указатель на обработчик
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    //указатель на следующий компонент
    Cl_Mech_BTN *pnt_Mech_BTN;
    //конструктор
    Cl_Mech_BTN(Cl_Sys *Sys, byte _pin, void (* _Do)());
    void setup() {
      pinMode(pin, INPUT);// подключить кнопку 
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    void loop () {
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ;                   // прочитать реальное значение на выводе
        if (!btn_old && btn) Do();
      }
    }
};
//----------------Cl_Sys------------------------------------------------------------
class Cl_Sys {
  public:
    // указатели на блоки однотипных классов в системе
    Cl_LED * Start_LED = NULL;
    Cl_Mech_BTN * Start_Mech_BTN = NULL;
    void setup() {
      for (Cl_LED *i = Start_LED; i != NULL; i = i->pnt_LED) i->setup();
      for (Cl_Mech_BTN *i = Start_Mech_BTN; i != NULL; i = i->pnt_Mech_BTN) i->setup();
    }
    void loop () {
      for (Cl_LED *i = Start_LED; i != NULL; i = i->pnt_LED) i->loop ();
      for (Cl_Mech_BTN *i = Start_Mech_BTN; i != NULL; i = i->pnt_Mech_BTN)  i->loop ();
    }
};
//-----------------конструкторы классов вход в систему-------------------------------
Cl_LED::Cl_LED(Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv) {
  pnt_LED = Sys->Start_LED;
  Sys->Start_LED = this;
}
Cl_Mech_BTN::Cl_Mech_BTN(Cl_Sys *Sys, byte _pin, void (* _Do)()): pin(_pin), Do(_Do) {
  pnt_Mech_BTN = Sys->Start_Mech_BTN;
  Sys->Start_Mech_BTN = this;
}
//------------------компоновка-------------------------------------------------------
Cl_Sys *Sys = new Cl_Sys();
Cl_LED *LED1 = new Cl_LED(Sys,/*пин*/A0,/*инверсия*/0);// создать светодиод LED1
Cl_LED *LED2 = new Cl_LED(Sys,/*пин*/A1,/*инверсия*/0);// создать светодиод LED2
Cl_LED *LED3 = new Cl_LED(Sys,/*пин*/A2,/*инверсия*/0);// создать светодиод LED3
Cl_LED *LED4 = new Cl_LED(Sys,/*пин*/A3,/*инверсия*/0);// создать светодиод LED4
Cl_LED *LED5 = new Cl_LED(Sys,/*пин*/A4,/*инверсия*/0);// создать светодиод LED5
Cl_LED *LED6 = new Cl_LED(Sys,/*пин*/A5,/*инверсия*/0);// создать светодиод LED6
Cl_LED *LED7 = new Cl_LED(Sys,/*пин*/11,/*инверсия*/0);// создать светодиод LED7
Cl_LED *LED8 = new Cl_LED(Sys,/*пин*/12,/*инверсия*/0);// создать светодиод LED8
void Do_BTN1() {
  LED1->ON(2000);
}
void Do_BTN2() {
  LED2->ON(2000);
}
void Do_BTN3() {
  LED3->ON(2000);
}
void Do_BTN4() {
  LED4->ON(2000);
}
void Do_BTN5() {
  LED5->ON(2000);
}
void Do_BTN6() {
  LED6->ON(2000);
}
void Do_BTN7() {
  LED7->ON(2000);
}
void Do_BTN8() {
  LED8->ON(2000);
}
Cl_Mech_BTN *BTN1 = new Cl_Mech_BTN(Sys,/*пин*/2,/*обработчик*/Do_BTN1);// создать кнопку BTN1
Cl_Mech_BTN *BTN2 = new Cl_Mech_BTN(Sys,/*пин*/3,/*обработчик*/Do_BTN2);// создать кнопку BTN2
Cl_Mech_BTN *BTN3 = new Cl_Mech_BTN(Sys,/*пин*/4,/*обработчик*/Do_BTN3);// создать кнопку BTN3
Cl_Mech_BTN *BTN4 = new Cl_Mech_BTN(Sys,/*пин*/5,/*обработчик*/Do_BTN4);// создать кнопку BTN4
Cl_Mech_BTN *BTN5 = new Cl_Mech_BTN(Sys,/*пин*/6,/*обработчик*/Do_BTN5);// создать кнопку BTN5
Cl_Mech_BTN *BTN6 = new Cl_Mech_BTN(Sys,/*пин*/7,/*обработчик*/Do_BTN6);// создать кнопку BTN6
Cl_Mech_BTN *BTN7 = new Cl_Mech_BTN(Sys,/*пин*/8,/*обработчик*/Do_BTN7);// создать кнопку BTN7
Cl_Mech_BTN *BTN8 = new Cl_Mech_BTN(Sys,/*пин*/9,/*обработчик*/Do_BTN8);// создать кнопку BTN8
//------------------ main()----------------------------------------------------------
void setup() {
  Sys->setup();
}

void loop() {
  Sys->loop();
}

митация нажатия кнопки.

Ваш код с восьмью таймера задержки.Может кто будет тоже искать.

Evgufa
Evgufa аватар
Offline
Зарегистрирован: 19.03.2016

народ, беда, помогите разобраться

if (timer != timerPress) не срабатывает эта строка
&& timer <= (timerPress + 300) и эта часть
код и монитор порта прологаю
версия arduino IDE 1.8.2

есть светодиод (полевик и набор из 20 шт 5730)
хочу управлять им и с пульта и с кнопки поэтому там button пульт будет задействован позже.
на пульте есть неиспользуемая кнопка... она сделана для других стран
я уже пробовал ее - работает код получен и прочее

СУТЬ! при нажатии на кнопку длительностью меньше 300 миллисекунд включает val = 255 - подаем на светодиод
при повторном нажатии меньше 300 миллисекунд подает val = 0
при удержании с выключенного положения больше 300 миллисекунд начинает прибавлять значение val (скажем прибавили до 180)
при нажатии менее 300 мс val=0
при длительном нажатии начинает убавлять(скажем 150) совсем не светит почти
и при длительном нажатии опять начинает прибавлять...

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

int val = 0; // создаем переменную регулировки и определяем её значение
boolean button = false; // нажатие кнопки (пульта или клацалки)
boolean flag = false; // сработка кнопки
unsigned long timer = 0; // таймер с момента включения
unsigned long timerPress = 0; // таймер удержания кнопки
int gatePin = 3; // указываем пин который будем управлять затвором
int buttonPin = 5; // указываем пин кнопки
int regim = 0; // режим
int trend = 1; //направление переключения режимов в большую или меньшую сторону


void setup() {
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
}

void loop() {
  timer = millis();

  button = digitalRead(buttonPin);

  // нажатие кнопки
  if (button == true) //если кнопка нажата ...
  {
    flag = true; //поднимаем флаг
    if (timer != timerPress) // и если таймеры не равны
    {
      timerPress = timer; //  то таймеру нажатия присваивается значение таймера
    }
  }
  //отпускание кнопки
  if (button == false && regim == 0 && flag == true && timer < (timerPress + 300) ) // если кнопка отжата и режим 0 и таймер меньше таймера нажатия на 300 мс
  {
    flag = false; // опускаем флаг
    regim  = 255; // режим равен 255
  }
  if (button == false && regim == 255 && flag == true && timer < (timerPress + 300) ) // если кнопка отжата и режим 255 и таймер меньше таймера нажатия на 300 мс
  {
    flag = false; // опускаем флаг
    regim  = 0; // режим равен 0
  }
  // ружимы
  if (regim == 0) {
    val = 0;
  }
  if (regim == 1) {
    val = 180;
  }
  if (regim == 2) {
    val = 180;
  }
  if (regim == 3) {
    val = 190;
  }
  if (regim == 4) {
    val = 200;
  }
  if (regim == 5) {
    val = 200;
  }
  if (regim == 6) {
    val = 210;
  }
  if (regim == 7) {
    val = 220;
  }
  if (regim == 8) {
    val = 230;
  }
  if (regim == 9) {
    val = 240;
  }
  if (regim == 10) {
    val = 255;
  }
  //вывод значения
  analogWrite(gatePin , val);
  //вывод в монитор
  Serial.print(" timer-");
  Serial.print (timer);
  Serial.print(" timerPress-");
  Serial.print (timerPress);
  Serial.print(" button-");
  Serial.print (button);
  Serial.print(" flag-");
  Serial.print (flag);
  Serial.print(" val-");
  Serial.println(val);
  //делея тут не будет в итоге
  delay(10);
}

 

это получаю в монитор порта

ткните носом в косяк

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013
  if (button == false && regim == 0 && flag == true && timer < (timerPress + 300) ) 

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

 

Строки 22-41 можно упростить до:

// нажатие кнопки
  if (button == true) //если кнопка нажата ...
  {
    flag = true; //поднимаем флаг
    if (timer != timerPress) // и если таймеры не равны
    {
      timerPress = timer; //  то таймеру нажатия присваивается значение таймера
    }
  }
  else //отпускание кнопки (button == false)
   {
      if ( flag == true && timer < (timerPress + 300) ) 
        {
           flag = false; // опускаем флаг
           if (regim == 0)  regim  = 255;
           else if(regim == 255) regim  = 0;
        }
}

Логика абсолютно та же, но читается легче.

Строки 72-45 заменить на swich... case. Мотив тот же.

Evgufa
Evgufa аватар
Offline
Зарегистрирован: 19.03.2016

суть проблемы, я держу кнопку больше 300мс отпускаю срабатывает, я она не должна  срабатывать, там другая функция должна идти - регулировка света(режимы) по сути режим выбрал, отпустил, он остался, а не погас.

за свитч кейс спасибо...

и первый вопрос - почему таймеры равны? я пытаюсь посчитать время нажатия кнопки

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

Попробуйте проанализировать такой код (я правда не понял при каких условиях  должно происходить отнимание поэтому сделал только додавание)

int val = 0; // создаем переменную регулировки и определяем её значение
boolean button = false; // нажатие кнопки (пульта или клацалки)
boolean flag = false; // сработка кнопки
unsigned long timer = 0; // таймер с момента включения
unsigned long timerPress = 0; // таймер удержания кнопки
int gatePin = 3; // указываем пин который будем управлять затвором
int buttonPin = 5; // указываем пин кнопки
int regim = 0; // режим
boolean trend = 1; //направление переключения режимов в большую или меньшую сторону


void setup() {
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
}

void loop() {
  timer = millis();

  button = digitalRead(buttonPin);

  // нажатие кнопки
  if (button == true && flag == false) //если кнопка нажата ...
  {
    flag = true; //поднимаем флаг
    timerPress = timer; //  то таймеру нажатия присваивается значение таймера
  }
  //отпускание кнопки
  if (button == false && regim < 255 && flag == true ) {
    if (timer < (timerPress + 300) ) // если кнопка отжата и режим 0 и таймер меньше таймера нажатия на 300 мс
    {
      flag = false; // опускаем флаг
      if (regim > 0)regim = 0;
      else regim = 10;
    }
    else {
      regim++;
      flag = false;
      if (regim > 10)regim = 0;
    }
  }

  //  if (button == false && regim >0 && flag == true){
  //  if (timer < (timerPress + 300) ) // если кнопка отжата и режим 255 и таймер меньше таймера нажатия на 300 мс
  //  {
  //    flag = false; // опускаем флаг
  //    regim  = 0; // режим равен 0
  //  }
  //  else regim--;
  //  }

  // ружимы
  if (regim == 0) {
    val = 0;
  }
  if (regim == 1) {
    val = 180;
  }
  if (regim == 2) {
    val = 180;
  }
  if (regim == 3) {
    val = 190;
  }
  if (regim == 4) {
    val = 200;
  }
  if (regim == 5) {
    val = 200;
  }
  if (regim == 6) {
    val = 210;
  }
  if (regim == 7) {
    val = 220;
  }
  if (regim == 8) {
    val = 230;
  }
  if (regim == 9) {
    val = 240;
  }
  if (regim == 10) {
    val = 255;
  }
  //вывод значения
  analogWrite(gatePin , val);
  //вывод в монитор
  Serial.print(" timer-");
  Serial.print (timer);
  Serial.print(" timerPress-");
  Serial.print (timerPress);
  Serial.print(" button-");
  Serial.print (button);
  Serial.print(" flag-");
  Serial.print (flag);
  Serial.print(" val-");
  Serial.println(val);
  //делея тут не будет в итоге
  delay(10);
}

 

Evgufa
Evgufa аватар
Offline
Зарегистрирован: 19.03.2016

да, я понял направление)) именно я с этим флагом промахнулся по месту использования))