AmazonでポチったロータリーエンコーダーHW-040を、Raspberry Pi Picoの割り込みとC言語で読み取る記事。ただ私は素人なので誤りが有るかも知れません。

開発環境

VSCode C/C++ Windows 11
RP2040 Raspberry Pi Pico

 

 

↓ 目標はロータリーエンコーダーでcentral_lineを上下に動かす事。

 

↓ DTの立ち上がり割り込み、又は立ち下がり割り込みの時、CLKの値を読み取り右回り、又は左回りを判断して1クリック毎に central_line の値を変化させます。

尚、画像中の#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の点灯で分かる仕組み。

2021年2月15日投稿 Pi PicoのADCで電圧表示

↑ 以前作ったラズパイPicoのプログラムを、Windows11にインストールしたPico用VSCode C/C++開発環境にコピペする。

以前のCMakeLists.txtでは駄目で、エラーやファールばかりを繰り返して大変でした。そもそも私はズブの素人、CMakeLists.txtの役目を知らずにやっているのですから、本当に大変でした。
でも、最終的にエラーやファール、警告も無く正常にuf2ファイルが出来たので、忘れない内にその方法を残します。

どの様なプログラムかと言うと、次の画像がそのプログラムの実行中の様子で、ADC0の電圧をADCで測定しSSD1331に表示する。と言う事をCore0で無限ループする。それに加え並列してCore1でLEDの点滅をさせています。

 

環境作りは以下のリンクから pico-setup-windows-0.3.5-x64.exe をダウンロードして行う。

pico-setup-windows

VSCodeの立ち上げは、必ず Visual Studio Code for Pico のショートカットを使用する。このショートカットはドキュメントフォルダに作られたPicoフォルダの中にある。

↓ New C/C++ Projectをクリック。

 

↓ New Pico Project
Name SSD1331_test
Board type Pico
Location c:\Users\JM1LXS\Documents\LXS_Pico
Select Pico SDK version v2.1.0
Features spi
Stdio support Console over USB
Code generation options Use project name as entry point file name
Generate C++ code
Debugger DebugProbe

 

↓ CMakeLists.txtに追記

hardware_adc
pico_multicore
pico_bootsel_via_double_reset

↑ pico_bootsel_via_double_reset は、リセットボタンをダブルクリックするとBOOTSELモードになる。なのでUSBケーブルの抜き差しは不要。

 

次は、Cソースファイルの内容を丸ごと入れ替える。

以前も今回もソースファイルは1つだけ。

以前のソースファイル pico_ssd1331_oled.c
今回のソースファイル SSD1331_test.cpp

SSD1331_test.cppの中身は削除して空にする。以前のpico_ssd1331_oled.cの中身をコピーしてSSD1331_test.cppにペーストする。

font.hはコピーしてSSD1331_testフォルダにペーストする。

 

↓ ビルドが成功して最終的なファイルはこんな感じ。

 

 

この記事で扱ったソースファイルをダウンロード出来ます。

LXS-TEST.zip

尚、SSD1331を初期化するコード lxs_oled_init()内のコマンド 0xAE 0x25から始まるそれは、ネット上で見つけた物で、私には何故そのコマンドなのかなど説明出来ません。
また、font.h内のフォントデータもネットから拝借した物です。

私は素人なので質問されても良い回答が出来ないので悪しからず。

次のリンク先のモデルをパクり、一部のデザインを変更して冷却ファンのブラケットを造形しました。

Ender 3 V3 SE Lightweight Fan Shroud

This link is the closest model to what I think is ideal.
I designed my model in homage to this model.

印刷条件は以下の通り。部屋温度が低く、PETGフィラメントなので、印刷速度は「超ゆっくり」ファン速度も「最低速」

そうしないと、角やカーブの所が積層に失敗してショートカットしちゃたり。ファン速度を速くすると直線でもカーブでも所々積層を失敗して、印刷面は荒れ凸凹になり、ビルドプートもフィラメントのカスだらけになってしまう。PETGフィラメントって、こんな感じ?

↓ 画像造形物の印刷条件

Ender-3 V3 SE
0.3mm ノズル Amazon
PETGフィラメント Amazon
スライサー UltiMaker Cura
レイヤー高さ 0.16mm
印刷速度 20mm/s
印刷温度 250℃
ビルドプート温度 80℃
ファン速度 1%
部屋温度 18℃

↓ フィラメントのカスも無く綺麗に造形出来ました。超時間かかったけど。

 

純正のエクストルーダーのカバーを外して、これにしたら、正面からノズルが良く見えるようになって、プリント中の確認をする姿勢が楽になりました。

このモデルの元になったオリジナルはネットに有り、それを少し私の考えを取り入れてOnshapeで作りました。

 

↓ 純正のカバーを外すと向かって左側にカバー用のビスとビス穴が1組余る。これを利用して解除レバーを操作しやすい様に突起物も造形しました。

 

【2024/11/18 追記】
PETGで造形したファンブラケットとエアダクトですが、これらを取り付けて印刷温度260℃、ビルドプート温度100℃で、別の物を連続6時間以上印刷したら、エアダクト(断面図のオレンジ色)が少し変形しました。

↓ 断面図

↓ 実際の画像

この後、エアダクトだけはABSフィラメントで造形しました。ファンブラケットもABSにしたいのですが、印刷中に積層割れしたり、印刷後まで割れしなくても、指で力を加えると必ず割れして脆いんです。

勿論、思っ切り力を加えればPLAやPETGだって割れちゃうけど、その割れ方とは違う。積層方向にカッターの刃を入れると、ABSは簡単に入るけど、PETGは苦労するくらい入らない。

エンクロージャーが無いとABSフィラメントは難しいのでしょうか。エンクロージャーが無い私のEnder-3 V3 SEでは、PLAやPETGフィラメントと比べるとABSは非常に脆いんです。