Skip to content
  • Категории
  • Главная
  • Документация
  • Последние
  • Пользователи
Collapse
  1. Главная
  2. Блоги сообщества Raspberry Pi
  3. Удаленное управление. События. Энкодер инкрементальный.

Удаленное управление. События. Энкодер инкрементальный.

Запланировано Прикреплена Закрыта Перенесена Блоги сообщества Raspberry Pi
1 Сообщения 1 Posters 64 Просмотры
  • Сначала старые
  • Сначала новые
  • По количеству голосов
Авторизуйтесь, чтобы ответить
Эта тема была удалена. Только пользователи с правом управления темами могут её видеть.
  • piP Не в сети
    piP Не в сети
    pi
    написал в отредактировано
    #1

    И снова здравствуйте!

    Отрыл сегодня инкрементальный енкодер на полке. Попытаюсь описать как с ним работать и как снимать направление вращения.

    Что такое этот энкодер, думаю, смысла говорить нет. Это легко гуглится. Выглядит эта штука вот так:

    7c20efe7-5a28-45df-8089-a32f5df60b01-image.png

    У него есть 3 пина и если посмотреть на железку сверху, то по часовой стрелке можно эти пины обозначить как A, O, B.

    Пин O - пин, работающий на выход, пины A и B работают на вход, то есть "читают" состояние пина O.

    Теперь ситуация:

    Поворачиваем енкодер по часовой стрелке и ...

    Сначала меняется состояние пина A

    потом B

    потом меняется состояние пина A обратно

    затем снова B возвращает свое первоначальное значение. Картина, в общем такая:

    36df1b86-31ef-4464-997e-5e9ff118371a-image.png

    (Картинка не моя; взял с интернета)

    Можно заметить, что в один момент времени пины принимают одинаковое значение, НО при этом имеют разный расклад на предыдущем шаге. Таким образом мы можем понять в какую сторону крутится ручка енкодера.

    Покажу на примере ferro-remote как можно это обработать и сделать простейший счетчик, который при повороте по часовой стрелке увеличивает значение, а против - уменьшает.

    Тут я описывал как можно ловить события (сигналы, прерывания ... называть можно как угодно) с пинов GPIO, работающих в режиме IN. Думаю повторить тоже самое для данного примера.

    Возьмем 3 пина на RPi: GPIO 2, 3, 4.

    2 будет A
    3 будет O
    4 будет B

    Для начала простой скрипт, который их откроет и расставит им верное направление

    -- gpio-encoder.lua
    gpio = fr.client.gpio -- алиас
    
    current = 0 -- сам счетчик. Просто глобальная переменная
    
    function main( argv ) 
         
        fr.run( ) -- нужно ждать события, скажем не завершать исполнение после  main
    
        -- откроем 3 пина 2, 4 - IN 3 - OUT
        local A = assert(gpio.export( 2, "in"  ))
        local O = assert(gpio.export( 3, "out" ))
        local B = assert(gpio.export( 4, "in"  ))
    
        -- для пинов A и B установим edge в значение both
        assert(A:set( "edge", "both" ))
        assert(B:set( "edge", "both" ))
    
    end
    

    Если такой скрипт исполднить lua_client'ом, то делать он не будет ничего, кроме того, что получит объекты для работы с пинами, а потом прибьет их сборщиком мусора.

    Добавлю-ка я ему обработку события. Тут сделаю так (я видел в интернетах, что у народа довольно большие проблемы с энкодерами и логикой работы с ними. Хотя ничего страшного и сложного нет):

    Оба события будет обрабатывать один и тот же обработчик. Можно сделать ДВА разных обработчика, но получится длинее и не уверен, что проще. В параметры обработчику будет передаваться признак того, какой именно пин сработал. false - сработал пин A, true - пин B. Мысль дальше: Чтобы понять как вращается ручка, в момент установки пина на 1, нужно уметь получить состояние другого пина, если оно установлено в 1, значит мы должны увеличить или уменьшить счетчик.

    Если мы в обработчике пина B и пин A изменен, то мы вращаем по часовой стрелке и нужно прибавить и наоборот. добавим это в код:

    • pin - false(А) или true(B)
    • states - таблица, которая изначально имеет такой вид: {[false] = 0, [true] = 0}
    • то есть оба состояние выставлены на 0
    function change_handler( data, pin, states )
    
        -- directions это просто вспомогательная таблица 
        --            суть ее в том, что в случае вращения по часовй стрелке
        --            к счетчику будет прибавляться 1, а против -- -1
        local directions  = { [false] = -1, [true] = 1 }
        states[pin] = data.value -- установит состояние текущего пина в текущее значение
    
        -- states[not pin] - состояние соседнего пина
        -- если текущий пин установлен и соседний тоже установлен
        if data.value == 1 and states[not pin] == 1 then
            current = current + directions[pin] -- прибавим или отнимем
            print( current ) 
        end
    end
    и того полный скрипт выглядит так:
    
    -- gpio-encoder.lua
    gpio = fr.client.gpio
    
    current = 0
    
    function change_handler( data, pin, states )
    
        local directions  = { [false] = -1, [true] = 1 }
        states[pin] = data.value
    
        if data.value == 1 and states[not pin] == 1 then
            current = current + directions[direct]
            print( current ) 
        end
    end
    
    function main( argv ) 
         
        fr.run( )
        
        local states = {[true] = 0, [false] = 0}
        local A = assert(gpio.export( 2, "in"  ))
        local O = assert(gpio.export( 3, "out" ))
        local B = assert(gpio.export( 4, "in"  ))
       
        assert(A:set( "edge", "both" ))
        assert(B:set( "edge", "both" ))
    
        -- подпишемся на события от GPIO
        assert(A:subscribe( "on_changed", change_handler, false, states, A )) -- пин А false
        assert(B:subscribe( "on_changed", change_handler, true, states, B ))  -- пин B true
    
    end
    

    Теперь код можно сохранить (например как gpio-encoder.lua) и выполнить lua_client'ом. 192.168.1.11:12345 - адрес и порт малины. Если при открытии не вылетело никаких ошибок, то можно покрутить ручку после запуска.

    $ lua_client -s 192.168.1.11:12345 -e gpio-encoder.lua
    1
    2
    3
    4
    5
    4
    3
    2
    1
    0
    -1
    -2
    -3
    -4
    -3
    -2
    -1
    0
    1
    2
    1
    0
    -1
    

    Работает! Можно использовать.

    PS: а нет никакого PS.

    1 ответ Последний ответ
    0

    • Войти

    • Нет учётной записи? Зарегистрироваться

    • Login or register to search.
    • Первое сообщение
      Последнее сообщение
    0
    • Категории
    • Главная
    • Документация
    • Последние
    • Пользователи