前回に続き、今回はロータリーエンコーダーを2個にしてみました。
複数のロータリーエンコーダーの同時読み取りは、switch-case分で対応出来ました。
その対応と言っても、人の指で2個のロータリーエンコーダーを普通にクルクル回す速さでの事です。モーターなどで機械的に高速で回した場合には対応出来ないかも。
「尚、私はロータリーエンコーダーを読み取るソースコードを書くのは始めたばかりだし、C言語も素人で、しかも初心者なので凄いソースコードは書けません。悪しからず」
この記事のソースコードや考えに誤り、非効率、プロならこんなソースコードは書かないとか、あるでしょうから先に言って置きます。
↓ 白色(PETG)の造形物は、私がOnshapeで設計、Ender-3 V3 SEで造形しました。
今は電子工作に3Dプリンターは、半田ごてくらいに必需品だと思う。無いなら自分で作ればいい。電子工作もその考えだし。3DCAD設計も楽しいしね。PC画面の3Dが現物になるんだから凄い。

3D model-viewer

↑↓ central_line の上下は0、x_speed(グラフ描画間隔)は1のロータリーエンコーダーで変化させる。
x_speedの値は待機時間。つまり、グラフ描画(左端から右端までの描画)後に、待機時間を設けて次のグラフ描画となる。オシロスコープで言う時間軸の変化みたいなもの。


↓ この関数で複数(2個)のロータリーエンコーダーの読み取りを行います。
void lxs_gpio_callback(uint gpio, uint32_t events)
↓ 次のソースコードは一部分ですが、core1で行うロータリーエンコーダーの読み取りに関係します。
void lxs_gpio_callback(uint gpio, uint32_t events) {
int lxs_clk;
gpio_put(5, 1);
gpio_set_irq_enabled(gpio, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, false);
sleep_ms(3);
switch (gpio) {
case PIN_DT0:
lxs_clk = gpio_get(PIN_CLK0);
switch (events) {
case GPIO_IRQ_EDGE_RISE:
if (lxs_clk == 1) {
central_line--;
} else if (lxs_clk == 0) {
central_line++;
}
break;
case GPIO_IRQ_EDGE_FALL:
if (lxs_clk == 0) {
central_line--;
} else if (lxs_clk == 1) {
central_line++;
}
break;
default:
central_line = central_line;
break;
}
break;
case PIN_DT1:
lxs_clk = gpio_get(PIN_CLK1);
switch (events) {
case GPIO_IRQ_EDGE_RISE:
if (lxs_clk == 1) {
x_speed = x_speed + 10;
} else if (lxs_clk == 0) {
x_speed = x_speed - 10;
}
break;
case GPIO_IRQ_EDGE_FALL:
if (lxs_clk == 0) {
x_speed = x_speed + 10;
} else if (lxs_clk == 1) {
x_speed = x_speed - 10;
}
break;
default:
x_speed = x_speed;
break;
}
break;
default:
central_line = 45;
x_speed = 920;
break;
}
gpio_set_irq_enabled(gpio, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true);
gpio_put(5, 0);
}
void core1_entry() {
const uint LED_PIN = 25;
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
gpio_init(PIN_CLK0);
gpio_init(PIN_DT0);
gpio_init(PIN_SW0);
gpio_init(PIN_CLK1);
gpio_init(PIN_DT1);
gpio_init(PIN_SW1);
gpio_init(5);
gpio_set_dir(PIN_CLK0, GPIO_IN);
gpio_set_dir(PIN_DT0, GPIO_IN);
gpio_set_dir(PIN_SW0, GPIO_IN);
gpio_set_dir(PIN_CLK1, GPIO_IN);
gpio_set_dir(PIN_DT1, GPIO_IN);
gpio_set_dir(PIN_SW1, GPIO_IN);
gpio_set_dir(5, GPIO_OUT);
gpio_pull_down(PIN_CLK0);
gpio_pull_down(PIN_DT0);
gpio_pull_down(PIN_SW0);
gpio_pull_down(PIN_CLK1);
gpio_pull_down(PIN_DT1);
gpio_pull_down(PIN_SW1);
gpio_set_input_hysteresis_enabled(PIN_CLK0, true);
gpio_set_input_hysteresis_enabled(PIN_DT0, true);
gpio_set_input_hysteresis_enabled(PIN_SW0, true);
gpio_set_input_hysteresis_enabled(PIN_CLK1, true);
gpio_set_input_hysteresis_enabled(PIN_DT1, true);
gpio_set_input_hysteresis_enabled(PIN_SW1, true);
gpio_set_irq_enabled_with_callback(PIN_DT0, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true, &lxs_gpio_callback);
gpio_set_irq_enabled_with_callback(PIN_DT1, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true, &lxs_gpio_callback);
gpio_set_irq_enabled(PIN_DT0, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true);
gpio_set_irq_enabled(PIN_DT1, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true);
while (true) {
if (gpio_get(PIN_CLK0) == 1) {
gpio_put(LED_PIN, 1);
} else {
gpio_put(LED_PIN, 0);
}
}
}
まぁ〜、このソースコード、C言語初心者の私にとっては趣味に使える。
でも、以下の事が、今後解決したらいいと思う。
【理解不能】
↓ 上記ソースコードの一部で、自分で書いて置きながら、私には理解出来ない事がある。割り込み用コールバック関数の登録で、ロータリーエンコーダーが2個だから2つ書いているけど、1つだけでも同様に動作する。なんで?
gpio_set_irq_enabled_with_callback(PIN_DT0, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true, &lxs_gpio_callback);
gpio_set_irq_enabled_with_callback(PIN_DT1, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true, &lxs_gpio_callback);
【意味不明】
上記の理解不能な件に加えて、コールバック関数内で使用するeventsの値が意味不明なのがある。
それは、ロータリーエンコーダーを回している時(1クリックごとに)、私が想定するeventsの値は0x4uと0x8uなんだけど、12(多分0x0Cuかな)が頻繁に発生する。
この12とは? なに? エラーとかファールのコード?
ググり方が不味いのか、ググっても解決していない。
これは仕方ないので、その部分のソースコードで想定外の値の時は、ロータリーエンコーダーを回しても(1クリック分だけ)変化しない事にした。↓
default:
central_line = central_line;
break;
default:
x_speed = x_speed;
break;