Реклама ⓘ
Главная » Arduino
Призовой фонд
на июль 2024 г.
1. 100 руб.
От пользователей

Похожие статьи:


Реклама ⓘ

Arduino UNO урок 6 - Энкодер

Энкодер

В очередном уроке мы рассмотрим работу Arduino с энкодером (который служит для преобразования угла поворота в эл. сигнал). С энкодера мы получаем 2 сигнала (А и В), которые противоположны по фазе. В данном уроке мы будем использовать энкодер фирмы SparkFun COM-09117, который имеет 12 положений на один оборот (каждое положение 30°). На приведенной ниже диаграмме вы можете видеть, как зависят выход А и В друг от друга при вращении энкодера по часовой или против часовой стрелки.

Диаграмма энкодера

Каждый раз, когда сигнал А переходит от положительного уровня к нулю, мы считываем значение выхода В. Если В в этот момент находится в положительном состоянии, значит энкодер вращается по часовой стрелке, если В нуль, то энкодер вращается против часовой стрелки. Считывая оба выхода, мы при помощи МК можем определить направление вращения, и при помощи подсчета импульсов с А выхода - угол поворота. Конечно можно пойти еще дальше и при помощи вычисления частоты, можно определить насколько быстро происходит вращение энкодера. Как вы видите, энкодер имеет много преимуществ по сравнению с обычным потенциометром.

Используя энкодер мы будем управлять яркостью LED светодиода при помощи ШИМ выхода. Для считывания данных энкодера мы будем использовать простейший метод, основанный на программных таймерах, которые мы изучали в третьем уроке.

Как было сказано выше, мы будем использовать энкодер sparkfun. Первое, что необходимо сделать, это определить как часто нам нужно обращаться к выходам энкодера для считывания значений. Итак, представим себе, что в лучшем случае, мы можем повернуть ручку энкодера на 180° за 1/10 сек, т.е. это будет 6 импульсов за 1/10 сек или 60 импульсов в секунду. В реальности быстрее вращать не сможете. Т.к. нам необходимо отслеживать все полупериоды, то частота должна быть минимум 120 Герц. Для полной уверенности, давайте примем 200 Гц. (Примечание: т.к. у нас механический энкодер, то возможен дребезг контактов, а низкая частота позволяет отфильтровывать дребезг).

Схема подключения энкодера и LED

По сигналам программного таймера нам необходимо постоянно сравнивать текущее значение выхода А энкодера с предыдущим значением. Если состояние изменилось от положительного к нулю, то мы проверяем значение выхода В и смотрим положительное оно или нет. В зависимости от полученного результата мы увеличиваем или уменьшаем счетчик значения яркости светодиода.

Устройство на макетной плате

Программа для данного урока приведена ниже. Она построена на базе предыдущего урока Fade, где использовалась функция millis() для задания временных интервалов. Временной интервал у нас будет 5 мс (200 Гц)

/*
** Энкодер
** Для управлением яркостью LED используется энкодер Sparkfun
*/

int brightness = 120;    	// яркость LED, начинаем с половины
int fadeAmount = 10;    	// шаг изменения яркости LED
unsigned long currentTime;
unsigned long loopTime;
const int pin_A = 12;  		// pin 12
const int pin_B = 11;  		// pin 11
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;

void setup()  {
  // declare pin 9 to be an output:
  pinMode(9, OUTPUT);		  // устанавливаем pin 9 как выход
  pinMode(pin_A, INPUT);
  pinMode(pin_B, INPUT);
  currentTime = millis();
  loopTime = currentTime; 
} 

void loop()  {
  currentTime = millis();
  if(currentTime >= (loopTime + 5)){	// проверяем каждые 5мс (200 Гц)
    encoder_A = digitalRead(pin_A);    	// считываем состояние выхода А энкодера 
    encoder_B = digitalRead(pin_B);    	// считываем состояние выхода B энкодера    
    if((!encoder_A) && (encoder_A_prev)){	 // если состояние изменилось с положительного к нулю
      if(encoder_B) {
        // выход В в полож. сост., значит вращение по часовой стрелке
        // увеличиваем яркость, не более чем до 255
        if(brightness + fadeAmount <= 255) brightness += fadeAmount;               
      }   
      else {
        // выход В в 0 сост., значит вращение против часовой стрелки     
        // уменьшаем яркость, но не ниже 0
        if(brightness - fadeAmount >= 0) brightness -= fadeAmount;               
      }   

    }   
    encoder_A_prev = encoder_A;     // сохраняем значение А для следующего цикла 
    
    analogWrite(9, brightness);   // устанавливаем яркость на 9 ножку
   
    loopTime = currentTime;
  }                       
}

Оригинал статьи

Теги:

Колтыков А.В. Опубликована: 2011 г. 0 1
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (17) | Я собрал (0) | Подписаться

0
DIMA #
Автор! Огромное спасибо! Я искал эту схему.

Повторил код- Всё работает!
Ответить
0
Zak #
Я новичок в ардуине и в контроллерах вообще. Но все получилось
Ответить
0
elf #
Возможно применение энкодера в изготовлении руля для компьютера?
Ответить
0
Дмитрий #
Возможно, но придётся отслеживать руль на начальное положение
Ответить
0
Артем #
Добавить на руль 2 пружины, тянущие в разные стороны. Во-первых - будут возвращать руль в исходное положение. Во-вторых - подгружать его, чтобы вращение было более тугим и приближенным к реальности
Ответить
0
ELiF #
Как изменить скетч, чтобы при вращении энкодера на двух различных пинах соответственно направлению вращения возникали импульсы по 15мс?
Т.е. вращаем влево- на одном пине появляются импульсы. Вращаем вправо- теперь импульсы появляются на втором, назначенном нами пине.
Ответить
0
Иван #
Никак. Сам энкодер работает так (подает импульсы). Чем тебе не нравится этот код? Можно пин A привязать к прерыванию.
Ответить
0
Иван #
Код:
byte pinB = 7; // Пин B - куда угодно
byte pinLed = 9; // Светодиод
byte brightness = 0; // Яркость

void setup() {
attachInterrupt(0, encoder, FALLING); // Пин А на пин 2 ардуино (можно на 3). Это 0-е прерывание (3 - это первое прерывание, меняем 0 на 1). FALLING - когда значение переходит с HIGH на LOW.
}

void loop() {
// Какой-то код...
}

void encoder() { // Функция обработки прерывания
if(digitalRead(pinB)) {
if(brightness + fadeAmount = 0) brightness -= fadeAmount;
}
analogWrite(pinLed, brightness); // устанавливаем яркость на 9 ножку
}
Ответить
0
Димон #
Иван, код не совсем точный
...
void encoder() { // Функция обработки прерывания
if (digitalRead(pinB)) {
if (brightness + fadeAmount < 255) {brightness += fadeAmount;}
} else {
if (brightness - fadeAmount > 0) {brightness -= fadeAmount;}
}
analogWrite(pinLed, brightness); // устанавливаем яркость на пин 9
}
Ответить
0
Джо Индеец #
А почему вы не использовали встроенные подтягивающие резисторы?
Ответить
+1
Denis #
Не противоположны по фазе, а фазы сдвинуты на Pi/2
Ответить
0
Ivan #
Спасибо за статью, сборку адаптировал под свой энкодер, все работает.
Ответить
0
Александр #
Если я не ошибаюсь то ардуина способна выдать 256 градаций , из этого следует что int brightness = 120; // яркость LED, начинаем с половины
int fadeAmount = 10; // шаг изменения яркости LED если взять простой энкодер на 24 такта , то каждый так увеличивает яркость на 10 , и того на полный круг 24 градации , что в свою очередь говорит о том что 10 множим на 24 получаем 240 , из этого смотрим дальше начинаем со 120 , и в итоге на пол оборота энкодера получим полное значение , и это обрабатывать с частотой 5 милисикунд , это 200 герц , где то около этого , сюда забыли преплюсовать работу бутлодера , и 200 герц частота счета , если перевести в обороты то это не так много , это 200 оборотов в секунду , помножим на минуту и это около 12 000 или близко к этому , из этого вывод что даже простой шаговик мы не сможем контролировать по шагам , не говоря про что то существенное , а если туда повесить производственный энкодер на 200 импульсов , то ардуино просто захлебнеться со счетом , ну как то так , могу и ошибаться , поправляйте если что
Ответить
0
Алекс-FS #
Да что тут поправлять, когда твой комментарий - это сплошной бред. Если у тебя "простые шаговики дают больше 12 тыс об/мин", то это клиника. Выздоравливай!
Ответить
0
Евгений Егоров #
Возможно ли с помощью 2х энкодоров снимать данные (угол поворота) с 2х осей с точностью до 0.1град и выгружать скажем в таблице экселя данные? Я новичек с этой системой, стою перед выбором исполнения для реализации тестера проверки готовой продукции.
Ответить
+2
ashelehov #
Один выход энкодера вешается на пин с прерываниями, по спаду, второй выход на обычный цифровой пин. Всё. Работает без глюков и на любой скорости вращения.
Ответить
0
q #
Не стоит так делать таймеры для чего-то важного. За примерно 50 дней значение millis() зациклится.
Если программа не успела до этого момента переполнить loopTime+5 (из-за долгого кода в таймере или прерывания, например), то таймер встанет на 50 дней. А если успела, то несколько миллисекунд код крутился без задержки.
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется сила тока?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Raspberry Pi 2
Raspberry Pi 2
DC-DC регулируемый преобразователь 1.5-37В 2А с индикатором Набор начинающего радиолюбителя
вверх