« WSL2でRustを動かす | トップページ | PimoroniボードをPicoで動かす »

2021年4月 1日 (木)

Arduino-IDEでPicoを動かす

2021/4/29
earlephilhower版専用になるがMulticoreのスケッチを追加した。

2021/4/23
もう一つの実装であるarduino純正ボード・ライブラリでの使用方法を追加した。
また、書き込みでエラーになるので、その解決方法についても記述した。

2021/4/5+
Arduno-IDEのwindows版でPicoの書き込みで
エラーになる場合の対応方法を追加した。

2021/4/4
LittleFSを使用したスケッチを追加した。

2021/4/3+
動作確認したスケッチを追加した。

2021/4/1+
初版

Pico Arduino Install

Pico Arduino Install

概要

Arduino-IDEでPicoを動かす。
ホスト環境は、ubuntu20.04とする。
なお、Arduino-IDEの最新版がインストール済みのものとする。

linuxのArduino-IDEのインストールについては以下を参照のこと。
Install the Arduino Software (IDE) on Linux

本記事は、linux版Arduino-IDEについて記述したものであるが、 ほとんど、そのままwindows版でも適応可能である。

ボード情報(*.json)のインストール

Arduino-IDEを起動して以下を実行する:
1.[ファイル]/[環境設定]を選択する
2.画面の「追加のボードマネージャーのURL」に以下を入力(追加)する

https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json # 今後、このjsonを利用したものをearlephilhower版と呼ぶことにする。

3.入力後、[OK]をクリックする
4.[ツール]/[ボード]/[ボードマネージャー]を選択する
5.検索欄に「pico」と入力する
6.検索結果から「Raspberry Pi Pico/RP2040」を選び、[インストール]をクリックする
7.インストール後、[閉じる]をクリックする

8.[ツール]/[ボード]/[Raspberry RP2040 boards]/[Raspberry Pi Pico]を選択する

以上で、ボードとして[Raspberry PiPico]が選択されたことになる。

なお、これ以外に以下のボードが選択できる:

Raspberry Pi Pico Raspberry Pi Pico (Picoprobe) Adafruit Feather RP2040 Adafruit Feather RP2040 (Picoprobe) Generic PR2040 Generic PR2040 (Picoprobe)

「(Picoprobe)」付きは、書き込みにopenocd(picoprobe)を使用するものになる。

Picoprobeを使った書き込み

Picoprobeを接続した場合、Arduino-IDEでボードを「Raspberry Pi Pico (Picoprobe)」を切り替える。その後は従来どおりの操作で書き込みができる。

以下、書き込み時の出力例:

<省略> Open On-Chip Debugger 0.10.0+dev-gd58c2ef5e-dirty (2021-03-28-18:41) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : only one transport option; autoselect 'swd' Warn : Transport "swd" was already selected adapter speed: 5000 kHz Info : Hardware thread awareness created Info : Hardware thread awareness created Info : RP2040 Flash Bank Command Info : clock speed 5000 kHz Info : SWD DPIDR 0x0bc12477 Info : SWD DLPIDR 0x00000001 Info : SWD DPIDR 0x0bc12477 Info : SWD DLPIDR 0x10000001 Info : rp2040.core0: hardware has 4 breakpoints, 2 watchpoints Info : rp2040.core1: hardware has 4 breakpoints, 2 watchpoints Info : starting gdb server for rp2040.core0 on 3333 Info : Listening on port 3333 for gdb connections target halted due to debug-request, current mode: Thread xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00 target halted due to debug-request, current mode: Thread xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00 ** Programming Started ** Info : RP2040 B0 Flash Probe: 2097152 bytes @10000000, in 512 sectors target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00 ... <省略> ... target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00 target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00 ** Programming Finished ** ** Verify Started ** target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00 target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00 ** Verified OK ** ** Resetting Target ** shutdown command invoked Info : SWD DPIDR 0x0bc12477 Info : SWD DLPIDR 0x00000001

留意点:
・シリアルを使っているスケッチは、USBシリアルを前提にしているので、そのままでは動かない。
・picoprobe接続時でもシリアルが利用可能だが、USBシリアルではなく、普通のシリアルにpicobrobe経由で接続している。(したがって、picoprobe経由でシリアルを使用する場合、スケッチの「Serial」を「Serial1」に置き換えると使用できる)

サンプルスケッチ

ボード設定が完了した後は、通常のArduinoボードとして使用できる。
リセットボタンがないので、リセットボタンを押されることを前提にしているスケッチは、無限ループにするなどの工夫が必要となる。
なお、(Picoprobeを使用していない場合は)書き込み前に書き込み用ストレージ(RPI-RP2)が見える状態にする必要がある。
# ただし、ボードのUSBシリアルが有効になっている場合、
# 自動的にリセットするのでbootselボタンを押してのUSBの抜き差しは
# 不要となる

以下、実際に動かしたスケッチを挙げる:

ASCIITablePico.ino

/* ASCII table Prints out byte values in all possible formats: - as raw binary values - as ASCII-encoded decimal, hex, octal, and binary values For more on ASCII, see http://www.asciitable.com and http://en.wikipedia.org/wiki/ASCII The circuit: No external hardware needed. created 2006 by Nicholas Zambetti <http://www.zambetti.com> modified 9 Apr 2012 by Tom Igoe This example code is in the public domain. http://www.arduino.cc/en/Tutorial/ASCIITable */ void setup() { //Initialize serial and wait for port to open: //Serial.begin(9600); Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // prints title with ending line break Serial.println("ASCII Table ~ Character Map"); } // first visible ASCIIcharacter '!' is number 33: int thisByte = 33; // you can also write ASCII characters in single quotes. // for example, '!' is the same as 33, so you could also use this: // int thisByte = '!'; void loop() { // prints value unaltered, i.e. the raw binary version of the byte. // The Serial Monitor interprets all bytes as ASCII, so 33, the first number, // will show up as '!' Serial.write(thisByte); Serial.print(", dec: "); // prints value as string as an ASCII-encoded decimal (base 10). // Decimal is the default format for Serial.print() and Serial.println(), // so no modifier is needed: Serial.print(thisByte); // But you can declare the modifier for decimal if you want to. // this also works if you uncomment it: // Serial.print(thisByte, DEC); Serial.print(", hex: "); // prints value as string in hexadecimal (base 16): Serial.print(thisByte, HEX); Serial.print(", oct: "); // prints value as string in octal (base 8); Serial.print(thisByte, OCT); Serial.print(", bin: "); // prints value as string in binary (base 2) also prints ending line break: Serial.println(thisByte, BIN); // if printed last visible character '~' or 126, stop: if (thisByte == 126) { // you could also use if (thisByte == '~') { thisByte = 33-1; Serial.println("----------------------------------------------"); Serial.println(""); delay(500); /* // This loop loops forever and does nothing while (true) { continue; } */ } // go on to the next character thisByte++; }

・標準に提供されているスケッチを無限ループにしたもの。
・シリアルはUSBシリアルを使用する。

Blink.ino

/* Blink Turns an LED on for one second, then off for one second, repeatedly. Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to the correct LED pin independent of which board is used. If you want to know what pin the on-board LED is connected to on your Arduino model, check the Technical Specs of your board at: https://www.arduino.cc/en/Main/Products modified 8 May 2014 by Scott Fitzgerald modified 2 Sep 2016 by Arturo Guadalupi modified 8 Sep 2016 by Colby Newman This example code is in the public domain. http://www.arduino.cc/en/Tutorial/Blink */ // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); } // the loop function runs over and over again forever void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }

・標準に提供されているスケッチが無修正で動作する。

bootselBlink.ino
bootselボタンをLED点滅のボタンに使用したスケッチ(トグル動作)

// bootselBlink int toggle = false; void setup() { Serial.begin(115200); delay(5000); // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); //Serial.println("I dare you to hit the BOOTSEL button..."); } int c = 0; void loop() { if (toggle) digitalWrite(LED_BUILTIN, HIGH); else digitalWrite(LED_BUILTIN, LOW); if (BOOTSEL) { Serial.printf("You pressed BOOTSEL %d times!\n", ++c); toggle = !toggle; // Wait for BOOTSEL to be released while (BOOTSEL) { delay(1); } } }

temperature.ino
CPUのコア温度を測ってシリアルに出力するスケッチ

/* Released into the public domain */ void setup() { Serial.begin(115200); delay(5000); } void loop() { Serial.printf("Core temperature: %2.1fC\n", analogReadTemp()); delay(1000); }

・このスケッチはearlephilhower版専用となる。

fade.ino

/* Fade This example shows how to fade the onboard Raspberry Pi Pico LED This example code is in the public domain. http://www.arduino.cc/en/Tutorial/Fade */ int led = LED_BUILTIN; // the PWM pin the LED is attached to int brightness = 0; // how bright the LED is int fadeAmount = 5; // how many points to fade the LED by // the setup routine runs once when you press reset: void setup() { // declare pin to be an output: pinMode(led, OUTPUT); } // the loop routine runs over and over again forever: void loop() { // set the brightness analogWrite(led, brightness); // change the brightness for next time through the loop: brightness = brightness + fadeAmount; // reverse the direction of the fading at the ends of the fade: if (brightness <= 0 || brightness >= 255) { fadeAmount = -fadeAmount; } // wait for 30 milliseconds to see the dimming effect //delay(30); delay(15); }

morse_blinky.ino
シリアルから入力した文字列をLED点滅のモールス信号で出力するスケッチ
(pico-sdkのサンプルのaruduino移植版)

// ported into Arduino platform on 2021/4/4 // modified on 2021/2/6 /** * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ /* #include <stdio.h> #include "pico/stdlib.h" #include "hardware/gpio.h" */ char str[100]; const uint LED_PIN = 25; const uint DOT_PERIOD_MS = 100; const char *morse_letters[] = { ".-", // A "-...", // B "-.-.", // C "-..", // D ".", // E "..-.", // F "--.", // G "....", // H "..", // I ".---", // J "-.-", // K ".-..", // L "--", // M "-.", // N "---", // O ".--.", // P "--.-", // Q ".-.", // R "...", // S "-", // T "..-", // U "...-", // V ".--", // W "-..-", // X "-.--", // Y "--.." // Z }; // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); //Initialize serial and wait for port to open: Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } } void put_morse_letter(const char *pattern) { for (; *pattern; ++pattern) { //gpio_put(LED_PIN, 1); digitalWrite(LED_BUILTIN, HIGH); if (*pattern == '.') //sleep_ms(DOT_PERIOD_MS); delay(DOT_PERIOD_MS); else //sleep_ms(DOT_PERIOD_MS * 3); delay(DOT_PERIOD_MS * 3); //gpio_put(LED_PIN, 0); digitalWrite(LED_BUILTIN, LOW); //sleep_ms(DOT_PERIOD_MS * 1); delay(DOT_PERIOD_MS * 1); } //sleep_ms(DOT_PERIOD_MS * 2); delay(DOT_PERIOD_MS * 2); } void put_morse_str(const char *str) { for (; *str; ++str) { if (*str >= 'A' && *str <= 'Z') { put_morse_letter(morse_letters[*str - 'A']); } else if (*str >= 'a' && *str <= 'z') { put_morse_letter(morse_letters[*str - 'a']); } else if (*str == ' ') { //sleep_ms(DOT_PERIOD_MS * 4); delay(DOT_PERIOD_MS * 4); } } } void loop() { Serial.printf("Enter String for Morse\n"); delay(1000); if (Serial.available()){ String sline = Serial.readStringUntil('\n'); sline.toCharArray(str, 100); Serial.printf("morse: %s\n", str); put_morse_str(str); } } /* int main() { stdio_init_all(); gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); while (true) { printf("Enter String for Morse\n"); fflush(stdin); scanf("%s",str); //gets(str); // does not work?? printf("morse: %s\n", str); //puts(str); //put_morse_str("Hello world"); put_morse_str(str); //sleep_ms(1000); } } */

内蔵ファイルシステム(FLASH)を使用したスケッチ

Pico用のLittleFSの書き込みツールを以下の手順でインストールする:

cd ~Downloads wget https://github.com/earlephilhower/arduino-pico-littlefs-plugin/releases/download/0.2.0/PicoLittleFS-0.2.0.zip # ダウンロードしたzipを解凍して # そのなかの picolittlefs.jar を次のディレクトリにコピーする mkdir -p ~/Arduino/tools/PicoLittleFS/tool cd ~/Arduino/tools/PicoLittleFS/tool #確認 ls picolittlefs.jar # Arduino-IDEを再起動する

スケッチのディレクトリ「FSUploadPico」にファイルシステムのデータ用の ディクトリ「data」を作り、保存したいファイルを置く。

cd FSUploadPico mkdir data cd data gedit file1.txt #任意のテキスト内容を編集する

FSUploadPico.ino

// Released to the public domain // // This sketch will read an uploaded file and increment a counter file // each time the sketch is booted. // Be sure to install the Pico LittleFS Data Upload extension for the // Arduino IDE from: // https://github.com/earlephilhower/arduino-pico-littlefs-plugin/ // The latest release is available from: // https://github.com/earlephilhower/arduino-pico-littlefs-plugin/releases // Before running: // 1) Select Tools->Flash Size->(some size with a FS/filesystem) // 2) Use the Tools->Pico Sketch Data Upload tool to transfer the contents of // the sketch data directory to the Pico #include <LittleFS.h> void setup() { Serial.begin(115200); delay(5000); LittleFS.begin(); char buff[32]; int cnt = 1; File f = LittleFS.open("counts.txt", "r"); if (f) { bzero(buff, 32); if (f.read((uint8_t *)buff, 31)) { sscanf(buff, "%d", &cnt); Serial.printf("I have been run %d times\n", cnt); } f.close(); } cnt++; sprintf(buff, "%d\n", cnt); f = LittleFS.open("counts.txt", "w"); if (f) { f.write(buff, strlen(buff)); f.close(); } Serial.println("---------------"); while(true) { File i = LittleFS.open("file1.txt", "r"); if (i) { while (i.available()) { Serial.write(i.read()); } Serial.println("---------------"); i.close(); } } // while forever } void loop() { }

・リセットボタンがないのでシリアル出力部分を無限ループに変更した。
・ボードのライブラリが最新版である必要がある。(ボードマネージャーで更新する)

書き込みと実行:
以下の手順でdata書き込みとスケッチの書き込みを行なう:
(1)Arduino-IDEで[ツール(tools)]/[Flash Size]で任意(ゼロ以外)を設定する
(2)Arduino-IDEで[ツール(tools)]/[PicoLittleFS Data Upload]を選択して dataディレクトリの内容をPicoのflashに書き込む
(3)書き込み(Upload)アイコンを押してスケッチのコンパイルと書き込みを実行する

出力例(USBシリアル):

# 以下のfile1.txtの内容を繰り返し出力する Hello! Welcome to the Raspberry Pi Pico using arduino-pico! this is LittleFS test#1. this is LittleFS test#2. this is LittleFS test#3. this is LittleFS test#4. this is LittleFS test#5. this is LittleFS test#6.

windows版Arduino-IDEでの書き込みエラーの対応方法

windows版Arduino-IDEでは、動作環境によっては、Pico書き込み時にエラーになり書き込めないことがある。

これは、windowsのドライブのボリューム名として、半角カタカナが使われている場合、 書き込みツールとして使用しているuf2conv.pyでutf8文字列変換がエラーになっていることが原因である。

この対応として、日本語のボリューム名を英語などに変更することで、エラーを回避でき、書き込みが正常に動作するようになる。

または、ボリューム名を(手動で)変更せずにwindowsのシステム言語を英語に変更することでボリューム名も英語に変更することで書き込みが可能になる。
ここでは、システム言語を変更する方法でエラーを回避する。

システム言語を英語にする方法については以下などを参照のこと:
Windows 10 表示言語を英語版にする

重要な注意:
[Windows display], [Apps & websites]のみを英語に変更すること。 他も英語にすると日本語キーボードなどが使用できなくなるなどの不都合が生じる。

参考:
日本語から英語にシステム言語を変更すると、uf2conv.pyの変数r(bytearray)の内容が以下のように変化する:(環境依存あり)

日本語の場合: b'DeviceID DriveType FileSystem VolumeName \r\r\nC: 3 NTFS Windows \r\r\nD: 3 NTFS \x83{\x83\x8a\x83\x85\x81[\x83\x80 \r\r\nE: 2 FAT RPI-RP2 \r\r\n\r\r\n' 英語の場合: b'DeviceID DriveType FileSystem VolumeName \r\r\nC: 3 NTFS Windows \r\r\nD: 3 NTFS Volume \r\r\nE: 2 FAT RPI-RP2 \r\r\n\r\r\n'

・この例ではドライブDのボリューム名が変化していることが分かる。
・「\x83{\x83\x8a\x83\x85\x81[\x83\x80」(83 7B 83 8A 83 85 81 5B 83 80)は半角カナの部分になる。

他の対応方法としては、uf2conv.pyの変数rの中の半角カナ部分をutf8変換可能な文字に置き換えるパッチが考えられる。
それには以下のように修正する:
uf2conv.py

#修正前 def to_str(b): return b.decode("utf-8") ↓ #修正後 def to_str(b): return b.decode("utf-8",errors="replace")


Multicore用スケッチ (2021/4/29)

PicoはDualCoreのCPUなので、2つのCPUをスケッチで動作させることができる。
以下のexamplesにあったものを掲載する。
examples(earlephilhower)

残念ながら自分の環境では1コア(core0)としてしか動作しなかった。
(今後のupdateでfixするものと思われる)

Multicore.ino

// Demonstrates a simple use of the setup1()/loop1() functions // for a multiprocessor run. // Will output something like, where C0 is running on core 0 and // C1 is on core 1, in parallel. // 11:23:07.507 -> C0: Blue leader standing by... // 11:23:07.507 -> C1: Red leader standing by... // 11:23:07.507 -> C1: Stay on target... // 11:23:08.008 -> C1: Stay on target... // 11:23:08.505 -> C0: Blue leader standing by... // 11:23:08.505 -> C1: Stay on target... // 11:23:09.007 -> C1: Stay on target... // 11:23:09.511 -> C0: Blue leader standing by... // 11:23:09.511 -> C1: Stay on target... // 11:23:10.015 -> C1: Stay on target... // Released to the public domain // The normal, core0 setup void setup() { Serial.begin(); delay(5000); } void loop() { Serial.printf("C0: Blue leader standing by...\n"); delay(1000); } // Running on core1 void setup1() { delay(5000); Serial.printf("C1: Red leader standing by...\n"); } void loop1() { Serial.printf("C1: Stay on target...\n"); delay(500); }

・このスケッチはearlephilhower版専用となる。

Arduino純正のボード・ライブラリを使用する(2021/4/23)

最近、Arduino純正のボード・ライブラリもサポートされたので、その使い方について述べる。
純正ライブラリなので.jsonの設定などは不要で、ボード・ライブラリのアップデートをするだけで良い。
(この版をearlephilhower版と区別するために純正版と呼ぶ)

ボード・ライブラリ設定は以下の手順で行なう:

(1)[ツール(tools)]/[ボードマネージャ]を選択する。 (2)「pico」で検索する。 (3)検索された候補のなかで[Arduino Mbed OS RP2040 Boards]を選択する。 (4)[インストール]をクリックする。 (5)[閉じる]をクリックする。

ボードを選択するためには以下の手順で行なう:

(1)[ツール(tools)]/[Arduino Mbed OS RP2040 Boards]/[Raspberry Pi Pico]を選択する。 (2)[ツール(tools)]/[シリアルポート]を選択する。

あとは、通常の方法でビルドと書き込みができる。

重要:
書き込み時にエラーになった場合、udev-ruleが登録されていない可能性があるので、
その場合、以下を実行してudev-ruleを登録する:

sudo ~/.arduino15/packages/arduino/hardware/mbed_rp2040/2.0.0/post_install.sh

書き込みが正常に動作すると以下のようなメッセージが出る:
(設定で「より詳細な情報を表示する:」で[書き込み]にチェックしている場合)

/home/xxxx/.arduino15/packages/arduino/tools/rp2040tools/1.0.2/rp2040load -v -D /tmp/arduino_build_yyyyy/zzzzz.ino.elf rp2040load 1.0.1 - compiled with go1.15.8 Loading into Flash: [==============================] 100%%

参考情報

earlephilhower版関連:
Arduino-Pico(Detailed Documentation)
examples(earlephilhower)

Pico-Arduino関連:
Arduino IDE support for RP2040 and Pico arrives
Display_Packをpico_arduinoで動かす

Arduino関連:
Arduino-Pico
Install the Arduino Software (IDE) on Linux
How to Program Raspberry Pi Pico With the Arduino IDE
pico-setup-windows installer
Arduino IDEライブラリのインストールとディレクトリ(フォルダ)構成 (Windows, Mac, Linux対応)

FS関連:
Arduino Pico LittleFS Filesystem Uploader
Filesystem
LittleFS
Arduino ESP8266 LittleFS Filesystem Uploader

OpenOCD関連:
PicoボードにPico_SDKでC言語をビルドする(Picoprobeの説明あり)
Debugging the Raspberry Pi Pico on Windows 10

Pico関連:
Raspberry Pi Pico – How to Interface (almost) Everything!

WSL2関連:
WSL2でRDPサーバーを動かす
WSL2でSSHサーバーを動かす
WSL2でのplatformioやPico-SDKの利用方法

python3関連:
How to permissively decode a UTF-8 bytearray?
bytes, bytearray/日本語エンコード名

その他:
文字コードの16進ダンプ

以上

|

« WSL2でRustを動かす | トップページ | PimoroniボードをPicoで動かす »

Arduino」カテゴリの記事

RaspberryPi」カテゴリの記事

Pico」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




« WSL2でRustを動かす | トップページ | PimoroniボードをPicoで動かす »