Работа с кнопкой, переключение режимов.

Nayn
Nayn аватар
Offline
Зарегистрирован: 22.01.2019

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

int regim=1; 
int flag=0; 

void setup() {
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}

void loop() {
  
     if(digitalRead(12)==HIGH&&flag==0)//если кнопка нажата   
     // и переменная flag равна 0 , то ... 
     { 
       regim++;   
       flag=1; 
         
        //это нужно для того что бы с каждым нажатием кнопки 
        //происходило только одно действие 
        // плюс защита от "дребезга"  100% 
          
        if(regim>4)//ограничим количество режимов 
        { 
          regim=1;//так как мы используем только одну кнопку, 
                    // то переключать режимы будем циклично 
        } 
       
     } 
       
      if(digitalRead(12)==LOW&&flag==1)//если кнопка НЕ нажата 
     //и переменная flag равна - 1 ,то ... 
     { 
          
        flag=0;//обнуляем переменную "knopka" 
     }  

  if(regim==1)//первый режим 
  { 
  delay(200);
  digitalWrite(3, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);  
  delay(1000);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);
  digitalWrite(7, LOW);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
  digitalWrite(10, LOW);
  delay(500);
  }
  
  if(regim==2)//второй режим 
  { 
  digitalWrite(3, HIGH);  delay(100);              
  digitalWrite(3, LOW);   delay(100);              
  digitalWrite(4, HIGH);  delay(100);              
  digitalWrite(4, LOW);   delay(100);              
  digitalWrite(5, HIGH);  delay(100);              
  digitalWrite(5, LOW);   delay(100);              
  digitalWrite(6, HIGH);  delay(100);              
  digitalWrite(6, LOW);   delay(100);              
  digitalWrite(7, HIGH);  delay(100);              
  digitalWrite(7, LOW);   delay(100);          
  digitalWrite(8, HIGH);  delay(100);              
  digitalWrite(8, LOW);   delay(100); 
  digitalWrite(9, HIGH);  delay(100);              
  digitalWrite(9, LOW);   delay(100); 
  digitalWrite(10, HIGH); delay(100);              
  digitalWrite(10, LOW);  delay(100); 
  digitalWrite(10, HIGH); delay(100);              
  digitalWrite(10, LOW);  delay(100);              
  digitalWrite(9, HIGH);  delay(100);              
  digitalWrite(9, LOW);   delay(100);              
  digitalWrite(8, HIGH);  delay(100);              
  digitalWrite(8, LOW);   delay(100);              
  digitalWrite(7, HIGH);  delay(100);              
  digitalWrite(7, LOW);   delay(100);              
  digitalWrite(6, HIGH);  delay(100);              
  digitalWrite(6, LOW);   delay(100);          
  digitalWrite(5, HIGH);  delay(100);              
  digitalWrite(5, LOW);   delay(100); 
  digitalWrite(4, HIGH);  delay(100);              
  digitalWrite(4, LOW);   delay(100); 
  digitalWrite(3, HIGH);  delay(100);              
  digitalWrite(3, LOW);   delay(100);
  }
 
  if(regim==3)//третий режим 
  {   
  digitalWrite(3, HIGH);  delay(200);              
  digitalWrite(4, HIGH);  delay(200);              
  digitalWrite(5, HIGH);  delay(200);              
  digitalWrite(6, HIGH);  delay(200);              
  digitalWrite(7, HIGH);  delay(200);
  digitalWrite(8, HIGH);  delay(200);  
  digitalWrite(9, HIGH);  delay(200);  
  digitalWrite(10, HIGH); delay(200);  
  digitalWrite(10, LOW);  delay(200);     
  digitalWrite(9, LOW);   delay(200);   
  digitalWrite(8, LOW);   delay(200);              
  digitalWrite(7, LOW);   delay(200);              
  digitalWrite(6, LOW);   delay(200);              
  digitalWrite(5, LOW);   delay(200);              
  digitalWrite(4, LOW);   delay(200);              
  digitalWrite(3, LOW);   delay(200);  
  }
  
  if(regim==4)//четвертый режим 
  { 
  digitalWrite(10, HIGH);  delay(200);              
  digitalWrite(9, HIGH);  delay(200);              
  digitalWrite(8, HIGH);  delay(200);              
  digitalWrite(7, HIGH);  delay(200);              
  digitalWrite(6, HIGH);  delay(200);
  digitalWrite(5, HIGH);  delay(200);  
  digitalWrite(4, HIGH);  delay(200);  
  digitalWrite(3, HIGH); delay(200);  
  digitalWrite(3, LOW);  delay(200);     
  digitalWrite(4, LOW);   delay(200);   
  digitalWrite(5, LOW);   delay(200);              
  digitalWrite(6, LOW);   delay(200);              
  digitalWrite(7, LOW);   delay(200);              
  digitalWrite(8, LOW);   delay(200);              
  digitalWrite(9, LOW);   delay(200);              
  digitalWrite(10, LOW);   delay(200);
  }   
}

 

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

Nayn пишет:

Я новичек по ардуино

Это отягчающее апстаятельство здесь

А по коду - избавься от всех delay().

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Вам сюда - читать до понимания.

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

Я все-таки, для начала, попроще предложу. Но это ТС не спасет. Здесь, не грех и про циклы разные и про функции почитать. ИМХО.

Nayn
Nayn аватар
Offline
Зарегистрирован: 22.01.2019

Изначально натыкал много delay() для регулировки вручную каждого светодиода по времени.

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

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

Попробую объяснить простейше, чтобы поняли принцип.
1. Читаете про функции и все ваши пять блоков выводите в отдельные.
2. В каждой функции режимов, после delay вызываете функцию чтения кнопки. Если после вызова номер режима изменился (потребуется дополнительная переменная), делаем return и выходим обратно в луп. Если нет, продолжаем дальше.
3. С задержками в 100-200мС будет подтормаживать, но терпимо, делеями в 500-1000мС придется пожертвовать или разбить их на 5-10штук и между ними вызов кнопок..
4. Для симпатичной работы понадобится еще одна функция, гашения всех светиков. Ее вызывать перед return.
5. В лупе остаются ифы с переходами на функции режимов и вызов чтения кнопок.
6. Код будет гнуснейший, но рабочий. 
7. Осмыслите принцип, можно миллисов пробовать прикорячить. ИМХО.

 

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

Ну если в образовательных целях то держи один из вариантов 

int regim=0; 
uint8_t temp_regim;
uint8_t number = 0;
uint8_t led = 3;
bool value = 1; 
int flag=0; 
uint32_t time;

void setup() {
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, INPUT);
}

void loop() {

  if(digitalRead(12)==HIGH && flag==0)//если кнопка нажата   
    // и переменная flag равна 0 , то ... 
  { 
    regim++;   
    flag=1; 
    number = 0;
    value = 1;
    led = 3;

    if(regim>2)//ограничим количество режимов 
    { 
      regim = 0;//так как мы используем только одну кнопку, 
      // то переключать режимы будем циклично 
    } 
    if(regim == 1) time = millis();
    for(int i=3; i<11; i++)
    {
      digitalWrite(i, LOW);
    }
  } 

  if(digitalRead(12)==LOW&&flag==1)//если кнопка НЕ нажата 
    //и переменная flag равна - 1 ,то ... 
  { 
    flag=0;//обнуляем переменную "knopka" 
  }  

  if(regim==1 && !flag)//первый режим 
  { 
    static uint16_t pausa = 200;
    //static uint8_t number = 0;
    if(millis() - time >= pausa)
    {
      time = millis();
      switch(number)
      {
      case 0:
        digitalWrite(3, HIGH);
        digitalWrite(4, HIGH);
        digitalWrite(5, HIGH);
        digitalWrite(6, HIGH);
        digitalWrite(7, HIGH);
        digitalWrite(8, HIGH);
        digitalWrite(9, HIGH);
        digitalWrite(10, HIGH);
        number++;
        pausa = 1000;            ///1000  
        break;
      case 1:
        digitalWrite(3, LOW);
        digitalWrite(4, LOW);
        digitalWrite(5, LOW);
        digitalWrite(6, LOW);
        digitalWrite(7, LOW);
        digitalWrite(8, LOW);
        digitalWrite(9, LOW);
        digitalWrite(10, LOW);
        number--;
        pausa = 700;            /// 
        break;
      }
    }
  }

  if(regim == 2 && !flag)//режим 2 
  { 
    static uint16_t pausa = 100;
    

    //static uint8_t number = 0;

    if(millis() - time >= pausa)
    {
      time = millis();
      switch(number)
      {
      case 0:
        digitalWrite(led, value);
        value = !value;
        number++;
        break;
      case 1:
        digitalWrite(led, value);
        value = !value;
        led++;
        if(led >= 10)number++;
        else number--;
        break;
      case 2:
        digitalWrite(led, value);
        value = !value;
        number++;
        break;
      case 3:
        digitalWrite(led, value);
        value = !value;
        led--;
        if(led <= 3)number = 0;
        else number--;
        break;
      }
    }
  }
}

 

Nayn
Nayn аватар
Offline
Зарегистрирован: 22.01.2019

Круто! Буду изучать, очень благодарен за помощь. Спасибо!

P.S. Подскажешь какую книгу по Ардуино почитать?

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

bwn пишет:

Попробую объяснить простейше, чтобы поняли принцип.
1. Читаете про функции и все ваши пять блоков выводите в отдельные.
2. В каждой функции режимов, после delay вызываете функцию чтения кнопки. Если после вызова номер режима изменился (потребуется дополнительная переменная), делаем return и выходим обратно в луп. Если нет, продолжаем дальше.
3. С задержками в 100-200мС будет подтормаживать, но терпимо, делеями в 500-1000мС придется пожертвовать или разбить их на 5-10штук и между ними вызов кнопок..
4. Для симпатичной работы понадобится еще одна функция, гашения всех светиков. Ее вызывать перед return.
5. В лупе остаются ифы с переходами на функции режимов и вызов чтения кнопок.
6. Код будет гнуснейший, но рабочий. 
7. Осмыслите принцип, можно миллисов пробовать прикорячить. ИМХО.

 

Теперь для расширения аудитории будем размещать на форуме порнографию?

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

andriano пишет:
Теперь для расширения аудитории будем размещать на форуме порнографию?

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

andriano пишет:

Теперь для расширения аудитории будем размещать на форуме порнографию?

Здря, Вы, так. Никакой порнографии нет. Сперва модификация, похоже самописного, а значит понятного скетча в псевдонеблокирующий. После усвоения принципа, переход к следующим уровням. Сам пользуюсь подобными методами и позорным сие не считаю. Но, главное, ТС должен написать его САМ. За время моего присутствия, можете припомнить, чтобы выклянчивал код, хотя не обещаю, что этого когда нибудь не случится.))))

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

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

И иногда - не один раз.

В данном случаке я бы посоветовал ТС преобразовывать код в 2 этапа:

- переписать то же самое с помощью массивов и циклов,

- используя готовые массивы, заменить внутренние циклы for на одни внешний loop.