「Raspberry Pi Pico」でデバッグ作業を行うには「デバッグプローブ」が必要ですが、「Pico」をデバッグプローブとして、他の「Picoシリーズ」をデバッグできるようなので試してみました。
「Pico」の基本的な使用方法やプログラム、「ArduinoIDE」を使用した開発環境の準備等は以下のリンクで詳しく紹介しています。
「Pico2」の基本仕様、使い方については「MicroPython」での使用方法を紹介した記事の以下のリンクで詳しく紹介しています。
1.デバッグとは
2.「Picoprobe」とは
3.「Picoprobe」の作り方
・ファームウェアのダウンロード
・ファームウェアの書き込み
・「Picoprobe」の配線図
・デバッグ対象のPicoとの接続、配線図
4.「ArduinoIDE」でのデバッグ方法
・デバッグ用サンプルプログラムの準備
・初期設定
・デバッグの実行
・シリアル通信の確認
・ブレークポイントの設定
・変数の値確認
・1行づつ実行
・プログラムの変更、再デバッグ
5.「Pico」本体の初期化方法
6.まとめ
1.デバッグとは
「デバッグ」とは、英語で「debug」と書かれ、「de(取り除く)」と「bug(バグ:虫や欠陥)」を組み合わせたものに由来し、「バグ」を取り除く作業のことを言います。
「デバッグ」は、以下のような手順で行います:
- ブレークポイントの設定:プログラムの特定の行で実行を一時停止させ、変数の値やプログラムの状態を確認します。
- ステップ実行:プログラムを一行ずつ実行し、どの部分で問題が発生しているかを特定します。
- 変数の監視:プログラムの実行中に変数の値を監視し、期待通りの値になっているかを確認します。
「Pico」のような「マイコン(マイクロコントローラー)」のデバッグを行うには、専用の「デバッグ環境」と「マイコン」と接続する「デバッグプローブ」が必要です。
2.「Picoprobe」とは
「Picoprobe」とは「Raspberry Pi Pico」に専用のファームウェアを書き込んで「デバッグプローブ」として使用できるようにしたものです。
「Pico」に数本の配線を接続するだけのため、比較的安価に製作することができ、互換品でも製作可能です。
専用のファームウェアは公式HPで紹介されており、GitHubからダウンロードすることができるため、以下から「Picoprobe」の作り方を詳しく紹介していきます。
3.「Picoprobe」の作り方
「Ricoprobe」は「Raspberry Pi Pico」があれば簡単に製作することができます。
製作手順から、デバッグ対象との接続方法まで、以下から配線図も交えて詳しく紹介していきます。
・ファームウェアのダウンロード
まずは以下のリンクをクリックしてRaspberry Piの公式ページへアクセスします。
以下のようなページが表示されたら矢印部の「GitHub」へのリンクをクリックします。
下画像のようなページが表示されたら[debugprobe_on_pico.uf2]をクリックしてファームウェアをダウンロードします。
ファイルは「ダウンロードフォルダ」に保存されています。
下画像のように、ブラウザの右上(Edgeの場合)にダウンロード結果が表示されたら[フォルダーに表示]アイコンをクリックすると、保存先の「ダウンロードフォルダ」が表示されます。
・ファームウェアの書き込み
次にダウンロードしたファームウェアを書き込みます。
下画像矢印部の「Pico」本体基板上の「BOOTSEL」ボタンを押しながら、USBケーブルでパソコンと接続します。
下画像のように、パソコンに認識された「RPI-RP2」フォルダ内に、ダウンロードしたファームウェア「debugprobe_on_pico.uf2」をドラッグアンドドロップで書き込みます。
「debugprobe_on_pico.uf2」を「RPI-RP2」へドラッグアンドドロップします。
「RPI-RP2」フォルダが自動で閉じて、パソコン側で認識されなくなれば書き込み完了です。
以上で「Pico」が「Picoprobe」として使用できるようになりました。
・「Picoprobe」の配線図
デバッグプローブ専用のファームウェアを書き込んだ「Pico」に、下画像のように配線を接続したら「Picoprobe」の完成です。
デバッグ作業を行うには、この「Picoprobe」をパソコンとUSBケーブルで接続しておき、デバッグ対象の「Pico/PicoW/Pico2」の「DEBUG端子」に「GND、SWDIO、SWCLK」の3本を接続することでデバッグを行うことができます。
「TXD、RXD」の2本はシリアル出力確認用のため、シリアル出力を使用しない場合は接続しなくてもデバッグはできます。
「VBUS、GND」の2本はデバッグ対象への電源供給用です。
デバッグ対象が既にバッテリー等で電源供給されていれば、この接続は不要です。
・デバッグ対象のPicoとの接続、配線図
「Picoprobe」とデバッグ対象の「Pico等」の接続は下画像のようになります。
実際にブレッドボードを使用して「Picoprobe」と「Pico2」を接続したものは下画像のようになります。画像右が「Picoprobe」で左がデバッグ対象の「Pico2」です。
デバッグ対象の「Pico2」の[DEBUG]端子にはピンヘッダーを実装しても良いですが、デバッグ終了後は使わなくなり、ピンが飛び出ているとショート等で破損の心配があるので、私は下写真のように「テストクリップ」を使用しています。
上画像はブレッドボードに差し込めるオスピン付のテストクリップです。
デバッグ対象の「Pico2」の[DEBUG]端子にはピンヘッダーを実装せず、基板のスルーホールにテストクリップを引っ掛けます。
上画像のようにテストクリップの爪は引っ掛けられるようになっているため、配線図を確認して各端子に接続します。
基板のスルーホールにしっかりと引っ掛かっているので引っ張っても外れることはありません。
上の配線図ではデバッグ対象への電源供給は「Picoprobe」から行い、デバッグ対象のシリアル通信「Serial1」の確認を行う場合の接続となります。
「Raspberry Pi Pico」のシリアル通信については、以下のリンクで詳しく紹介しています。
4.「ArduinoIDE」でのデバッグ方法
製作した「Picoprobe」を使用して「ArduinoIDE」でデバッグを行う方法を、デバッグ用「サンプルプログラム」を使用して詳しく紹介します。
「Raspberry Pi Pico」のための「ArduinoIDE」の使い方は以下のリンクで詳しく紹介しています。
・デバッグ用サンプルプログラムの準備
まずは「ArduinoIDE」を起動して、下画像のように「新規スケッチ」を開きます。
下画像のように「新規スケッチ」が開いたら、この下の「サンプルプログラム」を「コピペ」で貼り付けます。
サンプルプログラムは以下になります。
コピーは下の黒塗り部右上のアイコンクリックでもできます。
unsigned long beforTime = 0; // 前回の時間(ms)保持用
const long interval = 500; // LED点滅インターバル時間間隔 (ms)
int ledState = LOW; // LED状態保持用
// 初期設定 -------------------------------------------------------
void setup() {
Serial1.begin(9600); // デバッグ用シリアル出力1初期化
pinMode(LED_BUILTIN, OUTPUT); // LED端子を出力に設定
}
// メイン処理(繰り返し) ------------------------------------------
void loop() {
unsigned long nowTime = millis(); // 経過時間を現在時間として取得(ms)
if (nowTime - beforTime >= interval) { // 前回時間から現在時間がインターバル時間経過していたら
beforTime = nowTime; // 前回時間を現在時間で更新
if (ledState == LOW) { // LEDが消灯していれば
ledState = HIGH; // LED状態を点灯へ
Serial1.println("LED ON!"); // デバッガーへシリアル出力
} else { // LEDが点灯していれば
ledState = LOW; // LED状態を消灯へ
Serial1.println("LED OFF!"); // デバッガーへシリアル出力
}
}
digitalWrite(LED_BUILTIN, ledState); // LED出力処理実行
}
下画像のように「サンプルプログラム」を貼り付けたら準備完了です。
・初期設定
次に初期設定として「デバッグ対象の機種選択」、「ポート設定」、「使用するデバッグプローブの選択」を行います。
デバッグ対象の機種選択
まずは下画像のように[ツール]→[ボード:(ここは環境によって異なります)]→[Raspberry Pi Pico/RP2040/RP2350]→[Raspberry Pi Pico 2]を選択します。
ポート設定
続けて「通信ポート」の設定を行います。
下画像のように「Picoprobe」を接続した「通信ポート」を[ツール]→[ポート:(ここは環境によって異なります)]→[COM9(数字は環境によって異なります)]のように選択します。
通信ポートが複数表示されている場合は以下のように[ウインドウズアイコン]を右クリックして表示されるメニューから[デバイスマネージャ]をクリックします。
以下のようなウインドウが表示されたら[ポート(COMとLPT)]部の[ ∨ ]をクリックして展開すると認識されている「COM番号」が表示されます。
「Picoprobe」のUSBケーブルを抜き差しすることで「非表示/表示」となる「COM番号」が「Picoprobe」の「COM番号」です。
ポートが正しく認識されると下画像のように「ArduinoIDE」の画面右下に選択した「COM番号」が表示されます。
ポート選択前
ポート選択後
使用するデバッグプローブの選択
次に使用するデバッグプローブを選択します。
下画像のように[ツール]→[Upload Method:(ここは環境によって異なります)]→[Picoprobe/Debugprobe(CMSIS-DAP)]を選択します。
以上で初期設定は完了です。
・デバッグの実行
初期設定が完了したら、デバッグを実行してみましょう。
デバッグ前にはプログラムの「検証(コンパイル)」を行う必要があります。
下画像のように[検証]アイコンをクリックしましょう。
スケッチのコンパイルが終了したら、下画像のように[デバッグの開始]アイコンをクリックします。
プログラムの書き込みが実行され、下画像のようなデバッグ画面が表示されデバッグが開始されます。
デバッグが開始されるとデバッグ対象の基板上のLEDが下画像のように点滅するのが確認できると思います。
・シリアル通信の確認
デバッグが開始されたら、シリアル通信の出力を確認する「シリアルモニタ」を起動します。
下画像右上の[シリアルモニタ]アイコンをクリックします。
通信速度は[9600 baud]に設定しておきます。
上画像下の[シリアルモニタ部]に「LED ON!/LED OFF!」が繰り返し表示され、プログラムが実行されているのが確認できると思います。
・ブレークポイントの設定
プログラムが実行されているのが確認できたら「ブレークポイント」を設定します。
下画像のようにプログラム内の「16行目」の矢印部をクリックすると「赤丸」が表示されて「ブレークポイント」が設定されます。
「ブレークポイント」が設定されると、設定した行がハイライトされてデバッグが停止します。
「シリアルモニタ」の更新が停止し、基板本体のLEDの点滅も停止します。
デバッグを再開するには下画像矢印部の[続行]アイコンをクリックします。
[続行]アイコンをクリックするごとに「ブレークポイント」までの処理が繰り返され、本体LEDは点灯または消灯し「シリアルモニタ」の表示が更新されます。
・変数の値確認
「ブレークポイント」でデバッグを中断した時点での変数の値を確認してみましょう。
デバッグ画面左の[変数]部を展開すると「Local/Global/Static」変数の値や「Resisters」で各レジスタの状態も確認することができます。
下画像のように「Local」部を展開すると、今回の場合は「Local」変数として「nowTime」の値が一番上に表示されているのが確認できます。(値は実行状況によって異なります。)
次に[ウォッチ式]部で確認したい変数の値だけを確認してみましょう。
下画像のように[ウォッチ式]部を展開すると[+(式の追加)]アイコンがあるのでこれをクリックします。
以下のようなウインドウが表示されたら確認したい変数名、今回は[nowTime]を入力して[OK]ボタンをクリックします。
[ウォッチ式]部に[nowTime:]が表示され、現在の値が確認できます。
同様に[+]アイコンをクリックして[beforTime]と[ledState]の変数も表示して値を確認してみましょう。
・1行づつ実行
デバッグ環境には必ずプログラムを1行づつ実行する機能があります。
この機能を使用して、1行づつ実行しながら変数の値の変化を確認してみましょう。
プログラムを1行づつ実行するには、下画像の矢印部の[ステップイン]アイコンをクリックします。
ブレークポイントに設定した「16行目」では[beforTime]に[nowTime]の値を代入しています。
「ステップイン」が実行されると、「16行目」のプログラムが実行され、ハイライト行が「16行目」から「18行目」し、「beforTime:]の値が「nowTime:」の値に変化するのが確認できます。
再度[ステップイン]アイコンをクリックすると[ledState:]の状態によって「if 文」の分岐処理が実行されます。
さらに[ステップイン]アイコンをクリックすると[ledState:]が、[LOW(0)]なら[HIGH(1)]に、[HIGH(1)]なら[LOW(0)]に変化するプログラムが実行されます。
下画像の場合は[ledState = HIGH]で[HIGH(1)]にするプログラムが実行されます。
下画像の場合は[ledState:]が[HIGH(1)]になり、ハイライト行が「Serial.prinln 〜」の行に移動します。
下画像のようにハイライト行が「Serial.prinln 〜」のような関数の場合は[ステップイン]アイコンをクリックすると関数内の処理が実行されてしまうので、下画像の矢印部の[ステップオーバー]アイコンをクリックしましょう。
「Serial.prinln 〜」関数が実行されると下画像のように「シリアルモニタ」が更新され、「26行目」の「digitalWrite 〜」関数部がハイライトされます。
ここでも関数はスキップしたいので[ステップオーバー]アイコンをクリックしますが・・・
下画像のように「digitalWrite 〜」関数内の処理へ移行しました^^;
ここもスキップされることを期待しましたが、スキップされない場合もあるようです。
さらに[ステップオーバー]アイコンをクリックすると基板上のLEDの状態は変化しますが「while 文」のループが繰り返されます・・・
このような場合は、下画像のように[続行]アイコンをクリックすると「ブレークポイント」まで処理を進めることができるので[続行]アイコンをクリックしましょう。
デバッグ作業では、以上のようにプログラムを1行づつ実行しながら、変数の値ができます。
下画像のように[続行]アイコンをクリックすれば「ブレークポイント」で一時停止するごとに変数の値の変化を確認することもできます。
「ブレークポイント」は行番号の左をクリックするごとに「ON/OFF」を切り替えることができ、複数設定することができます。
・プログラムの変更、再デバッグ
プログラムのエラーを見つけて修正する時には、デバッグを停止させる必要があります。
試しにデバッグを停止して、プログラムを修正後に再度デバッグしてみましょう。
デバッグを停止させるには、下画像のように[停止]アイコンをクリックします。
今回は[interval]変数の設定値を「1000」に変更してみます。
これによりLEDの点滅間隔が「0.5秒」から「1.0秒」に変更されます。
下画像のようにプログラムを修正したら、必ず[検証(コンパイル)]アイコンをクリックします。
「コンパイル」が完了したら下画像のように[デバッグの開始]アイコンをクリックします
デバッグが開始されたら「ブレークポイント」を設定して、各変数の値の変化を確認してみましょう
以上が基本的な「ArduinoIDE」を使用したデバッグの方法です。
他にもいろいろな機能があるようなので、便利な機能があればまた追記したいと思います。
5.「Pico」本体の初期化方法
「Pico」の動作がおかしくなったり、手順を最初からやり直したい等で初期状態に戻したい場合もあると思います。
そんな時のためにラズパイPico本体を初期化する方法も紹介します。(PicoW、Pico2でも同じ)
以下のサイトにアクセスして、本体初期化用のファイルをダウンロードします。
表示されたページのに、下画像矢印部のようなリンクがあるので「UF2 file」をクリックします。
クリックすると「flash_nuke.uf2」というファイルがダウンロードされます。
「Pico」本体の「BOOTSEL」ボタンを押しながらパソコンと接続して認識された「RPI-RP2またはRP2350」フォルダに、このファイルをドラッグ&ドロップするだけで初期化は完了します。
6.まとめ
「Raspberry Pi Pico」をデバッグプローブに設定した「Picoprobe」の製作方法から、「ArduinoIDE」を使用した「デバッグ」方法まで詳しく紹介しました。
「Picoprobe」は「Pico」に専用のファームウェアを書き込むだけで製作でき、公式の「Raspberry Pi Debug Probe」と同じように使用することができます。
「Picoprobe」を使用して「ArduinoIDE」のデバッグ機能を使用することで、「ブレークポイント」の設定や「ステップ実行」を行いながら変数等の変化を簡単に確認できます。
「デバッグ」とはエラーを発見して修正、削除する作業ですが、プログラムがどのように実行されていくかも確認することができるため、プログラミング学習にも良い機能だと思います。
「Pico」をデバッグプローブとして使用できるため、公式のものより安価で製作できます。
メモリ容量が倍になった「Pico2」も発売されて「Pico」が余っているという方も、使わなくなった「Pico」はデバッグプローブとして有効活用しましょう。
コメント