ラズパイPico(Raspberry Pi Pico)を使用して、基本的な「Lチカ」や「入出力設定」「スイッチ入力」「アナログ入力(ADC)」「PWM出力」を行うための、コピペ用サンプルプログラムをまとめました。
プログラム言語は「Python」を使用し「MicroPython」と「CircuitPython」の両方でまとめていますので、お好みの言語で動作確認してみてください。
「ラズパイPico」の仕様や端子配列等の基本情報は以下のリンクで詳しく紹介しています。
「MicroPython」と「CircuitPython」の開発環境の準備については、以下リンクでそれぞれ詳しく紹介しています。
Picoと同等に使えて、さらに小型な互換ボード「XIAO RP2040」を使った「OLED表示」や「シリアル(UART)通信」についても、以下のリンクで詳しく紹介しています。
Picoでも同じプログラムで動作するのでぜひお試しを♪
1.動作確認の準備
・ラズパイPico端子配列
・端子機能(入出力、アナログ、PWM)
・配線図と動作紹介
・使用部品について
2.MicroPythoのサンプルプログラム(コピペ)
・Lチカ
・スイッチ入力、LED出力
・アナログ(ADC)入力
・PWM出力
・マルチコアで並列処理
3.CircuitPythonのサンプルプログラム(コピペ)
・Lチカ
・スイッチ入力、LED出力
・アナログ(ADC)入力
・PWM出力
4.本体の初期化方法
5.まとめ
1.動作確認の準備
動作確認に使用するラズパイPico(PicoWでも可)の端子配列や使用する部品、配線図について紹介します。
・ラズパイPico端子配列
端子配列は以下のようになります。(公式サイトより抜粋)
Picoの端子配列
Pico Wの端子配列
・端子機能(入出力、アナログ、PWM)
今回動作確認を行う「ラズパイPico」の基本的な端子機能については以下のようになります。
入出力端子(GPIO)
端子番号「GP0〜22, 26〜28」を入出力端子として使用することができます。
入力端子は外部スイッチやセンサーの状態を取得するために使用します。
出力端子は電圧を出力してLED等の外部素子を制御したりデバイスに信号を与えるために使用します。
入出力端子の使い方は以下リンクのスイッチとLEDについて、で詳しく紹介しています。
アナログ入力端子(ADC)
端子番号「GP26〜28(ADC0〜2)」をアナログ入力端子として使用することができます。
アナログ入力端子に入力された電圧(0〜3.3V)をデジタル値に変換して取得できます。
分解能は12bit(0〜3.3V = 0〜4095)ですが、プログラム上では16bit(0〜65535)で扱われます。
ボリュームについては以下のリンクで詳しく紹介しています。
PWM(Pulse Width Modulation)出力
各入出力端子はPWM出力端子としても使用することができます。
ラズパイPicoには、スライスと呼ばれる8つの独立した PWMジェネレータがあり、それぞれに2つのチャネルがあります。
これにより合計16chの PWM出力が使用でき、8Hz から 62.5MHz までクロック制御できます。
スライスの2つのチャネルは同じ周波数で実行されますが、異なるデューティサイクルを指定できます。2つのチャネルは通常、偶数/奇数の隣接する GPIOピンのペアに割り当てられます。
「PWM」については以下のリンクで詳しく紹介しています。(サンプルプログラムはC言語です。)
・配線図と動作紹介
配線図
動作確認を行うための配線図は下画像のようになります。
実際にブレッドボードを使用して接続したものは下写真のようになります。
動作紹介
動作については以下の動作をサンプルプログラム(コピペ)で確認できます。
- Lチカ:本体LED(緑)を点滅させます。(この動作はPico単体で動作確認できます)
- スイッチ入力、LED出力:外部スイッチを押すことで、外部LED(赤)を点灯させます。
- アナログ(ADC)入力:ボリュームで電圧を可変させ、アナログ入力値として取得し、電圧に換算してシリアルモニタに表示させて確認します。
- PWM出力:外部スイッチを押すことで、外部LED(赤)を点灯させますが、その明るさはPWM制御でボリュームのアナログ入力値を取得して指定することでコントロールします。
- マルチコアで並列動作(MicroPythonのみ):2つのCoreを使用して、本体LED(緑)を常時点滅させながら、スイッチONでLED(赤)を点滅させる動作を同時に実行する、並列動作の確認を行います。
・使用部品について
今回使用する部品については以下のようになります。
「スイッチ」や「発光ダイオード」「抵抗器(510Ω〜1kΩ程度)」は基本的には何でも良いです。
「ボリューム」はブレッドボードに挿せて指で回せるものが良いので、以下サンハヤト製の「スイッチ」と「ボリューム」のセットがおすすめです。
ブレッドボードは安いものはありますが、差し込みが固かったりするので少し高くてもやっぱりサンハヤト製がいいです。1列の穴数も一般的な5個ではなく6個あるので自由度も高くておすすめです。
サンハヤト製ばかりおすすめしてますが・・・ジャンプワイヤーも以下がおすすめです。
中華製でも使用上問題ないですが、長さがカラーコード(赤:2穴ピッチ、橙:3、黄:4・・・)で、わかるものの方が断然作業性は良いです。
「ラズパイPico」本体は基本的には端子は半田付けされていません。
ブレッドボードで使用する場合は、別途ピンヘッダーを購入して半田付けするか、以下のような端子が実装済のものを使用しましょう。
2.MicroPythoのサンプルプログラム(コピペ)
「MicroPython」を使用したサンプルプログラムはそれぞれ以下になります。
コピペで貼り付けて書き込んで実行してください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
・Lチカ
「MicroPython」で「Lチカ(LEDを点灯/消灯)」するプログラムは以下になります。
(このプログラムはラズパイPico本体だけでも動作確認できます。)
from machine import Pin # 入出力モジュールを準備
import time # タイマーモジュールを準備
# 出力ピン設定
led = Pin("LED", Pin.OUT) # 本体LEDピンをledとして出力に設定
# メイン処理 ---------------------------------------------------------
while True: # ずっと繰り返し
led.value(1) # LEDを点灯
time.sleep(0.5) # 0.5秒待つ
led.value(0) # LEDを点灯
time.sleep(0.5) # 0.5秒待つ
「5行目」で本体LEDピン(内部回路)を出力に設定しています。
・スイッチ入力、LED出力
「MicroPython」で「スイッチ」のON/OFFで「外部LED(赤)」をON/OFFするプログラムは以下になります。
from machine import Pin # 入出力モジュールを準備
import time # タイマーモジュールを準備
# 入力ピン設定
sw = Pin(17, Pin.IN, Pin.PULL_UP) # スイッチのピン番号を指定してswとして入力設定(プルアップ)
# 出力ピン設定
led = Pin(16, Pin.OUT) # 外部LEDのピン番号を指定してledとして出力設定
# メイン処理 ---------------------------------------------------------
while True: # ずっと繰り返し
print("sw = {:d}".format(sw.value())) # スイッチの状態(ON=0 /OFF=1)表示
if sw.value() == 0: # スイッチが押されていたら
led.value(1) # LEDを点灯
else: # スイッチが押されてい なければ
led.value(0) # LEDを消灯
time.sleep(0.5) # 待ち時間
シリアルモニタにはスイッチの状態(ON=0 /OFF=1)が表示され続けます。
「5行目」で「端子(GPIO)番号」を指定して「入力端子」の設定を行なっています。
入力端子のプルアップ、プルダウンもここで設定します。
「8行目」で「端子(GPIO)番号」を指定して「出力端子」の設定を行なっています。
「14〜17行目」で「if文」を使用することで、スイッチの状態を確認してLEDをON/OFFさせているため、この部分を以下で置き換えても同じ動作になります。
led.value(not sw.value()) # スイッチの状態でLEDを点灯(点灯=1 /消灯=0)
・アナログ(ADC)入力
「MicroPython」で端子に入力された「アナログ入力電圧」を取得する方法は以下になります。
from machine import Pin, ADC # 入出力とアナログ入出力制御用モジュールを準備
import time # タイマーモジュールを準備
# アナログ入力ピン設定
adc = ADC(Pin(28)) # 使用するアナログ入力(ADC0〜2)の端子番号(26〜28)をadcに設定
# メイン処理 ---------------------------------------------------------
while True: # ずっと繰り返し
adc_val = adc.read_u16() # アナログ入力(ADC)値を取得
adc_volt = (adc_val * 3.3) / 65536 # アナログ入力(ADC)値を電圧(3.3V)に変換
print("adc_val = {:5d} adc_volt = {:5.2f}V".format(adc_val, adc_volt)) # 結果を表示する
time.sleep(0.5) # 待ち時間
開発環境「Thonny」を使用した場合は、下画像のように「シェル」部に表示され続けます。
「1行目」でアナログ入出力を制御する「ADC」モジュールを追加します。
「9行目」でボリュームから入力された電圧を「アナログ入力値」として取得し「10行目」で「電圧値」に換算しています。
アナログ入力については以下のリンクで詳しく紹介しています。(サンプルプログラムはC言語です)
・PWM出力
「MicroPython」で「PWM出力」を使用してLEDの明るさをコントロールするプログラムは以下になります。
from machine import Pin, ADC, PWM # 入出力とアナログ入出力、PWM制御用モジュールを準備
import time # タイマーモジュールを準備
# 入力ピン設定
sw = Pin(17, Pin.IN, Pin.PULL_UP) # スイッチのピン番号を指定してswとして入力設定(プルアップ)
# アナログ入力ピン設定
adc = ADC(Pin(28)) # 使用するアナログ入力(ADC0〜2)の端子番号(26〜28)をadcに設定
# PWMピン設定
pwm = PWM(Pin(16 ,Pin.OUT)) # PWM出力ピン番号を指定してpwmとしてPWM出力設定
pwm.freq(1000) # PWM周波数を設定
# メイン処理 ---------------------------------------------------------
while True: # ずっと繰り返し
if sw.value(): # スイッチが押されてなければ
pwm.duty_u16(0) # PWM出力オフ(Duty比を0に設定)
else: # スイッチが押されていれば
adc_val = adc.read_u16() # アナログ入力(ADC)値を取得
adc_volt = (adc_val * 3.3) / 65536 # アナログ入力(ADC)値(16bit)を電圧(3.3V)に変換
print("adc_val = {:5d} adc_volt = {:5.2f}V".format(adc_val, adc_volt)) # 結果を表示する
pwm.duty_u16(adc_val) # アナログ入力(ADC)値をPWMのDuty比に設定(0〜65535)
time.sleep(0.1) # 待ち時間
ボリュームを変化させるとLEDの明るさが変化することが確認できます。
「1行目」でPWM制御を行うための「PWM」モジュールを追加しています。
「11〜12行目」で、使用する端子番号を指定して「PWM出力」の初期設定を行っています。
スイッチが押されていなければ「17行目」のように「Duty比」を「0」に設定して出力をOFFにします。
スイッチが押されていれば「23行目」のようにボリュームからのアナログ入力値(0〜65535)を「Duty比」に設定して、出力電圧を可変させてLEDの明るさをコントロールします。
「Duty比」については以下のリンクで図を使って詳しく紹介しています。
「PWM制御」でモーターの速度制御をする方法についても以下のリンクで詳しく紹介しています。
・マルチコアで並列処理
「MicroPython」で「Pico」の「2つのCore0/1」を使って、2つの処理を同時に実行(並列動作:マルチスレッド)させるプログラムは以下になります。
import _thread # 複数のタスクを同時に実行するスレッドモジュールを準備
from machine import Pin # 端子制御用モジュールを準備
import time # タイマーモジュールを準備
# 入力ピン設定
sw0 = Pin( 17, Pin.IN, Pin.PULL_UP) # スイッチのピン番号を指定してswとして入力設定(プルアップ)
# 本体LEDを出力設定
led = Pin("LED", Pin.OUT) # 本体LEDを出力設定
led0 = Pin(16, Pin.OUT) # 外部LEDのピン番号を指定してled0として出力設定
# Core1 並列処理(本体LED点滅) ---------------------------------------------------------------
def core1():
while True: # ずっと繰り返し
led.value(1) # 本体LEDを点灯
time.sleep(0.5) # 待ち時間
led.value(0) # 本体LEDを消灯
time.sleep(0.5) # 待ち時間
# Core0 メイン処理(スイッチONで外部LED点滅) ---------------------------------------------------------------
def core0():
while True: # ずっと繰り返し
if sw0.value() == 0: # スイッチが押されていたら
led0.value(1) # 外部LEDを点灯
time.sleep(0.5) # 待ち時間
led0.value(0) # 外部LEDを消灯
time.sleep(0.5) # 待ち時間
else: # スイッチが押されていなければ
led0.value(0) # LEDを消灯
# 新しいスレッドでcore1関数を実行
_thread.start_new_thread(core1, ())
# メインスレッドでcore0関数を実行
core0()
「Core1」では本体LED(緑)を常時点滅させ、スイッチをどのタイミングでONしてもLED(赤)は点滅を開始し、本体LED(緑)は安定して点滅を続けるため、「Core0」と「Core1」が並列動作していることが確認できます。
「1行目」で並列動作を行うための「_thread」モジュールを準備しています。
「13行目」でCore1で実行する「並列処理:本体LED点滅」をループ関数として準備します。
「21行目」でCore0で実行する「メイン処理:スイッチONで外部LED点滅」をループ関数として準備します。
「32行目」で「_thread.start_new_thread()」関数を使用してCore1の「並列処理」関数を実行します。
「34行目」でCore0の「メイン処理」関数を実行することで、2つの動作を同時に実行させることができます。
マルチコアで並列動作させる方法は以下のリンクで、より詳しく紹介しています。
3.CircuitPythonのサンプルプログラム(コピペ)
「CircuitPython」を使用したサンプルプログラムはそれぞれ以下になります。
コピペで貼り付けて書き込んで実行してください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
・Lチカ
「CircuitPython」で「Lチカ(LEDを点灯/消灯)」するプログラムは以下になります。
(このプログラムはラズパイPico本体だけで動作確認できます。)
import digitalio # 入出力ピン制御用モジュールを準備
from board import * # boardモジュールからすべてのピンの定義を準備
import time # 時間に関連する操作を行うためのモジュールを準備
# 出力ピン設定
led = digitalio.DigitalInOut(LED) # 本体LEDのピンをledに設定
led.direction = digitalio.Direction.OUTPUT # ledを出力モードに設定
# メイン処理 ---------------------------------------------------------
while True: # ずっと繰り返し
led.value = True # LEDを点灯
time.sleep(0.5) # 0.5秒待つ
led.value = False # LEDを消灯
time.sleep(0.5) # 0.5秒待つ
「6,7行目」で本体LEDピン(内部回路)を出力に設定しています。
・スイッチ入力、LED出力
「CircuitPython」で「スイッチ」のON/OFFで「外部LED(赤)」をON/OFFするプログラムは以下になります。
import digitalio # 入出力ピン制御用モジュールを準備
from board import * # boardモジュールからすべてのピンの定義を準備
import time # 時間に関連する操作を行うためのモジュールを準備
# 入力ピン設定
sw = digitalio.DigitalInOut(GP17) # スイッチのピン番号を指定してswとして設定
sw.direction = digitalio.Direction.INPUT # swを入力モードに設定
sw.pull = digitalio.Pull.UP # 内部プルアップ抵抗を有効化
# 出力ピン設定
led = digitalio.DigitalInOut(GP16) # 外部LEDのピン番号を指定してledとして設定
led.direction = digitalio.Direction.OUTPUT # ledを出力モードに設定
# メイン処理 ---------------------------------------------------------
while True: # ずっと繰り返し
print("sw = {:d}".format(sw.value)) # スイッチの状態(ON=0 /OFF=1)表示
if sw.value == 0: # スイッチが押されていたら
led.value = True # LEDを点灯
else: # スイッチが押されてい なければ
led.value = False # LEDを消灯
time.sleep(0.5) # 待ち時間
シリアルモニタにはスイッチの状態(ON=0 /OFF=1)が表示され続けます。
「6〜8行目」で「端子(GPIO)番号」を指定して「入力端子」の設定を行なっています。
入力端子のプルアップ、プルダウンもここで設定します。
「11,12行目」で「端子(GPIO)番号」を指定して「出力端子」の設定を行なっています。
「18〜21行目」で「if文」を使用することで、スイッチの状態を確認してLEDをON/OFFさせているため、この部分を以下で置き換えても同じ動作になります。
led.value = not sw.value # スイッチの状態でLEDを点灯(点灯=1 /消灯=0)
・アナログ(ADC)入力
「CircuitPython」で端子に入力された「アナログ入力電圧」を取得する方法は以下になります。
import analogio # アナログ入出力制御用モジュールを準備
from board import * # boardモジュールからすべてのピンの定義を準備
import time # 時間に関連する操作を行うためのモジュールを準備
# アナログ入力ピン設定
adc = analogio.AnalogIn(A2) # 使用するアナログ入力(ADC)番号(A0〜2)をadcに設定
# メイン処理 ---------------------------------------------------------
while True: # ずっと繰り返し
adc_val = adc.value # アナログ入力(ADC)値を取得
adc_volt = (adc_val * 3.3) / 65536 # アナログ入力(ADC)値を電圧(3.3V)に変換
print("adc_val = {:5d} adc_volt = {:5.2f}V".format(adc_val, adc_volt)) # 結果を表示する
time.sleep(1.0) # 待ち時間
開発環境「Thonny」を使用した場合は、下画像のように「シェル」部に表示され続けます。
「1行目」でアナログ入出力を制御する「analogio」モジュールをインポートします。
「10行目」でボリュームから入力された電圧を「アナログ入力値」として取得し「11行目」で「電圧値」に換算しています。
アナログ入力については以下のリンクで詳しく紹介しています。(サンプルプログラムはC言語です)
・PWM出力
「CircuitPython」で「PWM出力」を使用してLEDの明るさをコントロールするプログラムは以下になります。
import digitalio # 入出力ピン制御用モジュールを準備
import analogio # アナログ入出力制御用モジュールを準備
import pwmio # PWM制御用モジュールを準備
from board import * # boardモジュールからすべてのピンの定義を準備
import time # 時間に関連する操作を行うためのモジュールを準備
# 入力ピン設定
sw = digitalio.DigitalInOut(GP17) # スイッチのピン番号を設定
sw.direction = digitalio.Direction.INPUT # スイッチを入力モードに設定
sw.pull = digitalio.Pull.UP # 内部プルアップ抵抗を有効化
# アナログ入力ピン設定
adc = analogio.AnalogIn(A2) # 使用するアナログ入力(ADC)番号(A0〜2)をadcに設定
# PWMピン設定
pwm = pwmio.PWMOut(GP16, frequency=1000) # PWM出力ピン番号と周波数をpwmに設定
# メイン処理 ---------------------------------------------------------
while True: # ずっと繰り返し
if sw.value: # スイッチが押されてなければ
pwm.duty_cycle = 0 # PWM出力オフ(Duty比を0に設定)
else: # スイッチが押されていれば
adc_val = adc.value # アナログ入力(ADC)値を取得
adc_volt = (adc_val * 3.3) / 65536 # アナログ入力(ADC)値(16bit)を電圧(3.3V)に変換
print("adc_val = {:5d} adc_volt = {:5.2f}V".format(adc_val, adc_volt)) # 結果を表示する
pwm.duty_cycle = adc.value # アナログ入力(ADC)値をPWMのDuty比に設定(0〜65535)
time.sleep(0.1) # 待ち時間
ボリュームを変化させるとLEDの明るさが変化することが確認できます。
「3行目」でPWM制御を行うための「pwmio」モジュールをインポートします。
「16行目」で、使用する「端子(GPIO)番号」を指定して「PWM出力」の初期設定を行っています。
スイッチが押されていなければ「21行目」のように「Duty比」を「0」に設定して出力をOFFにします。
スイッチが押されていれば「27行目」のようにボリュームからのアナログ入力値(0〜65535)を「Duty比」に設定して、出力電圧を可変させてLEDの明るさをコントロールします。
「Duty比」については以下のリンクで図を使って詳しく紹介しています。
「PWM制御」でモーターの速度制御をする方法についても以下のリンクで詳しく紹介しています。
4.本体の初期化方法
いろいろな開発環境を試したりライブラリをインストールしたりしていると、思いどりに動かなかったり、動作がおかしくなったりして初期状態に戻したいと思うこともあると思います。
そんな時のために「ラズパイPico」本体を初期化する方法を紹介します。
以下のサイトにアクセスして、本体リセット用のファイルをダウンロードします。
下画像のようなページが表示されるので「UF2 file」をクリックします。
クリックすると「flash_nuke.uf2」というファイルがダウンロードされます。
「ラズパイPico」を本体の「BOOTSEL」ボタンを押しながらパソコンと接続して、表示されるフォルダにこのファイルをドラッグ&ドロップするだけで初期化は完了します。
5.まとめ
「ラズパイPico」を使用して、基本的な「Lチカ」や「入出力設定」「スイッチ入力」「アナログ入力(ADC)」「PWM出力」を行うための方法をまとめて詳しく紹介しました。
基板に実装されたマイコンボードのような電子回路でもプログラミング言語に「Python」を使用することで比較的簡単に制御することができます。
今回紹介したものは基本的なプログラムだけですが、これらを組み合わせるだけでもちょっとしたロボットの制御も行うことができるようになると思います。
プログラムを覚える必要はないので、使い方をマスターして、その都度コピペで組み合わせて使いこなしていきましょう。
応用編として、液晶表示や「PicoW」のWi-Fi機能を使用した遠隔操作の方法も以下リンクで紹介していますので、ぜひ挑戦してみてください。
コメント
いつもお世話になっております。
配線図のイラストですが
GPIO16(21ピン:出力)にスイッチ
GPIO17(22ピン:入力)へLEDが
繋がっています、逆ですよね。
正解は
GPIO16(21ピン:出力)にはLED
GPIO17(22ピン:入力)にはスイッチ
ですよね
下写真は、その通りになっています。
よろしくお願いいたします。
配線図確認しました。間違ってますね^^;
早速修正しました。
ご指摘感謝です。ありがとうございました。