Помогите пожалуйста с кодом

Тема в разделе "Arduino & Shields", создана пользователем grx1a, 10 фев 2013.

  1. grx1a

    grx1a Гик

    Здравствуйте, помогите пожалуйста, может кто-нибудь сталкивался с подобной проблемой. Написал код для механического энкодера, работает хорошо но есть мелкие проблемки. Первая в коде сделал фукцию которая распознает и генерирует короткий импульс при проварачивании колеса на один маленький шаг не важно в какую сторону. Функция работает, при смене шага этот импульс выскакивает, но дело в том что длинна этого импульса зависит от скорости прокрутки колеса, а еще хуже, если колесо остановить между двумя шагами, то этот импульс становится безконечным, пока чуть чуть не сдвинеш колесо (не доведеш до стабильного шага когда выход А и В 11 или 00). В идеале все должно быть так, как только на входе в функцию появился импульс то есть перепад с LOW на HIGH по фронту, он сразу возвращается на LOW и передает этот сигнал на выход с функциии, и остается в положении LOW пока снова не получит перепад по фронту с LOW на HIGH, в радиозлектронике я знаю как это сделать а вот программно что то не могу, думал что функция interrupt подойдет, но помоему она вообще к этому случаю никакого отношения не имеет. Про функцию Delay думаю отрицательно, потому как от нее нужно избавляться любыми способами. Второй причиной недостатков является не большой дребезг контактов энкодера, не знаю как с ним лучше поступить

    Вот код:
    #define pinA 3 //Первый PIN Сигнала с энкодера
    #define pinB 4 //Второй PIN Сигнала с энкодера
    #define ledpinH 12 //PIN Временно выведен на LED (Указывает направления вращения колеса (+).)
    #define ledpinL 11 //PIN Временно выведен на LED (Указывает направления вращения колеса (-).)
    #define ledpinS 13 //PIN Временно выведен на LED (Распознает шаг колеса в любом направлении.)
    boolean valA=0; //Текущее переменное значение енкодера на А ыходе энкодера
    boolean valB=0; //Текущее переменное значение енкодера на В ыходе энкодера
    boolean Estate=0; //Вспомогательная переменная необходимая для определения вращения
    boolean pulse = 0; //Импульс шага аспознает шаг колеса в любом направлении
    boolean Dir =0; //Переменная направления вращения (Если=1 то влево, если=0 то вправо)

    void setup(){
    pinMode(pinA,INPUT); //Вход A c энкодера
    pinMode(pinB,INPUT); //Вход В c энкодера
    pinMode(ledpinH,OUTPUT); //PIN Временно выведен на LED и показывает направление +
    pinMode(ledpinL,OUTPUT); //PIN Временно выведен на LED и показывает направление -
    pinMode(ledpinS,OUTPUT);} //PIN Временно выведен на LED и показывает выполнение сигнала шага
    void loop(){
    valA=digitalRead(pinA); //Читает и запоминает текущее состояние на выходе энкодера (Выход А)
    valB=digitalRead(pinB); //Читает и запоминает текущее состояние на выходе энкодера (Выход А)
    /*РАСПОЗНАНИЕ ИПУЛЬСА ШАГА (ПРОБЛЕМА В ЭТОМ РАЗДЕЛЕ!!!!!!!!!!!!!!!!!! Перепад по фронту с LOW на HIGH должен быть
    кратковременный и после мгновенного возврата в lOW оставаться не изменным до следующего перепада по фронту с LOW на HIGH функция delay здесь не очень желательна)*/
    if(valA+valB==HIGH){pulse=1;} //Определяет шаг и дает импульс шага на временный LED на ledpinS
    else{pulse=0;}
    if (pulse==1) // Выдает сигнал на временно установленый LED
    {digitalWrite(ledpinS,HIGH);}
    else
    {digitalWrite(ledpinS,LOW);}
    //ОПРЕДЕЛЕНИЕ ВСПОМОГАТЕЛЬНОЙ ПЕРЕМЕННОЙ ДЛЯ ОПРЕДЕЛЕНИЯ ВРАЩЕНИЯ КОЛЕСА
    if((valA==LOW)&&(valB==LOW)&&(valA<1)&&(valB<1))
    {Estate=1;} // Вспомогательная переменная для определения направления вращения колеса на (+)
    if((valA==HIGH)&&(valB==HIGH)&&(valA>0)&&(valB>0))
    {Estate=0;} // Вспомогательная переменная для определения направления вращения колеса на (-)

    //ОПРЕДЕЛЕНИЕ ВРАЩЕНИЯ КОЛЕСА
    if(((Estate==1)&&(valA==LOW)&&(valB==HIGH))||((Estate==0)&&(valA==HIGH)&&(valB==LOW)))
    {Dir=1;} //Направление вращения (+)
    if(((Estate==1)&&(valA==HIGH)&&(valB==LOW))||((Estate==0)&&(valA==LOW)&&(valB==HIGH)))
    {Dir=0;} //Направление вращения(-)
    if(Dir==1) // Выход сигнала направления вращения указывающий направление (+) на временный LED через ledpinH
    { digitalWrite(ledpinH,HIGH);}
    else
    { digitalWrite(ledpinH,LOW);}
    if(Dir==0) // Выход сигнала направления вращения указывающий направлени (-) на временный LED через ledpinL
    { digitalWrite(ledpinL,HIGH);}
    else
    { digitalWrite(ledpinL,LOW);}
    }
    Энкодер общим пином подключен на +питания, его выходы через подключены 10 кОм резисторам на землю а также на цифровые входы ARDUINO MEGA 2560
     
  2. grx1a

    grx1a Гик

    порядок работы энкодера
    А 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
    В 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0
     
  3. grx1a

    grx1a Гик

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

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

    Код (Text):
    byte buf[2];
     
    void setup()
    {
     // ...
     buf[0] = digitalRead(PIN_A)*2 +digitalRead(PIN_B);
    }
     
    void loop()
    {
     buf[1] = digitalRead(PIN_A)*2 +digitalRead(PIN_B);
     if (buf[0]!=buf[1])
     {
      // something has moved
      if ((2==buf[0] && 3==buf[1]) || (3==buf[0] && 1==buf[1]) || (1==buf[0] && 0==buf[1]) || (0==buf[1] && 2==buf[1]))
      {
      // left turn detected
      }
      if ((1==buf[0] && 3==buf[1]) || (3==buf[0] && 2==buf[1]) || (2==buf[0] && 0==buf[1]) || (0==buf[1] && 1==buf[1]))
      {
      // right turn detected
      }
      buf[0] = buf[1];
     }
     else
     {
      // nothing happened
     }
    }
     
    grx1a нравится это.
  5. grx1a

    grx1a Гик

    Огромное спасибо!!!
     
  6. grx1a

    grx1a Гик

    Я как это часто бывает пошел не самым легким путем, все гораздо проще
     
  7. Megakoteyka

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

    Дребезг контактов можно подавить конденсатором.
     
  8. grx1a

    grx1a Гик

    RC это легко, а вот програмно без использования функций которые в больших кодах козлят сильно, например функция delay это уже интересней, и все таки вопрос с энкодером до конца не раскрыт, я имею ввиду програмный формирователь короткого импульса запускаемый восходящим фронтом электрического сигнала, такая вещь еще много где может пригодиться, сижу пока думаю над этим,
     
  9. grx1a

    grx1a Гик

    хотя интуиция мне подсказывает что без delay в данной ситуации не обойтись
     
  10. grx1a

    grx1a Гик

    может я не прав
     
  11. hibiki

    hibiki Гик

    не delay, так таймер для формирования импульса определенной длительности. или еще веселее - таймер в режиме счетчика, настроенный на 1 счетный импульс.

    только я не понял, зачем вам этот импульс определенной длительности в коде
     
  12. grx1a

    grx1a Гик

    Во.... Дадумался, получилось, только правдо без DELAY не обошлось
    вот код
    /*
    Формирователь выходного импульса сигнала
    по восходящему фронту входного сигнала
    Входной сигнал высокого уровня может быть любой по вркмени
    время выходного импульса устанавливается функцией DELAY
    */
    #define ledpin 12
    #define butpin 8
    boolean insig=LOW; //Входнлй сигнал
    boolean outsig=LOW; //Выходной сигнал
    boolean outsigzapret=LOW; //Запрет выходного сигнала
    void setup()
    {
    pinMode(ledpin,OUTPUT);
    pinMode(butpin,INPUT);}
    void loop(){
    insig=digitalRead(butpin);
    if((insig==HIGH)&&(outsigzapret==LOW))
    {digitalWrite(ledpin,HIGH);
    delay(1); // DELAY Время работы выходного сигнала
    digitalWrite(ledpin,LOW);}
    outsigzapret=HIGH;
    if(insig==LOW){
    outsigzapret=LOW;
    delay(5);}} // DELAY антидребезга

    Это я что то вроде кодовых Brick-ов делаю, для более крупных тяжелых проектов с большим колличеством функций. Для чего этот код понадобился, пример можно прочитать в начале темы там как раз нужен такой мини код в большом коде. А по поводу таймера это очень интересно, надо их изучением углубленно заняться, я в програмировании чайник. Знаю что в прерываниях delay не работает. А как прерывания на таймер реагируют?
     
  13. Megakoteyka

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

    Не существует ситуации, в которой нельзя обойтись без delay() :)
     
  14. grx1a

    grx1a Гик

    да, я понимаю, но нужно их сводить к минимуму
     
  15. Megakoteyka

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

    Задержка делается так:
    long time;
    boolean flag = false;

    if(произошло событие) {
    time = millis();
    flag = true;
    // задержка началась
    }

    if(flag && (millis() - time) > INTERVAL)
    {
    // задержка закончилась
    flag = false;
    }

    При этом контроллер не простаивает и может выполнять другие задачи.
     
    grx1a нравится это.
  16. grx1a

    grx1a Гик

    Замечательно, спасибо огромное!!!