Проблемка с циклом while

arduinomaniaco
arduinomaniaco аватар
Offline
Зарегистрирован: 25.12.2013

Здравствуйте уважаемые  камрады!

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

В процессе экспериментов по программированию Ардуины, столкнулся с проблемой в цикле while...

Суть опыта в следующем:

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

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

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

Объясните, пожалуйста, где зарыта собака?  Каким образом заставить повторно работать цикл?

Есть ли какие команды, что бы после прохождения одного цикла происходил сброс параметров в исходное положение?

 

int regim=1;             
int flag=1;

int regim_1=1;
int flag_1=1;

int x=0;

void setup()      

// Задаем значение выходов для светодиодов
{
  pinMode(28,OUTPUT);  // Красный
  pinMode(30,OUTPUT);  // Зеленый
  pinMode(29,OUTPUT);  // Синий  
  pinMode(31,OUTPUT); // Белый
}

void loop()  
{                                                       

  //                                        Кнопка_1
  if(digitalRead(7)==HIGH&&flag==0)
  {
    regim++;        
    flag=1;         

    if(regim>2)
    {
      regim=1;
    }   
  }       

  if(digitalRead(7)==LOW&&flag==1)
  {     
    flag=0;
  }

  if(regim==1)
  {
    delay(50);  
    digitalWrite(28,LOW);

  }

  if(regim==2)
  {
    delay(50);
    digitalWrite(28,HIGH);
  }
 
  //                                   Кнопка_2

  if(digitalRead(6)==HIGH&&flag_1==0)
  {
    regim_1++;        
    flag_1=1;         

    if(regim_1>2)//ограничиваем режимы
    {
      regim_1=1;
    }   
  }       

  if(digitalRead(6)==LOW&&flag_1==1)
  {     
    flag_1=0;
  }

  if(regim_1==1)//первый режим
  {
    delay(50);  
    digitalWrite(30,LOW);
  }

  if(regim_1==2)//второй режим
  {
    delay(50);
    digitalWrite(30,HIGH);
  }
                                
//                     Запускаем цикл для белого светодиода

  if ((digitalRead(28)==HIGH)&&(digitalRead(30)==HIGH))
  {
    delay(300);
    while(x<=3)
    {      
      digitalWrite(31,HIGH);
      delay(300);
      digitalWrite(31,LOW);
      delay(300);
      x++;
regim=1;
regim_1=1;
    }
  }
}

olegab
Offline
Зарегистрирован: 09.04.2013

Сбрасывайте х где-нибудь.

 

arduinomaniaco
arduinomaniaco аватар
Offline
Зарегистрирован: 25.12.2013

Спасибо!!!! ЁПРСТ... Я этот "х" сбрасывал в теле цикла, поэтому было бесконечное мигание, но не дотумкал вынести х=0; перед последней фигурной скобкой...  Все заработало! Ура!  

olegab
Offline
Зарегистрирован: 09.04.2013

Для таких циклов лучше использовать for

arduinomaniaco
arduinomaniaco аватар
Offline
Зарегистрирован: 25.12.2013

Я пока не работаю над конкретной задачей, а неспешно экспериментирую с разными операторами... с циклом for пока все понятно, но вот этот while...

Раз уж открыл тему, то еще один вопросик... Хочу завершить вышеописанную задачу следующим образом, что бы светодиоды гасли поочередно с задержкой в 1 секунду, сначала зеленый, а затем, через секунду, красный. Но почему-то они гаснут одновременно через две секунды... Почему так? Ведь команды даны поочередно...

Прикрепляю крайнюю часть кода:

//                     Запускаем цикл для белого светодиода

  if ((digitalRead(28)==HIGH)&&(digitalRead(30)==HIGH))
  {
    delay(300);
    while(x<=3)
    {      
      digitalWrite(31,HIGH);
      delay(300);
      digitalWrite(31,LOW);
      delay(300);
      x++;
    }    
    x=0;
    delay(1000);
    regim_1=1; 
    delay(1000); 
    regim=1;
  }
  
} 

 

olegab
Offline
Зарегистрирован: 09.04.2013

Ых

Вы не гасите их с секундной задержкой, а меняете значения контроллирующих их переменных с секундной задержкой.

А гасятся они разом в соответствующих if при следующей итерации основного цикла

arduinomaniaco
arduinomaniaco аватар
Offline
Зарегистрирован: 25.12.2013

Спасибо! Сработало!

  if ((digitalRead(28)==HIGH)&&(digitalRead(30)==HIGH))
  {
    delay(300);
    while(x<=3)
    {      
      digitalWrite(31,HIGH);
      delay(300);
      digitalWrite(31,LOW);
      delay(300);
      x++;
    }    
    x=0;
    delay(1000);
    digitalWrite(30,LOW); 
    delay(1000); 
    digitalWrite(29,LOW);
    regim_1=1;
    regim=1;
  }

 

arduinomaniaco
arduinomaniaco аватар
Offline
Зарегистрирован: 25.12.2013

АХТУНГ! Братцы помогите, пожалуйста...
Как во время работы цикла без тормозов включать кнопку?
Допустим, отрабатывается программа и доходит до цикла из которого выйти можно нажатием на кнопку. В данный момент у меня сие выходит ни разу не с первого нажатия, а с 6-7ого, хотя кнопка подключена через антидребезговую функцию... Помогите, а-то процесс изучения заткнулся, в связи с чем накрыло обострение, аж глаз задергался... Целый день воюю - не могу найти решение... Думал установить delay, и во время паузы выходить из цикла, но видимо delay это жуткий тормоз...

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

не тормоз - просто, если сказано стоять, то кто тормоз?

http://arduino.ru/tutorials/BlinkWithoutDelay

olegab
Offline
Зарегистрирован: 09.04.2013

Без кода не понятно о чем речь.

Почитайте про операторы break и continue

arduinomaniaco
arduinomaniaco аватар
Offline
Зарегистрирован: 25.12.2013

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

Операторы break и continue, тоже прекрасны, но каким образом при их помощи можно выйти из проклятущего цикла?   Прога-то нормально не читает кнопку во время работы...

Вот страшный код:


// Объявляем переменные 

int regim=1;  // Объявляем переменную режима 
int flag=1;   // Объявляем переменную флага

int regim_1=1;
int flag_1=1;

int regim_2=1;
int flag_2=1;

int next_steep_1=0;


// Создаем функции
//________________________________________________________________

void fn_GRN_blink_1 () // Функция зажигания зеленого светодиода
   {    
    digitalWrite(30,HIGH);
   }  


void fn_GRN_blink_5 () // Функция мигания светодиодом 5 раз
{

  int x;
  while(x<=5)
  {      
    digitalWrite(30,HIGH);
    delay(300);
    digitalWrite(30,LOW);
    delay(300);
    x++;
  }  
}
//________________________________________________________________

int fn_BLU_blink_15 () // Функция мигания синим светодиодом 15 раз
{
  
  int x;
  while(x<=15)
  {      
    digitalWrite(29,HIGH);
    delay(50);
    digitalWrite(29,LOW);
    delay(50);
    x++;
  }  
 next_steep_1=1;
}
//________________________________________________________________

int fn_BLU_blink_3 () // Функция мигания синим светодиодом 3 раза
{

  int x;
  while(x<=3)
  {      
    digitalWrite(29,HIGH);
    delay(50);
    digitalWrite(29,LOW);
    delay(50);
    x++;
    next_steep_1=1;
  }  
}
//________________________________________________________________

void fn_WHT_blink_1 () // Функция мигания белым светодиодом 1 раз
{

  int x;
  while(x<=1)
  {      
    digitalWrite(31,HIGH);
    delay(500);
    digitalWrite(31,LOW);
    delay(500);
    x++;
  }  

}

//________________________________________________________________

void setup()      // Запускаем функцию подготовительного цикла программы


// Задаем значение выходов для светодиодов
{ 
  pinMode(28,OUTPUT);  // Красный
  pinMode(30,OUTPUT);  // Зеленый
  pinMode(29,OUTPUT);  // Синий     
  pinMode(31,OUTPUT); // Белый
} 

int x;


void loop()  // Запускаем основной цикл
{                                                       

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

    if(regim>2)//ограничим количество режимов 
    { 
      regim=1; //так как мы используем только одну кнопку, то переключать режимы будем циклично 
    }   
  }       

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

  if(regim==1)//первый режим 
  { 
    delay(50);
    digitalWrite(28,LOW);//выключаем все светодиоды   
  }

  if(regim==2)//второй режим 
  { 
    delay(50);
    digitalWrite(28,HIGH);//включае красный светодиод 
  }

//Кнопка_2////////////////////////////////////////////////////////////////////////////////

  if(digitalRead(6)==HIGH&&flag_1==0)
  { 
    regim_1++;        
    flag_1=1;         

    if(regim_1>2)//ограничиваем режимы
    { 
      regim_1=1; 
    }   
  }       

  if(digitalRead(6)==LOW&&flag_1==1)
  {     
    flag_1=0;
  } 

  if(regim_1==1)//первый режим 
  { 
    delay(50);  
    digitalWrite(30,LOW); 
  }

  if(regim_1==2)//второй режим 
  { 
    delay(50);
    digitalWrite(30,HIGH);
  }

  
 //Кнопка_3////////////////////////////////////////////////////////////////////////////////

  if(digitalRead(5)==HIGH&&flag_2==0)
  { 
    regim_2++;        
    flag_2=1;         

    if(regim_2>2)//ограничиваем режимы
    { 
      regim_2=1; 
    }   
  }       

  if(digitalRead(5)==LOW&&flag_2==1)
  {     
    flag_2=0;
  } 

  if(regim_2==1)//первый режим 
  { 
    delay(50);  
    digitalWrite(31,LOW); 
  }

  if(regim_2==2)//второй режим 
  { 
    delay(50);
    digitalWrite(31,HIGH);
  }                 
  
 // запускаем наикрутейший логический процесс         



  if(regim_1==2)// Если нажата вторая кнопка 
  { 
    delay(1000);
    fn_GRN_blink_1 (); // Зеленый 1 раз
    delay(1000);
    fn_GRN_blink_5 (); // Зеленый  5 раз
    delay(1000);
    fn_BLU_blink_15 (); // Синий  15 раз
  }

  regim_1=1;  // Сброс кнопки 2  Если не сбросить - бесконечный цикл зеленого
  
  
  if (next_steep_1==1)  // получаем после отработки функции fn_BLU_blink_15 ()
      {
        delay(5000);
        fn_BLU_blink_3 (); // Синий 3 раза  и входит в бесконечный цикл
      }
      
   if(regim_2==2) // если нажата кнопка 3   !!! ВОТ ТУТ ПРОБЛЕМА НАЖАТЬ КНОПКУ !!!
   {
    next_steep_1=0; //прекращаем предыдущий цикл
    regim_2=1;      // сбрасываем кнопку 3
   } 
   
}
  

 

olegab
Offline
Зарегистрирован: 09.04.2013

Честно говоря с вашел логикой "режимов" разбираться не стал, что сразубросается в глаза:

1. next_steep_1 не сбрасывается, поэтому "бесконечный цикл"

2. В строке 219 просто происходит проверка, было ли обнаружено нажатие кнопки в строке 168, нажатие кнопки там не анализируется и "жать ее там" не нужно

olegab
Offline
Зарегистрирован: 09.04.2013

Иво время 5 секундного delay не выполняется вообще ничего в вашем скетче, программа просто стоит 5 сек на строке 215, зачем вам там эта задержка?

arduinomaniaco
arduinomaniaco аватар
Offline
Зарегистрирован: 25.12.2013

С delaylлами все понятно... это есть ЗЛО и его нужно стараться избегать...  Что же касается next_steep_1=1, то именно нажатием кнопки я хочу сделать next_steep_1=0, что бы сбросить бесконечный цикл...  Но, как и описывал выше - есть проблема с чтением кнопки, так как программа находится в цикле и не дает нормально нажать на кнопку.
Однако, без бесконечного цикла в данной задаче не обойтись, бо обязательно нужно до нажатия кнопки получать по три импульса и задержку 5 сек и т.д.  Поэтому,  с глубокой печалью покамест занимаюсь изысканием методом тыка, что несомненно полезно для познания предмета... Но все же очень бы хотелось узнать мнение  великих гуру, как побороть, а в идеале зазырить какой нить код-подсказку...

olegab
Offline
Зарегистрирован: 09.04.2013

Строку 221 не заметил, т.е. со сбросом переменной все нормально

На фоне 5 секундной Задержки, процессорное время на обработку нажатий кнопок "мизерно", несколько микросекунд, поэтому не удивительно что они не обнаруживаются. Вам нужно чтобы основной цикл детектирующий нажатия крутился постоянно, задержку сделайте как предложил клапауций

arduinomaniaco
arduinomaniaco аватар
Offline
Зарегистрирован: 25.12.2013

Покурил еще разок пример с моргаловом без делая... Образовалась изящная мысля... Ничего пока не подсказывайте! Попробую сам решить задачку.

arduinomaniaco
arduinomaniaco аватар
Offline
Зарегистрирован: 25.12.2013

Ура!  Разобрался! Немножко почитал про тайминг, пошевелякал извилинами и все заработало как надо! Выражаю благодарность местным гуру, особенно его светлости Клапауцию за мощный вектор на правильный курс, господу богу за то, что сотворил меня таким сообразительным, умным и красивым, Владимиру Владимировичу, за мирное небо над головой, ну и на всякий случай  Генеральному Секретарю ООН Пан Ги Муну!    Всем желаю отличного настроения, хороших праздников, интересных проектов и Мира во всем Мире!

крайний кусочик кода для истории:

 // запускаем наикрутейший логический процесс


  if(regim_1==2)// Если нажата вторая кнопка 
  { 
    delay(1000);
    fn_GRN_blink_1 (); // Зеленый 1 раз
    delay(1000);
    fn_GRN_blink_5 (); // Зеленый  5 раз
    delay(1000);
    fn_BLU_blink_15 (); // Синий  15 раз
  }

  regim_1=1;  // Сброс кнопки 2  Если не сбросить - бесконечный цикл зеленого
  
 
  if (next_steep_1==1)
      {
       currentTime = millis();							
  if(currentTime > (loopTime + 2000)) 
      {				
      fn_BLU_blink_3 (); // Синий 3 раза
      loopTime = currentTime;
      }     
 
   if(regim_2==2)
   {
    
    regim_2=1;
    next_steep_1=0;
   } 
   
}
}