🛜

Raspberry Pi pico2wを使うためのコードエディタを紹介してみる

に公開

Raspberry Pi pico2wのPinout

Raspberry Pi pico2wは以下のようなピン配置をしている。

図1 Raspberry Pi pico2w
画像はRaspberry Piの公式サイトから拝借。
ここでPinoutが見づらかったら公式で画像を。
pico2wの販売元のリンクは以下から
https://akizukidenshi.com/catalog/g/g130330/
https://ssci.to/10053
価格は秋月電子が安いが送料が高い。技適のシールが別で入っている。
価格がSwitchScienceが高いがネコポスで200円。技適のシールはパッケージに貼ってある。
(価格は2025年5月現在)
はんだやピンヘッダ、LED、抵抗、ICなどの電子パーツ単位で購入するならば秋月、
高めのセンサなど買うならSwitchScienceといろんなサイトを比較して購入することを推奨。

動かすためのエディタは?

pico2wの使用にあたってコードの編集エディタを3つ比較する。

1.VSCode(Pico SDK v1.x.x)

Microsoft製のコードエディタであり主にPico SDKを利用した開発環境として利用する。
Windows環境で利用するには無料版Visual Studioやmsys2などでC言語の環境を構築する、
picoに書き込むためにGNU Arm Embedded Toolchainのインストールなど手間があり、
また環境変数をいじる必要があるため初心者にはお勧めできない。
またSDK内のライブラリを利用するにあたってCMakeLists.txtを編集しなければならず、
テキスト内でUSBによるシリアル通信や利用するヘッダーファイルの指定などやることが多い。
ディレクトリの管理も面倒で、ネストを深く設定しづらく少しディレクトリ内をいじるだけでも
コンパイルするときエラーを吐かれやすい。
picow系の目玉である無線通信の設定が面倒で扱いづらい事が一番の欠点。
通信機能を持たないpico(wなし)を利用するだけならばPico SDKは選択肢の一つに入るかも。
もし興味を持ったらリファレンスが公式にあるので眺めてみてほしい。
CMakeLists.txt管理の雰囲気を感じてみたい人は公式のpico-examplesをのぞいてみてほしい。
https://github.com/raspberrypi/pico-examples
再三書くがこの時は以下のツールがなかったので構造を読み解くことが面倒だった。

Pico SDK(v2.0)を利用したい人へ

以下にテストで使ったLチカのサンプルを記載する。
テストなので余計なコメントやコードがあるのは目をつむっていただきたい。

test_w.cpp
//Raspi Pico Test prongraming.
//buildはvisual studioのコマンドプロンプトよりcodeを実行してvscodeを実行する
//↑Cmakeがエラーを吐く
//新しい環境で開発する場合はディレクトリ(build)を削除する
//makeされた.uf2ファイルは親ディレクトリのbuild内に生成される

//printf()を.cppからエラーなしで実行するには
//stdio.h,stdlib.hを追加することで回避可能
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//Picoを制御するためのライブラリ(CMakeLists.txtに記載しないと利用できない)
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"

#include "hardware/gpio.h"
#include "hardware/i2c.h"
#include "hardware/spi.h"
#include "hardware/adc.h"
#include "hardware/uart.h"
#include "hardware/pwm.h"

//使用するGPIOピン番号をdefineで定義
#define LED_NUM1    22
#define LED_NUM2    25
#define LED_NUM3    27
#define SW_NUM      14
#define PullUp      0
#define UART_ID     uart1
#define UART_TX1    8
#define UART_RX1    9
#define PWM_NUM1    16
#define PWM_NUM2    17
#define ML_NUM_IN1  18
#define ML_NUM_IN2  19
#define MR_NUM_IN1  20
#define MR_NUM_IN2  21
#define MOSI    3
#define MISO    4
#define SCK     2
#define CS      5
#define SPI_PORT spi0

//classを書くテスト(C++としてでコンパイルできるかの確認) 
class DigitalOut{
    private:
        float nums=0.04f;
    public:
        bool on=1;
        bool off=0;
        int ll=102; 
        void Set(int gpio_num);
};
void DigitalOut::Set(int gpio_num){
    gpio_init(gpio_num);
    gpio_set_dir(gpio_num, GPIO_OUT);
}
class DigitalIn{
    private:
        float nums=0.04f;
    public:
        bool led=0;
        int ll=102; 
        void Set(int gpio_num, int Pull_Name);
};
//PullUp --> 0, PullDown --> 1
void DigitalIn::Set(int gpio_num, int Pull_Name){
    gpio_init(gpio_num);
    gpio_set_dir(gpio_num, GPIO_IN);
    switch(Pull_Name){
        case 0:
            gpio_pull_up(gpio_num);
            break;
        case 1:
            gpio_pull_down(gpio_num);
            break;
        default:

        break;
    }
}

DigitalOut led;
bool leds = led.on;
bool ledf = led.off;
DigitalIn sw;

void init_SPI(){
    spi_init(SPI_PORT, 2*100*100);    
}

int LED_pins[] = {LED_NUM2, LED_NUM1};

int sizeOfArray(int *dArray, int size){
    //printf("%d / %d = %d\r\n", size , sizeof dArray[0] , size/sizeof dArray[0]);
    return (size/sizeof dArray[0]);
}
//使用するGPIOピンの設定(一括)
void init_LED(int LEDs[], int size){
    for(int i=0;i<sizeOfArray(LEDs, size);i++){
        gpio_init(LEDs[i]);
        gpio_set_dir(LEDs[i], GPIO_OUT);
    }
}

int main() {
    //USB等を利用するためにPicoを初期化
    stdio_init_all();

    //GPIOピンを利用するための設定
    //DigitalOut
    init_LED(LED_pins, sizeof(LED_pins));
    /*
    gpio_init(LED_NUM1);
    gpio_set_dir(LED_NUM1, GPIO_OUT);
    gpio_init(LED_NUM2);
    gpio_set_dir(LED_NUM2, GPIO_OUT);
    */
    //DigitalIn
    gpio_init(SW_NUM);
    gpio_set_dir(SW_NUM, GPIO_IN);
    gpio_pull_up(SW_NUM);
    //PWM
    gpio_init(ML_NUM_IN1);
    gpio_set_dir(ML_NUM_IN1, GPIO_OUT);
    gpio_init(ML_NUM_IN2);
    gpio_set_dir(ML_NUM_IN2, GPIO_OUT);
    gpio_set_function(PWM_NUM1, GPIO_FUNC_PWM);
    gpio_set_function(PWM_NUM2, GPIO_FUNC_PWM);

    //picow搭載のLEDはCYW43439経由で点灯するため以下を設定
    if (cyw43_arch_init()) {
        printf("WiFi init failed");
        return -1;
    }
    
    //Digital output bool.(NOT:0<->1 はboolを利用)
    bool led1=0;
    bool led2=1;
    //ボタンを押している間、その状態を維持する。
    while(1){
        //"Hello World!"をシリアル通信で出力
        printf("Hello World!\r\n");
        if (gpio_get(SW_NUM)==1){
            printf("Push Switch.\r\n");
            //Blink green LED
            led1=!led1;
            led2=!led2;
        }
        else{
            printf("Keeping LEDs.\r\n");
            led1=led1;
            led2=led2;
        }
        //指定したGPIOピンからDigital出力(↓picowは特殊)
        cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, led1); //picow上のLEDを光らせる
        //gpio_put(LED_NUM2, led1); //pico上のLEDを光らせる
        gpio_put(LED_NUM1, led2);   //GPIOピンからLEDを光らせる
        printf("%d / %d = %d\r\n", sizeof(LED_pins)  , sizeof(LED_pins[0]) , sizeOfArray(LED_pins, sizeof(LED_pins)));
        sleep_ms(250);
    }
}

複数のディレクトリをまとめて管理する場合の親ディレクトリ設定(CMakeLists.txtの一部)

CMakeLists.txt
#Set the mimum required version of CMake(3.12.x <-> 3.20.x)
cmake_minimum_required(VERSION 3.12)

#Pull in SDK (must be before project)
include(pico_sdk_import.cmake)

#Set the project name, the programming language
project(pico_prj C CXX ASM) #C CXX ASM(.uf2を作成するために必要)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)	#追加することでC++の書き方もできるようになる
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.0")
    message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.3.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
endif()
#pico wを使うには↓の1行が必要 : picoとpicowの使う方でbuildを削除する
set(PICO_BOARD pico_w)
set(PICO_PATH ${PROJECT_SOURCE_DIR})
#Initialize the SDK
pico_sdk_init()


add_compile_options(-Wall
        -Wno-format          # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int
        -Wno-unused-function # we have some for the docs that aren\'t called
        -Wno-maybe-uninitialized
        )

#外部のライブラリを使用する場合の設定
#add_library(VL53L0X STATIC VL53L0X.cpp)
#target_link_libraries(VL53L0X pico_stdlib hardware_i2c)

#子ディレクトリを追加
add_subdirectory(test)
add_subdirectory(spi_test)
add_subdirectory(mcp3208)
add_subdirectory(seg_led)
add_subdirectory(gps_uart)

#picowを使用する場合の追加設定
if (PICO_CYW43_SUPPORTED) # set by BOARD=pico-w
    if (NOT TARGET pico_cyw43_arch)
        message("Skipping Pico W examples as support is not available")
    else()
        set(WIFI_SSID "${WIFI_SSID}" CACHE INTERNAL "WiFi SSID for examples")
        set(WIFI_PASSWORD "${WIFI_PASSWORD}" CACHE INTERNAL "WiFi password for examples")
        #picow(CYW43439)を使う場合↓の中に子ディレクトリをまとめなければならない
        add_subdirectory(test_w)
        add_subdirectory(wifi_pico)
        add_subdirectory(VL53L0X_I2C)

        if ("${WIFI_SSID}" STREQUAL "")
            message("Skipping some Pico W examples as WIFI_SSID is not defined")
        elseif ("${WIFI_PASSWORD}" STREQUAL "")
            message("Skipping some Pico W examples as WIFI_PASSWORD is not defined")
        else()
            #add_subdirectory(iperf)
        endif()
    endif()
endif()

Pico SDKを利用する際のディレクトリ構造は以下のようになる。
新たにディレクトリを作成するごとにCMakeLists.txtを追加して編集することになる。

Pico SDKのを利用する際のディレクトリの構造(例)
pico_prj/
    ├─build/    #picoに書き込む.uf2ファイルの保管場所
    │    ├─ test/
    │    :    ├─ test.uf2
    :    :    :
    :
    ├─ test/    #picoのLチカ
    │    ├─ main.cpp 
    │    └─ CMakeLists.txt  #ライブラリの管理
    │
    ├─ test_w/  #picowのLチカ
    │    ├─ main.cpp 
    │    └─ CMakeLists.txt  #ライブラリの管理
    │
    ├─ VL53L0X_I2C/ #picoでVL53L0Xを動かす
    │    ├─ VL53L0X/
    │    │     ├─ VL53L0X.hpp
    │    │     ├─ VL53L0X.cpp
    │    │     └─ CMakeLists.txt #ライブラリの中でも入れなければエラーが発生
    │    ├─ main.cpp
    │    └─ CMakeLists.txt  #ライブラリの管理
    :
    :
    └─ CMakeLists.txt #親ディレクトリの設定
Pico SDKでVL53L0Xを利用したい人へ

VL53L0XをPico SDKで利用するにはVL53L0Xの公式サイトからライブラリを拾ってきて
pico用に変換しなければならない。
この作業はとてつもなく面倒なのでgithubに投稿されているpico用のVL53L0Xライブラリが
あるのでcloneしてみよう。(秋月で販売されているVL53L0Xで動作確認済み)
https://github.com/shipp02/VL53L0X_Pico

2.Thonny(MicroPython)

pico系のコードはPythonでも書くことができる。
準備はMicroPython.uf2ファイルをpicoに入れるだけ。
MicroPython.uf2ファイルのダウンロードは下のリンクから。
https://micropython.org/download/
エストニアのTartu(タルトゥ)大学が開発したPythonの統合開発環境“Thonny”をインストールすればほぼ環境が出来上がる。
https://thonny.org/
書き方はとてもシンプルで初心者には環境構築が簡単だと思う。
Wi-Fiを利用するプログラムも簡単かつ短く書くことは魅力的。
しかしインタープリタ言語ゆえ実行が遅い事が欠点。
C,C++とPythonの実効速度はかなりの差がある。
(型宣言など工夫すればその差も縮まると思うが)
興味があるならば検索してみてほしい。
センサーの値を高速で取得したい、同時にアクチュエータも制御させたいなら
おすすめはしない。
これは願望であるが可能であればpythonみたいに書けて高速に動作するmojoを利用して
書いてみたい。

Pythonを利用してPicoの開発をやりたい方へ

下記にLチカのテストプログラムを記す。

test.py
import machine as pico
import utime
#LEDの出力設定
led = pico.Pin(25, pico.Pin.OUT)

while True:
    led.value(1)    #LED点灯
    utime.sleep(5)
    led.value(0)    #LED消灯
    utime.sleep(5)

こんなにも短く書ける。

3.Arudino IDE

イタリアのArduino社により開発されたオープンソースの開発環境。
ダウンロードは下記のリンクから。
https://www.arduino.cc/en/software/
OSの環境に対応したリンクをクリックして"JUST DOWNLOAD"をクリックすれば無料でダウンロードできる。寄付をしたいならば3ドルからできるのでしたい人は選択すればよい。
Arudinoは対応しているハードウェアならばほぼそのままプログラムコードが流用できることが良い。
C++で書くことができ、実行速度も申し分ない。
picow系を開発するにあたってはWi-Fi設定が簡単で様々なセンサや出力デバイスのライブラリが豊富である。
大抵は"センサ名 Arudino"で検索すると使用しているボードが違ってもコードの流用ができるので楽。

書き方も簡潔ではあるがloop文が無限ループとなっていることが厄介である。

test.ino
#include <Arduino.h>

void setup(){
    //初期設定
}

void loop(){
    //ここに書かれた命令がループで行われる。
}

C,C++の環境で説明すると

test.cpp
#include <stdio.h>
#include <Arduino.h>

void setup(){
    //初期設定
}

void loop(){
    //ここに書かれた命令がループで行われる。
}

int main(){
    setup();

    while(1){
        loop();
    }
}

のような構成になっている。
もしloop文の無限ループを止めたいならばexit(0);を追加すれば良い。

test.ino
#include <Arduino.h>
void setup(){
    //初期設定
}
void loop(){
    //ここに書かれた命令がループで行われる。
    exit(0); //ループの停止
}

対応するマイクロコンピュータならば色々流用できるArudinoだが、癖があるのが
Serial.println(),Serial.printなどのシリアル通信である。
例えばPico SDK(C,C++)では

test.cpp
~
int num0 = 0, num1=2;
printf("数値は%dと%d.\r\n", num0, num1);
~

pythonの場合では

test.py
~
num0 = 0
num1 = 2
print("数値は{}と{}.".format(num0, num1))
#または
print(f"数値は{num0}{num1}.")
~

のように文字列をシリアル通信で送信できる。
ArudinoではC,C++のようにprint文を書くとエラーが吐かれる。
つまり、

test.ino
~
int num0 = 0, num1=2;
Serial.print("数値は");
Serial.print(num0);
Serial.print("と");
Serial.print(num1);
Serial.println(".");
~

または

test.ino
~
int num0 = 0, num1=2;
Serial.println((String)"数値は" + num0 +"と" + num1 + ".");
~

のように書かなくてはいけない。一工夫必要になる。

Arudinoを利用してPicoの開発をやりたい方へ

環境構築は下記のサイトを参考にするとよい。
https://karakuri-musha.com/inside-technology/arduino-raspberrypi-pico-helloworld01/

ではどのコードエディタがいいの?

結論、人によるとしか書けない。
個人的にはpico2wへのプログラムの書き込みは開発環境やセンサのライブラリが多いArudino IDEが使いやすいと思う。マイコンボードの形は違えどコードを少し改変すれば応用が利き易く、参考になるコードが多く検索にかかりやすい。
v1.8.xまでは入力補完がなくVSCodeの拡張機能が生きていたためVSCodeの使い勝手が良かったが、v2.x.xからはVSCodeのサポートがなくなった分、入力補完が入りArudino IDEが使い易くなったと感じる。
上記以外でVSCodeではArudinoの互換としてPlatformIO IDEが以前からあるがライブラリを一括で管理したいので、コードエディタ内で完結するArudino IDEが楽。

Lチカプログラム(picoのLEDとGPIOのLED)

ここではArudino IDEを使ったLEDのLチカプログラムを記載する。
マイクロコンピュータのテストとしてはLEDを点滅させるLチカが最適。
pico2wにはボード上にLEDが搭載されているがGPIO出力の確認も込めて
別途LEDを用意して交互に点灯するプログラムを記載する。

PicowとLEDのブレッドボード配線図
他のサイトではプログラムを書き込むときBOOTSELボタンを押しながらUSBケーブルを挿してと記載されていることが多いが、上記の図のようにRUNピンにタクトスイッチをつけると
タクトスイッチ押す-->同時にBOOTSELボタンを押す-->タクトスイッチから指を離す
の操作でUSBケーブルを外さずに書き込むことができる。
LEDの配置を見て"抵抗いらないの?"と思うかもしれないが、秋月で販売されているチップ抵抗が入っている5V用LEDを使用しているからである。下記にリンクを貼っておく。色は5色ある。
https://akizukidenshi.com/catalog/g/g106245/
pico系はピン配置を見るとGP22とGNDが隣り合っているため、上記のような横着がしやすい。

以下にLEDを交互に光らせるプログラムを記載する。

blink_led.ino
#include <Arduino.h>
#define GPIO_NUM 22 //GP22を使用する

void setup() {
	pinMode(LED_BUILTIN, OUTPUT);   //pico2w上のLEDを使用する
	pinMode(GPIO_NUM, OUTPUT);	//GP22からLEDを使用する
}

bool led=0;
//500msごとにLEDが交互に点灯
void loop() {
	digitalWrite(GPIO_NUM, led); //GP22からLEDを制御
	led=!led;   //ループごとに0-->1, 1-->0を繰り返す。(型は必ずboolで)
	digitalWrite(LED_BUILTIN, led);//pico上のLEDを制御
	delay(500); //500ms待機
}

コピペしたら検証、または書き込みのボタンを押せばコンパイルして.uf2ファイルを生成してくれる。
エラーが出たらコピペして検索、エラーが出なかったらおめでとう。
初めて書き込む、または"USBを認識していません"の警告が出る場合は上記で太文字で示した操作を行ってから書き込みが良い。

まとめ

この記事はWindows上で各コードエディタを触ってみて思った感想と備忘録を兼ねたものです。記事の中にあるように"これがいい"、"このように工夫すればもっと簡単"など感じることは人それぞれなので違和感があるならばコメントしてください。(知らないことの勉強になるので)
もともとmbedでの開発が主だったので、mbedOSのサポートが2026年7月になくならなければRaspberry Pi pico2wの記事をこのようにまとめなかったと思います。
記事を読んでマイコンボード上での開発に興味を持ってくれれば幸いです。

記事途中のディレクトリ構造の書き方は下記のリンクを参考にしました。
https://qiita.com/paty-fakename/items/c82ed27b4070feeceff6

Discussion