Слабое звено "IF" конструкции или мой косяк?

Тема в разделе "Arduino & Shields", создана пользователем -Mark-, 22 ноя 2013.

  1. -Mark-

    -Mark- Гик

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

    Код (Text):
     case STATE_JOB4:
      {

        {
        digitalWrite(ledPin8, HIGH);  //Задаем направление  двигателю обрезки  бумаги
        digitalWrite(ledPin6, LOW);  //Включаем  двигатель обрезки бумаги
      }

      if (digitalRead(switchPin5) == LOW) // Ждем когда нож обрежет бумагу

        {
        digitalWrite(ledPin6, LOW);    //Выключаем двигатель обрезки бумаги
        digitalWrite(ledPin8, LOW);    //Выключаем двигатель обрезки бумаги
        delay (1000);
        state = STATE_JOB5;
        }

      break;
    }
    case STATE_JOB5:
    {
      {
        digitalWrite(ledPin8, LOW);  //Включаем реверс двигателя обрезки бумаги
        digitalWrite(ledPin6, HIGH);    //Включаем реверс двигателя обрезки бумаги
      }
      if (digitalRead(switchPin6) == LOW  ) // Ждем когда нож вернется в исходное положение
      {
        digitalWrite(ledPin6, LOW);    //Выключаем двигатель обрезки бумаги
        digitalWrite(ledPin8, LOW);    //Выключаем двигатель обрезки бумаги
        delay(200);
        digitalWrite(ledPin2, LOW);    //Выключаем прижим бумаги
        digitalWrite(ledPin5, LOW);    //Выключаем тормоз барабана с бумагой
        digitalWrite(ledPin4, LOW);    //Выключаем вакуумный насос
        state = STATE_JOB6;
      }
          break;

    }
     

    ну 1 сбой на 50 циклов было терпимо...сегодня же станок встал...данная операция выполнялась корректно 1 раз из 30 циклов! Немного подумал и переписал этот участок программы:

    Код (Text):
     case STATE_JOB4:
      {

      {
        digitalWrite(ledPin8, HIGH);  //Задаем направление  двигателю обрезки бумаги
        digitalWrite(ledPin6, LOW);  //Включаем  двигатель обрезки бумаги
      }
        do
        {
          delay (50);
          var=digitalRead (switchPin5);
        }
        while ( var==HIGH); // Ждем когда нож обрежет бумагу

        {
        digitalWrite(ledPin6, LOW);    //Выключаем двигатель обрезки бумаги
        digitalWrite(ledPin8, LOW);    //Выключаем двигатель обрезки бумаги
        delay (1000);
        state = STATE_JOB5;
        }

      break;
    }
    case STATE_JOB5:
    {
      {
        digitalWrite(ledPin8, LOW);  //Включаем реверс двигателя обрезки бумаги
        digitalWrite(ledPin6, HIGH);    //Включаем реверс двигателя обрезки бумаги
      }

      do
        {
          delay (50);
          var1=digitalRead (switchPin6);
        }
        while ( var1==HIGH);  // Ждем когда нож вернется в исходное положение

      {
        digitalWrite(ledPin6, LOW);    //Выключаем двигатель обрезки бумаги
        digitalWrite(ledPin8, LOW);    //Выключаем двигатель обрезки бумаги
        delay(200);
        digitalWrite(ledPin2, LOW);    //Выключаем прижим бумаги
        digitalWrite(ledPin5, LOW);    //Выключаем тормоз барабана с бумагой
        digitalWrite(ledPin4, LOW);    //Выключаем вакуумный насос
        state = STATE_JOB6;
      }


          break;

    }
     
    Все заработало идеально!!!!!
    Прощу пояснить знающих )))) Если провести параллель с реальной жизнью, то в первой части я сказал сотруднику моей фирмы, что мы работаем до 5 -и вечера...вежливо пояснил...тут смотрю ,что обычно он уходит в 5, но иногда и чуть раньше...а потом и вообще стал каждый раз на пол часа раньше уходить...тогда пришлось изменить условия...уйдешь раньше 5 вечера - без зарплаты останешься...я так понимаю эти два кода
     
    Последнее редактирование: 22 ноя 2013
  2. Корней

    Корней Гик

    Коротко: контроллер работает по коду, а не по комментариям.
    Развернуто:
    Код (Text):
    if (digitalRead(switchPin6) == LOW  ) // Ждем когда нож вернется в исходное положение
    Не "ждем", а однократно проверяем - вернулся ли.
    Код (Text):
     do
        {
          delay (50);
          var1=digitalRead (switchPin6);
        }
        while ( var1==HIGH);  // Ждем когда нож вернется в исходное положение
     
    Вот теперь действительно ждем.
     
    Megakoteyka нравится это.
  3. -Mark-

    -Mark- Гик

    Прошу прощения, но первый код почему-то пол года работал...иногда глючил, но работал же )))) Кстати, перед тем как написать блок с циклом (while) я сначала видоизменил конструкцию "IF" :
    Код (Text):
     case STATE_JOB4:
      {

        {
        digitalWrite(ledPin8, HIGH);  //Задаем направление  двигателю отрезки бумаги
        digitalWrite(ledPin6, LOW);  //Включаем  двигатель отрезки бумаги
      }
     
      if (digitalRead(switchPin5) == LOW && digitalRead(switchPin6) == HIGH) // Ждем когда нож обрежет бумагу
     
        {
        digitalWrite(ledPin6, LOW);    //Выключаем двигатель отрезки бумаги
        digitalWrite(ledPin8, LOW);    //Выключаем двигатель отрезки бумаги
        delay (1000);
        state = STATE_JOB5;
        }
        else  if (digitalRead(switchPin5) == HIGH )
        {
        state = STATE_JOB4;
        }
      break;
    }
    case STATE_JOB5:
    {
      {
        digitalWrite(ledPin8, LOW);  //Включаем реверс двигателя отрезки бумаги
        digitalWrite(ledPin6, HIGH);    //Включаем реверс двигателя отрезки бумаги
      }
      if (digitalRead(switchPin6) == LOW && digitalRead(switchPin5) == HIGH ) // Ждем когда нож обрежет бумагу
      {
        digitalWrite(ledPin6, LOW);    //Выключаем двигатель отрезки бумаги
        digitalWrite(ledPin8, LOW);    //Выключаем двигатель отрезки бумаги
        delay(200);
        digitalWrite(ledPin2, LOW);    //Выключаем прижим бумаги
        digitalWrite(ledPin5, LOW);    //Выключаем тормоз барабана с бумагой
        digitalWrite(ledPin4, LOW);    //Выключаем вакуумный насос
        state = STATE_JOB6;
      }
     
      else if (digitalRead(switchPin6) == HIGH )
      {
        state = STATE_JOB5;
      }
          break;

    }

     
    Так же сильно глючило.
     
  4. NR55RU

    NR55RU Гик

    Он у вас и работал бы, в сущности в первом варианте особой ошибки нет, хотя Корней верно указал на то что инструкция IF не совпадает с описанием и не ждет, а проверяет и продолжает работу.
    Вся ваше логика управляется статусом STATE, и того:
    Когда программа входит в блок SWITCH она выполнит лишь один из вариантов CASE а STATE у вас меняется только в одном из блоков и только когда выполняется IF.
    Таким образом когда у вас в JOB4 проверка не проходила программа просто выходила из блока SWITCH, после когда все что следует за ним выполнялось, снова входила в блок (так как скорее всего крутилась в LOOP), а так как STATE не поменялся из-за не сработавшего IF, снова попадала в JOB4 и снова проверяла условие.
    По своей сути комбинация STATE и вашего IF создали это ожидание, только не в одной строке а в рамках куда более больших.
    Скорее всего ошибка где-то в другом месте, если вы приведете полный текст программы, тогда можно будет посмотреть где может быть глюк.
     
  5. -Mark-

    -Mark- Гик

    Это я осознал печенкой, и решил загнать поэтому все в while :oops: Но во втором варианте с IF я вроде не выпускал ее из блока пока не выполнится то что мне надо а отправлял в начало блока...не?
     
  6. -Mark-

    -Mark- Гик

    Вся программа - набор из десятка CASE...и все переходит из одного в другой последовательно после выполнения каких либо условий...больше в loop ничего нет.
     
  7. NR55RU

    NR55RU Гик

    Вы немножко не понимаете как работает IF
    Вот пример:
    Код (Text):
    if(a == 1)
    {
       // block 1
    }
    else
    {
       // block 2
    }
    Конструкция IF выполняется только один раз и все, в зависимости от результата проверки будет выполнен один из блоков.
    То есть если a = 1 то выполнится блок 1 а если не равно 1 то выполнится блок 2, и все, потом программа пойдет дальше работать.
    То есть подобным условием вы ничего не держите, вы лишь выбираете какой из блоков кода выполнится.
    А у вас дальше стоит break который выкинет вашу программу из блока switch.
    А всю программу вы бы все же привели.
     
  8. Megakoteyka

    Megakoteyka Оракул Модератор

    И конструкцию заодно. Какой датчик "ждет" обрезку? Возможно, имеет место ложное срабатывание.
    JOB4 логично разделить на 2 состояния - включение двигателя и ожидание обрезки. Либо включать двигатель в предыдущей ветке.
    В операторах языка "косяка" быть не может, он может быть только в неверном понимании.
    Для полее полного понимания причин сбоев хорошо бы исследовать сигналы осциллографом или логическим анализатором - сразу все станет понятно.
     
  9. -Mark-

    -Mark- Гик


    Это Вы не поняли наверное...пунктом 2 (если не тот результат который меня устраивает) я отправляю ее в начало данного же блока! Или я очень сильно туплю ))))


    Датчики вот эти: http://amperka.ru/collection/sensors/product/infrared-sensor-switch
     
  10. -Mark-

    -Mark- Гик


    Да я и так наплодил этих CASE выше крыши...суть в том что я понял что while - это то что мне нужно и то что правильно...но я не понял почему если нет срабатывания датчика а предписано IF командой идти в начало этого же блока программа вылетает иногда из блока ((((
     
  11. NR55RU

    NR55RU Гик

    Оператор BREAK не отправляет программу в начало блока, не путайте с оператором continue для циклов.
    BREAK выходит из всего SWITCH но если в LOOP у вас только один SWITCH и все, тогда по факту да, вы вышли из SWITCH и тут же в него заново вошли, SWITCH определит CASE и выполнит блок.
    Код (Text):
    // block 1
    switch
    {
        case 1:
            // block 2
            break;
        case 2:
            // block 3
            break;
    }
    // block 4
    И того, данный пример выполняется так:
    Блок 1 - > блок 2 или блок 3 -> блок 4
    То есть как только SWICH увидит BREAK он сразу же перейдет к блоку 4

    Я еще раз предлагаю вам привести целиком текст программы, я вам даже попробую видоизменить ее сделав более понятной, если я правильно все понял, вам там вовсе не нужны CASE.
     
  12. -Mark-

    -Mark- Гик

    под рукой нет всего скетча...он на рабочем компе...вот чего я точно не понял, так это логики...если что то меня не устроило то послал в начало блока...оператор break он же ниже строчкой и как бы до него дело пока не дошло...наверное я опять не прав...чую печенкой ))))
     
  13. NR55RU

    NR55RU Гик

    Какой именно строчкой по вашему мнению вы посылаете все в начало блока ?
    Приведите именно небольшой фрагмент или строчку, и опишите как по вашему мнению он работает.
     
  14. -Mark-

    -Mark- Гик

    Код (Text):
     case STATE_JOB4:
      {

        {
        digitalWrite(ledPin8, HIGH);  //Задаем направление  двигателю отрезки бумаги
        digitalWrite(ledPin6, LOW);  //Включаем  двигатель отрезки бумаги
      }
      if (digitalRead(switchPin5) == LOW && digitalRead(switchPin6) == HIGH) // Ждем когда нож обрежет бумагу
        {
        digitalWrite(ledPin6, LOW);    //Выключаем двигатель отрезки бумаги
        digitalWrite(ledPin8, LOW);    //Выключаем двигатель отрезки бумаги
        delay (1000);
        state = STATE_JOB5;
        }
        else  if (digitalRead(switchPin5) == HIGH )
        {
        state = STATE_JOB4;
        }
      break;
    }

    пока коретка не наехала на зону датчика он будет всегда выдавать логическую 1...значит идет отрабатывать ДЖОБ 4 ))))) имхо
     
  15. Корней

    Корней Гик

    Включаю телепатию:
    case STATE_JOB4 находится в цикле loop() или в каком-то еще.
    В начале блока STATE_JOB4 выдаются команды на двигатель отрезки бумаги.
    Пока использовался if((digitalRead(switchPin5) ) каждую итерацию внешнего цикла выдавались команды на включение (оборудованию видимо все равно, включают ли двигатель обрезки тогда, когда он уже включен) и проверялось срабатывание датчика положения ножа.
    Пока оборудование было новым, датчик положения ножа работал устойчиво, поэтому глюков было мало.
    После периода эксплуатации датчик стал срабатывать крайне не стабильно, глюков стало много.
    Износились рабочие элементы датчика, или люфты механизма ножа стали слишком большие.
    Выключаю телепатию.

    Резюме: с if все в порядке.
    Рекомендация: реализуйте корректный конечный автомат, пока ваше железо не отрезало что-нибудь еще кроме бумаги. (повторное включение уже работающего двигателя нормально только для самодвижущихся повозок на конкурсах типа "юный робототехник")
    Возможно, целесообразно использование готовых решений пром.автоматики, у них должен быть специальный софт для визуального описания циклограмм, состояний и переходов КА и тд.
     
  16. -Mark-

    -Mark- Гик

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

    Корней Гик

    Намек не поняли.
    Отвечаю дельно и очень информативно:

    Ваш косяк. Абсолютно ваш.
    уж извините
     
  18. -Mark-

    -Mark- Гик


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

    NR55RU Гик

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

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

    15 января 1990г. международная телефонная система AT&T вышла из строя, оставив без телефонной связи 60 000 человек. В чем причина ?
    Программист, писавший для коммутатора код на Си, попытался применить оператор break для завершения инструкции if. Однако с помощью break инструкцию if завершить нельзя. В результате был пропущен целый участок кода, что привело к ошибке, которая на протяжении 9 часов вызвала разрыв 70 миллионов звонков...
     
    -Mark- нравится это.
  20. -Mark-

    -Mark- Гик


    Что-то мне это напомнило другого "специалиста", который посчитал, что нажав кнопку " ТОGA"...он уйдет на второй круг на Автомате (((