この記事でわかること
Raspberry Pi Pico Wの汎用入出力(GPIO)に接続したLEDを、C/C++を使って点灯・消灯させます。
実験準備
実験に必要な機器と部品を準備します。
機器
「Raspberry Pi Pico WとC/C++を始めよう。」記事で書きましたラズパイPicoWと、Visual Studio Code(以下 VSCode)をインストールしたRaspberry Pi5を準備します。
部品
LED(発光ダイオード)、固定抵抗など実験に使う部品を準備します。
部 品 名 | 規 格 | 数 量 | 取扱い店(参考) |
---|---|---|---|
LED | 3mm 赤色 | 1 | Amazon |
カーボン抵抗 | 1/4W 330Ω | 1 | Amazon |
ブレッドボード | SRH-21CE | 1 | Amazon |
ジャンパーワイヤ | オス-メス(約20cm) | 1 | Amazon |
機器/部品の実装とプログラミング
準備した機器と部品を実際につなぎ、C/C++でプログラミングを行いLEDを点灯・消灯させます。
配線
ブレッドボードを使って「赤いLED」、「抵抗」などをジャンパーワイヤでつなぎます。
サンプルファイルの購入
「STORES」からサンプルファイルの「7_c_cpp-digout.zip」をダウンロードします。
サンプルファイルのライセンス及びダウンロードと解凍方法については、こちらを参考にしてください。
サンプルファイルの読み込み
Raspberry Pi5のVSCodeを起動し、解凍したサンプルファイルが入っているフォルダ(gpio_blink)を読み込みます。
VSCodeのメニューから「ファイル」を選択し、ドロップダウンリストから「フォルダを開く…」を選択します。
「フォルダを開く」ダイアログが表示されますので、ダウンロードした「7_c_cpp-digout」フォルダにある「gpio_bilnk」フォルダを選択して開くをクリックします。
「このフォルダー内の・・・」ダイアログが表示されますので、「親フォルダー ’7_c_cpp-digout’・・・」に✔を入れ、「はい、作成者を信頼します」をクリックします。
処理がはじまります。(数十秒ほどかかります。)
左側のエクスプローラー・サイドバーから、「gpio_bilnk.c」を選択すると、編集エリアにソースの内容が表示されます。
【gpio_bilnk.cの一部抜粋】
//picoの標準ライブラリを組込
#include "pico/stdlib.h"
//標準関数のヘッダ関数を組込
#include <stdio.h>
//GPIOピン定義
#define LED_PIN 28
//LED点滅の間隔
#define LED_INTERVAL 500
//インターバルタイマ コールバック処理
bool timer_callback(repeating_timer_t *t)
{
//LED点滅処理
if ( gpio_get(LED_PIN) != 0)
{
//LED消灯
・・・
・・・
}
//メイン処理
int main() {
・・・
・・・
プログラムの実行
Raspberry Pi Pico Wに接続されているUSBケーブルを外し、「BOOTSEL」ボタンを押しながら、USBケーブルを差し込みます。
VSCodeの「F5」キーを押して実行すると、途中、Temporary breakpointsで一時停止しますので、もう一度、「F5」キーを押して続行します。
LEDが500ms間隔で点滅します。
パネルエリアで「シリアルモニター」を選択し、ポートを /dev/ttyACM0 – Raspberry Piに設定します。
ボーレートを115200に設定し、「監視の開始」をクリックすると、「LED ON」と「LED OFF」が500ms間隔で表示されます。
確認後、「Shift + F5」キーを押して、停止します。
回路の説明
ブレッドボードの配線を回路図に表すと次にようになります。
接続について
- 抵抗(R1)に接続されているGPピン28(34ピン)は、プログラムの設定でディジタル信号(HighまたはLow)の入力または出力を行います。(今回の実験ではLEDを点灯・消灯させますので出力として設定します。)
- 抵抗(R1)は、LEDに大きな電流が流れて壊れることを防ぐための電流制限抵抗です。
- LEDはアノードに電源のプラス側を、カソードにマイナス側を接続して電圧を加えると、アノードからカソードに向かって電流が流れ点灯しますので、アノード側に抵抗(R1)を接続し、カソード側をGND(38ピン)に接続します。
電気的特性と設定値
出力状態としてのGPピン28とLED(OSR5JA3Z74A同等品)の電気的特性から、電流制限抵抗(R1)の値を計算・設定します。
▶️出力状態としてのGPピン28の電気的特性
項 目 | 表 記 | 値 | 備 考 |
---|---|---|---|
Lowレベルの出力電圧 | VoL | 0V | 標準値 |
Highレベルの出力電圧 | VoH | 3.3V | 標準値 |
Highレベルの出力電流 | IoH | 4mA(最大8mA) | 初期設定値 |
▶️LED(OSR5JA3Z74A同等品)の電気的特性
項 目 | 表 記 | 値 | 備 考 |
---|---|---|---|
順方向電圧 | VF | 2.1V | 標準値 |
順方向電流 | IF | 20mA | 順方向電圧の時の電流 |
▶️電流制限抵抗(R1)値の計算・設定
電流制限抵抗「R1」にかかる電圧「VR」は、GPピン28のHighレベルの出力電圧「VoH」からLEDの順方向電圧「VF」を引いた値になります。
$$VR= {VoH}-{VF}={3.3V}-{2.1V}={1.2V}$$
LEDに電気的特性ではる順方向電流「IF」は20mAですが、GPピン28のHighレベルの出力電流は4mAですので、実際の「IF」は4mAとなります。
電流制限抵抗「R1」に流れる電流は、LEDに流れる順方向電流「IF」と等しいので、オームの法則より電流制限抵抗「R1」を計算します。
$$R1= \frac {\ VR}{IF}= \frac {\ 1.2V}{4mA}= \frac {\ 1.2V}{0.004A}={300Ω}$$
市販の抵抗はE系列という等比数列になっていますので、ここでは、安全のため計算値より大きい330Ωの抵抗に設定し、LEDに流れる順方向電流「IF」を計算し、GPピン28のHighレベルの出力電流の4mAを超えていないことを確認します。
$$IF= \frac {\ VR}{R1}= \frac {\ 1.2V}{330Ω}= {0.0036A}={3.6mA}<4mA$$
電流制限抵抗の計算の詳細については、「こちら」を参考にしてください。
プログラムの説明
VSCodeを起動し、「gpio_bilnk」フォルダを読み込み、「gpio_bilnk.c」の内容を編集エリアに表示させます。
プログラム全体の流れ
「LED点滅」プログラムは次の処理を行います。
流れ | 処理 | 説明 |
1 | ヘッダファイルの組み込み | picoの標準ライブラリと標準関数を組み込みます。 |
2 | GPIOピン番号を定義 | LEDを接続するGPIOピン番号を定義します。 |
3 | LEDの点滅間隔を定義 | GPIOピンに接続したLEDの点滅間隔をmsで定義します。 |
9 | インターバルタイマ コールバック処理 | タイマーにより、一定間隔で割り込みが発生した時に、呼び出される関数で、LEDを点灯/消灯させます。 |
4 | picoの入出力を初期化 | picoのUARTやUSB等を初期化します。 |
5 | LEDピンを初期化 | LEDピンを有効にし、入力モードに設定します。 |
6 | LEDピンを出力ピンに設定 | LEDピンの方向(入力/出力)を出力に設定します。 |
7 | LEDを消灯 | LEDピンの駆動(High(1)/Low(0))を「0」に設定します。 |
8 | インターバルタイマ設定 | ミリ秒単位で指定した間隔で繰り返し呼び出されるタイマーを設定します。タイマーの間隔で「流れ9のインターバルタイマ コールバック処理」が呼び出されます。 |
コメント
コメントはプログラムの処理に関係ないメモ書きです。
C言語では、「/*これはコメントです*/」のように、/**/で挟むことで、その間をコメントにすることができます。
C++言語ではこれに加え、「//これはコメントです」のように、文の最初に//が付けられた文は、その行の末尾(改行)まで「コメント」とみなします。
VSCodeは両方のコメントを使うことができます。
主に、書かれたコードを読みやすくする目的で、プログラム処理のはじめや終わりに、その部分がどのような処理をしているのかを書いたりします。
ヘッダファイルの組み込み(インクルード)
プログラムを再利用するための仕組みの一つとして、「ヘッダファイル」という仕組みがC/C++には備わっています。
ヘッダファイルには、変数や関数の宣言や定義のみが書いてあります。
ヘッダファイルを組み込むことで、それに対応するプログラムが記述されたファイル(ソースファイル)を利用することができます。
▶️ヘッダファイルの組み込み方法
ヘッダファイルの組み込みはインクルードと呼ばれ、「#include」により実行されます。
#include ヘッダファイル | |
ヘッダファイル | ヘッダファイル名(慣習でファイル名.hで表記されます。) |
「#」からはじまる1行分はマクロと呼ばれ、コンパイルの前に処理されます。
GPIOピン番号を定義
プログラムの中でGPIOピンを使用する際、意味のない番号を指定するより、意味がわかる文字列を指定したほうが可読性が向上します。
「#define」により、文字列を番号(GPIOピン番号)に置換します。
#define LED_PIN 28 | |
LED_PIN 28 | プログラムの中にあるLED_PINを28に置き換えます。 |
LEDの点滅間隔を定義
プログラムの中でLEDの点滅間隔(ミリ秒)を使用する際、数値を指定するより、意味がわかる文字列を指定したほうが可読性が向上します。
「#define」により、文字列を数値(点滅間隔 ミリ秒)に置換します。
#define LED_INTERVAL 500 | |
LED_INTERVAL 500 | プログラムの中にあるLED_INTERVALを500に置き換えます。 |
インターバルタイマ コールバック処理
タイマーにより、一定間隔で割り込みが発生した時に、呼び出される関数で、LEDを点灯/消灯させます。
bool timer_callback(repeating_timer_t *t) { //LED点滅処理 } | |
bool timer_callback (repeating_timer_t *t) | 関数「timer_callback」を定義します。 関数「timer_callback」は、一定間隔で割り込みが発生した時に、呼び出されるコールバック関数です。コールバック関数の引数は繰り返し時間に関する時間構造体です。(ここでは「t」としています。) |
//LED点滅処理 | 割り込みが発生する度に、「gpio_get」関数でLEDの状態を確認しながら、「gpio_put」関数で点灯/消灯させると同時に、「printf」関数でシリアル モニターにLED ON、OFFを表示させます。 |
picoの入出力を初期化
stdio_init_all(); |
picoのUARTやUSB等を初期化します。 |
LEDピンを初期化
gpio_init(LED_PIN); |
LEDピンを有効にし、入力モードに設定します。 |
LEDピンを出力ピンに設定
gpio_set_dir(LED_PIN, GPIO_OUT); |
LEDピンの方向(入力/出力)を出力に設定します。 |
LEDを消灯
gpio_put(LED_PIN, 0); |
LEDピンの駆動(High(1)/Low(0))を「0」に設定します。 |
インターバルタイマ設定
struct repeating_timer timer; add_repeating_timer_ms(-LED_INTERVAL, timer_callback, NULL, &timer); | |
struct repeating_timer timer; | 繰返しタイマーの構造体をtimerとして宣言します。 |
add_repeating_timer_ms( -LED_INTERVAL, timer_callback, NULL, &timer); | ・「add_repeating_timer_ms」関数はミリ秒単位で指定された間隔で繰り返し呼び出されるタイマーを追加します。 ・「-LED_INTERVAL」で繰返し間隔をミリ秒単位で指定します。符号は時間の計測開始タイミングを指定します。マイナスの場合は、設定した間隔、プラスの場合は、設定した間隔にコールバック処理時間を加えた時間になります。 ・「timer_callback」はタイマー割込みが発生した時に呼び出され関数です。(インターバルタイマ コールバック処理) ・「NULL」はNULLとして指定します。 ・「&timer 」は繰返しタイマーの構造体の先頭アドレスです。 |
まとめ
Raspberry Pi Pico WのGPIOピンにLEDを接続し、点灯/消灯を行いました。
LEDの接続の方法と、Raspberry Pi Pico WやLEDを壊さないために用いる、電流制限抵抗の計算方法を学びました。
ヘッダファイルを組み込み、LEDを周期的に点灯/消灯させるために必要な「gpio_set_dir」関数、「gpio_put」関数、タイマーの割り込み処理について学びました。
おすすめの一冊