【Arduino】Raspberry Pi Pico2を使う

it

RaspberryPiからRP2350を搭載したRaspberry Pi Pico2が発売されました。
これまでのRaspberry Pi Picoと比較しながら使ってみます。

記事の概要

主にRP2040搭載 Raspberry Pi Picoとの比較を主にRaspberry Pi Pico2 の特徴を紹介します。
外観と主な差分仕様、同じスケッチを動作させたときの結果についてまとめました。

Aruduino環境での開発をするための手順と、開発をしていて発生したトラブルと対処方法についても記載しています。
GPIOを使用した基本的なスケッチや、RP2350で使用できるスケッチを作成して紹介しています。

Raspberry Pi Pico2

簡単紹介

Raspberry Pi 公式 Pico2ページ : Pico-series Microcontrollers – Raspberry Pi Documentation

◆関連記事

ピン配置

外観

比較

スペック

数値上の違いはCPUのデフォルトクロックとSRAMのサイズです。
クロックの上限は同じなので単純な処理では違いはでなさそうです。

Pico2ではFPUが搭載されているため浮動小数演算が必要な処理で効果が期待できそうです。

Raspberry Pi Pico2Raspberry Pi Pico
CPUARM Cortex-M33 150MHz
(50 to 300MHz)
FPU
ARM Cortex-M0+ 133MHz
(50 to 300MHz)
SRAM520KB256KB

外観

画像左がRaspberry Pi Pico2、右がRaspberry Pi Picoです。
シルクが濃く見えますが、製造時期やロット依存でしょうか。

使ってみた

◆Raspberry Pi Picoのスケッチの互換確認
まずは基板上のユーザLEDの点滅をしました。
問題もなく点滅できます。


Raspberry Pi PicoのサンプルスケッチではSSD1306 OLEDとILI9341 LCDディスプレイの表示制御をしましたが、同じスケッチを使用してコンパイルと実行ができました。

Raspberry Pi Picoとの互換については気にすることなくスケッチの流用ができそうです。

◆CPU性能

CPUクロックの設定範囲はRaspberry Pi Picoと変わりませんが、デフォルトクロックが上がっています。
単純なGPIOのLow/Highを繰り返すサンプルをオシロスコープで計測するとRaspberry Pi Picoの方が早い結果になりました。
比較結果は詳細はこちらに掲載します。


RP2350にはFPUが搭載されています。
浮動小数点演算を複数回行う3D演算を行い、立方体を1回転させるまでの時間を比較をしてみました。CPU Clock はどちらも150MHzです。

Raspberry Pi Pico2(動画左の白のOLED)は10.26秒。
Raspberry Pi Pico(動画右の青のOLED)は10.81秒。

まとめ

Good

・Raspbrry Pi Picoの上位互換。スケッチはそのまま使える
・入手性が良い。電子部品実店舗、ネットストア、大手ショッピングサイトでも在庫多数
・浮動小数点演算が強化されている

Bad

・デジタルインプットの不具合がある
・期待していたほどの性能アップは無い(主観)


Raspberry Pi Picoほどのコスパ感はなく、デジタル入力のトラブルもあります。
浮動小数点演算の強みはありますが、Raspberry Pi Picoと比較してどちらを選択するかは悩ましいところです。

準備

Arduino環境の作成

◆開発環境

開発環境はArduinoを使用します。
Arduino環境の作り方はこちらを参照します。

◆ボードライブラリ

Arduino IDEのボードマネージャからRP2040用のライブラリのインストールとボードの選択をします。
ボードライブラリには「Raspberry Pi Pico/RP2040 by Earle F. Philhower, III」を使用します。

注意
Raspberry Pi Pio 2はライブラリバージョン4.0.0から追加されています。
4.0.0以降のバージョンをインストールします。

追加のボードマネージャのURLhttps://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
検索RP2350
ボードライブラリRaspberry Pi RP2040 Boards(x.x.x)※
選択するボードRaspberry Pi RP2040 Boards(x.x.x) > Raspberry Pi Pico 2
※動作確認はバージョン 4.1.1 です

モジュールライブラリ

I2CのサンプルではSSD1306 OLED、SPIのサンプルではILI9341を使用します。
サンプルを使用しない場合はインストール不要です。

◆SSD1306

ライブラリ名検索確認時のバージョン
Adafruit SSD1306 by AdafruitSSD13062.5.11
Adafruit GFX Library by AdafruitGFX1.11.10

◆ILI9341

ライブラリ名検索確認時のバージョン
Adafruit ILI9341 by AdafruitILI93411.6.1
Adafruit GFX Library by AdafruitGFX1.11.10

基板の初期化とシリアル認識

Raspberry Pi Picoの初期化で紹介した方法と同じで、Raspberry Pi Pico2用のuf2ファイルを作成し書き込みます。
1.uf2ファイルを作成する

Arduino IDEを起動します。
「File > New Sketch」より新しいスケッチファイルを開きます。
ボードライブラリは「Raspberry Pi Pico 2」を選択します。
「File > Save As」により、名前を付けて保存します。
ここでは「blank_RP2350」とします。
ここで生成したファイルはRP2350搭載基板で使用できるので適切な名前を付けます。
「Sketch > Export Compiled Binary」をクリックするとコンパイルが開始されます。

名前を付けて保存したファイルのフォルダ以下
(…)\buile\rp2040.rp2040.rpipico2 フォルダにコンパイル済みファイル(.uf2)が生成されます。

2.書き込む

Raspberry Pi Pico2のBOOTボタンを押しながらUSBケーブルを接続し電源を供給します。
Raspberry Pi Pico2はストレージ認識されます。

先に作成した.uf2ファイルフォルダを開き、生成された「blank_RP2350.ino.uf2」をストレージ認識されたRaspberry Pi Pico2にドラッグアンドドロップします。

この作業でRaspberry Pi Pico2はシリアル認識されArduinoでの開発ができます。

スケッチの書き込み

Raspberry Pi Picoと同じでArduino IDEの書き込みボタン、またはuf2ファイルを書き込みます。

1.Arduino IDEからの書き込み

注意
「基板の初期化とシリアル認識」を実施し、パソコンがシリアル認識している必要があります。

書き込みを行うRaspberry Pi Pico2のCOMポートを選択し、Arduino IDEの書き込みボタンをクリックすることで書き込みができます。

2.uf2ファイルの書き込み

「基板の初期化とシリアル認識」で作成した.uf2ファイルのように、作成したスケッチをコンパイルし、.uf2ファイルを作成します。

Raspberry Pi Pico2のBOOTボタンを押しながら、USBケーブルを接続し電源を供給します。
Raspberry Pi Pico2はストレージ認識されます。

.uf2ファイルフォルダを開き、生成された.uf2ファイルをストレージ認識されたRaspberry Pi Pico2にドラッグアンドドロップします。

トラブル

デジタル入力 PULLDOWN、PULLUPが使えない

現象

デジタル入力のパラメータによりPULLDOWN, PULLUPを指定しても期待通りの動作にならない。
信号はLOWまたはHIGHのどちらかにラッチされた状態になる。

RP2040では同じスケッチでも正常動作をおこなうため、RP2350のチップまたはライブラリ側の不具合と推定しています。

RP2350 – Wikipedia – GPIO hardware issue

対応

回路によるプルダウン、プルアップ回路を作成する。
現状ソフトウエアによる現象会費は難しいので、回路により解決を行う。

そのほか情報

現象確認時の状況
確認時期 : 2024/10
Arduino IDE : 2.3.3
Board Library : Raspberry Pi Pico/RP2040/RP2350 by Earle F.Philhower, III 4.1.1

スケッチサンプル

GPIOデジタル入出力

説明

タクトボタンを押している間基板実装LED(緑)を点灯させます。
基板実装LEDはGPIO25で、LED_BUILTINに定義されています。

GPIO15をプルダウン入力し、タクトボタンの状態を読み取ります。
タクトボタンが押されていればLEDを点灯、放されていればLEDを消灯させます。

注意
※2024/10/11時点では、スケッチパラメータによりプルダウン、プルアップ設定を行っても期待通りの動作をしないため、回路上でプルダウン回路を作成して対応しています。

配線

今回の期待動作では以下の配線ですが、この配線では正常動作しないためプルアップ抵抗を含めた配線を掲載します。

暫定対策(PULLDOWN抵抗を使う)

スケッチ

#define BUTTON_PIN (15)

void setup() 
{
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLDOWN);
}

void loop() 
{
  if(digitalRead(BUTTON_PIN) == LOW)
  {
    digitalWrite(LED_BUILTIN, LOW);
  }
  else
  {
    digitalWrite(LED_BUILTIN, HIGH);
  }
}

結果

期待動作はボタンを押している間は点灯、放している間は消灯です。

1.対策前
ボタンを押すことでLEDは点灯したが、ボタンを離してもLEDは点灯したまま。
入力がHIGHのままでラッチされていると推定します。



2.暫定対策後(PULLDOWN抵抗を使う)
ボタンを押すとLEDが点灯、放すと消灯しました。

PWM出力

説明

ボード実装されたLEDをPWM制御により、ゆっくり点灯ゆっくり消灯を繰り返します。
基板実装LEDはGPIO25で、LED_BUILTINに定義されています。

約0.5秒かけてゆっくり点灯、約0.5秒かけてゆっくり消灯を繰り返します。

配線

配線不要

スケッチ

#define WAIT_MS  (2)

void setup() 
{
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
  for(int i = 0; i < 256; i ++)
  {
    analogWrite(LED_BUILTIN, i);
    delay(WAIT_MS);
  }

  for(int i = 0; i < 256; i ++)
  {
    analogWrite(LED_BUILTIN, 255 - i);
    delay(WAIT_MS);
  }

}

結果

ゆっくり点灯とゆっくり消灯をしました。

信号の様子をオシロスコープ(OWON HDS272)でモニタしました。
Duty(Low信号とHihg信号の比)の変化している様子がわかります。
High時間が長くなるとLEDは明るくなり、High時間が短くなるとLEDが暗くなります。

ADC

説明

Raspberry Pi Pico2 にはADC(アナログデジタルコンバータ)を3ch使用できます。

GPIO28のADCから電圧を読み取りシリアル出力します。

電圧の入力にはESP32-LOLIN-Liteのアナログ出力を使用します。
0Vから3.3Vまで約0.5秒で上昇し、3.3Vから0Vまで約0.5秒で下降します。

配線

スケッチ

#define WAIT_MS  (2)

void setup() 
{
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
  for(int i = 0; i < 256; i ++)
  {
    analogWrite(LED_BUILTIN, i);
    delay(WAIT_MS);
  }

  for(int i = 0; i < 256; i ++)
  {
    analogWrite(LED_BUILTIN, 255 - i);
    delay(WAIT_MS);
  }

}

結果

シリアル出力した結果をプロットしました。
最小値は18(0.06V)、最大値は1014(3.27V)までノイズの少ない直線で読み出しています。

UART(UARTのピン設定)

説明

Raspberry Pi Pico2でのUARTで設定できるピンと設定方法について。

Raspberry Pi Pico2 のUARTは2ポート使用できます。
UARTで使用するTXとRXは決められたピンの範囲内で任意のピンに設定できます。

●ポイント●
Raspberry Pi Pico2はUSBからもシリアル(COM)通信ができます。
このシリアル通信は、UART0, UART1とは別の通信です。
USBからシリアル通信を行う場合はオブジェクトに[Serial]を使用します。

注意!!
設定できないピンに対して設定を行うと、コンパイルと書き込みはできますがRaspberry Pi Pico2は停止し、COMの認識もできなくなります。
基板の初期化とシリアル認識」を実施することで復旧できます。

UARTで使用できるピンと、TX, RXに設定できるピンの表です。

arduinoで使用する
オブジェクト名
表上の表記使用できるGPIOピン番号
SerialUSBポート
Serial1UART0(赤枠)TX : 0, 12, 16
RX : 1, 13, 17
Serial2UART1(青枠)TX : 4, 8
RX : 5, 9

設定と開始

Arduino上でのピン設定とUARTの開始。

//USBシリアルを使ってRaspberry Pi Pico2とパソコンを通信する場合
Serial.begin();

//UART0を使ってTXにGPIO0、RXにGPIO1を設定する。
Serial1.setTX(0);
Serial1.setRX(1);
Serial1.begin();

//UART1を使ってTXにGPIO4、RXにGPIO5を設定する。
Serial2.setTX(4);
Serial2.setRX(5);
Serial2.begin();

UART通信

説明

UART0を使って通信をします。

UART電文の送信と受信にはUARTシリアル変換モジュール(USB-TO-TTL-FT232)を使用します。

UARTシリアル変換モジュールから受信した文字(アルファベット)が大文字なら小文字、小文字なら大文字に変換して送信します。

配線

スケッチ

#include <ctype.h>

#define UART0_TX  (0)
#define UART0_RX  (1)

void setup()
{
  Serial1.setTX(UART0_TX);
  Serial1.setRX(UART0_RX);
  Serial1.begin(115200);
}

void loop()
{
  int8_t c;

  if(Serial1.available())
  {
    c = Serial1.read();
    if(('a' <= c) && (c <= 'z'))
    {
      c = toupper(c);
    }
    else if(('A' <= c) && (c <= 'Z'))
    {
      c = tolower(c);
    }
    Serial1.write(c);
  }
}

結果

Teratermを起動します。
Teratermの「新しい接続」ではUART-シリアル変換アダプタのCOMを選択します。
UART-シリアル変換アダプタは[COM11]でした。

●ポイント●
・実行環境によりCOM番号は変わります。
同じ環境やモジュールを使っても番号は変わることがあります。
・選択するCOMがRaspberry Pi Pico2 か UART-シリアル変換アダプタかわからない場合は、一度Raspberry Pi Pico2のUSBケーブルを外します。

Teratermの設定ではローカルエコー(入力した文字が表示される)設定になっています。
“tamanegi”と入力しました。

1文字ごとに変換して返答する処理なので、結果は”tTaAmMaAnNeEgGiI”となりました。

I2C(I2Cのピン設定)

説明

Raspberry Pi Pico2でのI2Cで設定できるピンと設定方法について。

Raspberry Pi Pico2 のI2Cは2ポート使用できます。
I2Cで使用するSDAとSCLは決められたピンの範囲内で任意のピンに設定できます。

注意!!
設定できないピンに対して設定を行うと、コンパイルと書き込みはできますがRaspberry Pi Pico2は停止し、COMの認識もできなくなります。
基板の初期化とシリアル認識」を実施することで復旧できます。

I2Cで使用できるピンと、SDA, SCLに設定できるピンの表です。

arduinoで使用する
オブジェクト名
表上の表記設定できるGPIOピン
WireI2C0(赤枠)SDA : 0, 4, 8, 12, 16, 20
SCL : 1, 5, 9, 13, 17, 21
Wire1I2C1(青枠)SDA : 2, 6, 10, 14, 18, 26
SCL : 3, 7, 11, 15, 19, 27

設定と開始

Arduino上でのピン設定とI2Cの開始。

#include <Wire.h>

//I2C0を使ってSDAにGPIO0、SCLにGPIO1を設定する。
Wire.setSDA(0);
Wire.setSCL(1);
Wire.begin();

//I2C1を使ってSDAにGPIO2、SCLにGPIO3を設定する。
Wire1.setSDA(2);
Wire1.setSCL(3);
Wire1.begin();

I2CでOLED(SSD1306)の表示制御

説明

0.96インチ OLEDディスプレイ SSD1306をRaspberry Pi Pico2のI2Cで表示制御します。
“Pico2″と”SSD1306″とテキスト表示するサンプルです。

スケッチのベースはRaspberry Pi Picoでも使用した”Adafruit SSD1306 by Adafruit”を使用します。

スケッチではI2C0(GPIO0にSDA, GPIO1にSCL)を使います。
I2C1を使う場合「I2C1の場合」のコメント行を解除し、「I2C0の場合」の行をコメント化します。
I2C1ではGPIO2にSDA、GPIO3にSCLを使います。

配線

スケッチ

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


#define PIN0_SDA 0
#define PIN0_SCL 1
#define PIN1_SDA 2
#define PIN1_SCL 3

#define SCREEN_WIDTH 128                //解像度 128 x 64 で使用します。
#define SCREEN_HEIGHT 64                //SCREEN_HEIGHTは 32 に設定することができます。

#define OLED_RESET     -1               //使用しないので -1を設定する。
#define SCREEN_ADDRESS 0x3C             //I2Cアドレスは 0x3C

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);     //I2C0の場合
//Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire1, OLED_RESET);     //I2C1の場合

                                        
void setup()
{
  
  //I2C0の場合
  Wire.setSDA(PIN0_SDA);
  Wire.setSCL(PIN0_SCL);

  //I2C1の場合
  // Wire1.setSDA(PIN1_SDA);
  // Wire1.setSCL(PIN1_SCL);


  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    for(;;);
  }

  display.clearDisplay();
  
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print(F("Pico2"));
  display.setCursor(25, 25);
  display.print(F("SSD1306"));

  display.display();
}

void loop()
{
}

結果

SSD1306 OLEDの表示ができました。
Raspberry Pi PicoとRaspberry Pi Pico2では共通のスケッチでコンパイルと実行ができました。

I2C(I2Cのピン設定)

説明

Raspberry Pi Pico2でのSPIで設定できるピンと設定方法について。

Raspberry Pi Pico2 のSPIは2ポート使用できます。
SPIで使用するMOSIとMISOとSCKは決められたピンの範囲内で任意のピンに設定できます。

注意!!
設定できないピンに対して設定を行うと、コンパイルと書き込みはできますがRaspberry Pi Pico2は停止し、COMの認識もできなくなります。
基板の初期化とシリアル認識」を実施することで復旧できます。

ポイント
・CSは任意のピンに設定することができます。
・表記上 TXは MOSI, RXは MISOです。

SPIで使用できるピンと、MOSI, MISO, SCKに設定できるピンの表です。

arduinoで使用する
オブジェクト名
表上の表記設定できるGPIOピン
SPISPI0(赤枠)MOSI(TX) : 3, 7, 19
MISO(RX) : 0, 4, 16, 20
SCK : 2, 6, 18, 22
SPI1SPI1(青枠)MOSI(TX) : 11, 15, 27
MISO(RX) : 8, 12, 28
SCK : 10,14, 26

設定と開始

Arduino上でのピン設定とSPIの開始。

//SPI0を使ってMOSIにGPIO19, MISOにGPIO16, SCKにGPIO18を設定する。
SPI.setTX(19);
SPI.setRX(16);
SPI.setSCK(18);
SPI.begin();

//SPI1を使ってMOSIにGPIO11, MISOにGPIO8, SCKにGPIO10を設定する。
SPI1.setTX(11);
SPI1.setRX(8);
SPI1.setSCK(10);
SPI1.begin();

SPI通信(LCDの表示)

説明

2.4インチ LCD ILI9341をRaspberry Pi PicoのSPIで表示制御します。
”TAMANEGI”
“2.4inch LCD”
“Res=320 x 240”
“ILI9341”
とテキスト表示するサンプルです。

スケッチのベースはRaspberry Pi Picoでも使用した”Adafruit SSD1306 by Adafruit”を使用します。

スケッチではI2C0(GPIO0にSDA, GPIO1にSCL)を使います。
I2C1を使う場合「I2C1の場合」のコメント行を解除し、「I2C0の場合」の行をコメント化します。
I2C1ではGPIO2にSDA、GPIO3にSCLを使います。

配線

スケッチ

#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include <SPI.h>

//SPI0の場合
#define TFT_CS              (17)   // CS
#define TFT_RST             (22)   // Reset 
#define TFT_DC              (28)   // D/C
#define TFT_MOSI            (19)   // SDI(MOSI)
#define TFT_SCK             (18)   // SCK

//SPI1の場合
// #define TFT_CS             (13)  // CS
// #define TFT_RST            (28)  // Reset 
// #define TFT_DC             (27)  // D/C
// #define TFT_MOSI           (15)  // SDI(MOSI)
// #define TFT_SCK            (14)  // SCK

//SPI0の場合
Adafruit_ILI9341 tft = Adafruit_ILI9341(&SPI, TFT_DC, TFT_CS, TFT_RST);

//SPI1の場合
//Adafruit_ILI9341 tft = Adafruit_ILI9341(&SPI1, TFT_DC, TFT_CS, TFT_RST);

void setup(void) 
{
  //SPI0の場合
  SPI.setTX(TFT_MOSI);
  SPI.setSCK(TFT_SCK);

  //SPI1の場合
  // SPI1.setTX(TFT_MOSI);
  // SPI1.setSCK(TFT_SCK);
   tft.begin();
  
  tft.fillScreen(ILI9341_BLACK);
  
  tft.setRotation(3);
  tft.setTextSize(4);
  
  tft.setCursor(0, 10);
  tft.setTextColor(ILI9341_GREEN);
  tft.printf("TAMANEGI\n\n");

  tft.setTextSize(3);
  tft.setTextColor(ILI9341_RED);               //赤
  tft.printf("2.4inch LCD\n");
  tft.setTextColor(ILI9341_YELLOW);            //黄
  tft.printf("Res=320 x 240\n");
  tft.setTextColor(ILI9341_BLUE);              //青
  tft.printf("ILI9341\n");
}

void loop()
{
}

結果

SSD1306 OLEDの表示ができました。
Raspberry Pi PicoとRaspberry Pi Pico2では共通のスケッチでコンパイルと実行ができました。

RP2350スケッチ

内部温度モニタ

説明

一秒ごとに内部温度を読み出し、シリアルに結果を出力します。

配線

配線不要

スケッチ

void setup() {
  Serial.begin(115200);
}

void loop() {
  float Temp_degC = analogReadTemp();

  Serial.printf("CPU Temperature = %lf\n", Temp_degC);
  delay(1000);
}

結果

結果はAruduino IDEのシリアルモニタから確認しました。

ハードウエアAPI GPIO

説明

ハードウエアAPIを使ってGPIOのLOW/HIGHを繰り返します。
Arduino環境でGPIO制御を行う「digitalWrite」より高速に信号を制御できます。

「結果」ではオシロスコープを使って信号の変化をモニタします。
Raspberry Pi Pico2でハードウエアAPIとdigitalWriteを使った時の信号の変化の差と、Raspberry Pi Picoとの差を比較します。

配線

配線不要

スケッチ

void setup() 
{
  gpio_init(0);
  gpio_set_dir(0, GPIO_OUT);    //GPIO0 を出力設定
}

void loop()
{
  while(1)
  {
   gpio_put_masked(0x0001,0x0001);  //GPIO0をHIGH
   gpio_put_masked(0x0001,0x0000);  //GPIO0をLOW
  }
}

Low/Highの繰り返し比較のためのサンプルスケッチ

void setup() 
{
  pinMode(0, OUTPUT);
}

void loop()
{
  while(1)
  {
    digitalWrite(0, HIGH);
    digitalWrite(0, LOW);
  }
}

結果

ハードウエアAPIを使用した時とdigitalWrite()を使用した時の繰り返しのサイクルを比較しました。
信号のLowとHighの繰り返し時間(図中水色のAとBのラインの時間差)を計測しています。

Raspberry Pi Pico2のハードウエアAPIの結果は図の左上、digitalWrite()を使用した結果は左下です。
digitalWrite()を使うよりも1/15程度でLow/Highを繰り返しています。

Raspberry Pi Pico(RP2040)も同じ条件(CPU Clock を 150MHz Overclock)に設定して比較しました。
Raspberry Pi PicoのハードウエアAPIの結果は図の右上、digitalWrite()を使用した結果は右下です。
同じCPUクロックですが、Raspberry Pi Pico2の方が20%弱遅い結果になりました。

コメント

タイトルとURLをコピーしました