ESP32のMicroPythonでロータリーエンコーダの読み取り
2020/07/12 categories:ESP32| tags:ESP32|MicroPython|
MicroPythonのファームウェアを入れたESP32でロータリーエンコーダを読み取るプログラムを作成してみました。使用した機能はGPIOの入力と外部割込みです。
Encorderクラス
エンコーダの処理のためにクラスを作成しました。コンストラクタでは入力ピンの設定やテーブル、変数の初期化をしています。check関数は外部割込みで実行する関数で、前回のエンコーダの値と現在のエンコーダの値、テーブルから回転方向と位置を計算する関数です。計算内容はネットにいろいろ書いているのでそれらを参考にしました。
外部割込みの処理内容が増えるとESP32が割り込み処理ばかりしてしまうので気を付けないといけません。この辺りはコンパイルしてマイコンに書き込む場合はわかりやすいかもしれませんが、MicroPythonの場合は実際に動作させてみないとわからなそうです。
class Encorder():
def __init__(self, pin_a, pin_b):
self.pin_a, self.pin_b = pin_a, pin_b
self.position, self.value, self.direction = 0, 0, 0
self.table = [
0, 1,-1, 0,
-1, 0, 0, 1,
1, 0, 0,-1,
0,-1, 1, 0
]
def check(self, pin):
self.value = (self.value << 2) + self.pin_a.value() + (self.pin_b.value() << 1)
self.value = self.value & 0x0F
self.direction = self.table[self.value]
self.position += self.direction
入力設定
エンコーダに接続するGPIOはPin.INで入力設定にしています。それらのピンをEncorderクラスに渡してEncorderクラスで処理すべきピンを指定しています。外部割込み時に実行するメソッドはPin.irq()で指定します。エンコーダのどちらかのピンの入力が変わった場合にEncorder.check()を実行するように記述しています。
## GPIO settings
pin32 = Pin(32, Pin.IN)
pin35 = Pin(35, Pin.IN)
## Encoorder settings
encorder = Encorder(pin32, pin35)
## Interrupt settings
pin32.irq( encorder.check )
pin35.irq( encorder.check )
PCにデータを送る処理
while True:で無限ループを作成してデータを送信しています。送信するタイミングは、前回と現在のencorder.positionと異なる場合としています。
tmp = 0
while True:
if tmp != encorder.position:
tmp = encorder.position
print(encorder.position, encorder.direction)
出力内容
エンコーダを回すとシリアル通信で現在位置と回転方向が送られてきます。
ソースコード
import time
from machine import Pin
class Encorder():
def __init__(self, pin_a, pin_b):
self.pin_a, self.pin_b = pin_a, pin_b
self.position, self.value, self.direction = 0, 0, 0
self.table = [
0, 1,-1, 0,
-1, 0, 0, 1,
1, 0, 0,-1,
0,-1, 1, 0
]
def check(self, pin):
self.value = (self.value << 2) + self.pin_a.value() + (self.pin_b.value() << 1)
self.value = self.value & 0x0F
self.direction = self.table[self.value]
self.position += self.direction
## GPIO settings
pin32 = Pin(32, Pin.IN)
pin35 = Pin(35, Pin.IN)
## Encoorder settings
encorder = Encorder(pin32, pin35)
## Interrupt settings
pin32.irq( encorder.check )
pin35.irq( encorder.check )
print('start')
tmp = 0
while True:
if tmp != encorder.position:
tmp = encorder.position
print(encorder.position, encorder.direction)