Друзья! Прошу Вашей помощи. Никак не получается научить энкодер KY-040 адекватно работать с arduino nano. Суть проблемы такая: при медленном вращении энкодер работает нормально. Как только вращение ускоряется, ардуина начинает "топтаться на месте", не понимая, в какую сторону идёт вращение. Чем быстрее скорость вращения энкодера, тем больше ошибок при считывании направления вращения. Пробовал обрабатывать энкодер двумя методами: с использованием библиотеки encoder.h и без неё. 1. С библиотекой Encoder.h код следующий: Код (C++): #include <Encoder.h> Encoder myEnc(4, 5); //создаем объект "энкодер" подключенный к ногам 4 и 5 long oldPosition = -999; //устанавливаем значение переменной для хранения текущей позиции void setup() { } void loop() { long newPosition = myEnc.read(); //считываем изменения на энкодере if (newPosition != oldPosition) //если новое значение позиции не равно старому, тогда { if(newPosition > oldPosition) //если значение новой позиции больше старой {frequency=frequency+settingstep; //то совершаем действие при вращении вправо oldPosition = newPosition; //приравниваем старую позицию к текущей } if(newPosition < oldPosition) //если значение новой позиции меньше старой {frequency=frequency-settingstep; //то совершаем действие при вращении влево oldPosition = newPosition; //приравниваем старую позицию к текущей } } } Результат - каждый шаг энкодера ардуина считает за 2, при быстром вращении топчется на месте, при очень быстром - вообще считает в противоположную сторону 2. Без библиотеки: Код (C++): unsigned char encoder_A, encoder_B, encoder_A_prev; //переменные для хранения уровней сигналов, полученных от энкодера. void setup() { } void loop() { encoder_A = digitalRead(5); //считываем на 5 ноге дату с ноги CLK энкодера encoder_B = digitalRead(4); //считываем на 4 ноге дату с ноги DT энкодера if(!encoder_A && encoder_A_prev) //если уровень сигнала на 5 ноге низкий, а в предыдущем цикле он был высокий, то { if(encoder_B) //если уровень на 4 ноге высокий { frequency=frequency+settingstep; //то считаем, что энкодер повернули вправо } else { frequency=frequency-settingstep; //в противном случае - влево } } encoder_A_prev = encoder_A; //сохраняем текущее состояние сигнала А } В таком варианте то же самое, что и с библиотекой, только для одного отсчёта необходимо провернуть валкодер в определенном направлении 2 раза (считывание происходит, наоборот, в 2 раза медленнее реального). Оба примера кода взяты со сторонних сайтов, и их авторы клятвенно божатся, что всё работает идеально. Я думал, может энкодер подсунули бракованный, поменял - история та же... Помогите, у кого есть опыт. Сильно не ругайте, если что не так, ибо я новичок, можно сказать...
По какой схеме подлючен энкодер? Попробуй. Отредактируй под себя. Там энкодер на один шаг выдает значения 4. Если у тебя выдает 2, то дели на 2. Код (C++): #define ENCODER_DO_NOT_USE_INTERRUPTS //используем энкодер без прерываний #include <Encoder.h> #include <avr/io.h> Encoder myEnc(4, 5); // пины к которому подключен энкодер long position = -9999; int voltSet = 0; long old = 0; void setup() { Serial.begin(9600); Serial.println("Basic NoInterrupts Test:"); } void loop() { long newPos = (myEnc.read()/4); // на один шаг энкодера выдает 4 поэтому, делим на 4 if (newPos != position) { position = newPos; Serial.print(position); Serial.print("\t"); Serial.print("|voltSet "); Serial.println(voltSet); } if (newPos > old) { voltSet = voltSet + 1; old = newPos; } else if (newPos < old) { voltSet = voltSet - 1; old = newPos; } }
Энкодер подключен без заморочек всяких: земля к земле, 5в к 5в, кнопка SW через подтягивающий резистор (к +5в) замыкается на землю, CLK подключен к D5, DT к D4
Отредактировал под себя. Делил на 2, ибо если делить на 4, то один шаг энкодера ардуина пропускает. Код получился следующий: Код (C++): long newPos = (myEnc.read()/2); // на один шаг энкодера выдает 4 поэтому, делим на 4 if (newPos != position) { position = newPos; } if (newPos > old) { frequency=frequency+settingstep; old = newPos; } else if (newPos < old) { frequency=frequency-settingstep; old = newPos; } История та же самая. При медленном вращении считывание происходит корректно, при быстром - топтание на месте. Уже три варианта испробовано - всё бесполезно.
Отвечу сам себе: помогло подключение библиотеки Button.h , в которой реализовано подавление дребезга контактов. Для энкодера KY-040 она тоже подходит.