Оптический энкодер и Arduino Leonardo

German

✩✩✩✩✩✩✩
18 Мар 2019
9
0
Рефералки необходимо убить!
Привет всем.

Относительно недавно начал баловаться Ардуино.
Ближе к делу. Имеется плата Arduino Leonardo (аналог от искры).
Имеется оптический инкрементный энкодер (вот этот с алика).
Суть проблемы, что не удается заставить работать этот энкодер.
Что я делаю: к плате подключена крона на 9 вольт для стабильных 5 вольт на выходе (измерил, с ней 5,06 В).
Цепляю к 3 и 4 пинам обычный поворотный энкодер (механический, с кнопочкой), загружаю скетч - все работает: в порт выводится число, которое сообщает, что вал отклонился. Там все стандартно, если надо - я приложу пример. Но проблема в том, что если я подключаю энкодер, который указал в ссылке - ничего не работает. Я не могу понять, как определить - он вообще живой или нет. Все что я на данный момент сделал это:
1. Прозвонил попарно контакты мультиметром - кз не обнаружил.
2. Разобрал корпус и прозвонил провода на предмет обрывов - обрывов не обнаружено (корпус собрал, лишних деталей не осталось).
3. Убедился, что на энкодер подается напряжение. При этом, на 1 из 2 выводов зафиксированы 5 вольт на выходе. На другом при этом 0.

Как можно гарантировано заставить работать этот оптический энкодер с леонардо? Либо как его можно проверить жив он вообще или нет? В интернете находил разные скетчи, как с использованием прерываний, так и без них - не помогло. Буду признателен за любую помощь.
 

German

✩✩✩✩✩✩✩
18 Мар 2019
9
0
@Wan-Derer,
Питание подал (пробвал и от ардуины и от внешнего модуля питания.
Как подключил и код - сегодня выложу ближе к вечеру.
 

German

✩✩✩✩✩✩✩
18 Мар 2019
9
0
Вот схема подключения (провода подключены так:красный = + 5В, черный = минус, зеленый = А, белый = В). А и В сидят на 3 и 4 пинах ардуинки:
Encoder_bb.png
Если тут стоит потенциометр (механический поворотный энкодер), то все работает. Если я туда цепляю свой оптический энкодер - не происходит ничего.

Там где в коде указаны иные пины, они были использованы для приема сигнала с каналов А и В соответсвенно.

Код1 и Код3 - механика работает, оптика - нет
Код2 и Код4 - механику не проверял, оптика не работает

В силу нехватки знаний, я не могу понять - то ли я неправильно что-то делаю, то ли у меня оптический энкодер мертвый.

C-like:
#define pin_CLK 3
#define pin_DT  4


unsigned long CurrentTime, LastTime;
enum eEncoderState {eNone, eLeft, eRight};
int EncoderA, EncoderB, EncoderAPrev, counter;

eEncoderState GetEncoderState() {
  // Считываем состояние энкодера
  eEncoderState Result = eNone;
  CurrentTime = millis();
  if (CurrentTime >= (LastTime + 5)) {
    // Считываем не чаще 1 раза в 5 мс для уменьшения ложных срабатываний
    LastTime = CurrentTime;
    {
      EncoderA = digitalRead(pin_DT);
      EncoderB = digitalRead(pin_CLK);
      if ((!EncoderA) && (EncoderAPrev)) { // Сигнал A изменился с 1 на 0
        if (EncoderB) Result = eRight;     // B=1 => энкодер вращается по часовой
        else          Result = eLeft;      // B=0 => энкодер вращается против часовой
      }
      EncoderAPrev = EncoderA; // запомним текущее состояние сигнала A
    }
  }
  return Result;
}

void setup() {
  pinMode(pin_DT,  INPUT);
  pinMode(pin_CLK, INPUT);
  Serial.begin(9600);
  counter = 0;
}

void loop() {
  switch (GetEncoderState()) {
    case eNone: return;
    case eLeft: {
        counter--;
        break;
      }
    case eRight: {
        counter++;
        break;
      }
  }
  Serial.println(counter);
}
C-like:
  byte seqA;
  byte seqB;
  int cnt1 = 0;
  int cnt2 = 0;
  bool left = false;
  bool right = false;
void setup()
{

  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
 
  // Включить внутренние подтягивающие резисторы
  digitalWrite(A1, HIGH);
  digitalWrite(A2, HIGH);
 
  PCICR =  0b00000010; // 1. PCIE1: Включить прерывание 1 по изменению состояния
  PCMSK1 = 0b00000111; // Включить прерывание по изменению состояния для A0, A1, A2
  Serial.begin(9600);
}

void loop()
{
  // Основной цикл
  Serial.println(cnt1);
  Serial.println(" ");
  Serial.println(cnt2);
  Serial.println("/////");
}

ISR (PCINT1_vect)
{



  // Если прерывание вызвано сигналами энкодера
  {
    
    // Прочитать сигналы A и B
    boolean A_val = digitalRead(A1);
    boolean B_val = digitalRead(A2);
    
    // Записать сигналы A и B в отдельные последовательности
    seqA <<= 1;
    seqA |= A_val;
    
    seqB <<= 1;
    seqB |= B_val;
    
    // Маскировать четыре старших бита
    seqA &= 0b00001111;
    seqB &= 0b00001111;
    
    // Сравнить запсанную последовательность с ожидаемой последовательностью
    if (seqA == 0b00001001 && seqB == 0b00000011)
    {
      cnt1++;
      left = true;
      Serial.println(cnt1);
    }
    
    if (seqA == 0b00000011 && seqB == 0b00001001)
    {
      cnt2++;
      right = true;
      Serial.println(cnt2);
    }
  }
 
}
C-like:
int val;
int encoder0PinA = 4;
int encoder0PinB = 3;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;

void setup() {
  pinMode (encoder0PinA,INPUT);
  pinMode (encoder0PinB,INPUT);
  Serial.begin (9600);
}

void loop() {
  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {
    if (digitalRead(encoder0PinB) == LOW) {
      encoder0Pos--;
    } else {
      encoder0Pos++;
    }
    Serial.print (encoder0Pos);
    Serial.print ("/");
  }
  encoder0PinALast = n;
}
C:
#define PIN_A 3
#define PIN_B 4

volatile unsigned long enabledA_time=0;
volatile bool fl=false; // флаг что нужно вывести
volatile bool value_b=0;
void setup(){
  Serial.begin(9600);
  digitalWrite(PIN_A,HIGH);
  digitalWrite(PIN_B,HIGH);
 
  attachInterrupt(0,handler_a,RISING);
 
  Serial.println("Ready");
}

void handler_a(){
  if(enabledA_time<millis()){
    value_b=digitalRead(PIN_B);
    fl=true;
    enabledA_time=millis()+500;// уж включили антидребезг так включили
  }
}

void loop(){
  if(fl){
    Serial.print(value_b);
    Serial.print(" ");
    fl=false;
  }
}
В поиске здесь подобного не нашел.
Цель - научиться считывать с энкодера показатель. В будущем он планируется в использовании как ось игрового руля.
 

German

✩✩✩✩✩✩✩
18 Мар 2019
9
0
@German, Попробуй входы назначать как INPUT_PULLUP
Попробовал на самом первом варианте кода. Никаких изменений. Я не знаю, можно ли было так делать, но я подключил в параллель оба энкодера. Не заработал ни 1. Когда оставил только механический - он продолжил работать (после сброса платы).
 

German

✩✩✩✩✩✩✩
18 Мар 2019
9
0
@Wan-Derer, премного благодарен. Поизучаю статью, напишу, к чему пришел. Как я понимаю, платформа Леонардо тоже та еще штучка капризная. Возможно дело в ней.
 

Wan-Derer

★★★★✩✩✩
Команда форума
31 Июл 2018
1,441
281
Москва
wan-derer.ru
@German, ну, если сомневаешься, потренируйся сначала на Нано. Тут же надо понять как железка работает, а уж библу заполнить по образу и подобию - дело техники :)
 

German

✩✩✩✩✩✩✩
18 Мар 2019
9
0
@Wan-Derer, попробовал на нано. Сперва решил, что вот оно - счастье. Взял скетч из статьи, прицепил библиотеку и в порт пошли данные, но как оказалось - это какой-то мусор. Если просто подключить энкодер к пинам и не подать напряжение - все равно плата ловит что-то и счетчик нарастает. В интернете нашел видео под свою модель, где чел напрямую подключил энкодер к плате, загрузил скетч и оно все взлетело. Видео под спойлером:

Там же можно ссылку на скетч найти. Увы - не взлетело. Энкодер питаю от 9В батарейки напрямую. Так что питания ему должно хватить. Все больше и больше думаю, что мне попался брак.

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

Wan-Derer

★★★★✩✩✩
Команда форума
31 Июл 2018
1,441
281
Москва
wan-derer.ru
@German, при расчёте гасящего резистора надо исходить из тока, который пойдёт через светодиод. Стандартно обычный СД требует 5 мА.
9В / 5 мА = 1.8 кОм
В реальности расчёт чуть сложнее, но здесь плюс-минус лапоть роли не играет. Есть онлайн-калькуляторы.
И батарейку свою проверь. Она точно даёт 9В под нагрузкой?
 

German

✩✩✩✩✩✩✩
18 Мар 2019
9
0
@Wan-Derer, огромное спасибо за помощь. Батарейка давала 8 вольт, а это значит что 1,6 кОм надо подобрать. В наличии были на 1 кОм и на 2,2 кОм. Проверял на обоих. Кроме того, нашел источник питания, который выдает ровно 9В. Проверял так же на обоих номиналах. Ничего не работает. Полярность у сд верная - я до этого ее проверил и подключил на макетку так, чтобы при прямой подаче напряжения они горели. Вот так просто - горят. Через энкодер - нет. Из чего я делаю вывод, что энкодер мертв. Увы. Если есть идеи для проверки - попробую. Но я уже не верю, что он может работать.
 

German

✩✩✩✩✩✩✩
18 Мар 2019
9
0
@Wan-Derer, раскручивал - все на месте. Провода припаяны, плата выглядит живой. Правда я не знаю, что и как прозванивать на ней. Если нужно - могу прикрепить фото, как энкодер выглядит изнутри.