基礎 · 読了まで16分

ブロックプログラミングからMicroPythonへ:センサーとRaspberry Pi Pico

ブロックプログラミングからMicroPythonへ。LDRとHC-SR04をブロックで読み、C++と見比べ、シリアルモニタを使ったあと、Raspberry Pi PicoでMicroPythonに切り替えます。

ブロックプログラミングからMicroPythonへの移行は、ブロックでセンサーを読めるようになると一気に楽になります。ブロックでセンサーを読むとは、コードを打たずに値を取り出すことです。「A0をアナログ読み取り」ブロックがLDRから明るさを取得し、「シリアル出力」ブロックがその数値をパソコンのシリアルモニタに送ります。この記事ではまず、LDRとHC-SR04のプロジェクトを使ってArduinoでブロックによるセンサー読み取りを行い、各ブロックを対応するanalogRead()、Serial.begin()、Serial.println()、pulseIn()の行と見比べます。そのあとRaspberry Pi PicoでブロックからMicroPythonへの一歩を踏み出し、同じブロックがPythonのコードになると何が変わるのかを見ていきます。

この記事は「ブロックからコードへ」シリーズの第5回です。前回はループと変数をブロックとC++で比べました。次回の最終回は教師向け:ブロックプログラミングで教えるロボットプログラミングの授業計画です。

これまでのシリーズのプログラムは、どれも外の世界に何かを起こすものでした。LEDを点け、ボタンを調べ、ループでカウンターを作りました。センサーの読み取りはその逆向きの働きです。ボードが外の世界を測り、その数値を見ることになります。そのため今回はシリアルポートも登場します。センサーが何を測っているのかを理解するいちばん簡単な方法は、その値を画面で見ることだからです。後半のRaspberry Pi Picoのブロックプログラミングプロジェクトでは、ブロックがC++ではなくMicroPythonに対応します。ここで使うプロジェクトはすべてBlueGraysで無料で、以下に引用するコードはプロジェクトのコードそのままです。

センサーを読むとは:デジタル入力とアナログ入力

ボタンが伝えるのは、押されているか押されていないかの2つの状態だけです。これはデジタルピンを読むブロック(digitalRead)で読み、結果は0か1になります。一方、LDR、ポテンショメーター、土壌水分センサーのような部品は、その間のあらゆる値を返します。ピンの電圧が0〜5 Vの間でなめらかに変化するのです。この電圧を数値に変える回路がADC(アナログ-デジタル変換器)です。Arduino UnoのADCは10ビットなので、電圧を1024段階に分けて0〜1023の数値を返します。1段階は約4.9 mVです。ESP32とPicoのADCは12ビットで、3.3 Vで動作します。このボードごとの違いは、ブロックからコードへ移るときに最も混乱しやすい点のひとつです。詳しくはADCとは?の記事を参照してください。

ボードADC値の範囲基準電圧コード
Arduino Uno10ビット0〜10235 VanalogRead(A0)
ESP3212ビット0〜4095約3.3 VanalogRead(34)
Raspberry Pi Pico12ビット(read_u16で16ビットに換算)0〜655353.3 VADC(26).read_u16()

ArduinoでLDRをブロックで読む

最初の例はLDRで光の強さを測定プロジェクトです。LDRは明るくなるほど抵抗値が下がる抵抗で、それ自体は電圧を生み出しません。測るには、固定の10 kΩ抵抗と直列につないで分圧回路を作り、その中点をA0につなぎます。下の配線ではLDRが5V側にあるので、明るいほどA0の電圧が上がり、読み取り値も大きくなります。LDRと抵抗を入れ替えると向きが逆になります。LDRの値ごとの分圧出力は分圧計算ツールで求められます。暗いところと明るいところでLDRが何オームになるかはLDR光センサーの記事で確認できます。表のPicoの列は、最後のほうのMicroPythonの例で使います。

接続Arduino UnoRaspberry Pi Pico
LDRの足15V3V3(OUT)、物理ピン36
LDRの足2+10 kΩの片端(中点)A0GP26 / ADC0、物理ピン31
10 kΩのもう一方の端GNDGND、物理ピン38(またはAGND、ピン33)
読み取り範囲0〜10230〜65535
「LDRで光の強さを測定」プロジェクトのブロック
「LDRで光の強さを測定」プロジェクトのブロック:valueは「グローバル変数(最初に宣言)」で宣言され、「セットアップ(1回だけ実行)」がシリアルポートを開始し、「ずっと繰り返す」が500 msごとにA0を読んで表示します。

ブロックは上から下へ読みます。グローバル変数(最初に宣言)の中にある「宣言:整数(int)value = 0」ブロックが、コードの先頭のint value;の行です。セットアップ(1回だけ実行)の部分にはブロックが1つだけあり、「シリアル通信を9600ボーで開始」がSerial.begin(9600);です。ずっと繰り返すの中では、まず「valueに(A0をアナログ読み取り)を代入」が来ます。これがvalue = analogRead(A0);の行です。続いて「シリアル出力」ブロックが2つあります。1つ目は「Value:」という文字を改行なしオプションで表示してSerial.print();になり、2つ目はvalueを改行ありオプションで表示してSerial.println()になります。こうすると、測定値が1回ごとに「Value: 512」のような1行で表示されます。最後のブロック「500 ms待つ」はdelay(500);なので、1秒に2回読み取ります。読み取り値を電圧に直すにはvalue × 5.0 / 1023を使います。512ならおよそ2.5 Vです。暗い部屋では値が数百まで下がり、LDRに懐中電灯を当てると900を超えます。正確な数値はLDRと部屋の明るさによって変わります。

C++ (Arduino IDE)
1int value;   // Işık değeri / Light reading (0-1023)
2
3void setup() {
4  Serial.begin(9600);   // Seri port 9600 baud / Serial at 9600 baud
5}
6
7void loop() {
8  value = analogRead(A0);   // LDR gerilimini oku / Read the LDR voltage
9  Serial.print("Value: ");
10  Serial.println(value);
11  delay(500);               // 0,5 sn bekle / Wait 0.5 s
12}

シリアルモニタを開いて値を見る

  1. コードをArduino IDEに貼り付け、ボードとポートを選んでから「書き込み」をクリックします。
  2. 書き込みが終わったら、右上の虫眼鏡アイコンをクリックするか、「ツール」>「シリアルモニタ」を開きます(ショートカットはCtrl+Shift+M)。
  3. シリアルモニタのボーレート欄をコードの値に合わせます。このプロジェクトでは9600ボーです。
  4. 0.5秒ごとに「Value: …」の行が流れます。LDRを手で覆って、数値が下がるのを確かめてください。
  5. 変化をグラフで見たいときは「ツール」>「シリアルプロッタ」を開きます。同じデータが時間軸に沿って描かれます。
  6. 改行コードの設定や、シリアルモニタからボードへデータを送る方法はArduinoのシリアルモニタの記事で詳しく説明しています。
シリアルモニタに文字化けが表示されるときは、ボーレートがコードと合っていません。プログラムに「シリアル通信を9600ボーで開始」ブロックがあるなら、モニタも9600にする必要があります。すべての数値が1行につながって表示されるときは、最後の「シリアル出力」ブロックが改行ありではなく改行なしになっています。コードでいえば、printlnではなくprintになっている状態です。

HC-SR04で距離を測る:µs単位の待ち時間とパルス幅のブロック

「HC-SR04で距離を測定(シリアルモニタ表示)」プロジェクトのブロック
「HC-SR04で距離を測定(シリアルモニタ表示)」:trigPinに10 µsのパルスを送り、echoPinのパルス幅に0.034を掛けて2で割り、3〜100 cmの範囲なら距離を表示します。

2つ目のセンサープロジェクトはHC-SR04で距離を測定(シリアルモニタ表示)です。ここでは新しいブロックが2つ加わります。「ピンtrigPinにHIGHを書き込む」で始まる3つのブロックは、センサーに音のパルスを出すよう指示します。真ん中の「10 µs待つ」ブロックはdelayMicroseconds(10);で、「… ms待つ」より1000倍短い待ち時間です。次の「durationに(ピンechoPinのHIGHパルス幅(µs))を代入」は、unsigned long duration = pulseIn(echoPin, HIGH);の行で、EchoピンがHIGHのままでいる時間を何マイクロ秒か測ります。音は空気中を約0.034 cm/µsで進み、この時間は往復分です。そこで「totalPathにduration × 0.034を代入」が往復の道のりを、「distanceにtotalPath ÷ 2を代入」が片道の距離を計算します。たとえば1000 µsのパルスなら道のりは34 cmなので、物体までの距離は17 cmです。distanceはintなので小数点以下は切り捨てられます。最後に「もしdistance > minDistanceかつdistance < maxDistance」ブロックはif (distance > minDistance && distance < maxDistance)になり、3〜100 cmの読み取り値だけを表示します。センサーにエコーが返ってこないとpulseIn()は0を返しますが、このチェックによってその誤った0も画面に出なくなります。コードではピンはtrigPin = 7、echoPin = 6です。センサーの測定範囲と精度についてはHC-SR04距離センサーの記事を参照してください。

ESP32でも考え方は同じ:12ビットのADC

同じLDRのロジックをESP32で行うのがESP32とLDRモジュールで光の強さを読み取るプロジェクトです。ブロックは引き続きC++に対応し、読み方もArduinoと同じですが、違いが3つあります。1つ目に、setup()でanalogReadResolution(12)によってADCを12ビットに固定するため、analogRead()は0〜1023ではなく0〜4095を返します。そのため「500未満なら暗い」のようなArduino向けのしきい値は、ESP32では同じ意味になりません。2つ目に、シリアルポートは9600ではなく115200ボーで動くので、シリアルモニタも115200に合わせてください。3つ目に、LDRモジュールのAO出力では、明るくなるほど電圧と生の値が下がります。そのためコードではキャリブレーション値RAW_DARK = 4000とRAW_LIGHT = 100を使い、constrain()で読み取り値をその範囲に収め、map()で暗いときを0%、明るいときを100%に変換しています。無印ESP32のDevKitでは、LDRはADC1の入力専用ピンであるGPIO 34につなぎます。Wi-FiがオンのあいだはADC2のピンを読めないため、アナログセンサーをADC1のピンにつなぐ習慣をつけておくと安心です。ボード全般の特徴についてはESP32とは?を参照してください。

Raspberry Pi PicoでブロックからMicroPythonへ

Picoのプロジェクトでは、ブロックがC++ではなくMicroPythonに対応します。ブロックの見た目は見慣れたものですが、その下にある言語は別物です。波かっこもセミコロンもなく、コードのまとまりはインデントで表し、setup()やloop()の関数もありません。いちばん簡単なプロジェクトRaspberry Pi Picoで外付けLEDを点灯(GP14+ブレッドボード)で切り替えてみましょう。回路はとても小さく、GP14(物理ピン19)から220〜330 Ωの抵抗を通ってLEDの長い足へ、LEDの短い足はGND(たとえば物理ピン18)へつなぎます。プログラムはLEDを0.5秒点け、0.5秒消し、そのたびにThonnyのシェル(Shell)に1行表示します。Picoが初めてならRaspberry Pi Picoとは?から始めてください。

「Raspberry Pi Picoで外付けLEDを点灯」プロジェクトのブロック
Raspberry Pi Picoで外付けLEDを点灯(GP14+ブレッドボード):「ピンled:GP LED_PIN、出力」ブロックがピンを準備し、「ずっと繰り返す」の中でLEDが0.5秒点灯、0.5秒消灯します。
MicroPython
1from machine import Pin
2import time
3
4# ============ PIN / PIN ============
5LED_PIN = 14                    # Boştaki herhangi bir GPIO / Any free GPIO
6led = Pin(LED_PIN, Pin.OUT)
7
8print("== BlueGrays: Pico Harici LED Blink ==")
9print("LED pin: GP" + str(LED_PIN))
10print("500ms yakip 500ms sonduruyor / 500ms on 500ms off")
11
12# ============ ANA DÖNGÜ / MAIN LOOP ============
13while True:
14    led.on()                    # LED'i yak / Turn the LED on
15    print("[LED] ACIK / ON")
16    time.sleep(0.5)
17
18    led.off()                   # LED'i söndür / Turn the LED off
19    print("[LED] KAPALI / OFF")
20    time.sleep(0.5)
ブロックMicroPythonメモ
グローバル変数(最初に宣言)→ 宣言:整数(int)LED_PIN = 14LED_PIN = 14Pythonには型名がなく、コードにintという語は出てきません
セットアップ(1回だけ実行)while Trueより前のすべての行setup()は別にありません。ファイルが上から下へ1回実行されます
ピンled:GP LED_PIN、出力led = Pin(LED_PIN, Pin.OUT)Pinはfrom machine import Pinの行から来ています
シリアル出力 “…” 改行ありprint("…")print()は常に改行を付けます
テキストを結合 “LED pin: GP” LED_PIN"LED pin: GP" + str(LED_PIN)数値はstr()で文字列にしないと文字列に足せません
ずっと繰り返すwhile True:中の行はスペース4つ分インデントします
ピンledをオンにする(on)led.on()ピンを3.3 Vにし、LEDが点きます
0.5秒待つtime.sleep(0.5)時間の単位は秒です。500 ms = 0.5
ピンledをオフにする(off)led.off()ピンを0 Vにし、LEDが消えます

この表からは4つのことがわかります。1つ目に、from machine import Pinとimport timeの行には対応するブロックがありません。Pythonでは必要なモジュールを先頭でインポートしますが、ブロックはそれを前提にしてくれています。2つ目に、Arduinoの「シリアル通信を9600ボーで開始」ブロックに当たるものはここにはありません。Picoではprint()の出力がUSB経由でそのままThonnyのシェルに届き、ボーレートを設定する必要がありません。3つ目に、待ち時間の単位が変わっています。Arduinoの「500 ms待つ」はdelay(500)ですが、Picoの「0.5秒待つ」はtime.sleep(0.5)です。4つ目が最も大切なインデントです。「ずっと繰り返す」ブロックの中にあるブロックはすべて、while True:の行の下にスペース4つ分下げて書かれます。ある行のインデントを消すと、その行はループから外れます。Pythonでは、C++の波かっこが担う役割をスペースが果たしているのです。MicroPythonのほかの基本ルールはMicroPythonの基本の記事にまとめています。

同じ処理を3つの言語で:ブロック、C++、MicroPython

処理ブロックArduino C++MicroPython(Pico)
1回だけ実行セットアップ(1回だけ実行)void setup() { … }while Trueより前の行
ずっと繰り返すずっと繰り返すvoid loop() { … }while True:(インデントする)
変数宣言:整数(int)LED_PIN = 14int LED_PIN = 14;LED_PIN = 14
出力ピンピン…を出力に設定 / ピンled:GP LED_PIN、出力pinMode(14, OUTPUT);led = Pin(14, Pin.OUT)
LEDを点けるピン…にHIGHを書き込む / ピンledをオンにする(on)digitalWrite(14, HIGH);led.on()
待つ500 ms待つ / 0.5秒待つdelay(500);time.sleep(0.5)
短い待ち時間10 µs待つdelayMicroseconds(10);time.sleep_us(10)
アナログ読み取りA0をアナログ読み取りanalogRead(A0) → 0〜1023ADC(26).read_u16() → 0〜65535
シリアル開始シリアル通信を9600ボーで開始Serial.begin(9600);不要
改行付きで表示シリアル出力 … 改行ありSerial.println(x);print(x)
同じ行に表示シリアル出力 … 改行なしSerial.print(x);print(x, end="")
文字列の結合テキストを結合Serial.print()を2回に分けて呼ぶ"LED pin: GP" + str(x)

自分で試す例:PicoのMicroPythonでLDRを読む

では、ArduinoのLDRプロジェクトをPicoに移してみましょう。配線は上の表のPicoの列のとおりです。LDRの片方の足を3V3(OUT)ピンに、もう片方の足をGP26と10 kΩ抵抗の片端の両方に、抵抗のもう一方の端をGNDにつなぎます。Picoにはアナログ値を読めるピンがGP26(ADC0)、GP27(ADC1)、GP28(ADC2)の3本あります。MicroPythonではADC(26)オブジェクトを作り、read_u16()を呼び出します。PicoのADCはハードウェアとしては12ビットですが、この関数は結果を0〜65535に換算して返します。電圧を求めるには、値に3.3を掛けて65535で割ります。プログラムの流れはArduino版と同じで、測る、表示する、0.5秒待つ、の繰り返しです。それに加えてしきい値を設け、部屋が暗くなるとボード上のLEDが点くようにしました。ブロックで考えると、while Trueより前の行が「セットアップ(1回だけ実行)」の部分、while True:が「ずっと繰り返す」、if/elseはシリーズ第3回で扱った「もし」ブロック、led.on()は「ピンledをオンにする(on)」、time.sleep(0.5)は「0.5秒待つ」、print()の中の+ str()は「テキストを結合」ブロックに当たります。ADC(26).read_u16()の行は、Arduinoの「A0をアナログ読み取り」ブロックの役割を果たします。THRESHOLDは、自分の部屋でシェルに表示される数値に合わせて調整してください。

MicroPython
1from machine import Pin, ADC
2import time
3
4# ============ PIN / PIN ============
5ldr = ADC(26)                   # GP26 = ADC0, bölücünün orta noktası / divider midpoint
6led = Pin(25, Pin.OUT)          # Dahili LED; Pico W'de Pin("LED") / Onboard LED; Pico W: Pin("LED")
7THRESHOLD = 20000               # Karanlık eşiği, odana göre ayarla / Darkness threshold, tune for your room
8
9print("== BlueGrays: Pico LDR ==")
10
11# ============ ANA DÖNGÜ / MAIN LOOP ============
12while True:
13    value = ldr.read_u16()                      # 0-65535
14    voltage = value * 3.3 / 65535               # Volt / Volts
15    print("Value: " + str(value) + "  Voltage: " + str(round(voltage, 2)) + " V")
16
17    if value < THRESHOLD:                       # Az ışık = küçük değer / Little light = small value
18        led.on()
19    else:
20        led.off()
21
22    time.sleep(0.5)                             # 0,5 sn = 500 ms / 0.5 s = 500 ms

Thonnyとmain.pyでPicoに書き込む

  1. パソコンにThonnyをインストールします。PicoにまだMicroPythonが入っていない場合は、BOOTSELボタンを押したままUSBケーブルを差し込みます。初回接続時にThonnyがMicroPythonのインストールを提案してくれます。
  2. Thonnyの右下で、インタープリターとしてMicroPython (Raspberry Pi Pico)を選びます。下のシェルに>>>のプロンプトが表示されれば接続できています。
  3. BlueGraysでプロジェクトのコードをコピーし、Thonnyのエディターに貼り付けます。
  4. 緑の実行(Run)ボタンをクリックするか、F5キーを押します。コードがPico上で動き、print()の出力がシェルに表示されます。止めるときは停止(Stop)ボタン(Ctrl+F2)を使います。
  5. パソコンなしでコードを動かしたい場合は、「ファイル」>「名前を付けて保存」を選び、ダイアログでRaspberry Pi Picoを選んでファイル名をmain.pyにします。Picoは電源が入るたびにこのファイルを自動で実行するので、USB充電器かモバイルバッテリーがあれば十分です。
  6. Thonnyがボードを認識しないときは、Raspberry Pi Picoが認識されないときの記事の順番でケーブルとドライバを確認してください。

そのほかの無料のPicoブロックプロジェクト

  • Raspberry Pi Picoの内蔵LEDを点滅(PicoとPico W):配線はまったく不要で、LED_PIN = 25(GP25)でボード上のLEDを点滅させます。コードは上のプロジェクトとほぼ同じなので、2つを並べて開くと、変わるのはピン番号だけだとわかります。Pico Wではボード上のLEDがWi-Fiチップにつながっているため、Pin("LED")を使います。
  • Raspberry Pi Picoで2個のLEDを交互に点滅(GP14+GP13):led1.value(1)とled2.value(0)で逆の状態から始め、ループの中で両方のLEDに対してtoggle()を呼びます。コードがfrom time import sleepと書いているので、待ち時間はtime.sleep(0.5)ではなくsleep(0.5)として出てきます。
  • Raspberry Pi Picoで信号機(3個のLEDを順に点灯、GP11/GP12/GP13):all_off()という関数がすべてのLEDを消します。青(緑のLED)が4秒、黄が1.5秒、赤が3秒点き、そのあと1秒間の赤+黄の発進前フェーズが続きます(日本の信号機にはないフェーズです)。
  • Raspberry Pi Picoでパトカーの点滅灯(赤+青、GP11+GP12):今回はWAIT_MS = 300として、sleep_ms(WAIT_MS)でミリ秒単位で待ちます。秒とミリ秒の関数を2つのプロジェクトで見比べることが、下にある最もよくある間違いを避けるいちばんの方法です。

よくある間違いと直し方

間違い症状対処
time.sleep(500)と書くLEDが点いたまま8分以上変わらないMicroPythonでは時間の単位は秒です。time.sleep(0.5)またはtime.sleep_ms(500)と書きます
インデントがずれているIndentationError、またはループ内で実行されない行があるwhile True:の下の行はすべて同じスペース4つで始め、タブとスペースを混ぜない
str()を使わずに数値を文字列に足すエラー:TypeError: can't convert 'int' object to str implicitly(intを暗黙的に文字列に変換できない)"LED pin: GP" + str(LED_PIN)と書きます
PicoのADCピンに5 Vを入れる読み取り値がおかしくなり、壊れてしまうおそれもあるPicoは3.3 Vロジックです。分圧回路は3V3(OUT)ピンから給電します
Arduinoのしきい値をそのままPicoに使う「value < 500」の条件がいつも同じ結果になる範囲を考慮します:Uno 0〜1023、ESP32 0〜4095、Pico read_u16() 0〜65535
シリアルモニタのボーレートが合っていない文字化けモニタをコードの速度(9600または115200)に合わせる
ESP32でADC2のピンを使うWi-Fiをオンにすると読み取れなくなるアナログセンサーはGPIO 32〜39などのADC1ピンにつなぐ
ファイルをmain.pyとして保存していないThonnyからは動くが、USBを抜くと動かないファイルをmain.pyとしてPicoに保存する

BlueGraysアプリでブロックを続けよう

この記事のプロジェクトはすべてBlueGraysアプリで無料です。プロジェクトのコード欄で「ブロックで表示」スイッチをオンにすると、コードが同じプログラムのブロックに置き換わります。画像をタップすると全画面で開きます。「ブロック解説」タブではプログラムをステップごとにたどり、各ステップのブロックとその働きだけを表示します。HC-SR04のプロジェクトでパルス幅のブロックが正確に何を測っているのか、Picoのプロジェクトでなぜsetupの部分がwhile Trueより前に来るのかも、そこで確認できます。「コードガイド」にあるArduinoとMicroPythonのコマンド例も、すべてブロックで表示されます。学んだことを試すなら、「今日のクイズ」でA1〜C2レベルの問題が1日5問出題され、週間ランキングとバッジもあります。なお、ブロックがボードに直接書き込まれることはありません。ボードに入るのは常にプロジェクトの実際のコードで、ArduinoとESP32ならArduino IDEに、PicoならThonnyにコピーして使います。プロジェクト一覧では「ブロック」バッジの付いたプロジェクトで絞り込めます。Arduino、ESP32、Picoのブロックプロジェクトはすべてブロックプログラミングのページで見られます。

シリアルポートとセンサーの読み取りを身につけたので、これでプロジェクトの基本的な部分をすべて、ブロックとしてもコードとしても読めるようになりました。シリーズの最終回では、これらのステップを教室に持ち込みます:教師向け:ブロックプログラミングで教えるロボットプログラミングの授業計画。それまでは、BlueGraysアプリでLDR、HC-SR04、PicoのLEDプロジェクトの回路図とコードをステップごとに見ていき、「ブロックで表示」で同じプログラムのブロック版に切り替え、「ブロック解説」で各ステップの働きをたどってみてください。

よくある質問

ブロックプログラミングからMicroPythonへはどう移行すればいいですか?

いちばん簡単なのは、プログラムのブロックとMicroPythonのコードを並べて見ることです。「ずっと繰り返す」がwhile True:、「ピンledをオンにする(on)」がled.on()、「0.5秒待つ」がtime.sleep(0.5)であることをいくつかのプロジェクトで確かめると、ブロックなしでもコードが読めるようになります。次に、待ち時間やピン番号のような小さな変更を加えて、自分でコードを編集してみましょう。

Raspberry Pi Picoはブロックプログラミングでプログラムできますか?

BlueGraysでは10個のPicoプロジェクトにブロック版があり、そのブロックはMicroPythonのコードと1対1で対応しています。そのうち5個は完全に無料です。ボードに入るのはブロックではなく、プロジェクトのMicroPythonコードです。それをThonnyに貼り付けて実行します。こうしてブロックでロジックを理解し、実際のコードでボードをプログラムできます。

ArduinoのanalogReadはなぜ0〜1023の値を返すのですか?

Arduino UnoのADCは10ビットで、0〜5 Vの範囲を1024段階に分けます。0 Vは0、5 Vは1023として読まれ、1段階は約4.9 mVです。読み取り値を電圧に直すにはvalue × 5.0 / 1023を使います。

Raspberry Pi Picoのread_u16はなぜ65535まであるのですか?

PicoのADCはハードウェアとしては12ビットですが、MicroPythonのread_u16()は、ボードが違っても範囲がそろうように結果を16ビットに換算します。そのため0 Vは0、3.3 Vは約65535として読まれます。Arduinoから持ってきたしきい値は、この範囲に合わせて計算し直す必要があります。

MicroPythonのtime.sleepの単位は秒ですか、ミリ秒ですか?

time.sleep()の単位は秒で、time.sleep(0.5)は0.5秒待ちます。ミリ秒ならtime.sleep_ms(500)、マイクロ秒ならtime.sleep_us(10)を使います。Arduinoのdelay(500)と混同してtime.sleep(500)と書くと、プログラムは8分以上待つことになります。

ThonnyのコードをPicoでずっと動かすにはどうすればいいですか?

「ファイル」>「名前を付けて保存」で、コードをmain.pyとしてRaspberry Pi Picoに保存します。Picoは電源が入るたびにmain.pyを自動で実行するので、パソコンは不要です。実行ボタンを押すだけではコードはPicoに保存されず、再起動すると動きません。

全プロジェクトを見る
LDRで光の強さを測定
#11初級

LDRで光の強さを測定

部屋の明るさを数値で見てみませんか?光に反応する小さな部品、LDRで周囲の光を測定し、Arduinoが0.5秒ごとにその値をコンピューターの画面に表示します。手で覆うと数値が変わる様子を確認できます。自動で点灯する常夜灯などのプロジェクトへの第一歩です。

4.6(81)
139
HC-SR04で距離を測定(シリアルモニタ表示)
#27初級

HC-SR04で距離を測定(シリアルモニタ表示)

HC-SR04センサーは、コウモリが暗闇で道を見つけるのと同じ仕組みで動作します。人には聞こえない音を出し、その反響を捉えて前方の物体までの距離を測ります。Arduinoは0.5秒ごとに距離をセンチメートル単位でコンピューターの画面に表示し、3〜100センチメートルの測定値を示します。駐車センサーや障害物を避けるロボットなどのプロジェクトの基礎になります。

4.6(46)
71
ESP32とLDRモジュールで光の強さを読み取る
#113初級

ESP32とLDRモジュールで光の強さを読み取る

LDRモジュールの生のADC値と、暗い状態・明るい状態の基準値から計算した相対的な明るさの割合を、シリアルモニタでリアルタイムに確認します。この割合はルクスの測定値ではありません。モジュールの校正の仕組みを学べます。しきい値の決定に使うため、プロジェクト10の前に取り組むのが適しています。

4.6(36)
55
Raspberry Pi Picoで外付けLEDを点灯(ブレッドボード)
#148初級

Raspberry Pi Picoで外付けLEDを点灯(ブレッドボード)

Picoの内蔵LEDの次は、ブレッドボードに外付けLEDを接続し、GP14ピンで制御します。このプロジェクトでは、Picoの汎用GPIOピンを出力として使う方法、LEDの極性(長い足=アノード/+、短い足=カソード/−)、電流制限抵抗(220Ω)が必要な理由を学びます。抵抗を入れないと、LEDに過大な電流が流れて壊れることがあります。回路はとても簡単です。Pico GP14 → 220Ω抵抗 → LED(+)→ LED(−)→ Pico GND。Wokwiでシミュレーションできます。

4.5(2)
7
Raspberry Pi Picoの内蔵LEDを点滅(PicoとPico W)
#147初級

Raspberry Pi Picoの内蔵LEDを点滅(PicoとPico W)

Raspberry Pi Picoシリーズの最初のプロジェクトです!ボード上の緑色LEDを点滅させて動作を確認する、定番の「Hello World」に相当する実験です。外付け部品は不要で、PicoとUSBケーブルだけで始められます。コードはMicroPython(Raspberry Pi Foundationが公式にサポートする言語)で書きます。Thonny IDEでmachine.Pinクラス、Pin.OUTモード、led.on()/off()メソッド、time.sleep()を学びます。シリアル(REPL)出力で、切り替わる様子をリアルタイムに確認できます。

5.0(1)
10
Raspberry Pi Picoで2個のLEDを交互に点滅
#149初級

Raspberry Pi Picoで2個のLEDを交互に点滅

PicoでLEDを1個点滅させた次は、2個のLEDを交互に点滅させる定番のフリップフロップパターンです。一方が消えるともう一方が点灯する、複数のGPIOを連動させる最も基本的な例です。このプロジェクトでは、色の異なる2個のLED(GP14に赤、GP13に緑)が500msごとに点灯状態を入れ替えます。MicroPythonのPin.toggle()メソッドを使うと、コードを短く読みやすくできます。同じ基本的な仕組みが、信号機、パトカーの点滅灯、流れるLEDなど、複数のLEDを使ったアニメーションの基礎になります。回路はとても簡単で、各LEDに220Ωの抵抗を使います。

5.0(2)
19
Raspberry Pi Picoで信号機(3個のLEDを順に点灯)
#150初級

Raspberry Pi Picoで信号機(3個のLEDを順に点灯)

赤・黄・緑のLEDで本物の信号機を再現する、Picoシリーズ初の3個のLEDを使うプロジェクトです!緑が4秒間「進め」、黄が1.5秒間「準備」、赤が3秒間「止まれ」、赤と黄が1秒間「発進準備」を示します(ヨーロッパの信号機のパターン)。関数の定義(def all_off())、状態機械の仕組み(順序)、複数のGPIOの同期を学びます。回路はとても簡単です。GP11(緑)、GP12(黄)、GP13(赤)に3個のLEDを接続し、それぞれに220Ωの電流制限抵抗を使います。

4.0(1)
12
Raspberry Pi Picoでパトカーの点滅灯(赤+青)
#151初級

Raspberry Pi Picoでパトカーの点滅灯(赤+青)

Raspberry Pi Picoで、パトカーの屋根にある点滅灯を最も簡単な形で再現します!赤と青のLEDが交互に点灯するフリップフロップ方式です。赤が点灯している間は青が消灯し、0.3秒ごとに状態を入れ替え、繰り返します。コードは1つのwhile Trueループに2つの動作を直接記述し、速度はWAIT_MS定数で設定します。

4.7(3)
10