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

triada13
Offline
Зарегистрирован: 04.01.2013

Да но в первых примерах он работал, и именно чтоб "отпустить" кнопку приходилось повторно щелкать по пину мышой. Получается он удерживал кнопу?

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Значит как то не правильно удерживает. 

triada13
Offline
Зарегистрирован: 04.01.2013

Выходит так.

leshak
Offline
Зарегистрирован: 29.09.2011

nestandart пишет:

leshak, ваша программа работает , но показывать ее новичку не стоит.

IMHO стоит. Иначе потом дикие проблемы с пониманием отлавливания "фронта сигнала" и "спада". А нужно это - чуть ли не везде (да и "понять" без этого как ваша програма работает - тоже сложновато, "магия" получается).

Ну разве что использование pressTime одновременно и для "хранения времени" и "в качестве флага" - немного переборщил. Возможно отдельный флаг bool timerStarted=false; для этого стоило выделить в явном виде.

Можно в вещи типа if(pressTime) писать более явно if(pressTime>0).... но ведь это "обычная практика кода". Или

if(!prevState && state)

писать

if(prevState==false && state==true)

Но ведь, много примеров написанно именно так. Нужно же когда приучать к тому что в реальном инете встретится :)

Я и так удержался от того как-бы я писал в "боевом коде" :

/****************  НАСТРОЙКА СКЕТЧА ****************/
#define BUTTON_PIN A0 // тут настраиваем какая на каком пине у нас кнопка
#define USE_PULLUP  // закоментируейте эту строку если используете внешнюю подтяжку к нулю и больше ничего менять не нужно

/*************** КОНЕЦ НАСТРОЙКИ СКЕТЧА */

#ifdef USE_PULLUP
#define IS_BUTTON_PRESSED !digitalRead(BUTTON_PIN)
#else
#define IS_BUTTON_PRESSED digitalRead(BUTTON_PIN)
#endif

void setup(){
#ifdef USE_PULLUP
  digitalWrite(BUTTON_PIN,HIGH);
#endif
}


void loop(){
    if(IS_BUTTON_PRESSED){
       // что-то делаем по нажатию кнопки
    }
}

nestandart пишет:

Кстати у вас  исключена цикличность инвертации светодиода.

Вообще не понял. Особенно что такое "циличность инвертации светодиода".

Да и не понял, зачем вы делаете этот счетчик, увиличивающийся "раз в секунда", а потом проверяете что он достиг 5-ти? Не проще ли один раз "раз в пять секунд" и без счетчика?

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

>>Да и не понял, зачем вы делаете этот счетчик, увиличивающийся "раз в секунда", а потом проверяете что он достиг 5-ти?<<

Так понятнее.

>>Вообще не понял. Особенно что такое "циличность инвертации светодиода".<<

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

triada13
Offline
Зарегистрирован: 04.01.2013

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

leshak
Offline
Зарегистрирован: 29.09.2011

nestandart пишет:

>>Да и не понял, зачем вы делаете этот счетчик, увиличивающийся "раз в секунда", а потом проверяете что он достиг 5-ти?<<

Так понятнее.

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

nestandart пишет:

>>Вообще не понял. Особенно что такое "циличность инвертации светодиода".<<

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

Ага. Ясно.  Но у меня это тоже не сложно сделать. При инвертации диода делать не pressTime=0;, а pressTime=millis();   и все :) Проверил. Работает. Просто я такое поведение посчитал "нежелательным" и "задавил его" :) Но если ТЗ говорит "надо", то "нет проблемм" ;)

leshak
Offline
Зарегистрирован: 29.09.2011

triada13 пишет:

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

А вас "автомобилям" тоже учило сразу 3 челвека (помните про 7-мь нянек ;), удаленно, через форум, в темных очках ночью (это я на ваш телевизор намекаю) , да еще при отсутсвии самого автомобиля?   :)

Так шо "по началу" - оно всегда трудно.

triada13
Offline
Зарегистрирован: 04.01.2013

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

А насчет трудностей, ведь без них не интересно.

leshak
Offline
Зарегистрирован: 29.09.2011

triada13 пишет:

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

Вот. Меня тоже так учили "вот в той книге все есть" (даже без намека в какой главе). Только потому и знаю что-то ;)

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

>>Просто я такое поведение посчитал "нежелательным" и "задавил его" <<

Оно и есть не желательное. Просто у меня избавление от него (при помощи флага) описано в примерах ниже а должно было быть в этом. Пропустил.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

По просьбе пользователя NE_XT.

 

>>А можно пример привести, задержки включения - выключения светодиода. Нажимаем кнопку....., 2-10 светодиодов включаются по порядку с задержкой например 1 секунда, ну и выключаются в обратном порядке .<<

Набросал программу последовательного включения/выключения  ряда светодиодов. Я использовал три светодиода , но можно и больше (просто лень было паять).

 

При нажатии кнопки последовательно включаются светодиоды 1 , 2 , 3  с задержкой 150мс.

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

При удержании кнопки ничего не происходит.

 

leshak, будьте добры почистите тему. Диалоги с triada13 можно удалить полностью. Остальное на ваше усмотрение.



int knopka=0;//переменная овечающая за состояние кнопки
int state=0;//переменная отвечающая за запуск функций ledonn и ledoff

void setup() 
{                
  
  pinMode(14, OUTPUT); //светодиод1 
  pinMode(15, OUTPUT); //светодиод2 
  pinMode(16, OUTPUT);//светодиод3     
}

void loop()
{
  
  
  
  if(digitalRead(9)&&!state&&!knopka)//если кнопка нажата, переменная state=0,
                                    // переменная knopka=0, то ...
{
 ledonn();//запускаем функцию
 delay(10);//небольшая защита от дребезга кнопки
}
 if(digitalRead(9)&&state&&!knopka)//если кнопка нажата, переменная state=1,
                                   // переменная knopka=0, то ...
{
 ledoff();//запускаем функцию
 delay(10);//небольшая защита от дребезга кнопки
}
if(!digitalRead(9))//если кнопка не нажата, то ...
{
  knopka=0;// обнуляем переменную knopka
  
}

  
}

void ledonn()//функция включения светодиодов
{
  digitalWrite(14, HIGH);//включаем светодиод 1
  delay(150);  //ждем            
 
  digitalWrite(15, HIGH);//включаем светодиод 2
  delay(150);  //ждем              
  
  digitalWrite(16, HIGH); //включаем светодиод 3
  delay(150);  //ждем              
  
   knopka=1;// присваиваем переменной значение 1
  state=1;// присваиваем переменной значение 1
  
}



void ledoff()//функция выключения светодиодов

{
  
  digitalWrite(16, LOW);//выключаем светодиод 3 
  delay(150); //ждем                
 
  digitalWrite(15, LOW);  //выключаем светодиод 2 
  delay(150); //ждем                
  
  digitalWrite(14, LOW);  //выключаем светодиод 1 
  delay(150); //ждем   

  
  knopka=1;// присваиваем переменной значение 1
  state=0;//обнуляем переменную
   
  
}

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Можно и без дополнительных функций. Внутри loop.

Можно и без delay , но сейчас я этого делать не буду.


int knopka=0;//переменная овечающая за состояние кнопки
int state=0;//переменная отвечающая за запуск функций ledonn и ledoff

void setup() 
{                
  
  pinMode(14, OUTPUT); //светодиод1 
  pinMode(15, OUTPUT); //светодиод2 
  pinMode(16, OUTPUT);//светодиод3     
 
}

void loop()
{
  
 
  if(digitalRead(9)&&!state&&!knopka)//если кнопка нажата, переменная state=0,
                                    // переменная knopka=0, то ...
{
  digitalWrite(14, HIGH);//включаем светодиод 1
  delay(150);  //ждем            
 
  digitalWrite(15, HIGH);//включаем светодиод 2
  delay(150);  //ждем              
  
  digitalWrite(16, HIGH); //включаем светодиод 3
  delay(150);  //ждем              
  
   knopka=1;// присваиваем переменной значение 1
  state=1;// присваиваем переменной значение 1
 delay(10);//небольшая защита от дребезга кнопки
}





 if(digitalRead(9)&&state&&!knopka)//если кнопка нажата, переменная state=1,
                                   // переменная knopka=0, то ...
{
 
  digitalWrite(16, LOW);//выключаем светодиод 3 
  delay(150); //ждем                
 
  digitalWrite(15, LOW);  //выключаем светодиод 2 
  delay(150); //ждем                
  
  digitalWrite(14, LOW);  //выключаем светодиод 1 
  delay(150); //ждем   

  
  knopka=1;// присваиваем переменной значение 1
  state=0;//обнуляем переменную
  
 delay(10);//небольшая защита от дребезга кнопки
}

if(!digitalRead(9))//если кнопка не нажата, то ...
{
  knopka=0;// обнуляем переменную knopka
  
}
  
}

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

leshak, а как бы вы написали прграмму из поста №65 ?

Мне интересна оптимизация  кода ( не силен я в ней).

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

Это просто оптимизация вашего кода

​byte pins[] = {14, 15, 16};

bool knopka = 0; //переменная овечающая за состояние кнопки
bool state = 0;  //переменная отвечающая за запуск функций ledonn и ledoff

void setup() 
{                
  for(char i = 0; i < 3; i++) pinMode(pins[i], OUTPUT); 
}

void loop()
{
  if(digitalRead(9) && !knopka)
  {
    state = !state;  
    Leds(state);    
    knopka = 1;
  }
  if(!digitalRead(9) && knopka) knopka = 0;
}


void Leds(bool state_leds) 
{
  if(state_leds){
    for(char i = 0; i < 3; i++)
    {
      digitalWrite(pins[i], HIGH);
      delay(150);  //ждем            
    }
  }
  else
  {
    for(char i = 2; i >= 0; i--)
    {
      digitalWrite(pins[i], LOW);
      delay(150);  //ждем            
    }
  }
}

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

maksim, компилятор жутко матюгается на вашу программу.

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

Прям уж жутко... вместо i опечатка l, перекопируйте еще раз.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Сейчас работает.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Мне интересно, почему народ не использует переменные, а вместо этого, например, читает из порта дважды?

Аналогично, постоянно используют конструкции millis() в сравнениях, потом снова считывают millis().

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

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

Например:

void loop()
{
  unsigned long l_current_millis = millis();
  boolean l_btn_pressed = ( digitalRead( 9 ) == HIGH );
  if( !l_btn_pressed )
  {
    ...
    lastMillis = l_current_millis;
  }
  ...
  if( l_btn_pressed )
  {
    ...
    lastMillis = l_current_millis;
  }
}

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

Понятно, что можно сказать "да это тестовая прога, пофиг", но ИМХО - это плохая практика.

Не настаиваю, пишите как хотите ;)

 

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

Еще можно так попробовать оптимизировать:

byte pins[] = {14, 15, 16};

bool knopka = 0; //переменная овечающая за состояние кнопки
bool state = 0;  //переменная отвечающая за запуск функций ledonn и ledoff

void setup() 
{                
  for(char i = 0; i < 3; i++) pinMode(pins[i], OUTPUT); 
}

void loop()
{
  if(digitalRead(9) && !knopka)
  {
    state = !state;  
    for(char i = state?0:2; state?i<3:i>=0; state?i++:i--)
    {
      digitalWrite(pins[i], state);
      delay(150);  //ждем            
    }    
    knopka = 1;
  }
  if(!digitalRead(9) && knopka) knopka = 0;
}

 

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

kisoft пишет:
Мне интересно, почему народ не использует переменные, а вместо этого, например, читает из порта дважды? ... что читая из одного и того же порта дважды, вы рискуете считать разные значения
Так ну и что с того, что разные значения, значит значение изменилось, переменные стоит использовать если действительно в этом есть необходимость. В этих примерах по этой причине глюков не будет. А "скорость" здесь не нужна.

chaytan
Offline
Зарегистрирован: 02.02.2012

сорри за мусор, но снимаю шляпу.... спасибо за доступное обьяснение.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Дополнение.

Включение чего либо по двойному клику.

bool state=0;//пременная состояния кнопки

unsigned long presstime=0;//пременная для хранения "Времени между нажатиями"
int val=0;//переменная для хранения количества нажатий

void setup() 
{                
 
  pinMode(13, OUTPUT);//инициализация пинов

}

void loop() 
{
  
  if(digitalRead(9)&&!state)//если кнопка нажата и state=0, то ...
  {
   
    presstime=millis();//фиксируем время нажатия
    state=1;//присваиваем переменной значение 1 
    val++;//прибавляем еденицу к val
    delay(10);//небольшая защита от дребезга
  }
  
  
  if(!digitalRead(9)&&state&&(millis()-presstime)>100)state=0;
  //если кнопка не нажата, state=1,
  //текущее время минус зафиксированое больше 100 
  //изменяя это значение можно регулировать минимальную длинну
  //пауз между нажатиями
 //обнуляем преременную state
 
 
  if(val&&(millis()-presstime)>1000)//если val больше 0,
  //текущее время минус зафиксировано больше 1000
  //изменяя это значение можно регулировать 
  //максимальное время между нажатиями
  {
  presstime=0;//обнуляем переменную
  val=0;//обнуляем переменную
  }
  
 
  if(val>1)//если переменная больше 1 или равна 2
  //изменяя это значение можно увеличивать количество нажатий
  {
    digitalWrite(13,!digitalRead(13));//инвертируем состояние пина
  
    presstime=0;//обнуляем переменную
    val=0;//обнуляем переменную
  }
  
  
}

 

Dmitry23
Offline
Зарегистрирован: 16.09.2012

long previousMillis = 0; 
 int val=0; 

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

 void loop() 

 { 
     if(digitalRead(14)==HIGH)//если кнопка нажата ... 
     { 
         
      if (millis() -previousMillis >500)    
     { 
        previousMillis = millis();     
        val++; 
     } 
     } 
     else 
     { 
       val=0; 
     } 
        
     if(val>=5) 
     { 
       digitalWrite(13,!digitalRead(13));//инвертируем состояние пина 
       val=0; 
     } 
        
        
 } 
 

Вот этот код из первого сообщения в этой теме! 

подскажите пожалуйста в 18 строке в if часте выражения есть число 500, как я понял это по сути время в миллисекундах

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

я ставлю вместо 500 к примеру  180000 и и в 29 строке меняю значение с 5 на 2

Запускаю программу и засекаю время проходит примерно 45 секунд и срабатывает отключение!!!

что я делаю не так??

 

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

Dmitry23 пишет:

что я делаю не так??

Показываете чужой код вместо своего.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Не ту перемеменную изменяете. Вот так будет работать.

Инвертация пина каждые три минуты.

 

long previousMillis = 0; 
 int val=0; 

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

 void loop() 

 { 
      
      if (millis() -previousMillis >=1000)    
     { 
        previousMillis = millis();     
        val++; 
     } 
    
        
     if(val>=180) 
     { 
       digitalWrite(13,!digitalRead(13));//инвертируем состояние пина 
       val=0; 
     } 
        
        
 } 
 

 

Dmitry23
Offline
Зарегистрирован: 16.09.2012

А все потому что в моем коде много лишнего и для отражения сути проблемы с которой я столкнулся и была скопирована часть кода из этой темы!!!

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

 

Dmitry23
Offline
Зарегистрирован: 16.09.2012

Большое спасибо за помощь все работает как надо!!!

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

Dmitry23 пишет:

А все потому что в моем коде много лишнего и для отражения сути проблемы с которой я столкнулся и была скопирована часть кода из этой темы!!!

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

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

long previousMillis = 0; 
int val = 0; 

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

void loop() 

{ 
  if(digitalRead(14) == HIGH)   //если кнопка нажата ... 
  { 
    if (millis()-previousMillis > 180000)    
    { 
      previousMillis = millis();     
      val++; 
    } 
  } 
  else 
  { 
    val=0; 
  } 
  if(val>=2) 
  { 
    digitalWrite(13,!digitalRead(13));    //инвертируем состояние пина 
    val=0; 
  } 
} 

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

Dmitry23
Offline
Зарегистрирован: 16.09.2012

для того чтобы все прояснилось привожу свой вариант кода!!!



const int ACCPin =  9; //контакт подключения реле АСС
const int passengerPin = 6; // контакт контроля нахождения людей в салоне
const int doorPin = 5; // контакт контроля состояния тригеров дверей
const int fuelPumpPin = 7; //контакт контроля состояния бензонасоса
int interval2 = 1000;
int regim = 0;
int flag = 0;
unsigned long pvMillis = 0;
int val=0; 


//переменные
int passenger = 0; //переменная для хранения данных с контакта контроля нахождения людей в салоне
int door = 0;//переменная для хранения данных с контакта контроля состояния тригеров дверей
int fuelPump = 0;//переменная для хранения данных с контакта реле бензонасоса
void setup() {
  // задаем режим выхода для порта, подключенного к реле
  
  pinMode(ACCPin, OUTPUT);
  // задаем режим входа для портов подключенных к кнопкам и датчикам
  pinMode (passengerPin, INPUT);
  pinMode (doorPin, INPUT);
  pinMode (fuelPumpPin, INPUT);
}
 
void loop()
{
  // код АСС

  passenger = digitalRead (passengerPin); //сохраняем состояние с контакта контроля пассажиров в переменную
  door = digitalRead (doorPin); //сохраняем состояние с контакта контроля тригеров дверей в переменную
  
  if (door == HIGH && flag == 0) //если дверь открыта , ТО
  {
    regim ++;
    flag = 1;
    if(regim>2)
   {
    regim = 1;
   } 
  }
  if(door == LOW  && flag == 1)
  {
    flag = 0;
  }
  if(regim == 1)
  {
    if(passenger==HIGH)
    {
      digitalWrite(ACCPin, HIGH);
    }
    if(passenger == LOW && fuelPump == LOW )
    {
      unsigned long curMillis = millis();
     if(curMillis - pvMillis > interval2) 
     {
       pvMillis = curMillis;  
       val ++ ;
      }
    } 
    else
    {
      val = 0;
    }
    if(val >=180 )
    {
      digitalWrite(ACCPin, LOW);
    }
  }
  if(regim == 2)
  {
    if(passenger == LOW && fuelPump == LOW )
    {
      unsigned long curMillis = millis();
     if(curMillis - pvMillis > interval2) 
     {
       pvMillis = curMillis;  
       val ++ ;
     
      }
    } 
    else
    {
      val = 0;
    }
    if(val >=300)
    {
      digitalWrite(ACCPin, LOW);
    }
  }  

а было вот так

const int ACCPin =  9; //контакт подключения реле АСС
const int passengerPin = 6; // контакт контроля нахождения людей в салоне
const int doorPin = 5; // контакт контроля состояния тригеров дверей
const int fuelPumpPin = 7; //контакт контроля состояния бензонасоса
int interval2 = 180000;
int regim = 0;
int flag = 0;
unsigned long pvMillis = 0;
int val=0; 


//переменные
int passenger = 0; //переменная для хранения данных с контакта контроля нахождения людей в салоне
int door = 0;//переменная для хранения данных с контакта контроля состояния тригеров дверей
int fuelPump = 0;//переменная для хранения данных с контакта реле бензонасоса
void setup() {
  // задаем режим выхода для порта, подключенного к реле
  
  pinMode(ACCPin, OUTPUT);
  // задаем режим входа для портов подключенных к кнопкам и датчикам
  pinMode (passengerPin, INPUT);
  pinMode (doorPin, INPUT);
  pinMode (fuelPumpPin, INPUT);
}
 
void loop()
{
  // код АСС

  passenger = digitalRead (passengerPin); //сохраняем состояние с контакта контроля пассажиров в переменную
  door = digitalRead (doorPin); //сохраняем состояние с контакта контроля тригеров дверей в переменную
  
  if (door == HIGH && flag == 0) //если дверь открыта , ТО
  {
    regim ++;
    flag = 1;
    if(regim>2)
   {
    regim = 1;
   } 
  }
  if(door == LOW  && flag == 1)
  {
    flag = 0;
  }
  if(regim == 1)
  {
    if(passenger==HIGH)
    {
      digitalWrite(ACCPin, HIGH);
    }
    if(passenger == LOW && fuelPump == LOW )
    {
      unsigned long curMillis = millis();
     if(curMillis - pvMillis > interval2) 
     {
       pvMillis = curMillis;  
       val ++ ;
      }
    } 
    else
    {
      val = 0;
    }
    if(val >=2 )
    {
      digitalWrite(ACCPin, LOW);
    }
  }
  if(regim == 2)
  {
    if(passenger == LOW && fuelPump == LOW )
    {
      unsigned long curMillis = millis();
     if(curMillis - pvMillis > interval2) 
     {
       pvMillis = curMillis;  
       val ++ ;
     
      }
    } 
    else
    {
      val = 0;
    }
    if(val >=5)
    {
      digitalWrite(ACCPin, LOW);
    }
  }  

и срабатывала ACC LOW через 45 секунд!

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

Вам нужно почитать про типы данных, а именно про тип int, в описании которого написанно, что данный тип может хранить числа от -32768 до 32767, а вы пытаетесь в него записать 180000, поэтому нужно просто поменять в 5-й строке тип переменной interval2 на например long и все заработает.

const int ACCPin =  9; //контакт подключения реле АСС
const int passengerPin = 6; // контакт контроля нахождения людей в салоне
const int doorPin = 5; // контакт контроля состояния тригеров дверей
const int fuelPumpPin = 7; //контакт контроля состояния бензонасоса
long interval2 = 180000;
int regim = 0;
int flag = 0;
unsigned long pvMillis = 0;
int val=0; 


//переменные
int passenger = 0; //переменная для хранения данных с контакта контроля нахождения людей в салоне
int door = 0;//переменная для хранения данных с контакта контроля состояния тригеров дверей
int fuelPump = 0;//переменная для хранения данных с контакта реле бензонасоса
void setup() {
  // задаем режим выхода для порта, подключенного к реле
  
  pinMode(ACCPin, OUTPUT);
  // задаем режим входа для портов подключенных к кнопкам и датчикам
  pinMode (passengerPin, INPUT);
  pinMode (doorPin, INPUT);
  pinMode (fuelPumpPin, INPUT);
}
 
void loop()
{
  // код АСС

  passenger = digitalRead (passengerPin); //сохраняем состояние с контакта контроля пассажиров в переменную
  door = digitalRead (doorPin); //сохраняем состояние с контакта контроля тригеров дверей в переменную
  
  if (door == HIGH && flag == 0) //если дверь открыта , ТО
  {
    regim ++;
    flag = 1;
    if(regim>2)
   {
    regim = 1;
   } 
  }
  if(door == LOW  && flag == 1)
  {
    flag = 0;
  }
  if(regim == 1)
  {
    if(passenger==HIGH)
    {
      digitalWrite(ACCPin, HIGH);
    }
    if(passenger == LOW && fuelPump == LOW )
    {
      unsigned long curMillis = millis();
     if(curMillis - pvMillis > interval2) 
     {
       pvMillis = curMillis;  
       val ++ ;
      }
    } 
    else
    {
      val = 0;
    }
    if(val >=1)
    {
      digitalWrite(ACCPin, LOW);
    }
  }
  if(regim == 2)
  {
    if(passenger == LOW && fuelPump == LOW )
    {
      unsigned long curMillis = millis();
     if(curMillis - pvMillis > interval2) 
     {
       pvMillis = curMillis;  
       val ++ ;
     
      }
    } 
    else
    {
      val = 0;
    }
    if(val >=5)
    {
      digitalWrite(ACCPin, LOW);
    }
  }  

Так же если вы хотите 3 минуты, а не 6 то и условие в 65 строке if(val >=2) нужно поменять на if(val >=1).

triada13
Offline
Зарегистрирован: 04.01.2013

nestandart пишет:

leshak, не чистите пока тему. Мне интересно как быстро triada13 найдет свою ошибку.

Прошу прощения что долго не отвечал.

Сегодня просмотрел свой код "вооруженным" глазом, и нашел свой касяк: я третий опеатор цикла if поместил во внутрь скобок первого оператора цикла if. То есть после val++; должно быть две закр. скобки "}".

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Да. Именно так.

triada13
Offline
Зарегистрирован: 04.01.2013

Просьба к модераторам удалить мой флуд.

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

Блин такой Хороший пример запинали. 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Nikelbak, это вы о чем ?

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

Да я так

YuraSh
Offline
Зарегистрирован: 18.01.2013

У меня тоже необходимость при одном нажатии кнопки выполнять одно действие. В голове вырисовался такой алгоритм.

К каждой кнопке есть переменная флаг. Вводим еще одну переменную (например Block-Buton). При нажатой кнопке  и переменной Block-Buton=0 флагу присваиваем 1 и Block-Buton тоже 1. Тогда, в зависимости какая кнопка была нажата производим необходимые действия и обнуляем флаг. Тогда проверяем отпущены ли все кнопки. Если да - обнуляем Block-Buton, нет - значит нет. Если Block-Buton не обнулился (читай какая то кнопка еще нажата) ни одному флагу не присвоится 1.

Artur1985
Offline
Зарегистрирован: 19.02.2013

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

Делаю свои робкие шаги в освоении Arduino.
Как правильно сделать, данное решение.

Есть кнопка, и концевик (по сути, тоже кнопка).
Нажиамем и удерживаем кнопку, запускается пневмо цилинд и идет до концевика или пока кнопка не отпущена. При этом он не должен выполнять операцию 1 и операцию 3.

У меня в голове получилось такое решение, но может оно не коректно
Разнести 1,2,3 оперции по кейзам.
 

switch(action)
{
     case 1:
       break;
      case 2:
       while (digitalRead(4) == HIGH && state != HIGH)
       {
         digitalWrite(13, digitalRead(4));
       }
       break;
      case 3:
       break;       
 }

Код корявый, знаю, но сама идея правильна?
 

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

>>Код корявый, знаю<<

Давайте весь код.

>>но сама идея правильна?<<

Не совсем. Использование while нецелесообразно. Получается так что вся ваша программа стоит колом, пока вы не выйдете из while. Это не есть хорошо.

Artur1985
Offline
Зарегистрирован: 19.02.2013

>> Давайте весь код.

Его еще нет, пока обдумываю как сделать.
Этот набил, чтобы было понятнее.

>> Получается так что вся ваша программа стоит колом, пока вы не выйдете из while. Это не есть хорошо.
Да, я это понимаю. Но меня это не смущало, пока вы об этом не упомянули.

Переменная state, будет меняться по прерыванию от концевика. Она может не изменить из-за цикла?

>> Использование while нецелесообразно
А как это делают?
Нужно не просто включить выключить, а именно нажать и держать, пока нажата кнопка цилиндр идет.

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Все это можно сделать с помощью конструкций if else.

Вы полностью весь алгоритм набросайте. ПОсмотрим что можно сделать.

Artur1985
Offline
Зарегистрирован: 19.02.2013

Я так понял, вы предлагаете проверять на каждом выполнении loop и выставлять включение, выключение.

Ок, думаю, к обеду завтра напишу.

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

Спасибо.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

>>Делаю свои робкие шаги в освоении Arduino.
Как правильно сделать, данное решение.<<

Вы спросили как правильно ?

 Я сказал свое мнение.

Тем более что это начало вашей дружбы с МК. И , изначально привыкать к вот таким решениям не стоит. Их нужно применять когда нет другого варианта. 

Я имею в виду торможение (а тем более остановку) программы. 

Artur1985
Offline
Зарегистрирован: 19.02.2013

>> Вы спросили как правильно ?
>> Я сказал свое мнение.
Наверно я не правильно выразился.

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

>> И заодно проверю, срабатывает прерывание и таймер, то, что он останавливает ход выполнения это не минус, в данном конкретном случае.
Это простое любопытсво, во мне заиграло:).

Разумеется, хочется правильно, поэтому и обратился.

 

Artur1985
Offline
Зарегистрирован: 19.02.2013

Уф, даже быстрее управился, думал уйдет день.
 

// Переменные контактов
int btnMode = 27; // Кнопка выбора режима

int btnStop = 28; // Кнопка экстренной остановки

int btnPause = 29; // Кнопка остановки

int btnStart = 30; // Кнопка старта

// Для автоматического режима
int keyFrameDown = 31; // Запуск опускания рамки
int senFrameDown = 32; // Концевик опускания рамки 32

int keyPlateForward = 33; // Запуск плиты вперед
int senPlateForward = 34; // Концевик запуска плиты вперед 34

int keyStartPlate = 35; // Включение плиты
int senPlateStartTimmer = 32; // Получение от плиты команды на запуск таймера 36

int keyPlateBack = 37; // Запуск плиты назад 
int senPlateBack = 34; // Концевик плиты назад 38

int keyBulgeOn = 39; // Включение раздува

int keyFormUp = 40; // Подъем формы
int senFormUp = 32; // Концевик подъема формы 41

int keyVacuumOn = 42; // Включение вакуума

int keyBlowingupOn = 43; // Включение раздува воздуха

int keyFrameUp = 44; // Запуск подъема рамки
int senTFrameUp = 34; // Концевик подъема рамки 45
// /Для автоматического режима
// Для ручного режима
int btnFrameDown = 22; // Кнопка опускания рамки

int btnPlateForward = 23; // Кнопка запуска плиты вперед

int btnStartPlate = 19; // Кнопка включения плиты

int btnPlateBack = 18; // Кнопка запуска плиты назад 

int btnBulgeOn = 17; // Кнопка включения раздува

int btnFormUp = 16; // Кнопка подъема формы

int btnVacuumOn = 15; // Кнопка включения вакуума

int btnBlowingupOn = 14; // Кнопка включение раздува воздуха

int btnFrameUp = 7; // Запуск подъема рамки
// /Для ручного режима
// /Переменные контактов

// Перечисления автомата
typedef enum {
  STATE_None, // Начало работы
  STATE_Start, // Старт программы + запуск опускания рамки
  STATE_WaitFrameDown, // Ждем сработки от концовика опускания рамки
  STATE_PlateForward, // Запуск плиты вперед
  STATE_WaitPlateForward, // Ждем сработки от концовика запуска плиты вперед
  STATE_StartPlate, // Включение обогрева плиты
  STATE_WaitStartPlate, // Ждем сработки окончания обогрева плиты + Отключение обогрева плиты + Запуск плиты назад 
  STATE_WaitPlateBack, // Ждем сработки от концовика запуска плиты назад + Остановка плиты назад + Включение раздува + Подъем формы
  STATE_WaitFormUp, // Ждем сработки от подъема формы + Отключение подъема формы + Отключение раздува + Включение вакумма + таймер + Отключение вакумма + Включение поддува воздуха + таймер + Отключение поддува воздуха + Запуск подъема рамки
  STATE_WaitFrameUp, // Ждем сработки от концовика подъема рамки
  STATE_End // Конец работы
 } ESTATE;
  
ESTATE state = STATE_None;
// Перечисления автомата

// Переменные COM порта
int speedCom = 9600;
// /Переменные COM порта

// Переменные
boolean currentBtnMode = LOW; // Тек. значение для кнопки выбора режима
boolean lastBtnMode = LOW; // Последние значение для кнопки выбора режима

boolean currentBtnStop = LOW; // Тек. значение для кнопки экстренной остановки
boolean lastBtnStop = LOW; // Последние значение для кнопки экстренной остановки

boolean currentBtnStart = LOW; // Тек. значение для кнопки старта
boolean lastBtnStart = LOW; // Последние значение для кнопки старта

boolean currentBtnFrameDownStatus = LOW; //  Тек. значение для кнопки опускания рамки
boolean lastBtnFrameDownStatus  = LOW; // Последние значение для кнопки опускания рамки

boolean currentBtnPlateForwardStatus = LOW; //  Тек. значение для кнопки запуска плиты вперед
boolean lastBtnPlateForwardStatus  = LOW; // Последние значение для кнопки запуска плиты вперед
// /Переменные

// Переменные таймера
int plateStartTimmerCountSec = 5; // Время в секундах, после получение от плиты команды
int vacuumOnCountSec = 5; // Время в секундах, после получение вакумма
int blowingupOnCountSec = 5;  // Время в секундах, после включения раздува воздуха

unsigned long currentPlateStartTimmer; // Считываем время, прошедшее с момента запуска программы, после получение от плиты команды
unsigned long loopPlateStartTimmer; // Считываем время, прошедшее с момента запуска таймера, после получение от плиты команды

unsigned long currentVacuumOnCountSec; // Считываем время, прошедшее с момента запуска программы, после получение вакуума
unsigned long loopVacuumOnCountSec; // Считываем время, прошедшее с момента запуска таймера, после получение вакуума

unsigned long currentBlowingupOnCountSec; // Считываем время, прошедшее с момента запуска программы, после включения раздува воздуха
unsigned long loopBlowingupOnCountSec; // Считываем время, прошедшее с момента запуска таймера, после включения раздува воздуха
// /Переменные таймера

// Настройки
void setup() 
{
  // Настраиваем контакты
  pinMode(btnMode, INPUT);  // Кнопка выбора режима
  
  pinMode(btnStop, INPUT);  // Кнопка экстренной остановки
  
  pinMode(btnPause, INPUT);  // Кнопка остановки
  
  pinMode(btnStart, INPUT);  // Кнопка старта
  
  // Для автоматического режима
  pinMode(keyFrameDown, OUTPUT);  // Запуск опускания рамки
  pinMode(senFrameDown, INPUT); // Концевик опускания рамки
  
  pinMode(keyPlateForward, OUTPUT);  // Запуск плиты вперед
  pinMode(senPlateForward, INPUT); // Концевик запуска плиты вперед
  
  pinMode(keyStartPlate, OUTPUT); // Включение плиты
  pinMode(senPlateStartTimmer, INPUT); // Получение от плиты команды на запуск таймера
  
  pinMode(keyPlateBack, OUTPUT);  // Запуск плиты назад 
  pinMode(senPlateBack, INPUT); // Концевик плиты назад 
  
  pinMode(keyBulgeOn, OUTPUT);  // Включение раздува
  
  pinMode(keyFormUp, OUTPUT);  // Подъем формы
  pinMode(senFormUp, INPUT); // Концевик подъема формы
  
  pinMode(keyVacuumOn, OUTPUT);  // Включение вакуума
  
  pinMode(keyBlowingupOn, OUTPUT);  // Включение раздува воздуха
    
  pinMode(keyFrameUp, OUTPUT);  // Запуск подъема рамки
  pinMode(senTFrameUp, INPUT); // Концевик подъема рамки
  // /Для автоматического режима
  // Для ручного режима
  pinMode(btnFrameDown, INPUT); // Кнопка опускания рамки
  
  pinMode(btnPlateForward, INPUT); // Кнопка запуска плиты вперед
 
  pinMode(btnStartPlate, INPUT); // Кнопка включения плиты

  pinMode(btnPlateBack, INPUT); // Кнопка запуска плиты назад 
  
  pinMode(btnBulgeOn, INPUT); // Кнопка включения раздува 
  
  pinMode(btnFormUp, INPUT); // Кнопка подъема формы
  
  pinMode(btnVacuumOn, INPUT); // Кнопка включения вакуума

  pinMode(btnBlowingupOn, INPUT); // Кнопка включение раздува воздуха

  pinMode(btnFrameUp, INPUT); // Запуск подъема рамки
  // /Для ручного режима
  // /Настраиваем контакты
  
  // Создаем COM объект
  Serial.begin(speedCom);  
  // /Создаем COM объект
  
  // Иницилизация
  Serial.println("Initialization"); 
  // /Иницилизация
}

// Основная программа
void loop()
{
  // Проверка нажата ли кнопка ручного режима
  if (digitalRead(btnMode) == HIGH)
  //if (digitalRead(btnMode) == LOW)
  {
    // Автоматический режим   
    switch (state) {
      // Начало работы
      case STATE_None:
        if (digitalRead(btnStart) == HIGH)
        {
          state = STATE_Start;
          Serial.println("Start Auto Cycle"); // Запуск автоматического режима
        }
        break;
      case STATE_Start:
        digitalWrite(keyFrameDown, HIGH); // Старт программы + запуск опускания рамки
        state = STATE_WaitFrameDown;
        Serial.println("A_1");
        break;
      case STATE_WaitFrameDown:
        if (digitalRead(senFrameDown) == HIGH)
        {
          digitalWrite(keyFrameDown, LOW); // Остановка опускания рамки
          state = STATE_PlateForward;
          Serial.println("A_2");
        }
        break;
      case STATE_PlateForward:
        digitalWrite(keyPlateForward, HIGH); // Запуск плиты вперед
        state = STATE_WaitPlateForward;
        Serial.println("A_3");
        break;
      case STATE_WaitPlateForward:
        if (digitalRead(senPlateForward) == HIGH)
        {
          digitalWrite(keyPlateForward, LOW);  // Остановка плиты вперед
          state = STATE_StartPlate;
          Serial.println("A_4");
        }
        break; 
      case STATE_StartPlate:
        digitalWrite(keyStartPlate, HIGH);  // Включение обогрева плиты
        state = STATE_WaitStartPlate;
        Serial.println("A_5");
        break;
      case STATE_WaitStartPlate:
        if (digitalRead(senPlateStartTimmer) == HIGH)
        {
          // Включаю таймер
          SetTimmerOnMillis(currentPlateStartTimmer, loopPlateStartTimmer, plateStartTimmerCountSec);
          
          digitalWrite(keyStartPlate, LOW); // Отключение обогрева плиты
          digitalWrite(keyPlateBack, HIGH); // Запуск плиты назад 
          
          state = STATE_WaitPlateBack;
          Serial.println("A_6");
        }
        break;
      case STATE_WaitPlateBack:
        if (digitalRead(senPlateBack) == HIGH)
        {
          digitalWrite(keyPlateBack, LOW); // Остановка плиты назад 
          digitalWrite(keyBulgeOn, HIGH); // Включение раздува
          digitalWrite(keyFormUp, HIGH); // Подъем формы
          
          state = STATE_WaitFormUp;
          Serial.println("A_7");
        }
        break;
      case STATE_WaitFormUp:
        if (digitalRead(senFormUp) == HIGH)
        {
          digitalWrite(keyFormUp, LOW); // Отключение подъема формы
          digitalWrite(keyBulgeOn, LOW); // Отключение раздува
          digitalWrite(keyVacuumOn, HIGH); // Включение вакумма
          
          // Включаю таймер
          SetTimmerOnMillis(currentVacuumOnCountSec, loopVacuumOnCountSec, vacuumOnCountSec);
          
          digitalWrite(keyVacuumOn, LOW); // Отключение вакумма
          digitalWrite(keyBlowingupOn, HIGH); // Включение поддува воздуха
          
          // Включаю таймер
          SetTimmerOnMillis(currentBlowingupOnCountSec, loopBlowingupOnCountSec, blowingupOnCountSec);
          
          digitalWrite(keyBlowingupOn, LOW); // Отключение поддува воздуха    
          digitalWrite(keyFrameUp, HIGH);  // Запуск подъема рамки
          
          state = STATE_WaitFrameUp;
          Serial.println("A_8");
        }
        break;
      case STATE_WaitFrameUp:
        if (digitalRead(senTFrameUp) == HIGH)
        {
          digitalWrite(keyFrameUp, LOW);  // Отключение подъема рамки
          
          state = STATE_None;
          Serial.println("End Auto Cycle");
        }
        break;  
    }
  }
  else if (digitalRead(btnMode) == LOW)
  {
    // Ручной режим
    if (digitalRead(btnFrameDown) == HIGH && digitalRead(senFrameDown) != HIGH)
    {
      digitalWrite(keyFrameDown, HIGH); // Запуск опускания рамки
      Serial.println("M_1");
    }
    else if ((digitalRead(btnFrameDown) == LOW || digitalRead(senFrameDown) == HIGH))
    {
      if (digitalRead(keyFrameDown) == HIGH)
      {
        digitalWrite(keyFrameDown, LOW); // Остановка опускания рамки
        Serial.println("M_1_1");
      }
    }
    
    if (digitalRead(btnPlateForward) == HIGH && digitalRead(senPlateForward) != HIGH)
    {
      digitalWrite(keyPlateForward, HIGH); // Запуск опускания рамки
      Serial.println("M_2");
    }
    else if ((digitalRead(btnPlateForward) == LOW || digitalRead(senPlateForward) == HIGH))
    {
      if (digitalRead(keyPlateForward) == HIGH)
      {
        digitalWrite(keyPlateForward, LOW); // Остановка опускания рамки
        Serial.println("M_2_1");
      }
    }
  }
}

// Функция таймер с задержкой, вместо delay
void SetTimmerOnMillis(long currentPlateStartTimmer, long loopPlateStartTimmer, int plateStartTimmerCountSec)
{
    currentPlateStartTimmer = millis();       // считываем время, прошедшее с момента запуска программы
    loopPlateStartTimmer = currentPlateStartTimmer;  
    while (currentPlateStartTimmer <= (loopPlateStartTimmer + (plateStartTimmerCountSec * 1000)))
    {
      currentPlateStartTimmer= millis(); 
    }
}

/* Не используется */ 
// Функция удаления дребезга кнопок
boolean Debounce(boolean lastValue, int switchPin)
{
  boolean currentValue = digitalRead(switchPin);
  if (lastValue != currentValue)
  {
    long currentTime  = millis();
    long loopTime = currentTime;  
    while (currentTime <= (loopTime + 5))
    {
      currentTime = millis(); 
    }
    
    currentValue = digitalRead(switchPin);
  }
  return currentValue;
}

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

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

Сейчас коректно?

Исправил в 18.47, там была ошибка, оказывается порты с 14 по 21, как-то забавно себя ведут.
Код очень похож на C#, мне моментом стало все понятно.

Вот в электронике пока, ни чего не смылю.

 

Artur1985
Offline
Зарегистрирован: 19.02.2013

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

nestandart большое спасибо.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Извиняюсь , но я еще не изучал вашу программу.

Занят с срочным заказом. Посмотрю завтра.

Artur1985
Offline
Зарегистрирован: 19.02.2013

Тут не за что извинятся.
Спасибо. 

Artur1985
Offline
Зарегистрирован: 19.02.2013
// Переменные контактов
int btnMode = 27; // Кнопка выбора режима

int btnStop = 28; // Кнопка экстренной остановки

int btnPause = 29; // Кнопка остановки

int btnStart = 30; // Кнопка старта

// Для автоматического режима
int keyFrameDown = 31; // Запуск опускания рамки
int senFrameDown = 32; // Концевик опускания рамки 32

int keyPlateForward = 33; // Запуск плиты вперед
int senPlateForward = 34; // Концевик запуска плиты вперед 34

int keyStartPlate = 35; // Включение плиты
int senPlateStartTimmer = 32; // Получение от плиты команды на запуск таймера 36

int keyPlateBack = 37; // Запуск плиты назад 
int senPlateBack = 34; // Концевик плиты назад 38

int keyBulgeOn = 39; // Включение раздува

int keyFormUp = 40; // Подъем формы
int senFormUp = 32; // Концевик подъема формы 41

int keyVacuumOn = 42; // Включение вакуума

int keyBlowingupOn = 43; // Включение раздува воздуха

int keyFrameUp = 44; // Запуск подъема рамки
int senFrameUp = 34; // Концевик подъема рамки 45
// /Для автоматического режима
// Для ручного режима
int btnFrameDown = 21; // Кнопка опускания рамки

int btnPlateForward = 20; // Кнопка запуска плиты вперед

int btnStartPlate = 19; // Кнопка включения плиты

int btnPlateBack = 18; // Кнопка запуска плиты назад

int btnBulgeOn = 17; // Кнопка включения раздува

int btnFormUp = 16; // Кнопка подъема формы 

int btnVacuumOn = 15; // Кнопка включения вакуума

int btnBlowingupOn = 14; // Кнопка включение раздува воздуха 14

int btnFrameUp = 22; // Запуск подъема рамки 7
// /Для ручного режима
// /Переменные контактов

// Перечисления автомата
typedef enum {
  STATE_None, // Начало работы
  STATE_Start, // Старт программы + запуск опускания рамки
  STATE_WaitFrameDown, // Ждем сработки от концовика опускания рамки
  STATE_PlateForward, // Запуск плиты вперед
  STATE_WaitPlateForward, // Ждем сработки от концовика запуска плиты вперед
  STATE_StartPlate, // Включение обогрева плиты
  STATE_WaitStartPlate, // Ждем сработки окончания обогрева плиты + Отключение обогрева плиты + Запуск плиты назад 
  STATE_WaitPlateBack, // Ждем сработки от концовика запуска плиты назад + Остановка плиты назад + Включение раздува + Подъем формы
  STATE_WaitFormUp, // Ждем сработки от подъема формы + Отключение подъема формы + Отключение раздува + Включение вакуума + таймер + Отключение вакуума + Включение поддува воздуха + таймер + Отключение поддува воздуха + Запуск подъема рамки
  STATE_WaitFrameUp, // Ждем сработки от концовика подъема рамки
  STATE_End // Конец работы
 } ESTATE;
  
ESTATE state = STATE_None;
// Перечисления автомата

// Переменные COM порта
int speedCom = 9600;
// /Переменные COM порта

// Переменные
boolean currentBtnMode = LOW; // Тек. значение для кнопки выбора режима
boolean lastBtnMode = LOW; // Последние значение для кнопки выбора режима

boolean currentBtnStop = LOW; // Тек. значение для кнопки экстренной остановки
boolean lastBtnStop = LOW; // Последние значение для кнопки экстренной остановки

boolean currentBtnStart = LOW; // Тек. значение для кнопки старта
boolean lastBtnStart = LOW; // Последние значение для кнопки старта

boolean flagStartPlate = LOW; // Флаг хранения состояния кнопки включение плиты

boolean currentBtnBulgeOn = LOW; // Тек. значение для кнопки раздува
boolean lastBtnBulgeOn = LOW; // Последние значение для кнопки раздува
boolean flagBulgeOn = LOW; // Флаг хранения состояния кнопки раздува

boolean currentBtnVacuumOn = LOW; // Тек. значение для кнопки вакуума
boolean lastBtnVacuumOn = LOW; // Последние значение для кнопки вакуума
boolean flagVacuumOn = LOW; // Флаг хранения состояния кнопки вакуума

boolean currentBtnBlowingupOn = LOW; // Тек. значение для кнопки раздува воздуха
boolean lastBtnBlowingupOn = LOW; // Последние значение для кнопки раздува воздуха
boolean flagBlowingupOn = LOW; // Флаг хранения состояния кнопки раздува воздуха
// /Переменные

// Переменные таймера
int plateStartTimmerCountSec = 5; // Время в секундах, после получение от плиты команды
int vacuumOnCountSec = 5; // Время в секундах, после получение вакуума
int blowingupOnCountSec = 5;  // Время в секундах, после включения раздува воздуха

unsigned long currentPlateStartTimmer; // Считываем время, прошедшее с момента запуска программы, после получение от плиты команды
unsigned long loopPlateStartTimmer; // Считываем время, прошедшее с момента запуска таймера, после получение от плиты команды

unsigned long currentVacuumOnCountSec; // Считываем время, прошедшее с момента запуска программы, после получение вакуума
unsigned long loopVacuumOnCountSec; // Считываем время, прошедшее с момента запуска таймера, после получение вакуума

unsigned long currentBlowingupOnCountSec; // Считываем время, прошедшее с момента запуска программы, после включения раздува воздуха
unsigned long loopBlowingupOnCountSec; // Считываем время, прошедшее с момента запуска таймера, после включения раздува воздуха
// /Переменные таймера

// Настройки
void setup() 
{
  // Настраиваем контакты
  pinMode(btnMode, INPUT);  // Кнопка выбора режима
  
  pinMode(btnStop, INPUT);  // Кнопка экстренной остановки
  
  pinMode(btnPause, INPUT);  // Кнопка остановки
  
  pinMode(btnStart, INPUT);  // Кнопка старта
  
  // Для автоматического режима
  pinMode(keyFrameDown, OUTPUT);  // Запуск опускания рамки
  pinMode(senFrameDown, INPUT); // Концевик опускания рамки
  
  pinMode(keyPlateForward, OUTPUT);  // Запуск плиты вперед
  pinMode(senPlateForward, INPUT); // Концевик запуска плиты вперед
  
  pinMode(keyStartPlate, OUTPUT); // Включение плиты
  pinMode(senPlateStartTimmer, INPUT); // Получение от плиты команды на запуск таймера
  
  pinMode(keyPlateBack, OUTPUT);  // Запуск плиты назад 
  pinMode(senPlateBack, INPUT); // Концевик плиты назад 
  
  pinMode(keyBulgeOn, OUTPUT);  // Включение раздува
  
  pinMode(keyFormUp, OUTPUT);  // Подъем формы
  pinMode(senFormUp, INPUT); // Концевик подъема формы
  
  pinMode(keyVacuumOn, OUTPUT);  // Включение вакуума
  
  pinMode(keyBlowingupOn, OUTPUT);  // Включение раздува воздуха
    
  pinMode(keyFrameUp, OUTPUT);  // Запуск подъема рамки
  pinMode(senFrameUp, INPUT); // Концевик подъема рамки
  // /Для автоматического режима
  // Для ручного режима
  pinMode(btnFrameDown, INPUT); // Кнопка опускания рамки
  
  pinMode(btnPlateForward, INPUT); // Кнопка запуска плиты вперед
 
  pinMode(btnStartPlate, INPUT); // Кнопка включения плиты

  pinMode(btnPlateBack, INPUT); // Кнопка запуска плиты назад 
  
  pinMode(btnBulgeOn, INPUT); // Кнопка включения раздува 
  
  pinMode(btnFormUp, INPUT); // Кнопка подъема формы
  
  pinMode(btnVacuumOn, INPUT); // Кнопка включения вакуума

  pinMode(btnBlowingupOn, INPUT); // Кнопка включение раздува воздуха

  pinMode(btnFrameUp, INPUT); // Запуск подъема рамки
  // /Для ручного режима
  // /Настраиваем контакты
  
  // Создаем COM объект
  Serial.begin(speedCom);  
  // /Создаем COM объект
  
  // Иницилизация
  Serial.println("Initialization"); 
  // /Иницилизация
}

// Основная программа
void loop()
{
  // Проверка нажата ли кнопка ручного режима
  if (digitalRead(btnMode) == HIGH)
  //if (digitalRead(btnMode) == LOW)
  {
    // Автоматический режим   
    switch (state) {
      // Начало работы
      case STATE_None:
        if (digitalRead(btnStart) == HIGH)
        {
          state = STATE_Start;
          Serial.println("Start Auto Cycle"); // Запуск автоматического режима
        }
        break;
      case STATE_Start:
        digitalWrite(keyFrameDown, HIGH); // Старт программы + запуск опускания рамки
        state = STATE_WaitFrameDown;
        Serial.println("A_1");
        break;
      case STATE_WaitFrameDown:
        if (digitalRead(senFrameDown) == HIGH)
        {
          digitalWrite(keyFrameDown, LOW); // Остановка опускания рамки
          state = STATE_PlateForward;
          Serial.println("A_2");
        }
        break;
      case STATE_PlateForward:
        digitalWrite(keyPlateForward, HIGH); // Запуск плиты вперед
        state = STATE_WaitPlateForward;
        Serial.println("A_3");
        break;
      case STATE_WaitPlateForward:
        if (digitalRead(senPlateForward) == HIGH)
        {
          digitalWrite(keyPlateForward, LOW);  // Остановка плиты вперед
          state = STATE_StartPlate;
          Serial.println("A_4");
        }
        break; 
      case STATE_StartPlate:
        digitalWrite(keyStartPlate, HIGH);  // Включение обогрева плиты
        state = STATE_WaitStartPlate;
        Serial.println("A_5");
        break;
      case STATE_WaitStartPlate:
        if (digitalRead(senPlateStartTimmer) == HIGH)
        {
          // Включаю таймер
          SetTimmerOnMillis(currentPlateStartTimmer, loopPlateStartTimmer, plateStartTimmerCountSec);
          
          digitalWrite(keyStartPlate, LOW); // Отключение обогрева плиты
          digitalWrite(keyPlateBack, HIGH); // Запуск плиты назад 
          
          state = STATE_WaitPlateBack;
          Serial.println("A_6");
        }
        break;
      case STATE_WaitPlateBack:
        if (digitalRead(senPlateBack) == HIGH)
        {
          digitalWrite(keyPlateBack, LOW); // Остановка плиты назад 
          digitalWrite(keyBulgeOn, HIGH); // Включение раздува
          digitalWrite(keyFormUp, HIGH); // Подъем формы
          
          state = STATE_WaitFormUp;
          Serial.println("A_7");
        }
        break;
      case STATE_WaitFormUp:
        if (digitalRead(senFormUp) == HIGH)
        {
          digitalWrite(keyFormUp, LOW); // Отключение подъема формы
          digitalWrite(keyBulgeOn, LOW); // Отключение раздува
          digitalWrite(keyVacuumOn, HIGH); // Включение вакуума
          
          // Включаю таймер
          SetTimmerOnMillis(currentVacuumOnCountSec, loopVacuumOnCountSec, vacuumOnCountSec);
          
          digitalWrite(keyVacuumOn, LOW); // Отключение вакуума
          digitalWrite(keyBlowingupOn, HIGH); // Включение поддува воздуха
          
          // Включаю таймер
          SetTimmerOnMillis(currentBlowingupOnCountSec, loopBlowingupOnCountSec, blowingupOnCountSec);
          
          digitalWrite(keyBlowingupOn, LOW); // Отключение поддува воздуха    
          digitalWrite(keyFrameUp, HIGH);  // Запуск подъема рамки
          
          state = STATE_WaitFrameUp;
          Serial.println("A_8");
        }
        break;
      case STATE_WaitFrameUp:
        if (digitalRead(senFrameUp) == HIGH)
        {
          digitalWrite(keyFrameUp, LOW);  // Отключение подъема рамки
          
          state = STATE_None;
          Serial.println("End Auto Cycle");
        }
        break;  
    }
  }
  else if (digitalRead(btnMode) == LOW)
  {
    // Ручной режим, отладка
    if (digitalRead(btnFrameDown) == HIGH && digitalRead(senFrameDown) != HIGH)
    {
      digitalWrite(keyFrameDown, HIGH); // Запуск опускания рамки
      Serial.println("M_1");
    }
    else if ((digitalRead(btnFrameDown) == LOW || digitalRead(senFrameDown) == HIGH))
    {
      if (digitalRead(keyFrameDown) == HIGH)
      {
        digitalWrite(keyFrameDown, LOW); // Остановка опускания рамки
        Serial.println("M_1_1");
      }
    }
    
    if (digitalRead(btnPlateForward) == HIGH && digitalRead(senPlateForward) != HIGH)
    {
      digitalWrite(keyPlateForward, HIGH); // Запуск плиты вперед
      Serial.println("M_2");
    }
    else if ((digitalRead(btnPlateForward) == LOW || digitalRead(senPlateForward) == HIGH))
    {
      if (digitalRead(keyPlateForward) == HIGH)
      {
        digitalWrite(keyPlateForward, LOW); // Остановка плиты вперед
        Serial.println("M_2_1");
      }
    }
    
    if (flagStartPlate == LOW && digitalRead(btnStartPlate) == HIGH && digitalRead(senPlateStartTimmer) != HIGH)
    {
      digitalWrite(keyStartPlate, HIGH); // Включение обогрева плиты
      flagStartPlate = HIGH;
      
      Serial.println("M_3");
    }
    else if (digitalRead(senPlateStartTimmer) == HIGH)
    {
      if (flagStartPlate == HIGH && digitalRead(keyStartPlate) == HIGH)
      {
        // Включаю таймер
        SetTimmerOnMillis(currentPlateStartTimmer, loopPlateStartTimmer, plateStartTimmerCountSec);
          
        digitalWrite(keyStartPlate, LOW); // Отключение обогрева плиты
        flagStartPlate = LOW;
        
        Serial.println("M_3_1");
      }
    }
    
    if (digitalRead(btnPlateBack) == HIGH && digitalRead(senPlateBack) != HIGH)
    {
      digitalWrite(keyPlateBack, HIGH); // Запуск плиты назад 
      Serial.println("M_4");
    }
    else if ((digitalRead(btnPlateBack) == LOW || digitalRead(senPlateBack) == HIGH))
    {
      if (digitalRead(keyPlateBack) == HIGH)
      {
        digitalWrite(keyPlateBack, LOW); // Остановка плиты назад 
        Serial.println("M_4_1");
      }
    }
    
    currentBtnBulgeOn = Debounce(lastBtnBulgeOn, btnBulgeOn);
    if(currentBtnBulgeOn == HIGH && flagBulgeOn == LOW)
    { 
       flagBulgeOn = HIGH;       
    } 
       
    if(currentBtnBulgeOn == LOW && flagBulgeOn == HIGH)
    { 
        digitalWrite(keyBulgeOn, !digitalRead(keyBulgeOn)); // Включаем или отключаем раздув
        if (digitalRead(keyBulgeOn) == HIGH)
        {
          Serial.println("M_5");
        }
        else 
        {
          Serial.println("M_5_1");
        }
        flagBulgeOn = LOW;
    }
   
    if (digitalRead(btnFormUp) == HIGH && digitalRead(senFormUp) != HIGH)
    {
      digitalWrite(keyFormUp, HIGH); // Запуск подъема формы
      Serial.println("M_6");
    }
    else if ((digitalRead(btnFormUp) == LOW || digitalRead(senFormUp) == HIGH))
    {
      if (digitalRead(keyFormUp) == HIGH)
      {
        digitalWrite(keyFormUp, LOW); // Отключение подъема формы
        Serial.println("M_6_1");
      }
    }
    
    currentBtnVacuumOn = Debounce(lastBtnVacuumOn, btnVacuumOn);
    if(currentBtnVacuumOn == HIGH && flagVacuumOn == LOW)
    { 
       flagVacuumOn = HIGH;       
    } 
       
    if(currentBtnVacuumOn == LOW && flagVacuumOn == HIGH)
    { 
        digitalWrite(keyVacuumOn, !digitalRead(keyVacuumOn)); // Включаем или отключаем вакуума
        if (digitalRead(keyVacuumOn) == HIGH)
        {
          Serial.println("M_7");
        }
        else 
        {
          Serial.println("M_7_1");
        }
        flagVacuumOn = LOW;
    }
    
    currentBtnBlowingupOn = Debounce(lastBtnBlowingupOn, btnBlowingupOn);
    if(currentBtnBlowingupOn == HIGH && flagBlowingupOn == LOW)
    { 
       flagBlowingupOn = HIGH;       
    } 
       
    if(currentBtnBlowingupOn == LOW && flagBlowingupOn == HIGH)
    { 
        digitalWrite(keyBlowingupOn, !digitalRead(keyBlowingupOn)); // Включаем или отключаем вакуума
        if (digitalRead(keyBlowingupOn) == HIGH)
        {
          Serial.println("M_8");
        }
        else 
        {
          Serial.println("M_8_1");
        }
        flagBlowingupOn = LOW;
    }
    
    if (digitalRead(btnFrameUp) == HIGH && digitalRead(senFrameUp) != HIGH)
    {
      digitalWrite(keyFrameUp, HIGH); // Запуск подъема рамки
      Serial.println("M_9");
    }
    else if ((digitalRead(btnFormUp) == LOW || digitalRead(senFrameUp) == HIGH))
    {
      if (digitalRead(keyFrameUp) == HIGH)
      {
        digitalWrite(keyFrameUp, LOW); // Отключение подъема рамки  
        Serial.println("M_9_1");
      }
    }
  }
}

// Функция таймер с задержкой, вместо delay
void SetTimmerOnMillis(long currentPlateStartTimmer, long loopPlateStartTimmer, int plateStartTimmerCountSec)
{
    currentPlateStartTimmer = millis();       // считываем время, прошедшее с момента запуска программы
    loopPlateStartTimmer = currentPlateStartTimmer;  
    while (currentPlateStartTimmer <= (loopPlateStartTimmer + (plateStartTimmerCountSec * 1000)))
    {
      currentPlateStartTimmer= millis(); 
    }
}

// Функция удаления дребезга кнопок
boolean Debounce(boolean lastValue, int switchPin)
{
  boolean currentValue = digitalRead(switchPin);
  if (lastValue != currentValue)
  {
    long currentTime  = millis();
    long loopTime = currentTime;  
    while (currentTime <= (loopTime + 5))
    {
      currentTime = millis(); 
    }
    
    currentValue = digitalRead(switchPin);
  }
  return currentValue;
}

Конечное решение на сегодняшний день. Еще появится ручной режим, но это все после того, как станок будет сделан в металле . Может еще какие-то удобства для оператора.