Запуск функции при долгом зажатии кнопки

Otto
Offline
Зарегистрирован: 26.06.2016

Такая проблема, вроде и не сложная, но не могу понять как решить. Переделал функцию button1() на кнопке №1, что бы при обычных (коротких) нажатиях переключался regim1 на значения 0 или 1, а при удержании этой кнопки 2 или более секунд включался режим auto с функции pir() (датчика движения). Так вот, кнопка отлично переключается во всех трёх режимах, но почему то при выборе auto режима функция pir() не срабатывает. Возможно где то перепутал с условиями проверок в функции button1()....

***
boolean Status1 = true;                // объявляем Status1 реле в 0, инверсия...
boolean btnPress1 = false;             // объявляем что кнопка №1 не нажата "0"
boolean lastbtnStat1 = false;          // временная переменная для хранения статуса1

int regim1 = 0;               // Режимы по умолчанию при включении

bool button_long_state = false;   // Булево значение для выбора режима button1()
uint32_t ms_button = 0;           // Беззнаковый тип конкретного размера для выбора режима button1()

***

void button1() {                     // Функция для кнопки №1
  btnPress1 = digitalRead(BUTTON_1);    // Считываем значение кнопки в btnPress1
  Status1 = digitalRead(RELAY_1);       // Считываем значение реле в Status1
  if (btnPress1 && !lastbtnStat1) {     // Если btnPress1 нажата и lastbtnStat1 ИСТИНА...
    delay(30); // защита от дребезга
    btnPress1 = digitalRead(BUTTON_1);  // ... записываем результат в btnPress1
  }

  uint32_t ms = millis();   //Задаём переменную для хранения времени
  // Фиксируем нажатие кнопки (более 10 мкр./сек.)
  if (btnPress1 == false && !lastbtnStat1 && (ms - ms_button) > 10) {
    lastbtnStat1 = true;
    button_long_state = false;
    ms_button = ms;
  }
  // Фиксируем длинное нажатие кнопки (больше или равно 2-м секундам)
 if ( (btnPress1 == false) && (!button_long_state) && (( ms - ms_button ) >= 2000) ) {
    button_long_state = true;
    regim1 = 2;
    pir();
  }

  // Фиксируем отпускание кнопки (более 10 мкр./сек.)
  if (btnPress1 == true && !lastbtnStat1 && ( ms - ms_button ) > 10) {
    lastbtnStat1 = false;
    ms_button = ms;
    // Цикл проверки/переключения 0 и 1 режима
    if (btnPress1) {                 // Если кнопка нажата, то...
      regim1++;                      // переключаем на слежующий режим
      if (regim1 > 1) {              // если действующий режим > второго, то...
        regim1 = 0;                  // возвращаемся на нулевой режим
      }
    }
    if (regim1 == 0) {                  // Если режим 1=0, то...
      Status1 = true;                   // Status1 ИСТИНА (инверсия для Реле)
      digitalWrite(RELAY_1, Status1);   // Выключаем Реле №1
    }
    if (regim1 == 1) {                  // Если режим 1=1, то...
      Status1 = false;                  // Status1 ЛОЖЬ (инверсия для Реле)
      digitalWrite(RELAY_1, Status1);   // Включаем реле №1
    }
  }

  lastbtnStat1 = btnPress1;     // Копируем значение из кнопки в lastbtnStat1
}

 

 

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

Попробуем разобраться теоретически. Кнопка висит на земле. 0 нажата 1 нет. Что бы избежать дребезга и многократного срабатывания ловят переход 1-0 (или 0-1) . Считали пауза считали . Но все вся эта песня накрывается если начинается начинаем отделять короткое нажатие от длиного. Это как комьютерная мышка. Вещь простая, но что бы она работала нужно взаимодействие всей системы. 

Вот какой длительности должно быть у вас длиное нажатие . Думаю 1 сек. Так вот если делать выборки с периодом 0.6 сек будет следующее. 1-1-1 клавиша не нажата. 1-0-1 короткое нажатие . 1-0-0 длительное нажатие. То есть в реальности если пользоваться таким подходом программирования , то  button1(). будет длиться не меньше 1-1,5 сек. И не важно было ли нажатие, кратковеременое нажатие или длинное нажатие. И ваша система будет не реагировать ни на что, так как опрашивает клавишу. 

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

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

 // базовый класс   - согласовывает работу программы
class qw_basic {            
  public:  
    qw_basic(uint32_t span);
    virtual uint8_t go();
protected:    
    uint32_t span;         // интервал гашения или включения
    uint32_t future;     // время сменить состояние гашения или включения    
};
qw_basic::qw_basic(uint32_t span){
    this->span = span ;
    future = span +  millis();
}
uint8_t qw_basic::go() {           // конструктор qw_basic
    if (millis() < future) return 1;
    future  = span + millis();
    return 0;
}

// ====== Программа ======
qw_basic Time_per_600msec(600);
 const int buttonPin = 2;  // клавиша на ноге 2 0 нажата 1 нет
 uint8_t statButtom1;
 uint8_t statButtom2;
 uint8_t statButtom3;
 
 
 void setup() {
 pinMode(buttonPin, INPUT);
 statButtom1=1;
 statButtom2=1;
 statButtom3=1;
}

void loop() {
  if ( ! Time_per_600msec.go()) {
  // место которое работает раз в 0,6 секунды. Оставшее просто пропускает
 statButtom1=statButtom2;
 statButtom2=statButtom3;
 statButtom3=digitalRead(buttonPin);
 if ((statButtom1 == 1)&&(statButtom2 == 1)&&(statButtom3 == 1)){}; // клавиша не нажата
 if ((statButtom1 == 1)&&(statButtom2 == 0)&&(statButtom3 == 1)){}; // клавиша коротко нажата
 if ((statButtom1 == 1)&&(statButtom2 == 0)&&(statButtom3 == 0)){}; // клавиша длинно нажата  
  
 };
}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

qwone, Ваши рассуждения неубедительны.

Измеряем время между нажатием и отпусканием клавиши. В зависимости от величины измеренного интервала:

- если короче 50 мс - игнорируем (считаем, что это дребезг),

- если от 50 до 2000 мс - интерпретируем как короткое нажатие,

- если больше 2000 мс- интерпретируем как длинное.

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

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

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

Otto
Offline
Зарегистрирован: 26.06.2016

vvadim пишет:

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

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

Cessi71
Offline
Зарегистрирован: 21.05.2016

На пару тем выше Вашей смотрите.

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

Такая пробемка с преобразованием данных появилась. При компиляции ругается на: btnPress1 = digitalRead(BUTTON_1);

 BUTTON_1.read(); // обновляем состояние переменных кнопки BUTTON_1

  btnPress1 = digitalRead(BUTTON_1);    // Считываем значение кнопки в btnPress1
  Status1 = digitalRead(RELAY_1);       // Считываем значение реле в Status1
  if (btnPress1 && !lastbtnStat1) {     // Если btnPress1 нажата и lastbtnStat1 ИСТИНА...
    delay(30); // защита от дребезга
    btnPress1 = digitalRead(BUTTON_1);  // ... записываем результат в btnPress1
  }
  // Цикл проверки/переключения 0 и 1 режима
  if (btnPress1) {                 // Если кнопка нажата, то...
    regim1++;                      // переключаем на слежующий режим
    if (regim1 > 1) {              // если действующий режим > второго, то...
      regim1 = 0;                  // возвращаемся на нулевой режим
    }
  }

  if (BUTTON_1.click_down) {       // делаем при нажатии
    if (regim1 == 0) {                  // Если режим 1=0, то...
      Status1 = true;                   // Status1 ИСТИНА (инверсия для Реле)
      digitalWrite(RELAY_1, Status1);   // Выключаем Реле №1
    }
    if (regim1 == 1) {                  // Если режим 1=1, то...
      Status1 = false;                  // Status1 ЛОЖЬ (инверсия для Реле)
      digitalWrite(RELAY_1, Status1);   // Включаем реле №1
    }
  }

  if (BUTTON_1.retention) {           //делаем при нажатии и удержании в течении 2 сек.
    if (regim1 == 2) {
      pir();
    }
  }

  lastbtnStat1 = btnPress1;     // Копируем значение из кнопки в lastbtnStat1
}

Появляется такая ошибка при незакомментированном pinMode:

C:\Users\Linux\Documents\Arduino\MusorDEL\MQTT_LOL\MQTT_LOL.ino: In function 'void button1()':

MQTT_LOL:163: error: cannot convert 'BUTTON' to 'uint8_t {aka unsigned char}' for argument '1' to 'int digitalRead(uint8_t)'

   btnPress1 = digitalRead(BUTTON_1);    // Считываем значение кнопки в btnPress1

                                   ^

MQTT_LOL:167: error: cannot convert 'BUTTON' to 'uint8_t {aka unsigned char}' for argument '1' to 'int digitalRead(uint8_t)'

     btnPress1 = digitalRead(BUTTON_1);  // ... записываем результат в btnPress1

                                     ^

exit status 1
cannot convert 'BUTTON' to 'uint8_t {aka unsigned char}' for argument '1' to 'void pinMode(uint8_t, uint8_t)'

 

Ошибка такая, если закомментирываю pinMode:

C:\Users\Linux\Documents\Arduino\MusorDEL\MQTT_LOL\MQTT_LOL.ino: In function 'void button1()':

MQTT_LOL:163: error: cannot convert 'BUTTON' to 'uint8_t {aka unsigned char}' for argument '1' to 'int digitalRead(uint8_t)'

   btnPress1 = digitalRead(BUTTON_1);    // Считываем значение кнопки в btnPress1

                                   ^

MQTT_LOL:167: error: cannot convert 'BUTTON' to 'uint8_t {aka unsigned char}' for argument '1' to 'int digitalRead(uint8_t)'

     btnPress1 = digitalRead(BUTTON_1);  // ... записываем результат в btnPress1

                                     ^

exit status 1
cannot convert 'BUTTON' to 'uint8_t {aka unsigned char}' for argument '1' to 'int digitalRead(uint8_t)'

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

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

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

Судя по строке 17, BUTTON_1 - это объект, а для digitalRead нужен номер пина.

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

vvadim пишет:

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

я запрещаю кретинам пользоваться умными вещами

Otto пишет:

delay(30); // защита от дребезга

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

Ладно выложу свой рабочий код . Мож потом пригодится кому-то

Это яндекс диск https://yadi.sk/d/B-xRa1fXu3aEq

const int buttonPin=2;// вывод кнопки 0 нажата 1 нет
uint32_t last_millis; // переменные: последний  millis

uint8_t botton(){
  if (digitalRead(buttonPin) == 1){ // кнопка не нажата     
     last_millis = millis();
     return 0;}
   delay(30);
   while (digitalRead(buttonPin) == 0);
   delay(30);
   if (last_millis+65 > millis()){ // ложное срабатывание
     //Serial.println(millis()-last_millis);
     last_millis = millis();
     return 0;}
   if (last_millis+300 > millis()){ // короткое нажатие меньше 0.30 сек
     //Serial.println(millis()-last_millis);
     last_millis = millis();
     return 1;}
   //Serial.println(millis()-last_millis);
   last_millis = millis(); // длинное нажатие больше 0.30 сек
   return 2;
};


void setup() 
{  
  Serial.begin(9600); // Запускаем последовательный порт
  pinMode(buttonPin, INPUT_PULLUP); // вывод на ввод с подтягивающим резистром 
  last_millis = millis();  
}
void loop()
 {
   switch (botton()) {
      case 1:  Serial.println("Short press");
         break;
     case 2:  Serial.println("Long press");
         break;
   } 
 }

ПС: В качестве кнопки для отладки я использовал Джойстик http://greenchip.com.ua/23-0-146-0.html

Cessi71
Offline
Зарегистрирован: 21.05.2016

В предыдущем посте Калапуцций носом ткнул в дилей30, а Вы следом дилей30 и выложили..... )

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

Клапауций отвечает за свой код, а я за свой. Свой я проверяю на макетке.

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

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

А теперь тоже самое но на базе Енкодера http://www.banggood.com/ru/KY-040-Rotary-Decoder-Encoder-Module-For-Arduino-AVR-PIC-p-914010.html

"Короткое нажатие" "длиное нажатие" "по часовой" и "против часовой".

Код на диске http://yadi.sk/d/iZ7XcUs-u3ss7

// обработчик кнопки
const int buttonPin=A0;// вывод кнопки 0 нажата 1 нет
uint32_t last_millis; // переменные: последний  millis

uint8_t botton(){
  if (digitalRead(buttonPin) == 1){ // кнопка не нажата     
     last_millis = millis();
     return 0;}
   delay(30);
   while (digitalRead(buttonPin) == 0);
   delay(30);
   if (last_millis+65 > millis()){ // ложное срабатывание
     //Serial.println(millis()-last_millis);
     last_millis = millis();
     return 0;}
   if (last_millis+300 > millis()){ // короткое нажатие меньше 0.30 сек
     //Serial.println(millis()-last_millis);
     last_millis = millis();
     return 1;}
   //Serial.println(millis()-last_millis);
   last_millis = millis(); // длинное нажатие больше 0.30 сек
   return 2;
};
// обработчик энкодера
const int CLK_Pin=A2;// вывод CLK кнопки 0 нажата 1 нет
const int DT_Pin=A1; // вывод DT  кнопки 0 нажата 1 нет
uint8_t statCLK,statCLK_old; // переменные: состояние CLK вывода сейчас и раньше

uint8_t Encoder(){
  statCLK = digitalRead(CLK_Pin);  
  if ((statCLK == 0)&&(statCLK_old ==1 )){ //  счет по фронту
     statCLK_old=statCLK;
     return (digitalRead(DT_Pin)+1);
    };
  statCLK_old=statCLK; 
  return 0;
};

void setup() 
{  
  Serial.begin(9600); // Запускаем последовательный порт
  pinMode(buttonPin, INPUT_PULLUP); // вывод на ввод с подтягивающим резистром 
  last_millis = millis();
  pinMode(CLK_Pin, INPUT);
  pinMode(DT_Pin, INPUT); 
  statCLK_old = digitalRead(CLK_Pin);   
}
void loop()
 {
   switch (botton()) {
      case 1:  Serial.println("Short press");
         break;
     case 2:  Serial.println("Long press");
         break;
   } 
   switch (Encoder()) {
      case 1:  Serial.println("clockwise");
         break;
     case 2:  Serial.println("counter-clockwise");
         break;
   } 
 }

 

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

бля. delay(30);

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

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

бля. delay(30);

Точно Делай 30. Без этого ну никак.

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

qwone пишет:

Точно Делай 30. Без этого ну никак.

ну, прекращай этот тупняк - или используй делай везде, или не используй нигде

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

Раз не нравится delay() используй antidelay();

void antidelay(uint32_t timing){
timing += millis();
while(millis()<=timing);
}
void setup() {
 pinMode(13, OUTPUT);
}
void loop() {
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  antidelay(1000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  antidelay(1000);  
}

 

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

qwone пишет:

Раз не нравится delay() используй antidelay();

и, в чём разница?

 

Otto
Offline
Зарегистрирован: 26.06.2016

чЁ сума сходить и так фанатически реагировать на функцию delay? Это же не супер проект всемирный какой то, главное что бы программа работала достаточно стабильно - остальное дело хозяйское, кто как хочет, тот так и создаёт код.

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

Otto пишет:

чЁ сума сходить и так фанатически реагировать на функцию delay? Это же не супер проект всемирный какой то, главное что бы программа работала достаточно стабильно - остальное дело хозяйское, кто как хочет, тот так и создаёт код.

у тебя на автомобиле диски одинаковые или три автомобильные, а один от велосипеда?

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

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

Против delay() можно сказать одно . Команда режет прерывание. antidelay() же этого не делает. Если чел не понимает разницы, то это только его проблемы. Если при этом он и "заводится", то можно забить на комплексы этого чела. Программа работает. Кто хочет может взять код, кто не хочет, тот может идти лесом. Я не пользуюсь принципом МИГАЕМ БЕЗ DELAY. Я прользуюсь инструментом millis.Когда решает проблему использую, только и всего. Если у вас есть личный автомобиль это не значит, что вы обязаны ездить на работу на нем. Можно ездить на работу на маршрутке, автобусе, трамвае, на электричке. Хотя бы потому что, так дешевле и удобнее для некоторых людей.

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

qwone пишет:

Можно ездить на работу...

ясно - ты из тех, кто ходит на работу пешком в разных носках.

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

Для тех кто из леса добавлю. Я хожу на работу еще и разными ногами- одной правой и одной левой. А не тремя правыми ногами.

Otto
Offline
Зарегистрирован: 26.06.2016

Клапауций 232, Не надо быть таким принципиальным человеком, мы все поняли, что ты офигенный программист, можешь не доказывать это. Если не нравится delay() - не пользуйся, твоё дело и что то доказывать ненужно никому.

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

чё ругаться то.
ну пусть с делеями код используют если хочется.

я делеи не люблю, хотя тоже иногда применяю))))

Otto
Offline
Зарегистрирован: 26.06.2016

qwone пишет:

Ладно выложу свой рабочий код . Мож потом пригодится кому-то

Это яндекс диск https://yadi.sk/d/B-xRa1fXu3aEq

const int buttonPin=2;// вывод кнопки 0 нажата 1 нет
uint32_t last_millis; // переменные: последний  millis

uint8_t botton(){
  if (digitalRead(buttonPin) == 1){ // кнопка не нажата     
     last_millis = millis();
     return 0;}
   delay(30);
   while (digitalRead(buttonPin) == 0);
   delay(30);
   if (last_millis+65 > millis()){ // ложное срабатывание
     //Serial.println(millis()-last_millis);
     last_millis = millis();
     return 0;}
   if (last_millis+300 > millis()){ // короткое нажатие меньше 0.30 сек
     //Serial.println(millis()-last_millis);
     last_millis = millis();
     return 1;}
   //Serial.println(millis()-last_millis);
   last_millis = millis(); // длинное нажатие больше 0.30 сек
   return 2;
};


void setup() 
{  
  Serial.begin(9600); // Запускаем последовательный порт
  pinMode(buttonPin, INPUT_PULLUP); // вывод на ввод с подтягивающим резистром 
  last_millis = millis();  
}
void loop()
 {
   switch (botton()) {
      case 1:  Serial.println("Short press");
         break;
     case 2:  Serial.println("Long press");
         break;
   } 
 }

ПС: В качестве кнопки для отладки я использовал Джойстик http://greenchip.com.ua/23-0-146-0.html

Спасибо, поразбираюсь как он работает на будущее

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

Продолжаю выкладывать программы на эту тему .

С помощью этого джойстика http://greenchip.com.ua/23-0-146-0.html и программы можно подавать команды на 9 устройств(левовверх-0 ,, правовниз 8) Для примера 8 устройство это светодиод 13 короткое включить длиное выключить

Место для скачки программы https://yadi.sk/d/SYEYuaJ0u5mAr

// == Устройство 0 =================================================
const int Dev0_Pin=2;//  вывод устройствa 0
void Dev0_ini(){ //  инициализация устройствa 0
}
void Dev0_Short(){ //  действие  устройствa 0 при коротком нажатии
Serial.println("Short press 0");
}
void Dev0_Long(){ //  инициализация устройствa 0 при длином нажатии
Serial.println("Long press 0");
}
// == Устройство 1 ==================================================
const int Dev1_Pin=3;//  вывод устройствa 1
void Dev1_ini(){ //  инициализация устройствa 1
}
void Dev1_Short(){ //  действие  устройствa 1 при коротком нажатии
Serial.println("Short press 1");
}
void Dev1_Long(){ //  инициализация устройствa 1 при длином нажатии
Serial.println("Long press 1");
}
// == Устройство 2 ===================================================
const int Dev2_Pin=4;//  вывод устройствa 2
void Dev2_ini(){ //  инициализация устройствa 2
}
void Dev2_Short(){ //  действие  устройствa 2 при коротком нажатии
Serial.println("Short press 2");
}
void Dev2_Long(){ //  инициализация устройствa 2 при длином нажатии
Serial.println("Long press 2");
}
// == Устройство 3 ==================================================
const int Dev3_Pin=5;//  вывод устройствa 3
void Dev3_ini(){ //  инициализация устройствa 3
}
void Dev3_Short(){ //  действие  устройствa 3 при коротком нажатии
Serial.println("Short press 3");
}
void Dev3_Long(){ //  инициализация устройствa 3 при длином нажатии
Serial.println("Long press 3");
}
// == Устройство 4 ==================================================
const int Dev4_Pin=6;//  вывод устройствa 4
void Dev4_ini(){ //  инициализация устройствa 4
}
void Dev4_Short(){ //  действие  устройствa 4 при коротком нажатии
Serial.println("Short press 4");
}
void Dev4_Long(){ //  инициализация устройствa 4 при длином нажатии
Serial.println("Long press 4");
}
// == Устройство 5 ===================================================
const int Dev5_Pin=7;//  вывод устройствa 5
void Dev5_ini(){ //  инициализация устройствa 5
}
void Dev5_Short(){ //  действие  устройствa 5 при коротком нажатии
Serial.println("Short press 5");
}
void Dev5_Long(){ //  инициализация устройствa 5 при длином нажатии
Serial.println("Long press 5");
}
// == Устройство 6 ===================================================
const int Dev6_Pin=8;//  вывод устройствa 6
void Dev6_ini(){ //  инициализация устройствa 6
}
void Dev6_Short(){ //  действие  устройствa 6 при коротком нажатии
Serial.println("Short press 6");
}
void Dev6_Long(){ //  инициализация устройствa 6 при длином нажатии
Serial.println("Long press 6");
}
// == Устройство 7 ====================================================
const int Dev7_Pin=9;//  вывод устройствa 7
void Dev7_ini(){ //  инициализация устройствa 7
}
void Dev7_Short(){ //  действие  устройствa 7 при коротком нажатии
 Serial.println("Short press 7");
}
void Dev7_Long(){ //  инициализация устройствa 7 при длином нажатии
 Serial.println("Long press 7");
}
// == Устройство 8 ====================================================
const int Dev8_Pin=13;//  вывод устройствa 8
void Dev8_ini(){ //  инициализация устройствa 8
  pinMode(Dev8_Pin, OUTPUT);
}
void Dev8_Short(){ //  действие  устройствa 8 при коротком нажатии
 digitalWrite(Dev8_Pin, HIGH); 
 Serial.println("Short press 8");
}
void Dev8_Long(){ //  инициализация устройствa 8 при длином нажатии
 digitalWrite(Dev8_Pin, LOW);
 Serial.println("Long press 8");
}
// === функция обработки аналоговой части джойстика Arduino  ===
const int VRx_Pin=A0;// аналоговый вывод VRx джойстика Arduino
const int VRy_Pin=A1;// аналоговый вывод VRy джойстика Arduino
uint16_t VRx;
uint16_t VRy;
uint8_t AnalogRd(){
  VRx = analogRead(VRx_Pin);
  VRy = analogRead(VRy_Pin);
  return((VRx>340)+(VRx>680)+3*(VRy>340)+3*(VRy>680));
};
void DoShort(){ // делать при коротком нажатии
  switch (AnalogRd()) {
    case 0:  Dev0_Short() ;//делать когда  равно 0
      break;
    case 1:  Dev1_Short();      //делать когда  равно 1
      break;
    case 2:  Dev2_Short();      //делать когда  равно 2
      break;
    case 3:  Dev3_Short();      //делать когда  равно 3
      break;
    case 4:  Dev4_Short();      //делать когда  равно 4
      break;
    case 5:  Dev5_Short();      //делать когда  равно 5
      break;
    case 6:  Dev6_Short();     //делать когда  равно 6
      break;
    case 7:  Dev7_Short();      //делать когда  равно 7
      break;
    case 8:  Dev8_Short();      //делать когда  равно 8
      break;                  
  }
}
void DoLong(){ // делать при длином нажатии
  switch (AnalogRd()) {
    case 0:  Dev0_Long();      //делать когда  равно 0
      break;
    case 1:  Dev1_Long();      //делать когда  равно 1
      break;
    case 2:  Dev2_Long();      //делать когда  равно 2
      break;
    case 3:  Dev3_Long();      //делать когда  равно 3
      break;
    case 4:  Dev4_Long();      //делать когда  равно 4
      break;
    case 5:  Dev5_Long();      //делать когда  равно 5
      break;
    case 6:  Dev6_Long();      //делать когда  равно 6
      break;
    case 7:  Dev7_Long();      //делать когда  равно 7
      break;
    case 8:  Dev8_Long();      //делать когда  равно 8
      break;                  
  }  
}
// === antidelay замена обычного delay  ===
void antidelay(uint32_t timing){
timing += millis();
while(millis()<=timing);
};
// === функция обработки кнопки джойстика Arduino ===
const int SW_Pin=A2;// вывод SW кнопки  джойстика Arduino 0 нажата 1 нет
uint32_t last_millis; // переменные: последний  millis

uint8_t botton(){
  if (digitalRead(SW_Pin) == 1){ // кнопка не нажата     
     last_millis = millis();
     return 0;}
   antidelay(30);
   while (digitalRead(SW_Pin) == 0);
   antidelay(30);
   if (last_millis+65 > millis()){ // ложное срабатывание
     //Serial.println(millis()-last_millis);
     last_millis = millis();
     return 0;}
   if (last_millis+300 > millis()){ // короткое нажатие меньше 0.30 сек
     //Serial.println(millis()-last_millis);
     last_millis = millis();
     return 1;}
   //Serial.println(millis()-last_millis);
   last_millis = millis(); // длинное нажатие больше 0.30 сек
   return 2;
};

// === главная часть программы ===
void setup() 
{  
  Serial.begin(9600); // Запускаем последовательный порт
  Dev0_ini(); //  инициализация устройствa 0
  Dev1_ini(); //  инициализация устройствa 1
  Dev2_ini(); //  инициализация устройствa 2
  Dev3_ini(); //  инициализация устройствa 3
  Dev4_ini(); //  инициализация устройствa 4
  Dev5_ini(); //  инициализация устройствa 5
  Dev6_ini(); //  инициализация устройствa 6
  Dev7_ini(); //  инициализация устройствa 7
  Dev8_ini(); //  инициализация устройствa 8
  pinMode(SW_Pin, INPUT_PULLUP); // вывод на ввод с подтягивающим резистром 
  last_millis = millis();

  
}
void loop()
 {
   switch (botton()) {
      case 1: // Serial.println("Short press");
         DoShort();
         break;
     case 2: // Serial.println("Long press");
         DoLong();
         break;
   } 
 }