CircuitPython

Для работы с модулем джойстика используем библиотеку robotclass_ledgauge, которую можно скачать по ссылке в конце урока. Всё, что нам нужно сделать для её установки — это скопировать файл robotclass_ledgauge.mpy в папку lib на накопителе CIRCUITPY.

Более подробно о работе с библиотеками CircuitPython мы писали в одном из ранних наших уроков: Библиотеки для CircuitPython

УСТАНОВКА ЗАВИСИМОСТЕЙ

Чтобы библиотека robotclass_ledgauge заработала, необходимо будет добавить еще две «зависимости»:

  • adafruit_bus_device
  • adafruit_register

Все эти библиотеки есть в сборнике от Adafruit. Точно также, копируем их на накопитель CIRCUITPY.

Программа

Пусть самая первая программа сначала проверит работу всех светодиодов, а затем в бесконечном цикле выводит в консоль текущее положение ручки энкодера/потенциометра.

Для составления программы используем среду разработки Mu. Начнём с подключения всех необходимых библиотек. Помним, что в python это делается с помощью команды import.

Кроме robotclass_ledgauge нам будут нужны еще три библиотеки:

  • time — предоставляет функцию sleep для организации паузы;
  • busio — предоставляет интерфейс для работы с шиной I2C.
import time

import busio
from robotclass_ledgauge import *

Затем создаём объект I2C, который организует работу с шиной. Следом — объект класса RobotClass_LedGauge, в котором описаны нужные для работы с индикатором функции.

i2c = busio.I2C()

gauge = RobotClass_LedGauge(i2c)

Функция test включает процедуру тестирования светодиодов, последовательное зажигая их всеми тремя цветами. Используем её, чтобы проверить работоспособность модуля.

Сброс текущего положения энкодера осуществляется функцией reset без аргументов.

Для получения текущего положения ручки энкодера/потенциометра используем функцию getState без аргументов, которая возвращает словарь вида:

{'position': текущая_позиция, 'button': состояние_кнопки}

Поле position — это число в некотором диапазоне, который можно менять (об этом далее). По умолчанию для инкрементального энкодера диапазон изменения позиции: от 0 до 15, а для потенциометра: от 0 до 4095.

Поле button может принимать всего два значения: 1 и 0 — нажата кнопка или нет. После нажатия кнопки, контроллер индикатора фиксирует это состояние на 200 мс, так что за это время нам надо успеть опросить датчик, иначе мы пропустим это событие.

Напишем пример для индикатора с энкодером. Программа будет отправлять его состояние в последовательный порт каждые 100 мс.

import time

import board
from robotclass_ledgauge import *

i2c = board.I2C()
gauge = RobotClass_LedGauge(i2c)

gauge.test()
time.sleep(3)

while True:
state = gauge.getState()
print("pos = %d, btn = %d" % (state['position'], state['button']))
time.sleep(0.1)

Сохраняем программу, открываем монитор последовательного порта (кнопка «Последовательный»), крутим ручку прибора и смотрим на результат.

pos = 5, btn = 0
pos = 5, btn = 0
pos = 5, btn = 0
pos = 6, btn = 1
pos = 7, btn = 0
pos = 8, btn = 0

При использовании инкрементального энкодера с кнопкой, значение btn будет меняться на 1 при нажатии на кнопку. В примере вывода как раз такой случай.

Настройка индикации

Для установки режима отображения используется функция setMode. Единственный аргумент этой функции — код режима: MODE_POINT, MODE_LEVEL, MODE_FLOOD. По умолчанию, в прошивке индикатора установлен режим MODE_LEVEL, но мы попробуем установить другой.

Функция setBrightness устанавливает яркость светодиодов. Единственный аргумент — число от 0 до 31, где 0 — полное выключение светодиодов. По умолчанию яркость равна 5, а мы сделаем в три раза ярче.

Изменение основного цвета индикатора осуществляется вызовом функции setColor с тремя аргументами, которые отвечают за RGB компоненты цвета. Каждая компонента может принимать значение от 0 до 255. Сделаем фиолетовый цвет.

import time

import board
from robotclass_ledgauge import *

i2c = board.I2C()
gauge = RobotClass_LedGauge(i2c)

gauge.setMode(MODE_POINT)
gauge.setBrightness(15)
gauge.setColor(128, 0, 255)


while True:
state = gauge.getState()
print("pos = %d, btn = %d" % (state['position'], state['button']))
time.sleep(0.1)

Проверяем работу программы. При вращении ручки текущая позиция будет отображаться фиолетовой точкой.

Фильтр нижних частот для потенциометра

Если мы повернем ручку потенциометра до некоторого положения и оставим её в покое, то увидим, что значение, которое мы получаем от АЦП ведет себя нестабильно. Чтобы значение не «прыгало» можно применить программный сглаживающий фильтр (он же ФНЧ или альфа-бета фильтр).

Настроить фильтр можно с помощью функции setPotLPF. Аргумент функции — число от 1 до 15, которое отражает силу фильтра. Чем больше число, тем стабильнее сигнал, но медленнее реакция индикатора на поворот ручки.

Пределы энкодера

С помощью функции setEncMax можно указать сколько щелчков энкодера необходимо сделать, чтобы позиция индикатора сдвинулась на единицу. У функции есть один аргумент — число, определяющее это отношение (от 0 до 6).

Для удобства определены константы ENC_LIMIT_1, ENC_LIMIT_2 , ENC_LIMIT_4 и т.д. При ENC_LIMIT_1 место соотношение 1:1, то есть, каждый щелчок энкодера смещает позицию индикатора на единицу. При ENC_LIMIT_2 будет отношение 2:1. А при ENC_LIMIT_6 получим 64:1.

Вторая полезная функция setEncLimit включает и выключает режим ограничения энкодера. Если в эту функцию передать True, то при достижении энкодером максимального значения он перестанет увеличивать свою позицию.

import time

import board
from robotclass_ledgauge import *

i2c = board.I2C()
gauge = RobotClass_LedGauge(i2c)

gauge.setEncMax(ENC_LIMIT_2)
gauge.setEncLimit(True)

while True:
state = gauge.getState()
print("pos = %d, btn = %d" % (state['position'], state['button']))
time.sleep(0.1)

Сохраняем программу. Если докрутить ручку энкодера до 15 светодиода, то индикатор не сбросится, а просто перестанет реагировать. То же самое произойдет, если попытаться вращать ручку против часовой стрелки из нулевой позиции.


Изменено: