Новый энкодер и привязка к старому коду.

Igoreck
Offline
Зарегистрирован: 01.03.2017

Раньше с этим кодом, у меня четко работали энкодеры от магнитол, за один щелчек код выдавал 1 такт.

Сейчас они закончились, и я купил новые, но в этом коде все энкодеры дают 4 такта за один щелчек.

Что изменить в коде, чтобы новый энкодер, который дает 4 такта за один щелчек, отрабатывался как один такт?

/* This code is without the push button function
    These pins can not be changed 2/3 are special pins -> Interrupt */
    const uint8_t encoderPin1 = 2;
    const uint8_t  encoderPin2 = 3;

    volatile int lastEncoded = 0;
    volatile long encoderValue = 0;
    long lastencoderValue = 0;
    uint8_t lastMSB = 0;
    uint8_t lastLSB = 0;

    void setup() {
      Serial.begin (9600);

      pinMode(encoderPin1, INPUT);
      pinMode(encoderPin2, INPUT);

      digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
      digitalWrite(encoderPin2, HIGH); //turn pullup resistor on
      /* Call updateEncoder() when any high/low changed seen
      on interrupt 0 (pin 2), or interrupt 1 (pin 3)*/
      attachInterrupt(0, updateEncoder, CHANGE);
      attachInterrupt(1, updateEncoder, CHANGE);
    }

    void loop() {
      //Do stuff here
      Serial.println(encoderValue);
      delay(1000); //just here to slow down the output, and show it will work even during a delay
    }

    void updateEncoder() {
      int MSB = digitalRead(encoderPin1); //MSB = most significant bit
      int LSB = digitalRead(encoderPin2); //LSB = least significant bit
      int encoded = (MSB << 1) | LSB; //converting the 2 pin value to single number
      int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
      if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
      if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;
      lastEncoded = encoded; //store this value for next time
    }

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Igoreck,

я вот смотрю на Ваши предыдущие темы (например, и ещё есть) и замечаю, что у Вас есть привычка задать вопрос и исчезнуть. Например, в пролинкованной теме я довольно долго бил пальцы об клавиатуру, пытаясь Вам помочь, а Вы просто исчезли - Вам это неинтересно. Вот и подумаешь, а стоит ли снова бить пальцы, чтобы Вы снова исчезли? Получается ведь, что наша писанина уходит в пустоту.

Как Вы думаете?

Igoreck
Offline
Зарегистрирован: 01.03.2017

ЕвгенийП пишет:

Igoreck,

я вот смотрю на Ваши предыдущие темы (например, и ещё есть) и замечаю, что у Вас есть привычка задать вопрос и исчезнуть. Например, в пролинкованной теме я довольно долго бил пальцы об клавиатуру, пытаясь Вам помочь, а Вы просто исчезли - Вам это неинтересно. Вот и подумаешь, а стоит ли снова бить пальцы, чтобы Вы снова исчезли? Получается ведь, что наша писанина уходит в пустоту.

Как Вы думаете?

Секундочку. Никуда я не исчезал, елку наряжал, а так все в силе. И вообще - то спасибо за то что помогаете учится. И как только допишу то все покажу.

 

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Оставить только одно прерывание, и изменить его c CHANGE на RISING или FALLING

Igoreck
Offline
Зарегистрирован: 01.03.2017

Kakmyc пишет:
Оставить только одно прерывание, и изменить его c CHANGE на RISING или FALLING

Не помогло.

sadman41
Offline
Зарегистрирован: 19.10.2016

Приумножение нивелируется разделением. Так всегда было вроде?

Igoreck
Offline
Зарегистрирован: 01.03.2017

Неполучается настроить внешнее прерывания на пинах D5 и D6.

Может кто поможет.

//Энкодер на пинах А0, А1. Используется внутренняя подтяжка.
volatile int enc;
void setup(){                
Serial.begin(9600);
pinMode(A0,INPUT_PULLUP);
pinMode(A1,INPUT_PULLUP);
PCIFR=PCIF2;
PCICR=1<<PCIE2; //разрешить прерывание второй группы
PCMSK1=1<<PCINT21 | 1<<PCINT22; //выбрать вход на котором сработает прерывание 
}

ISR(PCINT2_vect){
static char EncPrev=0;      //предыдущее состояние энкодера
static char EncPrevPrev=0;  //пред-предыдущее состояние энкодера
  char EncCur = 0;
  if(!(PINC & (1 << PC0))){EncCur  = 1;} //опрос фазы 1 энкодера
  if(!(PINC & (1 << PC1))){ EncCur |= 2;} //опрос фазы 2 энкодера
  if(EncCur != EncPrev)             //если состояние изменилось,
  {
    if(EncPrev == 3 &&        //если предыдущее состояние 3
       EncCur != EncPrevPrev )      //и текущее и пред-предыдущее не равны,
    {
      if(EncCur == 2)          //если текущее состояние 2,
        enc++;            //шаг вверх
      else                          //иначе
        enc--;            //шаг вниз
    }
    EncPrevPrev = EncPrev;          //сохранение пред-предыдущего состояния
    EncPrev = EncCur;               //сохранение предыдущего состояния
  }


  }



void loop() {
Serial.println(enc); 
}

 

Upper
Offline
Зарегистрирован: 23.06.2020

Весь скетч не проверял. Может есть еще ошибки.

В девятой строке не в тот регистр пишите.

И в loop выводите на печать или с задержками, или если данные изменились.

Igoreck
Offline
Зарегистрирован: 01.03.2017

работающий код для пинов А0 и А1.

//Энкодер на пинах А0, А1. Используется внутренняя подтяжка.
volatile int enc;
void setup(){                
Serial.begin(9600);
pinMode(A0,INPUT_PULLUP);
pinMode(A1,INPUT_PULLUP);
PCIFR=PCIFR; PCICR=1<<PCIE1; //разрешить прерывание
PCMSK1=1<<PCINT8 | 1<<PCINT9; //выбрать вход на котором сработает прерывание 
}

ISR(PCINT1_vect){
static char EncPrev=0;      //предыдущее состояние энкодера
static char EncPrevPrev=0;  //пред-предыдущее состояние энкодера
  char EncCur = 0;
  if(!(PINC & (1 << PC0))){EncCur  = 1;} //опрос фазы 1 энкодера
  if(!(PINC & (1 << PC1))){ EncCur |= 2;} //опрос фазы 2 энкодера
  if(EncCur != EncPrev)             //если состояние изменилось,
  {
    if(EncPrev == 3 &&        //если предыдущее состояние 3
       EncCur != EncPrevPrev )      //и текущее и пред-предыдущее не равны,
    {
      if(EncCur == 2)          //если текущее состояние 2,
        enc++;            //шаг вверх
      else                          //иначе
        enc--;            //шаг вниз
    }
    EncPrevPrev = EncPrev;          //сохранение пред-предыдущего состояния
    EncPrev = EncCur;               //сохранение предыдущего состояния
  }


  }



void loop() {
Serial.println(enc); 
}

Мне же надо для пинов D5 и D6.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Что мешает открыть даташит и посмотреть какие именно регистры в какое состояние должны быть выставлены ?
Ждёте когда кто то сделает это за вас ?

b707
Offline
Зарегистрирован: 26.05.2017

Kakmyc пишет:
Что мешает открыть даташит и посмотреть какие именно регистры в какое состояние должны быть выставлены ? Ждёте когда кто то сделает это за вас ?

"зачем тогда форум?" (с)

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Igoreck, По коду в #6
Ошибки в строках:
05,06,07,09,16,17

Igoreck
Offline
Зарегистрирован: 01.03.2017

Знающие, скажите здесь я верно написал?

PCICR=1<<PCIE2; //разрешить прерывание второй группы
PCMSK2=1<<PCINT21 | 1<<PCINT22; //выбрать вход на котором сработает прерывание

 

Igoreck
Offline
Зарегистрирован: 01.03.2017

dimax пишет:
Igoreck, По коду в #6 Ошибки в строках: 05,06,07,09,16,17

О Дима с новым годом. Спасибо щас буду пробовать.

Igoreck
Offline
Зарегистрирован: 01.03.2017

Не пойму, все вроде исправил. Но что не так в строке 16, 17?

//Энкодер на пинах А0, А1. Используется внутренняя подтяжка.
volatile int enc;
void setup(){                
Serial.begin(9600);
pinMode(5,INPUT_PULLUP);
pinMode(6,INPUT_PULLUP);
PCIFR=PCIFR;
PCICR=1<<PCIE2; //разрешить прерывание второй группы
PCMSK2=1<<PCINT21 | 1<<PCINT22; //выбрать вход на котором сработает прерывание 
}

ISR(PCINT2_vect){
static char EncPrev=0;      //предыдущее состояние энкодера
static char EncPrevPrev=0;  //пред-предыдущее состояние энкодера
  char EncCur = 0;
  if(!(PINC & (1 << PC0))){EncCur  = 1;} //опрос фазы 1 энкодера
  if(!(PINC & (1 << PC1))){ EncCur |= 2;} //опрос фазы 2 энкодера
  if(EncCur != EncPrev)             //если состояние изменилось,
  {
    if(EncPrev == 3 &&        //если предыдущее состояние 3
       EncCur != EncPrevPrev )      //и текущее и пред-предыдущее не равны,
    {
      if(EncCur == 2)          //если текущее состояние 2,
        enc++;            //шаг вверх
      else                          //иначе
        enc--;            //шаг вниз
    }
    EncPrevPrev = EncPrev;          //сохранение пред-предыдущего состояния
    EncPrev = EncCur;               //сохранение предыдущего состояния
  }


  }



void loop() {
Serial.println(enc); 
}

 

b707
Offline
Зарегистрирован: 26.05.2017

Igoreck, какие пины вы пытаетесь настроить и какой контроллер?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013
Igoreck,  имя порта "PINC"  и  биты "PC0/1" так и остались от порта С

 

Igoreck
Offline
Зарегистрирован: 01.03.2017

атмега 328, пины D5 D6.

Igoreck
Offline
Зарегистрирован: 01.03.2017

dimax пишет:

Igoreck,  имя порта "PINC"  и  биты "PC0/1" так и остались от порта С

 

А какие биты выставить?

  if(!(PIND & (1 << PC0))){EncCur  = 1;} //опрос фазы 1 энкодера
  if(!(PIND & (1 << PC1))){ EncCur |= 2;} //опрос фазы 2 энкодера

 

Igoreck
Offline
Зарегистрирован: 01.03.2017

Igoreck пишет:

dimax пишет:

Igoreck,  имя порта "PINC"  и  биты "PC0/1" так и остались от порта С

 

А какие биты выставить?

  if(!(PIND & (1 << PC0))){EncCur  = 1;} //опрос фазы 1 энкодера
  if(!(PIND & (1 << PC1))){ EncCur |= 2;} //опрос фазы 2 энкодера

 

Есть контакт.

Всем спасибо.

  if(!(PIND & (1 << PD5))){EncCur  = 1;} //опрос фазы 1 энкодера
  if(!(PIND & (1 << PD6))){ EncCur |= 2;} //опрос фазы 2 энкодера

 

b707
Offline
Зарегистрирован: 26.05.2017

Igoreck пишет:

Всем спасибо.

  if(!(PIND & (1 << PD5))){EncCur  = 1;} //опрос фазы 1 энкодера
  if(!(PIND & (1 << PD6))){ EncCur |= 2;} //опрос фазы 2 энкодера

 

слава ойцам, через двадцать сообщений наконец разобрались, что для проверки прерываний на пине PD5 надо проверять-таки PD5, а не PC0 :)