Сдвоенный энкодер — различия между версиями
=DeaD= (обсуждение | вклад) |
(→Тонкости реализации алгоритмов для контроллеров AVR: Пример реализации четырёхкратной точности с использованием PCINTx для одного энкод) |
||
(не показано 20 промежуточных версий 2 участников) | |||
Строка 1: | Строка 1: | ||
− | ''Англ. - '''Quadrature encoder''' '' | + | ''Англ. - '''Quadrature encoder''' или '''Q-encoder''' '' |
+ | |||
+ | [[Изображение:Quadrature_encoder.gif|thumb|200px|Диск сдвоенного энкодера|right]] | ||
Разновидность инкрементального энкодера, которая состоит из двух датчиков срабатывающих со смещением в полшага, что позволяет практически полностью гарантировать отсутствие ложных срабатываний на границе одного из энкодеров. Кроме того, этот вариант позволяет контролировать не только длину, но и направление перемещения. | Разновидность инкрементального энкодера, которая состоит из двух датчиков срабатывающих со смещением в полшага, что позволяет практически полностью гарантировать отсутствие ложных срабатываний на границе одного из энкодеров. Кроме того, этот вариант позволяет контролировать не только длину, но и направление перемещения. | ||
+ | |||
+ | |||
+ | Т.е. если первый из энкодеров меняет своё состояние с A на B и при этом второй энкодер в состоянии C, тогда направление вычисляется функцией dir=A xor C или если короче dir=A^C. | ||
+ | |||
+ | |||
+ | Иногда в таком энкодере вводят дополнительный канал включающийся 1 раз за полный поворот, чтобы обеспечить еще большую защиту от ошибок подсчета даже при длительной эксплуатации и обеспечить определение точного положения вала при хотя-бы одном произведенном полном обороте. | ||
+ | |||
+ | |||
+ | '''Дополнение:''' | ||
+ | |||
+ | Сигнал с энкодера | ||
+ | Состояния выходов A и B: | ||
+ | {| style="white-space: nowrap;" cellspacing="20" | ||
+ | | | ||
+ | {| class="wikitable" width="180" | ||
+ | |+ Код Грея для<br/>вращения по часовой стрелке | ||
+ | !Фаза !!A !!B | ||
+ | |- | ||
+ | |1||0||0 | ||
+ | |- | ||
+ | |2||0||1 | ||
+ | |- | ||
+ | |3||1||1 | ||
+ | |- | ||
+ | |4||1||0 | ||
+ | |} | ||
+ | | | ||
+ | {| class="wikitable" width="180" | ||
+ | |+ Код Грея для<br/>вращения против часовой стрелки | ||
+ | !Фаза !!A !!B | ||
+ | |- | ||
+ | |1||1||0 | ||
+ | |- | ||
+ | |2||1||1 | ||
+ | |- | ||
+ | |3||0||1 | ||
+ | |- | ||
+ | |4||0||0 | ||
+ | |} | ||
+ | |} | ||
+ | [[Image:Quadrature Diagram.svg|thumb|300px|right|Сигнал с квадратурного энкодера (вращение по часовой стрелке).]] | ||
+ | |||
+ | == Измерение сигнала с энкодера == | ||
+ | Первым делом нужно подключить энкодер к контроллеру. | ||
+ | |||
+ | [[Image:Encoder_connector.jpg|Выходы энкодера]] | ||
+ | |||
+ | Обычно энкодер имеет выходы A,B, питание, земля, и (возможно) сигнал полного оборота. | ||
+ | |||
+ | Сигнал полного оборота появляется один раз за один оборот, и может использоваться для подсчёта количества оборотов, или расчёта точного положение относительно начала оборота. | ||
+ | |||
+ | |||
+ | Для определения положения вала энкодера, используют счётчики сигналов A,B. | ||
+ | |||
+ | Как правило счётчик увеличивается если направление по часовой стрелке и уменьшается если направление против часовой стрелки. | ||
+ | |||
+ | |||
+ | Существует три способа измерения данных с выхода энкодера. | ||
+ | |||
+ | Они отличаются точностью измерения и нагрузкой на контроллер. | ||
+ | |||
+ | = Однократная точность = | ||
+ | Один из каналов энкодера (пусть будет A) подключается к внешнему прерыванию контроллера, второй канал (B) подключается на обычный цифровой вход. | ||
+ | |||
+ | Настаивается прерывание по фронту канала А. | ||
+ | |||
+ | Измерение проводят только по фронту канала A, | ||
+ | |||
+ | при этом сравнивается состояние вывода B, если на канале B низкий уровень то вращение против часовой стрелки. | ||
+ | |||
+ | Если на канале B высокий уровень то вращение по часовой стрелки. | ||
+ | |||
+ | [[Image:Quadrature_encoding_x1.jpg|Однократная точность]] | ||
+ | |||
+ | Такой способ измерения использует только четверть данных с энкодера, зато минимизирует нагрузку на контроллер, достаточно проверить состояние канала B. | ||
+ | |||
+ | Этот способ будет показывать одно и тоже направление, даже если будут пропуски импульсов от энкодера, например в случае если программа не будет успевать обрабатывать прерывания. | ||
+ | |||
+ | Естественно потерянные импульсы ничем не заменить. | ||
+ | |||
+ | Например если настроить прерывание по фронту для сигнала A то работать будет так: | ||
+ | |||
+ | {| style="white-space: nowrap;" cellspacing="20" | ||
+ | | | ||
+ | {| class="wikitable" width="180" | ||
+ | |+ Код Грея для<br/>вращения по часовой стрелке<br/> и алгоритм в действии | ||
+ | !Фаза !!A !!B !!операция сравнения B | ||
+ | |- | ||
+ | |1||0||0|| - | ||
+ | |- | ||
+ | |2||0||1|| - | ||
+ | |- | ||
+ | |3||1||1|| B равно 1 | ||
+ | |- | ||
+ | |4||1||0|| - | ||
+ | |} | ||
+ | | | ||
+ | {| class="wikitable" width="180" | ||
+ | |+ Код Грея для<br/>вращения против часовой стрелки<br/> и алгоритм в действии | ||
+ | !Фаза !!A !!B !!операция сравнения B | ||
+ | |- | ||
+ | |1||1||0 || B равно 0 | ||
+ | |- | ||
+ | |2||1||1 || - | ||
+ | |- | ||
+ | |3||0||1 || - | ||
+ | |- | ||
+ | |4||0||0 || - | ||
+ | |} | ||
+ | |} | ||
+ | |||
+ | Но так же, для проверки направления, можно выполнить операцию Xor для A и B, см пример для двукратной точности. | ||
+ | |||
+ | = Двукратная точность = | ||
+ | |||
+ | Один из каналов энкодера (пусть будет A) подключается к внешнему прерыванию контроллера, второй канал (B) подключается на обычный цифровой вход. | ||
+ | |||
+ | Настаивается прерывание по фронту и спаду канала А. | ||
+ | |||
+ | Измерение проводят только по фронту и спаду канала A, | ||
+ | |||
+ | при этом сравнивается состояние вывода B и учитывается какое именно прерывание произошло по фронту или по спаду, | ||
+ | |||
+ | Если на канале B низкий уровень и прерывание на А по фронту, или если на канале B высокий уровень и прерывание на А по спаду, то вращение против часовой стрелке. | ||
+ | |||
+ | Если на канале B высокий уровень и прерывание на А по фронту, или если на канале B низкий уровень и прерывание на А по спаду, то вращение по часовой стрелке. | ||
+ | |||
+ | [[Image:Quadrature_encoding_x2.jpg|Двукратная точность]] | ||
+ | |||
+ | Такой способ измерения использует половину данных с энкодера. | ||
+ | |||
+ | Для проверки направления достаточно выполнить операцию Xor для A и B. | ||
+ | |||
+ | Например если настроить прерывание по фронту и спаду для сигнала A то работать будет так: | ||
+ | |||
+ | {| style="white-space: nowrap;" cellspacing="20" | ||
+ | | | ||
+ | {| class="wikitable" width="180" | ||
+ | |+ Код Грея для<br/>вращения по часовой стрелке<br/> и алгоритм в действии | ||
+ | !Фаза !!A !!B !!операция xor | ||
+ | |- | ||
+ | |1||0||0|| 0 ^ 0 = 0 | ||
+ | |- | ||
+ | |2||0||1|| состояние A не изменилось | ||
+ | |- | ||
+ | |3||1||1|| 1 ^ 1 = 0 | ||
+ | |- | ||
+ | |4||1||0|| состояние A не изменилось | ||
+ | |} | ||
+ | | | ||
+ | {| class="wikitable" width="180" | ||
+ | |+ Код Грея для<br/>вращения против часовой стрелки<br/> и алгоритм в действии | ||
+ | !Фаза !!A !!B !!операция xor | ||
+ | |- | ||
+ | |1||1||0 || 1 ^ 0 = 1 | ||
+ | |- | ||
+ | |2||1||1 || состояние A не изменилось | ||
+ | |- | ||
+ | |3||0||1 || 0 ^ 1 = 1 | ||
+ | |- | ||
+ | |4||0||0 || состояние A не изменилось | ||
+ | |} | ||
+ | |} | ||
+ | |||
+ | = Четырёхкратная (максимальная) точность = | ||
+ | |||
+ | Оба канала подключаются к выводам для внешних прерываний контроллера и настраиваются прерывания по фронту и спаду на оба канала. | ||
+ | |||
+ | [[Image:Quadrature_encoding_x4.jpg|Максимальная точность]] | ||
+ | |||
+ | Такой способ измерения использует все данные с энкодера, и требует чтобы контроллер помнил состояние А и B с момента предыдущего прерывания. | ||
+ | |||
+ | '''Так же стоит отметить, что в отличие от двух предыдущих методов, в случае пропуска импульсов от энкодера, возможны ошибки направления!''' | ||
+ | |||
+ | В качестве частичной защиты, можно делать проверку на количество изменённых битов между двумя состояниями, если изменилось два бита, то был один или несколько пропусков. | ||
+ | |||
+ | Между соседними состояниями всегда изменяется только один бит. | ||
+ | |||
+ | Хороший и простой алгоритм предложил Scott Edwards, in Nuts&Volts Vol 1 Oct. 1995 [[http://www.parallax.com/dl/docs/cols/nv/vol1/col/nv8.pdf]] | ||
+ | |||
+ | Если применить операцию "исключающее или" для двух любых последовательностей, то | ||
+ | сравнивая правый бит предыдущего состояния с левым битом нового состояния всегда даст 1 в случае если последовательность от вращения по часовой стрелки | ||
+ | и 0 в случае вращения против часовой стрелки. | ||
+ | |||
+ | Например: | ||
+ | |||
+ | {| style="white-space: nowrap;" cellspacing="20" | ||
+ | | | ||
+ | {| class="wikitable" width="180" | ||
+ | |+ Код Грея для<br/>вращения по часовой стрелке<br/> и алгоритм в действии | ||
+ | !Фаза !!A !!B !!операция xor | ||
+ | |- | ||
+ | |1||0||0||1(0) ^ (0)0 =0 | ||
+ | |- | ||
+ | |2||0||1||0(0) ^ (0)1 =0 | ||
+ | |- | ||
+ | |3||1||1||0(1) ^ (1)1 =0 | ||
+ | |- | ||
+ | |4||1||0||1(1) ^ (1)0 =0 | ||
+ | |} | ||
+ | | | ||
+ | {| class="wikitable" width="180" | ||
+ | |+ Код Грея для<br/>вращения против часовой стрелки<br/> и алгоритм в действии | ||
+ | !Фаза !!A !!B !!операция xor | ||
+ | |- | ||
+ | |1||1||0 ||0(0) ^ (1)0 = 1 | ||
+ | |- | ||
+ | |2||1||1 ||1(0) ^ (1)1 = 1 | ||
+ | |- | ||
+ | |3||0||1 ||1(1) ^ (0)1 = 1 | ||
+ | |- | ||
+ | |4||0||0 ||0(1) ^ (0)0 = 1 | ||
+ | |} | ||
+ | |} | ||
+ | |||
+ | В скобках биты над которыми производится операция xor для вычисления направления. | ||
+ | |||
+ | = Тонкости реализации алгоритмов для контроллеров AVR = | ||
+ | |||
+ | Предполагается, что читатель понимает, что такое прерывания и как они настраиваются в AVR. | ||
+ | |||
+ | Хочу отметить, хотя контроллер avr и имеет возможность включения прерывания практически на любой ноге, но есть большая разница между PCINTx и INTx. | ||
+ | |||
+ | Прерывания PCINTx ''' всегда происходят по любому изменению''' на любой из ног, где разрешены прерывания, тогда как для INTx можно чётко задать срабатывание по фронту/спаду/изменению/низкому уровню. | ||
+ | |||
+ | Другими словами, невозможно использовать алгоритм одинарной точности, в случае если энкодер подключен к выводам PCINTx., т.к. '''Прерывание всегда будет происходить по фронту и спаду'''. | ||
+ | |||
+ | За то, на выводах PCINTx можно использовать двукратную и четырёхкратную точность. | ||
+ | |||
+ | Как я уже отметил, прерывания PCINTx происходят '''по любому изменению''' на любой из ног, т.е. если мы подключим к PCIE1 выводы A и B c двух энкодеров, то это прерывание будет происходить при изменении состояния на | ||
+ | любой из ног любого энкодера, т.е. для того чтобы определить от какой ноги, и какого энкодера произошло прерывание необходимо хранить состояния этих выводов на момент предыдущего прерывания, чтобы можно было | ||
+ | сравнить какая нога от какого энкодера вызвала прерывание. | ||
+ | |||
+ | Так же стоит отметить особенность поведения контроллера в случае если возникло несколько одинаковых прерываний. | ||
+ | |||
+ | В этом случае в очереди прерываний будет только одно прерывание. | ||
+ | |||
+ | Поэтому, если два или более энкодеров находятся на одном прерывании, если они будут одновременно вращаться , то возможны пропуски прерываний. | ||
+ | |||
+ | Поэтому такие энкодеры лучше раскидывать по разным прерываниям PCIE0, PCIE1 , PCIE2 и т.д. | ||
+ | |||
+ | Пример реализации четырёхкратной точности с использованием PCINTx для одного энкодера http://forum.pololu.com/viewtopic.php?t=484 | ||
+ | |||
+ | = Ссылки = | ||
+ | http://en.wikipedia.org/wiki/Rotary_encoder | ||
+ | |||
+ | http://forum.pololu.com/viewtopic.php?t=484 | ||
+ | |||
+ | http://zone.ni.com/devzone/cda/tut/p/id/7109 |
Текущая версия на 08:18, 5 июля 2011
Англ. - Quadrature encoder или Q-encoder
Разновидность инкрементального энкодера, которая состоит из двух датчиков срабатывающих со смещением в полшага, что позволяет практически полностью гарантировать отсутствие ложных срабатываний на границе одного из энкодеров. Кроме того, этот вариант позволяет контролировать не только длину, но и направление перемещения.
Т.е. если первый из энкодеров меняет своё состояние с A на B и при этом второй энкодер в состоянии C, тогда направление вычисляется функцией dir=A xor C или если короче dir=A^C.
Иногда в таком энкодере вводят дополнительный канал включающийся 1 раз за полный поворот, чтобы обеспечить еще большую защиту от ошибок подсчета даже при длительной эксплуатации и обеспечить определение точного положения вала при хотя-бы одном произведенном полном обороте.
Дополнение:
Сигнал с энкодера Состояния выходов A и B:
|
|
Содержание
Измерение сигнала с энкодера
Первым делом нужно подключить энкодер к контроллеру.
Обычно энкодер имеет выходы A,B, питание, земля, и (возможно) сигнал полного оборота.
Сигнал полного оборота появляется один раз за один оборот, и может использоваться для подсчёта количества оборотов, или расчёта точного положение относительно начала оборота.
Для определения положения вала энкодера, используют счётчики сигналов A,B.
Как правило счётчик увеличивается если направление по часовой стрелке и уменьшается если направление против часовой стрелки.
Существует три способа измерения данных с выхода энкодера.
Они отличаются точностью измерения и нагрузкой на контроллер.
Однократная точность
Один из каналов энкодера (пусть будет A) подключается к внешнему прерыванию контроллера, второй канал (B) подключается на обычный цифровой вход.
Настаивается прерывание по фронту канала А.
Измерение проводят только по фронту канала A,
при этом сравнивается состояние вывода B, если на канале B низкий уровень то вращение против часовой стрелки.
Если на канале B высокий уровень то вращение по часовой стрелки.
Такой способ измерения использует только четверть данных с энкодера, зато минимизирует нагрузку на контроллер, достаточно проверить состояние канала B.
Этот способ будет показывать одно и тоже направление, даже если будут пропуски импульсов от энкодера, например в случае если программа не будет успевать обрабатывать прерывания.
Естественно потерянные импульсы ничем не заменить.
Например если настроить прерывание по фронту для сигнала A то работать будет так:
|
|
Но так же, для проверки направления, можно выполнить операцию Xor для A и B, см пример для двукратной точности.
Двукратная точность
Один из каналов энкодера (пусть будет A) подключается к внешнему прерыванию контроллера, второй канал (B) подключается на обычный цифровой вход.
Настаивается прерывание по фронту и спаду канала А.
Измерение проводят только по фронту и спаду канала A,
при этом сравнивается состояние вывода B и учитывается какое именно прерывание произошло по фронту или по спаду,
Если на канале B низкий уровень и прерывание на А по фронту, или если на канале B высокий уровень и прерывание на А по спаду, то вращение против часовой стрелке.
Если на канале B высокий уровень и прерывание на А по фронту, или если на канале B низкий уровень и прерывание на А по спаду, то вращение по часовой стрелке.
Такой способ измерения использует половину данных с энкодера.
Для проверки направления достаточно выполнить операцию Xor для A и B.
Например если настроить прерывание по фронту и спаду для сигнала A то работать будет так:
|
|
Четырёхкратная (максимальная) точность
Оба канала подключаются к выводам для внешних прерываний контроллера и настраиваются прерывания по фронту и спаду на оба канала.
Такой способ измерения использует все данные с энкодера, и требует чтобы контроллер помнил состояние А и B с момента предыдущего прерывания.
Так же стоит отметить, что в отличие от двух предыдущих методов, в случае пропуска импульсов от энкодера, возможны ошибки направления!
В качестве частичной защиты, можно делать проверку на количество изменённых битов между двумя состояниями, если изменилось два бита, то был один или несколько пропусков.
Между соседними состояниями всегда изменяется только один бит.
Хороший и простой алгоритм предложил Scott Edwards, in Nuts&Volts Vol 1 Oct. 1995 [[1]]
Если применить операцию "исключающее или" для двух любых последовательностей, то сравнивая правый бит предыдущего состояния с левым битом нового состояния всегда даст 1 в случае если последовательность от вращения по часовой стрелки и 0 в случае вращения против часовой стрелки.
Например:
|
|
В скобках биты над которыми производится операция xor для вычисления направления.
Тонкости реализации алгоритмов для контроллеров AVR
Предполагается, что читатель понимает, что такое прерывания и как они настраиваются в AVR.
Хочу отметить, хотя контроллер avr и имеет возможность включения прерывания практически на любой ноге, но есть большая разница между PCINTx и INTx.
Прерывания PCINTx всегда происходят по любому изменению на любой из ног, где разрешены прерывания, тогда как для INTx можно чётко задать срабатывание по фронту/спаду/изменению/низкому уровню.
Другими словами, невозможно использовать алгоритм одинарной точности, в случае если энкодер подключен к выводам PCINTx., т.к. Прерывание всегда будет происходить по фронту и спаду.
За то, на выводах PCINTx можно использовать двукратную и четырёхкратную точность.
Как я уже отметил, прерывания PCINTx происходят по любому изменению на любой из ног, т.е. если мы подключим к PCIE1 выводы A и B c двух энкодеров, то это прерывание будет происходить при изменении состояния на любой из ног любого энкодера, т.е. для того чтобы определить от какой ноги, и какого энкодера произошло прерывание необходимо хранить состояния этих выводов на момент предыдущего прерывания, чтобы можно было сравнить какая нога от какого энкодера вызвала прерывание.
Так же стоит отметить особенность поведения контроллера в случае если возникло несколько одинаковых прерываний.
В этом случае в очереди прерываний будет только одно прерывание.
Поэтому, если два или более энкодеров находятся на одном прерывании, если они будут одновременно вращаться , то возможны пропуски прерываний.
Поэтому такие энкодеры лучше раскидывать по разным прерываниям PCIE0, PCIE1 , PCIE2 и т.д.
Пример реализации четырёхкратной точности с использованием PCINTx для одного энкодера http://forum.pololu.com/viewtopic.php?t=484
Ссылки
http://en.wikipedia.org/wiki/Rotary_encoder