Проблема с работой поворотного энкодера KY040 *РЕШЕНО*

Тема в разделе "Arduino & Shields", создана пользователем Guri, 10 июн 2016.

  1. Guri

    Guri Нерд

    Добрый день!
    Пытаюсь подключить энкодер по статье:
    https://bigdanzblog.wordpress.com/2014/08/16/using-a-ky040-rotary-encoder-with-arduino/
    Заливаю код на УНО- все работает, подключаю к НАНО с тем же кодом- начинает сильно глючить (особенно кнопка).
    В чем может быть причина?
    Спасибо!

    Код (немного измененный):

    Код (C++):

    volatile boolean TurnDetected;
    volatile boolean up;

    const int PinCLK=2;                   // Used for generating interrupts using CLK signal
    const int PinSW=3;                   // Used for the push button switch
    const int PinDT=4;                    // Used for reading DT signal

    void isr ()  {                    // Interrupt service routine is executed when a HIGH to LOW transition is detected on CLK
    if (digitalRead(PinCLK))
       up = digitalRead(PinDT);
    else
       up = !digitalRead(PinDT);
    TurnDetected = true;
    }


    void setup ()  {
    pinMode(PinCLK,INPUT);
    pinMode(PinDT,INPUT);
    pinMode(PinSW,INPUT);
    attachInterrupt (0,isr,FALLING);   // interrupt 0 is always connected to pin 2 on Arduino UNO
    Serial.begin (9600);
    Serial.println("Start");
    }

    void loop ()  {
    static long virtualPosition=0;    // without STATIC it does not count correctly!!!

    if (!digitalRead(PinSW)&&virtualPosition) {      // check if pushbutton is pressed
       virtualPosition=0;              // if YES, then reset counter to ZERO
       Serial.print ("Reset = ");      // Using the word RESET instead of COUNT here to find out a buggy encoder
     
       Serial.println (virtualPosition);
    }
    if (TurnDetected)  {        // do this only if rotation was detected
       if (up)
         virtualPosition--;
       else
         virtualPosition++;
       TurnDetected = false;          // do NOT repeat IF loop until new rotation detected
       Serial.print ("Count = ");
       Serial.println (virtualPosition);
    }

      }
     
  2. Guri

    Guri Нерд

    Да, конечно же при правильном подключении к пинам 2, 3, 4 все работает.
    Я на самом деле пытался подключить PinSW к А7 и там уже была проблема. но я ее исправил.

    Спасибо, тема закрыта.
     
  3. Vitaly_TM

    Vitaly_TM Нуб

    Я бы не сказал, что тема закрыта. Срабатывание прерывания по спаду ведет к пропуску одного поворотного "клика" колеса прокрутки. Посему прерывание должно срабатывать на изменение уровня, т.е.
    attachInterrupt (0,isr,CHANGE);
    Но у меня проблема с таким энкодером, в одну сторону вращение без ошибок, а в другую на определенном месте происходит "шаг назад", один или два раза.
     
  4. qwone

    qwone Гик

    Промой спиртом. У вас наверно флюс во внутрь попал.Вот контакт и пропадает. Китайцы иногда шлют отбраковку по нижней цене.
     
  5. Vitaly_TM

    Vitaly_TM Нуб

    Разобрал энкодер, промыл спиртом, смазал SW-92SA смазкой для пластиковых механизмов. Результат - 0. Думаю, что должно быть решение на программном уровне (аля дребезг контактов).
    Пока проблему решил (шаг назад не наблюдаю) установкой задержки с числом 10 перед каждым чтением с пина даты.
    Главное, что подобное наблюдаю и на китайских поделках (например - RK8512), бывает что ошибка не зависит от направления вращения.
     

    Вложения:

  6. qwone

    qwone Гик

    Ну мой вариант .Полный скетч здесь.https://yadi.sk/d/aeYxE17v3Dhusf
    А головной файл
    Код (C++):
    /* class_do_Encoder_KY_040.ino https://yadi.sk/d/aeYxE17v3Dhusf
      #1 энкодер  CLK->2 (CLK_PIN)
                   DT->3 (DT_PIN)
                   SW->4 (SW_PIN)
      Принцип кода:В сериал отправляется действие на энкодере.
    */

    //#1 энкодер
    #include "Cl_do_Encoder_KY_040.h"
    const byte CLK_pin = 2;
    const byte DT_pin = 3;
    const byte SW_pin = 4;
    Cl_do_Encoder_KY_040 Encoder; // ( CLK,DT,SW )создать энкодер на пинах 2,3,4
    void func_SW(void) {
      Serial.println("Press SW");
    }
    void func_plus(void) {
      Serial.println("Turn +");
    }
    void func_minus(void) {
      Serial.println("Turn -");
    }
    void setup() {
      Serial.begin(9600);
      //#1 энкодер
      Encoder.setup(CLK_pin, DT_pin, SW_pin);
    }
    void loop() {
      //#1 энкодер
      Encoder.loop(& func_SW , & func_plus, & func_minus );
    }
     
    Vitaly_TM нравится это.
  7. dreamwait

    dreamwait Нуб

    Тут проблема глубже - а именно в качестве энкодера. Эти имеют конструктивный дефект - при вращении в одну сторону проскакивают импульсы "обратного" вращения. Лечится 2 способами - покупкой качественного энкодера (ну, тут жаба резко против - они на порядок дороже) или программно - учитываем направление предыдущего вращения - если совпадает - Ок, если противоположное - ничего не делаем, ждем еще одного отсчета - дальше наверное все понятно. Так с минимальными затратами все хорошо работает, без сбоев.