以下Visual Studio Codeを起動します。
はじめてVisual Studio Code を起動した場合、上記の初期画面が表示されますが、既存または新規プロジェクトを過去開き作業をした場合、終了時の編集状態が表示されます。
画面左メニュー上一番上のエクスプローラークリックで、pico-examplesプロジェクトを開きます。PICOインストール先のホルダに”pico-examples"のフォルダが作成されているはずですので、これを選択し、"フォルダー選択"のボタンを押します。
以下、"pico-examples"プロジェクトがオープンされます。
5.1.1.プログラムの確認
プロジェクトは階層構造をとります、プロジェクトフォルダは複数のプロジェクトで構成されており、また、その下位階層各プロジェクトは、さらに複数のプロジェクトに分かれます。
もし、画面下のブルーのバーに”No Kit Selected"が表示されている場合、ここをクリックし、コンパイラを選択します。Kitの一覧が表示されるので"GCC 10.3.1 arm-none-eabi"を選択します。
ここでblinkプロジェクトをクリックします。クリックすると、blinkプロジェクトに必要なファイルが以下表示されます。
blink.c
CMakeLists.txt
blink.cはこのプロジェクトのメインのC言語ソースリストです。この中のmain()関数が、実行時まず呼び出されます。CMakeLists.txtはCMakeがビルドに使用する設定ファイルです。プロジェクトには最低この2つのファイルが必要です。blink.Cをクリックし、ソースリストを開きます。プログラムを確認してみます。
#include "pico/stdlib.h"
int main() {
#ifndef PICO_DEFAULT_LED_PIN
#warning blink example requires a board with a regular LED
#else
const uint LED_PIN = PICO_DEFAULT_LED_PIN;
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
while (true) {
gpio_put(LED_PIN, 1);
sleep_ms(250);
gpio_put(LED_PIN, 0);
sleep_ms(250);
}
#endif
}
他サンプルプログラムでも、#ifndef PICO_DEFAULT_LED_PINの記述が多くありますが、これは、全サンプルプログラムでLEDピンのGPIO番号を共通して定義できるため、使用されています。このGPIO番号は25です。もしプログラムが動作しない場合、PICO_DEFAULT_LED_PINの定義が確実か、または、正しいヘッダーが読み込まれているか確認する必要があります。不明な場合、以下を追加し、LEDピンの定義を確実にしてもいいでしょう。
#define PICO_DEFAULT_LED_PIN 25
プログラムはまず、gpio_init(LED_PIN)でLEDのGPIOピン25を初期化します。次に、gpio_set_dir(LED_PIN, GPIO_OUT)でGPIOピンを出力モードにします。この後While{true}で永久ループに入ります。この{}部分には、ループを続けるための条件式を入力します。この場合trueのため、条件式は常にオンとなり、永久ループとなります。
ループ内では、
gpio_put(LED_PIN, 1)
sleep_ms(250)
と
gpio_put(LED_PIN, 0);
sleep_ms(250);
の各処理があります。前半は、LEDを250msオンし、後半は250msオフします。
GPIOの出力関数gpio_putに出力GPIOピン番号、および値をセットします、値は1でオン、0でオフとなります。sleep_ms関数は指定msec秒待機します。
5.1.2.ビルド
画面下、ブルーのステイタスバーで、ギアマーク横"Build"をクリックします。このとき、この"Build"ボタン横に[all]と表示されていれば、pico-examplesプロジェクト以下の下層のすべてのプロジェクトがビルドされ、かなり時間がかかります。これを避けるためには、
[all]をクリックすると一覧が表示されるので、この一覧から"blink EXECUTABLE"を選択します。完了するとステイタスバーに[blink]と表示されます。
これらの操作は、画面左横のツールバーの"CMake"をクリックし、プロジェクト一覧を表示後、ビルドするプロジェクトを選択し、[elf]をクリック後、横に表示されるビルドアイコンをクリックすることでも可能です。
ビルドを開始します。
ビルド処理中は、画面下、処理出力表示部に結果が出力されます。
…
…
[driver] Build completed: 00:01:11.311
[build] Build finished with exit code 0
Exit code 0 で正常に出力が完了したことが確認できます。
これで、実行ファイルが作成されました。過去に一度ビルドを行い、その後、インクルードファイル、本体ソースファイル等関連するソースファイルが変更されていない場合、ビルドを行っても、実行ファイルは更新されません。ファイル日付は古いままです。
インストール先の”pico-examples>build>blink”のフォルダを開きます。
ビルドされた各種ファイルが確認できます。Picoの実行ファイルは拡張子がuf2のファイルです。blink.uf2が実行ファイルです。他サンプルプロジェクトも同じですが、ビルド結果は”pico-examples"下の各プロジェクトフォルダには作成されません。”pico-examples>build>”の各プロジェクト下に作成されます。
5.1.3.プログラムの書き込みと実行
BOOTSELボタンを先に押したまま、PicoとPCをUSBケーブルTypeA-microBで接続します。ピコという音と共に外部ドライブとして認識されます。
Blink.uf2をコピーします。Uf2ファイル日付が、ビルド実行日付になっていることを確認してください。これはビルドが正常に終了し最新の実行ファイルに更新されたことを意味します。
PicoがRPI-RP2(X:)、マスストレージとして、PCに認識されますが、このストレージドライブに先ほどコピーしたBlink.uf2ファイルを貼り付けます。貼り付けと同時にストレージドライブが解除され、プログラムが実行され、LEDが点滅を開始します。
While以下のソースを以下のように変更してみます。
while (true) {
int interval = 2000;
for(int i = 0; i < 5; i++)
{
int timespan = 0;
while(timespan < 10000)
{
gpio_put(LED_PIN, 1);
sleep_ms(interval);
timespan += interval;
gpio_put(LED_PIN, 0);
sleep_ms(interval);
timespan += interval;
}
interval /= 2;
}
}
この改造されたプログラムではLED点滅が次第に早くなります。5ステップの点滅速度で繰り返されます。各ステップが10秒、計50秒で永久にくりかえします。
5.2.Hello Wordプログラム-標準出力への出力
ここでは次のサンプルプログラムとして"Hollo Word”を取り上げます。Picoインストール先の"pico-examples>hello_world>usb"がプロジェクトフォルダです。さきのblinkプロジェクトと異なり、hello_worldにはプロジェクトが2つあります。usb、およびserialプロジェクトです。usbプロジェクトは標準出力をusb経由でシリアルポートに出力します。
SerialプロジェクトではGPIOピンに設定されたUARTポートに出力します。今回は、ケーブル配線が不要のため、usb経由での標準出力を確認します。
5.2.1. Hello Wordプログラムのビルド
hello_usb.cのソースリストは以下となります。
#include <stdio.h>
#include "pico/stdlib.h"
int main() {
stdio_init_all();
while (true) {
printf("Hello, world!\n");
sleep_ms(500);
}
return 0;
}
<stdio.h>が必要となります。usb経由シリアル出力stdioが定義されています。
Main先頭で、stdioを初期化します。
stdio_init_all();
次のwhileの永久ループで、500msec毎に、標準出力、usb経由シリアルに"Hello world!"を出力します。
先のBlinkプログラム同様に、ビルドします。画面下、ブルーのバーで、ギアマーク横"Build"をクリックします。ビルド完了後の”pico-examples>build>hello_world>usb”のフォルダを開きます。ここにhellow_usb.uf2のファイルが作成されていますので、コピーします。ソースが変更された場合、uf2ファイル日付が、ビルド実行日付になっていることを確認してください。これはビルドが正常に終了し最新の実行ファイルに更新されたことを意味します。特に変更しなければ、過去ビルドの日付になっています。次にPicoからUSBケーブルを抜き、BOOTSELボタンを押しながら、再度ケーブルを差します。最後にBOOTSELボタンをはなします。PicoがRPI-RP2(X:)、マスストレージとして、PCに認識されますので、uf2ファイルをPicoに書き込みます。
これで、hello_worldプログラムは実行されますが、このままでは確認できません。以下のステップで、ターミナルソフトをインストール、実行し、プログラムが正常に動いているか確認します。
5.2.2.WindowsPCへのTeraTermVTインストール
開発に使用している同じPCでターミナルソフトTera Termを起動させます。インストールされていない場合は以下、https://ja.osdn.net/projects/ttssh2/releases/から無料ダウンロードします。
Tera Termを起動します。
シリアルを選択し、USBシリアルデバイスのポートを選択します。ポート番号は、お使いのPC環境で違ってきます。OKボタンで終了します。
この一覧にPico間のUSBシリアルポートが表示されるのは、uf2プログラムを書き込み、実行した後です。ストレージモード中では一覧に表示されません。PicoのUSB標準出力はPicoが実行されてはじめて、PCで認識でき、このポート一覧に表示されます。
この段階で、Tera Termの画面に "Hello,world!"が表示されますが、ボーレイトを変更する必要があります。上部メニューから「設定」 > 「シリアルポート」を選択します。ここでスピードを115200に変更します。Raspberry Pi Picoのスピード、ボーレイトの初期値は115200です。
「現在の接続を再設定」ボタンをクリックし、表示画面に戻ります。
「編集」>「画面クリア」で画面をクリアできます。
5.3.時刻出力プログラム
標準出力に時刻を出力するプログラムを作成してみます。Picoにはリアルタイムクロックのライブラリが備わっています。このライブラリを使用します。ただし、電源オフ時の時刻のバックアップ機能ありません。電源オフでもバックアップ可能なRTCボードプロジェクトは、後の12章で参照してください。同時に日付の関数も使用します。ライブラリを追加する場合、Cソースでヘッダーファイルをインクルードする必要があると同時に、CMakeLists.txtにも追加が必要です。
以下、CMakeLists.txtです。
if(TARGET tinyusb_device)
add_executable(hello_usb hello_usb.c)
# pull in common dependencies
#target_link_libraries(hello_usb pico_stdlib) # <<<ここを変更
target_link_libraries(hello_usb pico_stdlib hardware_rtc) #<<< hardware_rtc追加
# enable usb output, disable uart output
pico_enable_stdio_usb(hello_usb 1)
pico_enable_stdio_uart(hello_usb 0)
# create map/bin/hex/uf2 file etc.
pico_add_extra_outputs(hello_usb)
# add url via pico_set_program_url
example_auto_set_url(hello_usb)
elseif(PICO_ON_DEVICE)
message(WARNING "not building hello_usb because TinyUSB submodule is not initialized in the SDK")
endif()
ソースリストは以下です。まずrtc.hおよびdatetime.hのインクルードを追加します。都次にMain.cの先頭部分で
rtc_init();
rtc_set_datetime(&t);
sleep_us(64);
とリアルタイムクロックを初期化します。Sleep_us(64)は64uec待機します。ハードウエア上必要な待機時間です。あとは永久ループ内で rtc_get_datetime(&t)で現在時間をよみとり、文字列に変換し、USBシリアルに出力します。
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/rtc.h"
#include "pico/util/datetime.h"
int main() {
stdio_init_all();
char datetime_buf[256];
char *datetime_str = &datetime_buf[0];
datetime_t t = {
.year = 2023,
.month = 02,
.day = 27,
.dotw = 1, // 0 is Sunday, so 5 is Friday
.hour = 11,
.min = 16,
.sec = 00
};
rtc_init();
rtc_set_datetime(&t);
sleep_us(64);
while (true) {
printf("Hello, world!\n");
rtc_get_datetime(&t);
datetime_to_str(datetime_str, sizeof(datetime_buf), &t);
printf("%s\n", datetime_str);
sleep_ms(1000);
}
return 0;
画面下、ブルーのバーで、ギアマーク横[Build]をクリックしビルドします。”pico-examples>build>hello_world>usb”のフォルダ内にhellow_usb.uf2のファイルが作成されていますので、コピーします。次にPicoからUSBケーブルを抜き、BOOTSELボタンを押しながら、再度ケーブルを差します。最後にBOOTSELボタンをはなします。PicoがRPI-RP2(X:)、マスストレージとして、PCに認識されますので、uf2ファイルをPicoに書き込みます。TersaTErmVTを起動し、プログラムが正常に動いているか確認します。
1秒毎に、現在の日付、時刻が表示されます。
5.4.Picoオンボード温度計測
Hello worldの最後のプログラム例としてPico内蔵の温度センサー値を読み込む温度ロガーを作成します。Adcライブラリを使用します。CMakeLists.txtにadcライブラリを追加します。
以下、CMakeLists.txtです。先のrtcライブラリと同様、以下のように追加します。
#target_link_libraries(hello_usb pico_stdlib hardware_rtc)
target_link_libraries(hello_usb pico_stdlib hardware_rtc hardware_adc) <<<追加
次にCソードリストの変更です。ヘッダーでadcライブラリをインクルードします。
#include "hardware/adc.h"
以下、最終ソースリストです
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/rtc.h"
#include "pico/util/datetime.h"
#include "hardware/adc.h"
int main() {
stdio_init_all();
char datetime_buf[256];
char *datetime_str = &datetime_buf[0];
datetime_t t = {
.year = 2023,
.month = 02,
.day = 27,
.dotw = 1, // 0 is Sunday, so 5 is Friday
.hour = 11,
.min = 16,
.sec = 00
};
rtc_init();
rtc_set_datetime(&t);
sleep_us(64);
/* 12-bit conversion, assume max value == ADC_VREF == 3.3 V */
const float conversionFactor = 3.3f / (1 << 12);
adc_init();
adc_set_temp_sensor_enabled(true);
adc_select_input(4);
while (true) {
printf("Hello, world!\n");
rtc_get_datetime(&t);
datetime_to_str(datetime_str, sizeof(datetime_buf), &t);
printf("%s\n", datetime_str);
float adc = (float)adc_read() * conversionFactor;
float tempC = 27.0f - (adc - 0.706f) / 0.001721f;
printf("Onboard temperature = %.02fC\n", tempC);
sleep_ms(1000);
}
return 0;
}
同様にビルド後、BOOTSELモードで、uf2ファイルをPicoに書き込みます。実行が開始されるので、Tera Term VTを起動して結果を確認します。
時刻とともに、温度が表示されるのを確認できます。
コメントをお書きください