GPIO IN, OUT (ESP-IDF 環境 + C 言語)

プログラムの書き方

GPIO で使われる関数については, ESP-IDF Programming GuideAPI ReferenceGPIO & RTC GPIO を参照して欲しい.

以下に最低限使う必要のある関数を挙げる.

//ヘッダファイルの読み込み
#include "driver/gpio.h" 

// ピン番号の型 gpio_num_t 
gpio_num_t  pin = 13;

// ピンのリセット
gpio_reset_pin( pin );

// ピンの入力の指定
gpio_set_direction(pin, GPIO_MODE_INPUT);
gpio_set_pull_mode(pin, GPIO_PULLUP_ONLY); //内部的にプルアップ

// ピンの入力値. 戻り値は 0 or 1
gpio_get_level(pin);

// ピンの出力の指定
gpio_set_direction(pin, GPIO_MODE_OUTPUT);

// ピンの出力.第 2 引数は 0 or 1
gpio_set_level(pin, 0);
gpio_set_level(pin, 1);

Lチカの例題

電子工作における hello world と言える L チカを実行する.

プロジェクトの準備

サンプルプロジェクトをコピーする.Linux を使う場合はターミナルで以下のように打鍵する.

$ cd ~/esp

$ idf.py create-project blink

    Executing action: create-project
    The project was created in /home/sugiyama/esp/blink

$ cd blink

一方で,Windows の場合は PowerShell で以下のように打鍵する.

> cd C:\esp\v5.5.4

> idf.py create-project blink

    Executing action: create-project
    The project was created in C:\esp\v5.5.4\blink

> cd .\blink\

プログラムの作成

このサンプルプロジェクトのメインファイルは main ディレクトリ以下の blink.c であるので, そのファイルを編集する.エディタとして,vi, emacs, gedit, code (VS code) などが使える. code (VS code) を使う場合は以下のように打鍵すると良い

Linux の場合

$ code main/blink.c

Windwos の場合

> code.cmd .\main\blink.c

blink.c を以下のように書き換えて保存する.

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"

void app_main(void)
{
   // LED ピン
   gpio_num_t pin = 13;                       // ピン番号
   gpio_reset_pin(pin);                       // ピンのリセット
   gpio_set_direction(pin, GPIO_MODE_OUTPUT); // ピンを出力で利用

   while(1) {
      gpio_set_level(pin, 0);                 // ピンの値を0に
      vTaskDelay(1000 / portTICK_PERIOD_MS);  // 1 秒の待ち

      gpio_set_level(pin, 1);                 // ピンの値を1に
      vTaskDelay(1000 / portTICK_PERIOD_MS);  // 1 秒の待ち
   }
}

なお,上記プログラム中の vTaskDelay(1000 / portTICK_PERIOD_MS); の行は, 1 秒 = 1000 ミリ秒だけ動作を止めるという命令である. ESP-IDF 環境では, 待ち時間 (単位 ミリ秒) を portTICK_PERIOD_MS (FreeRTOS の割込み周期)で割り算した結果を vTaskDelay の引数に与える必要がある.

1 番目の LED が定期的に点灯・消灯することを確認されたい.

ビルドとマイコンへの書き込み

idf.py build コマンドを実行する.

$ idf.py build

マイコンに書き込むのは idf.py flash コマンド, 標準出力を表示するのは idf.py monitor コマンドである. まとめて idf.py flash monitor としても良い.

$ idf.py flash monitor

実習ボードの左端の LED が点灯することが確認できるであろう.

monitor を終了するのは Ctrl-] である.
他の LED も点灯させてみよ.

レポート課題 1: GPIO (PULL_UP)

実施方法

[1] 目的:

  • GPIO のプログラムにおいて,入力 (gpio_get_level 関数) で得られる数字とGPIO の出力 (gpio_set_level 関数) の引数で与える数字が,LED およびスイッチの挙動とどのような関係になっているか理解する.さらに,それらの数字が回路図とどのような関係になっているか理解する.

[2] 使用する機器:

  • マイコンボード
  • LED (マイコンボード上の LED を利用.左端の LED 以外を使うこと)
  • タクトスイッチ

[3] 機器の接続方法

  • タクトスイッチをケーブルで接続すること
    • 黒色のケーブル (GND) を GND のピンに接続
    • 赤色のケーブル (VCC) を適当なピンに接続 → 実験ボードのピン配置参照

[4] プログラム:

  • 以下のプログラムの穴埋め (4 箇所, <穴1>~<穴4>) を行い,「ボタンを押すと LED が点灯する」プログラムを完成させること.

    #include <stdio.h>
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "driver/gpio.h"
    
    void app_main(void)
    {
       // LED ピン
       gpio_num_t pin = <穴1>;                     // ピン番号
       gpio_reset_pin(pin);                        // ピンのリセット
       gpio_set_direction(pin, GPIO_MODE_OUTPUT);  // ピンを出力で利用
    
       //スイッチピン
       gpio_num_t pin2 = <穴2>;                    // ピン番号
       gpio_reset_pin(pin2);                       // ピンのリセット
       <穴3>;                                      // ピンを入力で利用
       <穴4>;                                      // 入力で使うピンを内部的にプルアップ
    
       while(1) {
          if (gpio_get_level(pin2) == <穴5>)      //スイッチの ON/OFF の判断
          {
             gpio_set_level(pin, 0);                 //ピンの値を0に(=消灯)
          }
          else if (gpio_get_level(pin2) == <穴6>) //スイッチの ON/OFF の判断
          {
             gpio_set_level(pin, 1);                 //ピンの値を1に(= 点灯)
          }
          vTaskDelay(1000 / portTICK_PERIOD_MS);  //1秒の待ち
       }
    }

[5] プログラムの実行:

  • 作成したプログラムを実行し,期待通りに動作しているか確認すること.

レポートのまとめ方

以下の内容を記述すること.

  • 実験の目的
  • 実験方法
    • 利用する機器の一覧
    • 機器の接続方法
      • タクトスイッチをマイコンボードのどのピンに接続したか明記すること
  • 実験設定
    • プログラムの穴埋め部に何を入れたかまとめて示すこと.以下のような表形式で示すこと(表には表番号を付すこと).
      • 書き方の例:「作成したプログラムは実験手順書に書かれているサンプルプログラムを元にした.サンプルプログラム中の<穴1>~<穴6>に入れた数字を表 X に示す.」
      • プログラム全部をレポートで示す必要はありません.

穴1穴2穴3穴4穴5穴6
........................

  • 実験結果
    • 作成したプログラムを実行したときに,何が起きたか説明すること.但し,以下に示すような表を作成し,その表を引用する形で説明文を書くこと.
      • スイッチのボタンを押したとき・押していないときに,LED が点灯・消灯のどちらになったかを示すこと.
      • スイッチのボタンを押したとき・押していないときに,gpio_get_level の戻り値がどうなっていたかを示すこと.

LEDgpio_set_levelスイッチgpio_get_levelの戻り値
点灯1 ON or OFF 0 or 1
消灯0 ON or OFF0 or 1

  • 議論
    • おそらく実験結果は,スイッチの ON/OFF と gpio_get_level の戻り値 (0 or 1) との関係が直感的でないと思われる.その理由を以下の回路図を元に議論をしなさい.なお,回路図はレポートに書いて図番号を付し,その図番号を引用する形で説明文を書くこと.なお,今回スイッチに使うピンは PULL_UP 抵抗を内蔵しているので,回路図的にはマイコンの中に抵抗が存在する形となる.
      • PULL_UP 回路 (PULL_UP 抵抗) の役割は?
      • なぜスイッチ ON のときに gpio_get_level の戻り値 が (0 or 1) なのか?
      • なぜスイッチ OFF のときに gpio_get_level の戻り値 が (0 or 1) なのか?

レポート課題 2: GPIO (チャタリング)

実施方法

[1] 目的:

  • スイッチを ON/OFF した際,接点が物理的に跳ね返ることで,GPIO の値が 0 と 1 の間で高速にバタつく現象(チャタリング)をオシロスコープで確認する.

[2] 使用する機器:

  • タクトスイッチ
  • マイコンボード
    • ボード上の LED で使っているピンをオシロスコープに接続すること
  • オシロスコープ
  • ブレッドボート
  • ジャンパーケーブル

[3] 機器の接続方法

  • ブレッドボートとジャンパーケーブルを用いて配線せよ.
    • 黒色のケーブル (GND) を GND のピンに接続
    • 赤色のケーブル (VCC) を LED で使っている適当なピンに接続 → 実験ボードのピン配置参照

[4] プログラム:

  • レポート課題 1 と同じ (タクトスイッチの接続するピンを変更していない場合は)
    • もしタクトスイッチの接続するピンを変更した場合は,プログラム中のスイッチのピン番号 (pin2) を変更する必要がある.

[5] オシロスコープでの観察・スケッチ

  • プログラムを実行し 10 回行い,波形が安定するまでの秒数を読み取り,それを記録する.
  • 最後の 1 回について,波形をスケッチする.
    • 電圧が「1」から「0」へ一瞬で落ちるのではなく、何度か上下に暴れている様子(チャタリング)を正確にスケッチしてください。
    • スケッチにはグラフ用紙を使用することとし,単位等を正確に記述すること.

オシロスコープの使い方

1. プローブの接続
   1-1. オシロスコープの CH1(チャンネル1) にプローブを接続する
      ・プローブの 測定針(フック) を,スイッチと繋がっているジャンパーケーブルに接続する.
      ・プローブの 黒いワニ口クリップ(GND)をマイコン基板の GND ピンと繋がっているジャンパーケーブルに接続する         

2. オシロスコープの初期設定(画面の整理)
   前の人の設定が残っていると測定に失敗するため,必ず工場出荷時の状態にリセットする.
   2-1. パネル右上の [DEFAULT SETUP] ボタンを押す.
   2-2. 画面に不要なメニューが出ている場合は、[Menu Off] ボタン(画面右下)を押して消す.
   2-3. CH1の波形(黄色の線)だけが表示されていることを確認する.

3. スケール(縦軸・横軸)の調整
   波形を画面に収めるために設定する.
   3-1. 縦軸(電圧)の設定:
      ・CH1の [SCALE] ツマミ(大きい方)を回し,画面左下の表示を 「CH1 1.00V/div」(1目盛りが1V)にする.
      ・CH1の [POSITION] ツマミ(小さい方)を回し,黄色の線を画面の真ん中の横線に合わせる
       (ここが 0 V の基準になる)
   3-2. 横軸(時間)の設定:
      ・HORIZONTAL(水平)エリアの [SEC/DIV] ツマミを回し,画面に波形が十分な解像度で表示されるようにする.

4. トリガ(待ち伏せ)の設定
   スイッチを入れた瞬間の高速な変化を逃さず,「パシャッ」とカメラのように撮影するための設定を行う.
   4-1. TRIGGER(トリガ)エリアの [TRIG MENU] ボタンを押す.画面右側にメニューが出る.
   4-2. メニュー横のボタンを押して以下のように設定する.
      ・タイプ:エッジ
      ・ソース:CH1
      ・スロープ:立ち下がり (※スイッチをONにした瞬間、3.3Vから0Vに落ちる現象を狙うため)
   4-3. [TRIG LEVEL] ツマミを回して画面右端にある黄色の小さな矢印(トリガレベルの目印)を
        1.5V〜2.0V付近の高さに合わせる.
        (※マイコンの電圧3.3Vと0Vの「真ん中」にトラップを仕掛けるイメージ)

5. 測定の実行(シングルショット撮影)
   5-1. TRIGGERエリアの [SINGLE](またはSINGLE SEQ)ボタンを 1回だけ押す
   5-2. 画面上部に 「Ready」 または 「待機中」 と表示されたことを確認する
       (これでオシロスコープが待ち伏せ状態になる)
   5-3. マイコン基板のスライドスイッチを 「OFF」から「ON」へ カチッと動かす.
   5-4. 画面に波形が表示され,上部の表示が 「Stop」 に変わったら撮影成功.

レポートのまとめ方

以下の内容を記述すること.

  • 実験の目的
  • 実験方法
    • 利用する機器の一覧
    • 機器の接続方法
      • オシロスコープをマイコンボードのどのピンに接続したか明記すること
  • 実験設定
    • レポート課題 1 のプログラムの何行目をどのように変更したか明記すること (プログラム全部を書き写す必要はありません)
  • 実験結果1
    • 10 回実施し,各回について値が安定するまでにかかった時間を表形式でまとめる.
      • 10 回分の平均値も計算して表に入力すること.
    • 表には単位を付けるのを忘れないこと!

試行回数安定するまでの時間(ms)
1170.0
2210.0
......
平均221.0

  • 実験結果2
    • 最後の 1 回について,オシロスコープで得られた電圧波形のスケッチを示すこと.
  • 議論
    • 得られた結果より何が言えるか考えよ.
      • ヒント:無限ループ内の sleep 時間はチャタリングが収まるまでの時間より長くする必要があります.