Новый энкодер и привязка к старому коду.
- Войдите на сайт для отправки комментариев
Пт, 31/12/2021 - 15:21
Раньше с этим кодом, у меня четко работали энкодеры от магнитол, за один щелчек код выдавал 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
}
Igoreck,
я вот смотрю на Ваши предыдущие темы (например, и ещё есть) и замечаю, что у Вас есть привычка задать вопрос и исчезнуть. Например, в пролинкованной теме я довольно долго бил пальцы об клавиатуру, пытаясь Вам помочь, а Вы просто исчезли - Вам это неинтересно. Вот и подумаешь, а стоит ли снова бить пальцы, чтобы Вы снова исчезли? Получается ведь, что наша писанина уходит в пустоту.
Как Вы думаете?
Igoreck,
я вот смотрю на Ваши предыдущие темы (например, и ещё есть) и замечаю, что у Вас есть привычка задать вопрос и исчезнуть. Например, в пролинкованной теме я довольно долго бил пальцы об клавиатуру, пытаясь Вам помочь, а Вы просто исчезли - Вам это неинтересно. Вот и подумаешь, а стоит ли снова бить пальцы, чтобы Вы снова исчезли? Получается ведь, что наша писанина уходит в пустоту.
Как Вы думаете?
Секундочку. Никуда я не исчезал, елку наряжал, а так все в силе. И вообще - то спасибо за то что помогаете учится. И как только допишу то все покажу.
Оставить только одно прерывание, и изменить его c CHANGE на RISING или FALLING
Не помогло.
Приумножение нивелируется разделением. Так всегда было вроде?
Неполучается настроить внешнее прерывания на пинах 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); }Весь скетч не проверял. Может есть еще ошибки.
В девятой строке не в тот регистр пишите.
И в loop выводите на печать или с задержками, или если данные изменились.
работающий код для пинов А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.
Что мешает открыть даташит и посмотреть какие именно регистры в какое состояние должны быть выставлены ?
Ждёте когда кто то сделает это за вас ?
"зачем тогда форум?" (с)
Igoreck, По коду в #6
Ошибки в строках:
05,06,07,09,16,17
Знающие, скажите здесь я верно написал?
О Дима с новым годом. Спасибо щас буду пробовать.
Не пойму, все вроде исправил. Но что не так в строке 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); }Igoreck, какие пины вы пытаетесь настроить и какой контроллер?
атмега 328, пины D5 D6.
А какие биты выставить?
if(!(PIND & (1 << PC0))){EncCur = 1;} //опрос фазы 1 энкодера if(!(PIND & (1 << PC1))){ EncCur |= 2;} //опрос фазы 2 энкодераА какие биты выставить?
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 энкодераВсем спасибо.
if(!(PIND & (1 << PD5))){EncCur = 1;} //опрос фазы 1 энкодера if(!(PIND & (1 << PD6))){ EncCur |= 2;} //опрос фазы 2 энкодераслава ойцам, через двадцать сообщений наконец разобрались, что для проверки прерываний на пине PD5 надо проверять-таки PD5, а не PC0 :)