AmazonでポチったロータリーエンコーダーHW-040を、Raspberry Pi Picoの割り込みとC言語で読み取る記事。ただ私は素人なので誤りが有るかも知れません。
開発環境
VSCode C/C++ | Windows 11 |
RP2040 | Raspberry Pi Pico |
↓ 目標はロータリーエンコーダーでcentral_lineを上下に動かす事。
↓ DTの立ち上がり割り込み、又は立ち下がり割り込みの時、CLKの値を読み取り右回り、又は左回りを判断する。尚、画像中の#A、#B、#C、#Dは、ソースコードにあるそれと一致します。
↓ ロータリーエンコーダーの読み取りはcore1で行い、ADCとOLEDの表示はcore0で行う。次のコードはcore1で処理する部分で、ロータリーエンコーダーの読み取りをGPIOの割り込みで処理します。尚、ソースコード中の#A、#B、#C、#Dは上記画像のそれと一致します。
// コールバック関数
// ロータリーエンコーダーを回した時(割り込み発生時)に呼ばれる関数
void lxs_gpio_callback(uint gpio, uint32_t events) {
int lxs_clk;
// この関数実行中のみ点灯させて
// ロータリーエンコーダーの
// 立ち上がり
// 立ち下がり を確認する為のLED
gpio_put(5, 1); // GP5のLED点灯
// 割り込みの禁止
gpio_set_irq_enabled(gpio, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, false);
sleep_ms(3); // 0.003秒 念の為のチャタリング対策
// CLKの状態を取得
lxs_clk = gpio_get(PIN_CLK);
// DTの立ち上がり割り込み
if (gpio == PIN_DT && events == GPIO_IRQ_EDGE_RISE) {
if (lxs_clk == 1) { // #A
central_line--;
} else if (lxs_clk == 0) { // #C
central_line++;
}
// DTの立ち下がり割り込み
} else if (gpio == PIN_DT && events == GPIO_IRQ_EDGE_FALL) {
if (lxs_clk == 0) { // #B
central_line--;
} else if (lxs_clk == 1) { // #D
central_line++;
}
}
// 割り込み禁止の解除
gpio_set_irq_enabled(gpio, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true);
gpio_put(5, 0); // GP5のLED消灯
}
void core1_entry() {
const uint LED_PIN = 25;
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
// GPIOの初期化(ロータリーエンコーダー用)
gpio_init(PIN_CLK); // GP4
gpio_init(PIN_DT); // GP3
gpio_init(PIN_SW); // GP2
// 立ち上がり、立ち下がりの割り込み確認用LED
gpio_init(5); // GP5
// 入出力設定
gpio_set_dir(PIN_CLK, GPIO_IN);
gpio_set_dir(PIN_DT, GPIO_IN);
gpio_set_dir(PIN_SW, GPIO_IN);
gpio_set_dir(5, GPIO_OUT);
// 内部プルダウン設定
gpio_pull_down(PIN_CLK);
gpio_pull_down(PIN_DT);
gpio_pull_down(PIN_SW);
// ヒステレリス設定(シュミットトリガ利用)念の為のチャタリング対策
gpio_set_input_hysteresis_enabled(PIN_CLK, true);
gpio_set_input_hysteresis_enabled(PIN_DT, true);
gpio_set_input_hysteresis_enabled(PIN_SW, true);
// 割り込み用コールバック関数の登録
gpio_set_irq_enabled_with_callback(PIN_DT, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true, &lxs_gpio_callback);
// 割り込み禁止の解除
gpio_set_irq_enabled(PIN_DT, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true);
// 基板実装LED(GP25)の点灯用ループ
while (true) {
if (gpio_get(PIN_CLK) == 1) {
gpio_put(LED_PIN, 1);
} else {
gpio_put(LED_PIN, 0);
}
}
}
↓ GP5に繋げた緑色のLEDは、ロータリーエンコーダーを回した時に呼ばれる関数 lxs_gpio_callback() の実行中だけ点灯。立ち上がり、立ち下がりの割り込みをLEDの点灯で分かる仕組み。