Проблема с оператором For !!!

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Добрый день!!!Использую оператор for в своем коде для запуска генератора.Вот эта часть:

     for (int i = 0; i<=3; i++) 
    { 
      digitalWrite(10,LOW);
      digitalWrite(8,LOW); //то гасим индикатор работы от сети
      digitalWrite(11,HIGH); //зажигание
      digitalWrite(12,HIGH); //подсос
      delay(5000); //задержка подсоса на 5 секунд 
      digitalWrite(13,HIGH); //пробуем завести генератор
      delay(5000); //задержка на 5 секунд
     } 
  

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

step962
Offline
Зарегистрирован: 23.05.2011

А где стоит кусок этого кода? В setup() или в loop()?

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Этот кусок кода стоит в Void loop()

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

> фигурных скобках выполнился трижды, пока i не примет значение 3

Будет выполнять при i=0,1,2,3 - То есть четыре раза выполнится. Вам нужно либо i начинать с единицы, либо использоват оператор "меньше", а не "меньше или равно".

>цикл этот выполняется бесконечно

Как говорил Швейк: "осмелюсь доложить - что-то я сомневаюсь".

Как вы это узнали?  Намного вероятней что, из-за того что он в loop(), сам for целиком запускается раз-за разом.

Сделайте перед ним Serial.println("start"); и после него Serial.println("done");

Откройте сериал монитор. Если там будет одно слово "start" и больше ничего - значит случилось чудо и действительно цикл бесконечно крутится.
А если будете видить "start done start done start done" - значит вы его запускаете раз за разом, и бага в коде который вы не показали.

DeN-iZ
Offline
Зарегистрирован: 04.04.2013




void setup()
{
  pinMode(2,INPUT); //сеть
  pinMode(3,INPUT); //генератор
  pinMode(4,INPUT); //сброс
  pinMode(8,OUTPUT); //индикатор сети
  pinMode(9,OUTPUT); //индикатор генератора
  pinMode(10,OUTPUT); //индикатор аварии
  pinMode(11,OUTPUT); //зажигание
  pinMode(12,OUTPUT); //подсос
  pinMode(13,OUTPUT); //стартер
  
}
void loop()
{ 
  digitalWrite(8,LOW); //начальное положение у всех портов "0"
  digitalWrite(9,LOW); //
  digitalWrite(10,LOW); //
  digitalWrite(11,LOW); //
  digitalWrite(12,LOW); //
  digitalWrite(13,LOW); //
  if(digitalRead(2)==LOW) //если есть сеть
  {
    digitalWrite(8,HIGH); //то зажигаем индикатор работы от сети
  }
    if(digitalRead(2)==HIGH &&digitalRead(3)==HIGH) //если нет сети
   
     for (int i = 0; i<=3; i++) 
    { 
      digitalWrite(10,LOW);
      digitalWrite(8,LOW); //то гасим индикатор работы от сети
      digitalWrite(11,HIGH); //зажигание
      digitalWrite(12,HIGH); //подсос
      delay(5000); //задержка подсоса на 5 секунд 
      digitalWrite(13,HIGH); //пробуем завести генератор
      delay(5000);
      
   }   
     
     if (digitalRead(3)==LOW && digitalRead(2)==HIGH) //если заработал генератор и нет сети
   { 
     digitalWrite(9,HIGH); //включаем индикатор работы от генератора
     digitalWrite(8,LOW); //гасим все остальное
     digitalWrite(10,LOW); //
     digitalWrite(11,LOW); //
     digitalWrite(12,LOW); //
     digitalWrite(13,LOW); // 
   }
  }

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

 

 

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Сделал как Вы сказали и получил на последовательном порту "start done start done start done" 

step962
Offline
Зарегистрирован: 23.05.2011

Объявите переменную

char done;

Поставьте в setup()

done=0;

В loop() оберните свой цикл конструкцией:

if(!done) {
  done=1;
// тут ваш цикл
}

Расскажите о результате

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Если правильно Вас понял сделал вот так :

char done;
void setup()
{
  done=0;
  pinMode(2,INPUT); //сеть
  pinMode(3,INPUT); //генератор
  pinMode(4,INPUT); //сброс
  pinMode(8,OUTPUT); //индикатор сети
  pinMode(9,OUTPUT); //индикатор генератора
  pinMode(10,OUTPUT); //индикатор аварии
  pinMode(11,OUTPUT); //зажигание
  pinMode(12,OUTPUT); //подсос
  pinMode(13,OUTPUT); //стартер
  
}
void loop()
{ 
  digitalWrite(8,LOW); //начальное положение у всех портов "0"
  digitalWrite(9,LOW); //
  digitalWrite(10,LOW); //
  digitalWrite(11,LOW); //
  digitalWrite(12,LOW); //
  digitalWrite(13,LOW); //
  if(digitalRead(2)==LOW) //если есть сеть
  {
    digitalWrite(8,HIGH); //то зажигаем индикатор работы от сети
  }
    if(digitalRead(2)==HIGH &&digitalRead(3)==HIGH) //если нет сети
  
     if(!done) { 
      done=1;
      digitalWrite(10,LOW);
      digitalWrite(8,LOW); //то гасим индикатор работы от сети
      digitalWrite(11,HIGH); //зажигание
      digitalWrite(12,HIGH); //подсос
      delay(1000); //задержка подсоса на 5 секунд 
      digitalWrite(13,HIGH); //пробуем завести генератор
      delay(1000);
    }   
    
     if (digitalRead(3)==LOW && digitalRead(2)==HIGH)
   { 
     digitalWrite(9,HIGH); //включаем индикатор работы от генератора
     digitalWrite(8,LOW); //гасим индикатор работы от сети
     digitalWrite(10,LOW);
     digitalWrite(11,LOW); //
     digitalWrite(12,LOW); //
     digitalWrite(13,LOW); // //гасим индикатор аварии
   
   }
   
}

 

В результате цикл в Вашей конструкции выполнился один раз!!!) 

Я попробовал сразу прописать в конструкции done=3;  , думая что цикл выполнится 3 раза, но не получилось))))))))он выполнился тоже один раз)))

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

Почитайте что такое setup() и что такое loop()

setup() - это то что выполняется один раз при старте скетча.

loop() - то что запускается раз за разом. когда loop() выполняется до конца - его выполнение опять начинается с начала.

Поэтому "начальное положение у всех портов "0" логично было-бы видеть в setup(), а не в loop(), по крайней мере если вам не нужно выставлять все в Low() раз за разом.

Учитывая свойство loop(), ваш for будет запускаться раз-за разом, до тех пор пока выполняется условие digitalRead(2)==HIGH &&digitalRead(3)==HIGH

Внимание!!! не в момент "когда оно первый раз настанет", а "все время, пока выполняется". До тех пор пока 2 или 3тий пин не упадут в low

И еще. Вот этот if - в строке 26 очень не красиво выглядит. Желательно все-таки обернуть for в {}  (как вы делали с if-ом в 22 строке). А то ни скобками, ни отсутупами (кстати их тоже желательно сделать), не видно что for отсносится к этому if-фу.

Кстати на 80% уверен, что когда вы добавляли print-ты - вы забыли про это. И это добавление - полностью сменило вам логику (вместо того что-бы просто "показать что происходит). А если бы for был обернут в скобки, то println ничего не менял-бы в поведении, только давал возможность "подглядеть".

Snubist
Offline
Зарегистрирован: 18.02.2013

 

DeN-iZ пишет:

 

Я попробовал сразу прописать в конструкции done=3;  , думая что цикл выполнится 3 раза, но не получилось))))))))он выполнился тоже один раз)))

Тогда обьявлять ее надо как int, и проверять if(done<3) инкременируя ее каждый раз

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

В прошлом посте нумерация строк относилась с скетчу #4

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

>В результате цикл в Вашей конструкции выполнился один раз!!!) 

Как там может выполнится цикл один раз, если там вообще нет цикла? Там только набор digitalWrite-тов, вы не внимаетльно читали что вам писал step962.

А писал он оберните свой цикл конструкцией, а не "оберните тело своего цикла". Вы же выбросили for, зачем? Вот весь for целиком с потрохами и нужно було пихать в конструкцию step962

leshak
Offline
Зарегистрирован: 29.09.2011
if(!done){
   done=1;
   for(....){
     digitalWrite(.....)
    .....
   }
}

P.S. А я бы done объявилу как bool, тогда было-бы понятенй  что это флаг делал done=true;

Snubist
Offline
Зарегистрирован: 18.02.2013

Если как флаг то согласен, вопрос только зачем ему вообще здесь нужен цикл? вполне можно было обойтись и без него. Тем самым сэкономить память.

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

 

Snubist пишет:

Если как флаг то согласен, вопрос только зачем ему вообще здесь нужен цикл? вполне можно было обойтись и без него. Тем самым сэкономить память.

Если какое-то действие нужно выполнить четко три раза - то именно цикл экономит память.

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

 

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

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

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Речь идет про запуск бензинового генератора  на даче при изчезновении сетевого питания.

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

А у вас в цикле, нет "трех попыток".

При первом проходе цикла - выставтся digitalWrite-ты. И так и останутся до тех пор пока цикл не закончится. То есть каждый проход цикла - добавляет вам "ожидание 2sec" и больше ничего. 

При этом, если генератор завелся сразу, то все-равно еще 5-ть секунд будет крутится стратер. Не знаю конструкцию вашего генератора, но в автомобиле это означает "трындец стартеру". Если повезет - после нескольких таких стартов, если нет - сразу.

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

leshak пишет:

А у вас в цикле, нет "трех попыток".

При первом проходе цикла - выставтся digitalWrite-ты. И так и останутся до тех пор пока цикл не закончится. То есть каждый проход цикла - добавляет вам "ожидание 2sec" и больше ничего. 

Блин вот это тупанул.Не прописал выключения digitalWrit-ов!!!!!!!!!!!

if(!done) { 
        done=1;
        for (int i = 0; i<=3; i++)
      { 
      digitalWrite(10,LOW);
      digitalWrite(8,LOW); //то гасим индикатор работы от сети
      digitalWrite(11,HIGH); //зажигание
      digitalWrite(12,HIGH); //подсос
      delay(5000); //задержка подсоса на 5 секунд
      digitalWrite(12,LOW); //выключаем подсос
      digitalWrite(13,HIGH); //пробуем завести генератор
      delay(5000);
      digitalWrite(13,LOW);
      }    
            }

Если так?

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

Ну - больше похоже на правду.

Но...
1. Я уже писал выше, что цикл у вас выполняется не три, а четыре раза.
2. Непонятно зачем строки с 05 по 10 внесены в цикл. IMHO их можно просто один раз выполнить до цикла, а внутри - игратся только с 13-тым пином.
3. Нет проверки что генератор таки завелся. Но.. даже если вы ее вставите, то во время delay(5000) - стартер будет маслать в люобм случае. Нормально для вашего стартера работать 5 секунд при включенном движке - я не знаю. IMHO delay() нужно вообще убирать.
4. Зачем выключать подсос при кручении стартера - не понятно (но может это специфика вашего генератора).

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

С учетом последних замечаний прописал вот так:

if(!done) { 
        done=1;
        for (int i = 0; i<=2; i++)
   { 
      
      digitalWrite(11,HIGH); //зажигание
      digitalWrite(12,HIGH); //подсос
      delay(5000); //задержка подсоса на 5 секунд
      digitalWrite(13,HIGH); //пробуем завести генератор
      delay(5000);
      digitalWrite(13,LOW);
    }    
            }

 

Но вот как туда засунуть проверку и чтоб при запуске генератора выйти из цикла не зависимо от того на какой (с 1 по 3) попытке мы находимся?

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

> i<=2

Можно и так. Но более традиционным является for(int i=0;i<3;i++)

Так "какая цифра" "столько раз и выполнятся будет". Это скорее "традиция" которой придерживаются 99%. Поэтому любой читающий бегло ваш код - быстрее поймет, меньше шансов что ошибется.

> выйти из цикла не зависимо от того на какой

Можно почитать документацию Программирование Ардуино | Аппаратная платформа Arduino  и в разделе "Управляющие операторы" узнать о существовании волшебного оператора break  (кстати там и пример - близок к вашей задаче). А вообще нужно ОБЯЗАТЕЛЬНО проштудировать и знать все эти операторы (кроме goto - про него лучше забыть навсегда).

Если бы я делал - то я бы вообще просто вынес все эту логику старта в отдельную функцию. Скажем runStarter() и просто делал return() как только генератор завелся.


loop(){
   if(НУЖНО_СТАРТОВАТЬ)    runStarter();
}

void runStarter(){
  // тут пишем то что один раз достаточно выполнить
  for(byte i=0;i<3;i++){
     // включили стартер
     // подождали
    // выключили стартер
     if(генератор_запустился)return;// все прекратили попытки
     // подождали
  }
  
  // попытки не увенчались успехом
  onError(); // уходя - гасите всех

}

void onError(){ // что делать при ошибке
digitalWrite(ERROR_PIN, HIGH);  // сигнализируем об ошибке


  while(true){} // и останавливаем скетч, в предположении что при ошибке нужно остановится и ждать человека для перезапуска всего
  
}

 

Snubist
Offline
Зарегистрирован: 18.02.2013

 

for (int i = 0; i<3; i++)
   { 
      digitalWrite(11,HIGH); //зажигание
      digitalWrite(12,HIGH); //подсос
      delay(5000); //задержка подсоса на 5 секунд
      digitalWrite(13,HIGH); //пробуем завести генератор
      delay(5000);
      digitalWrite(13,LOW);
      if(digitalRead(3)==HIGH) i=3 // если завелся, выйти из цикла
    }    
}

 

leshak
Offline
Зарегистрирован: 29.09.2011
 if(digitalRead(3)==HIGH) i=3 // если завелся, выйти из цикла

Вариант. Работать - будет. Но в любой комманде сделают как минимум щелобан в нос за такое :) Есть специальный оператор для этого - даже ссылку выше дал. И вообще менять i в таких циклах внутри тела цикла - ОЧЕНЬ плохой тон. Очень затрудняет, потом, сопровождение кода, поиск ошибкой и т.п.

Да банально. завтра решите что попыток нужно 5-ть. В форе поменяете, а внизу - забудете. И привет бесконечный попытки завестись.

Snubist
Offline
Зарегистрирован: 18.02.2013

Моветон согласен, но тут вопрос не о красоте.

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

Snubist пишет:

Моветон согласен, но тут вопрос не о красоте.

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

Представте себе что к вам пришел мастер что-то чинить. И забивает гвозди плоскогубцами. При этом молоток лежит рядом. А гвоздь пытается держать пальцами ног. Ваше мнение о таком мастере? Что вы будете ждать от него кроме "ну когда же уже врежет по пальцам?" и "только бы не сломал то_что_чинит". Даже если гвоздь он все-таки забъет.

Snubist
Offline
Зарегистрирован: 18.02.2013

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

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


int PuskCount=0;
void setup()
{
  pinMode(2,INPUT); //сеть
  pinMode(3,INPUT); //генератор
  pinMode(4,INPUT); //сброс
  pinMode(8,OUTPUT); //индикатор сети
  pinMode(9,OUTPUT); //индикатор генератора
  pinMode(10,OUTPUT); //индикатор аварии
  pinMode(11,OUTPUT); //зажигание
  pinMode(12,OUTPUT); //подсос
  pinMode(13,OUTPUT); //стартер

}
void loop()
{ 
  digitalWrite(8,LOW); //начальное положение у всех портов "0"
  digitalWrite(9,LOW); //
  digitalWrite(10,LOW); //
  digitalWrite(11,LOW); //
  digitalWrite(12,LOW); //
  digitalWrite(13,LOW); //
  if(digitalRead(2)==LOW) //если есть сеть
  {
    digitalWrite(8,HIGH); //то зажигаем индикатор работы от сети
  }
  if(digitalRead(2)==HIGH &&digitalRead(3)==HIGH) //если нет сети
  {
    if(PuskCount<3) 
    { 
      PuskCount++;
      digitalWrite(10,LOW);
      digitalWrite(8,LOW); //то гасим индикатор работы от сети
      digitalWrite(11,HIGH); //зажигание
      digitalWrite(12,HIGH); //подсос
      delay(1000); //задержка подсоса на 5 секунд 
      digitalWrite(13,HIGH); //пробуем завести генератор
      delay(1000);
    }   
  }
  if (digitalRead(3)==LOW && digitalRead(2)==HIGH)
  { 
    digitalWrite(9,HIGH); //включаем индикатор работы от генератора
    digitalWrite(8,LOW); //гасим индикатор работы от сети
    digitalWrite(10,LOW);
    digitalWrite(11,LOW); //
    digitalWrite(12,LOW); //
    digitalWrite(13,LOW); // //гасим индикатор аварии

  }

}

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

>А вопрос тут помоему стоит стандартный, "Вам шашечки или ехать?"

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

 

> я бы вообще избавился от цикла.

можно и так, но...

PuskCount - нигде не обнуляется (а вдуг заглохо не один раз?)

 

Snubist
Offline
Зарегистрирован: 18.02.2013

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

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

Snubist пишет:

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

Это не "много чего нет". Вы оттолкнулись - "можно без for". Значит и вариант должен быть "эквивалентным". Как минимум иметь те же функции.

А так вы показали "альтернативный вариант", которые не делает того что делал изначальный. При повторном пропадании - опять делать три попытки. Вот когда будет "аналогичное поведение", тогда и можно будет смотреть "как проще". А то выйдет что "без for-а, зато 5-ть if-ов добавилось).

Snubist
Offline
Зарегистрирован: 18.02.2013

пожалуйста

 


int PuskCount=0; //счетчик запусков генератора
void setup()
{
  pinMode(2,INPUT); //сеть
  pinMode(3,INPUT); //генератор
  pinMode(4,INPUT); //сброс
  pinMode(8,OUTPUT); //индикатор сети
  pinMode(9,OUTPUT); //индикатор генератора
  pinMode(10,OUTPUT); //индикатор аварии
  pinMode(11,OUTPUT); //зажигание
  pinMode(12,OUTPUT); //подсос
  pinMode(13,OUTPUT); //стартер

}
void loop()
{ 
  digitalWrite(8,LOW); //начальное положение у всех портов "0"
  digitalWrite(9,LOW); //
  digitalWrite(10,LOW); //
  digitalWrite(11,LOW); //
  digitalWrite(12,LOW); //
  digitalWrite(13,LOW); //
  if(digitalRead(2)==LOW) //если есть сеть
  {
    digitalWrite(8,HIGH); //то зажигаем индикатор работы от сети
  }
  if(digitalRead(2)==HIGH &&digitalRead(3)==HIGH) //если нет сети, и генератор не запущен
  {
    if(PuskCount<3) 
    { 
      PuskCount++;
      digitalWrite(10,LOW);
      digitalWrite(8,LOW); //то гасим индикатор работы от сети
      digitalWrite(11,HIGH); //зажигание
      digitalWrite(12,HIGH); //подсос
      delay(1000); //задержка подсоса на 5 секунд 
      digitalWrite(13,HIGH); //пробуем завести генератор
      delay(1000);
    }   
  }
  if (digitalRead(3)==LOW && digitalRead(2)==HIGH) //если работает генератор
  { 
    PuskCount=0; //сбрасываем сетчик запусков
    digitalWrite(9,HIGH); //включаем индикатор работы от генератора
    digitalWrite(8,LOW); //гасим индикатор работы от сети
    digitalWrite(10,LOW);
    digitalWrite(11,LOW); //
    digitalWrite(12,LOW); //
    digitalWrite(13,LOW); // //гасим индикатор аварии

  }

}