Как правильно подключить энкодер к ардуино?

Тема в разделе "Схемотехника, компоненты, модули", создана пользователем PushKeeN, 15 фев 2018.

  1. PushKeeN

    PushKeeN Нуб

    Здравствуйте!
    Есть желание сделать устройство для натяжения проволоки в процессе перемотки с одной катушки на другую.
    В связи с этим с помощью 3д принтера и всяких подручных запчастей было сооружено нечто, что вы можете лицезреть на фото) Это экспериментальный макет.
    IMG_20180214_204152.jpg
    Есть "потребитель" проволоки, т.е. проволока через все ролики вытягивается другим устройством и наматывается на катушку. Катушка, которая сидит на шаговом двигателе должна изменять скорость вращения в зависимости от скорости "потребления". За это отвечает рычаг, который закреплен в правой части устройства на подшипниках и, соответственно, левая часть может перемещаться вверх-вниз по дуге. Груз на рычаге создает необходимое натяжение.
    Идеальная картина выглядит в моей фантазии так: независимо от скорости перемотки рычаг находится постоянно в горизонтальном положении и при изменении скорости максимально быстро возвращается в это положение. По сути - это обыкновенная задача "обратный маятник".
    Первоначально на подшипниковом "узле" был установлен потенциометр, и все вроде бы работало, однако время от времени происходили какие-то глюки и шаговик пытался моментально развить максимальную сокрость, что приводило к его зависанию (ротор за полем не успевал). Я грешил именно на резистор, его дребезг и мое неумелое сглаживание :) Заменил его на инкрементальный энкодер.
    Идея была в том, что я примерно знаю количество импульсов энкодера "от стола" до верхнего положения рычага, а значит знаю ориентировочное желаемое значение положения рычага. В моем случае это 55.
    Энкодер у меня самый простой китайский: LPD3806-400BM-G5-24C на 400 импульсов. Провод состоит из 4 жил (Vcc, GND, A, B) и оплетки экранирования. Подключено все напрямую, т.е. питание к питанию, логические контакты к ардуино экранирование на GND.
    Я все это подключил, однако результатом остался недоволен. Резкие всплески пропали, но появился другой эффект - в процессе работы энкодер явно сбивается со счета. Т.е. точка 55 время от времени смещается в пространстве и через какое-то время может оказаться у "стола" или в противоположной стороне.
    Для меня совершенно очевидно три варианта: либо я накодил криво и энкодер пропускает импульсы, либо я неправильно подключил энкодер (на что я надеюсь больше всего), либо неисправен/плохого_качества сам энкодер.
    И еще заметил, что если отключить ноутбук от ардуины все работает намного лучше, но все равно не идеально, к сожалению. А когда ноут подключен, он иногда немного "кусается"!
    Подскажите, пожалуйста, куда копать и на что смотреть.
    Код (C++):
    #include <PID_v1.h>
    #define MOT 9                         // Step драйвера шаговика
    #define ENCODER 2                     // Пин энкодера для определения направления вращения
    int current_pos = 0;
    int max_steps = 3500;                 // Максимальная частота, передаваемая двигателю

    //НАСТРОЙКИ ПИД РЕГУЛЯТОРА
    float Kp = 45;                        //Initial Proportional Gain-+
    float Ki = 40;                        //Initial Integral Gain
    float Kd = 0;                         //Initial Differential Gain
    double Setpoint, Input, Output;       //These are just variables for storingvalues
    PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, P_ON_M, DIRECT);

    void setup() {
      pinMode(MOT, OUTPUT);
      attachInterrupt(0, encoder_secondary_pin, RISING);    // Прерывание для энкодера
      pinMode(ENCODER, INPUT_PULLUP);                       // Пин для считывания состояния второго пина энкодера (определение направления)
      pinMode(3, INPUT_PULLUP);                             // Пин для считывания состояния первого пина энкодера
      Setpoint = 55;                                        // Желаемое значение, к которому будет стремится ПИД-регулятор
     
      myPID.SetMode(AUTOMATIC);                             //Turn on the PID loop
      myPID.SetSampleTime(sampleRate);                      //Sets the sample rate
      myPID.SetOutputLimits(0, max_steps);                  // Настройка минимального и максимального значения, выдаваемого ПИД-регулятором
    }

    void loop() {

      Input = current_pos; //Засовываем текущее положение в регулятор
      myPID.Compute(); //Run the PID loop
      int frq = Output - max_steps;

      tone(MOT, frq, 10);          // Передаем частоту в драйвер

      if (current_pos == Setpoint)
        digitalWrite(13, 1);
      else
        digitalWrite(13, 0);
    }

    // Вызывается по прерыванию на первый провод энкодера для проверки состояния второго и определения направления движения вала
    void encoder_secondary_pin()
    {
      if (digitalRead(ENCODER) == LOW)
        current_pos = current_pos - 1;
      else
        current_pos = current_pos + 1;
    }
     
  2. mcureenab

    mcureenab Гуру

    Схему подключения приложите. Похоже подключение неправильное, вместо сигнала помехи идут.
     
  3. mcureenab

    mcureenab Гуру

    У вас порт 3 не используется.

    Прерывание повешено на порт 2, значит нужно в прерывании читать порт 3.

    Переменную current_pos нужно объявлять с модификатором volatile.
     
  4. parovoZZ

    parovoZZ Гуру

    Энкодер с открытым коллектором. Вы его как подключили ко входу МК?
    Какой алгоритм определения вращения энкодера? В прерывание уходим по фронту на 2 пине и в нем же считываем 2 пин. А он всегда High. По идее надо считывать 3 пин.
     
  5. PushKeeN

    PushKeeN Нуб

    К сожалению, не знаю как показать схему. Питание с пина +5, земля и экран к GND, сигнальные провода пробовал напрямую к пинам 2 и 3, также пробовал с подтягиванием к земле через 1к резисторы.
    А вот это действительно похоже на правду) Видимо просто запутался с нумерацией и поставил неправильный пин!)
    Смогу посмотреть что да как только в понедельник, но обязательно отпишусь!
    Спасибо за ваши ответы :)
     
  6. PushKeeN

    PushKeeN Нуб

    Вчера тестировал отдельно энкодер без двигателя и пид-регулятора.
    Перевернул конструкцию, что бы получить маятник. В скетче с маятником, вроде бы правильно пины указаны:
    Код (C++):
    int current_pos = 0;

    void setup() {
      attachInterrupt(0, encoder_secondary_pin, RISING);
      pinMode(2, INPUT_PULLUP);                            
      pinMode(3, INPUT_PULLUP);                            
      pinMode(13, OUTPUT);
      Serial.begin(9600);
    }

    void loop() {
      if (current_pos == 0)
        digitalWrite(13, 1);
      digitalWrite(13, 0);
      if (millis()%100==0){
      Serial.println(current_pos);
      Serial.println(0);}
    }

    void encoder_secondary_pin()
    {
      if (digitalRead(2) == 0)
        current_pos++;
      else
        current_pos--;
    }
    Результат:

    Возможно действительно поможет смена типа переменной current_pos - в понедельник попробую.
     
  7. parovoZZ

    parovoZZ Гуру

    Нарисовать? изиида, например)))
     
  8. PushKeeN

    PushKeeN Нуб

    Хох, господа! Я понял почему вы мне в пин №2 тыкаете :) Забыл упомянуть, что использую искру нео, а у нее прерывание 0 - третий порт, а не второй. Так что я правильно все делал: прерывание было по третьему пину, а второй пин читался по прерыванию.
    Ну, сейчас попробую нарисовать))
    Замена int на volatile int никак не отразилась на результате(
     
  9. PushKeeN

    PushKeeN Нуб

    Ну что-то в этом роде) Питание на искру подается через usb.
    Безымянный3.png
    Самое интересное, что значения прыгают туда-сюда! Вот сейчас качал маятник, на третьей итерации после "успокоения" маятника, значение было 13, на пятой итерации - 1.
    Я прошу прощения, я совершенно профан в электронике, рисовании схем и так далее.
     
    Последнее редактирование: 19 фев 2018
  10. parovoZZ

    parovoZZ Гуру

    Вообще порт у МК - это аж 8 пинов)))
    Энкодер оптический? А он тоже дребезжит. Отсюда и значения прыгают туда-сюда.
     
  11. PushKeeN

    PushKeeN Нуб

    Энкодер оптический, да! Дребезг? Ну, с кнопкой - понятно что такое дребезг, а вот с оптической системой - не очень. Но я почитаю :)
    Про порт - учту, спасибо :) Плаваю в терминологии!
     
  12. PushKeeN

    PushKeeN Нуб

    Ну что ж, я почитал) Кто-то дебаунсит оптические энкодеры, кто-то утверждает, что у оптического энкодера не может быть дребезга, в общем, мнения разнятся!
    Я собрал схему дебаунса вот такую:
    HTB1YoXGPpXXXXXpXXXXq6xXFXXXe.jpg
    Работает не идеально. При включении искры, переменная current_pos = 0 и это положение при котором маятник в покое. Я переписал скетч на счёт по двум прерываниям на "change", соответственно увеличил "точность" в 4 раза и имею на данный момент 1600 импульсов на оборот. Так вот неточность состаяляла около -5..+5 импульсов.
    В итоге на просторах интернета нашел скетч, который проверяет таблицу возможных значений состояний пинов и вкупе со схемой дебаунса все заработало как надо. Единственный нюанс, что после первого покачивания состояние покоя смещается в -1 и там остается. Меня, в принципе, это устраивает!
    Спасибо за мнения, советы и так далее)
     
  13. mcureenab

    mcureenab Гуру

    В оптическом датчике уровень сигнала меняется слишком медленно, поэтому его сигнал по сути нельзя считать цифровым.
    Для чёткого переключения попробуйте пропустить сигнал от энкодера через триггер Шмитта хотя бы на пин прерывания.
    Пин направления к тому времени должен уже находится в стабильном состоянии. Его не обязательно даже фильтровать.
     
  14. parovoZZ

    parovoZZ Гуру

    Триггер Шмидта уже стоит в МК на входе))))
     
  15. Kamikadze

    Kamikadze Гик

    только вот если аналоговый сигнал на цифровой подавать, он будет отображаться не корректно или вообще не будет (проверено). Т.е. если плавно падает напряжение с 5 до 0.5 волтьа на пине может висеть как 1 так и 0 бесконечно долго, после чего сменить свое значение. Как и при повышении с 0 на 5 так же на пине может висеть 0. А 74HCT14 вполне как раз таки решает данную проблему. И правильнее все же Шмитта, а не Шмидта...
     
  16. parovoZZ

    parovoZZ Гуру

    Хм, это странно. Такого быть не должно. Пожалуй, я тоже проверю при случае.
    А, это айфон, сука, исправляет))))
     
  17. Kamikadze

    Kamikadze Гик

    Да не должно по идее Лоу 0-0.8 свыше 2.5 это логическая еденица. Но с ардуиной на практике не так... М.б. конечно то что она не оригинальная а китайская. Проверенно как на меге так и на уно. Подавал напряжение от 0.5 до 3 и было параллельно, либо висел 0 и через некоторое лишь время 1, или пока не переподключишь контакт к пину.
     
  18. parovoZZ

    parovoZZ Гуру

    Мне имхуется, что эксперимент поставлен не корректно. Как минимум, источник напряжения надо нагрузить на килоом, чтобы имитировать внутреннее сопротивление буфера. А если мк китайчатина, то это 100% отбраковка. По какому параметру отбраковано - даже узкоглазые не в курсе.
     
  19. Kamikadze

    Kamikadze Гик

    Эксперимент ставился через делитель напряжения 1.5/1.5 т.е. нагрузка была. А что касается китайского брака, м.б. Однако работают данные девайсы вполне себе долго и стабильно. две уны висят на управлении драйверов для шаговых двигателях, а одна из мег, как раз таки рулит этими унами. (точнее рулила...)
     
  20. parovoZZ

    parovoZZ Гуру

    Я это проверю у себя. Мне даже интересно.