Pico

2021年4月26日 (月)

Display_Packをpico_arduinoで動かす

2021/4/28
LEDとSWの制御スケッチを追加した。

2021/4/25
初版

pio Pico Arduino Display Pack

pio Pico Arduino Display Pack

概要

以下のDisplay_Packをpico_arduinoで動かす
Pico Display Pack
(ホストはubuntu20.04を想定している)
platformioが既にインストールされている前提で説明する。

platformioのインストールについては以下などを参照のこと:
arduinoフレームワーク用platformio.ini集

platformio.ini

以下のplatformio.iniを利用する:

[env:pico] platform = https://github.com/platformio/platform-raspberrypi.git framework = arduino board = pico build_flags = -DPICO upload_port = /dev/ttyACM0 monitor_port = /dev/ttyACM0 monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = adafruit/Adafruit BusIO @ ^1.7.3 adafruit/Adafruit ST7735 and ST7789 Library @ ^1.7.1

graphicstest.ino

テスト用プログラムを以下のように作成する:
src/graphicstest.ino

// modified for pimoroni display pack (2021/4/25) /************************************************************************** This is a library for several Adafruit displays based on ST77* drivers. Works with the Adafruit 1.8" TFT Breakout w/SD card ----> http://www.adafruit.com/products/358 The 1.8" TFT shield ----> https://www.adafruit.com/product/802 The 1.44" TFT breakout ----> https://www.adafruit.com/product/2088 The 1.14" TFT breakout ----> https://www.adafruit.com/product/4383 The 1.3" TFT breakout ----> https://www.adafruit.com/product/4313 The 1.54" TFT breakout ----> https://www.adafruit.com/product/3787 The 2.0" TFT breakout ----> https://www.adafruit.com/product/4311 as well as Adafruit raw 1.8" TFT display ----> http://www.adafruit.com/products/618 Check out the links above for our tutorials and wiring diagrams. These displays use SPI to communicate, 4 or 5 pins are required to interface (RST is optional). Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried/Ladyada for Adafruit Industries. MIT license, all text above must be included in any redistribution **************************************************************************/ #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7735.h> // Hardware-specific library for ST7735 #include <Adafruit_ST7789.h> // Hardware-specific library for ST7789 #include <SPI.h> #ifndef PICO #if defined(ARDUINO_FEATHER_ESP32) // Feather Huzzah32 #define TFT_CS 14 #define TFT_RST 15 #define TFT_DC 32 #elif defined(ESP8266) #define TFT_CS 4 #define TFT_RST 16 #define TFT_DC 5 #else // For the breakout board, you can use any 2 or 3 pins. // These pins will also work for the 1.8" TFT shield. #define TFT_CS 10 #define TFT_RST 9 // Or set to -1 and connect to Arduino RESET pin #define TFT_DC 8 #endif // OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique // to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and // SCLK = pin 13. This is the fastest mode of operation and is required if // using the breakout board's microSD card. // For 1.44" and 1.8" TFT with ST7735 use: Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); // For 1.14", 1.3", 1.54", and 2.0" TFT with ST7789: //Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); // OPTION 2 lets you interface the display using ANY TWO or THREE PINS, // tradeoff being that performance is not as fast as hardware SPI above. //#define TFT_MOSI 11 // Data out //#define TFT_SCLK 13 // Clock out // For ST7735-based displays, we will use this call //Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST); // OR for the ST7789-based displays, we will use this call //Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST); #endif #ifdef PICO // setup for pico display pack #define TFT_CS 17 #define TFT_RST -1 #define TFT_DC 16 #define TFT_MOSI 19 // Data out #define TFT_SCLK 18 // Clock out #define BL_EN 20 // backlit enable Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST); #endif float p = 3.1415926; void setup(void) { //pinMode(BL_EN, OUTPUT); //digitalWrite(BL_EN, HIGH); //Serial.begin(9600); Serial.begin(115200); Serial.print(F("Hello! ST77xx TFT Test")); #ifndef PICO // Use this initializer if using a 1.8" TFT screen: tft.initR(INITR_BLACKTAB); // Init ST7735S chip, black tab // OR use this initializer if using a 1.8" TFT screen with offset such as WaveShare: // tft.initR(INITR_GREENTAB); // Init ST7735S chip, green tab // OR use this initializer (uncomment) if using a 1.44" TFT: //tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab // OR use this initializer (uncomment) if using a 0.96" 160x80 TFT: //tft.initR(INITR_MINI160x80); // Init ST7735S mini display // OR use this initializer (uncomment) if using a 1.3" or 1.54" 240x240 TFT: //tft.init(240, 240); // Init ST7789 240x240 // OR use this initializer (uncomment) if using a 2.0" 320x240 TFT: //tft.init(240, 320); // Init ST7789 320x240 // OR use this initializer (uncomment) if using a 1.14" 240x135 TFT: //tft.init(135, 240); // Init ST7789 240x135 // SPI speed defaults to SPI_DEFAULT_FREQ defined in the library, you can override it here // Note that speed allowable depends on chip and quality of wiring, if you go too fast, you // may end up with a black screen some times, or all the time. //tft.setSPISpeed(40000000); #endif #ifdef PICO tft.init(135, 240); // Init ST7789 240x135 //tft.setRotation(3); // landscape tft.setRotation(2); // rotate for matching printing chars on the board tft.setSPISpeed(40000000); #endif Serial.println(F("Initialized")); uint16_t time = millis(); tft.fillScreen(ST77XX_BLACK); time = millis() - time; Serial.println(time, DEC); delay(500); // large block of text tft.fillScreen(ST77XX_BLACK); testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", ST77XX_WHITE); delay(1000); // tft print function! tftPrintTest(); delay(4000); // a single pixel tft.drawPixel(tft.width()/2, tft.height()/2, ST77XX_GREEN); delay(500); // line draw test testlines(ST77XX_YELLOW); delay(500); // optimized lines testfastlines(ST77XX_RED, ST77XX_BLUE); delay(500); testdrawrects(ST77XX_GREEN); delay(500); testfillrects(ST77XX_YELLOW, ST77XX_MAGENTA); delay(500); tft.fillScreen(ST77XX_BLACK); testfillcircles(10, ST77XX_BLUE); testdrawcircles(10, ST77XX_WHITE); delay(500); testroundrects(); delay(500); testtriangles(); delay(500); mediabuttons(); delay(500); Serial.println("done"); delay(1000); } void loop() { tft.invertDisplay(true); delay(500); tft.invertDisplay(false); delay(500); } void testlines(uint16_t color) { tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(0, 0, x, tft.height()-1, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(0, 0, tft.width()-1, y, color); delay(0); } tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(tft.width()-1, 0, 0, y, color); delay(0); } tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(0, tft.height()-1, x, 0, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(0, tft.height()-1, tft.width()-1, y, color); delay(0); } tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color); delay(0); } } void testdrawtext(char *text, uint16_t color) { tft.setCursor(0, 0); tft.setTextColor(color); tft.setTextWrap(true); tft.print(text); } void testfastlines(uint16_t color1, uint16_t color2) { tft.fillScreen(ST77XX_BLACK); for (int16_t y=0; y < tft.height(); y+=5) { tft.drawFastHLine(0, y, tft.width(), color1); } for (int16_t x=0; x < tft.width(); x+=5) { tft.drawFastVLine(x, 0, tft.height(), color2); } } void testdrawrects(uint16_t color) { tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color); } } void testfillrects(uint16_t color1, uint16_t color2) { tft.fillScreen(ST77XX_BLACK); for (int16_t x=tft.width()-1; x > 6; x-=6) { tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1); tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2); } } void testfillcircles(uint8_t radius, uint16_t color) { for (int16_t x=radius; x < tft.width(); x+=radius*2) { for (int16_t y=radius; y < tft.height(); y+=radius*2) { tft.fillCircle(x, y, radius, color); } } } void testdrawcircles(uint8_t radius, uint16_t color) { for (int16_t x=0; x < tft.width()+radius; x+=radius*2) { for (int16_t y=0; y < tft.height()+radius; y+=radius*2) { tft.drawCircle(x, y, radius, color); } } } void testtriangles() { tft.fillScreen(ST77XX_BLACK); uint16_t color = 0xF800; int t; int w = tft.width()/2; int x = tft.height()-1; int y = 0; int z = tft.width(); for(t = 0 ; t <= 15; t++) { tft.drawTriangle(w, y, y, x, z, x, color); x-=4; y+=4; z-=4; color+=100; } } void testroundrects() { tft.fillScreen(ST77XX_BLACK); uint16_t color = 100; int i; int t; for(t = 0 ; t <= 4; t+=1) { int x = 0; int y = 0; int w = tft.width()-2; int h = tft.height()-2; for(i = 0 ; i <= 16; i+=1) { tft.drawRoundRect(x, y, w, h, 5, color); x+=2; y+=3; w-=4; h-=6; color+=1100; } color+=100; } } void tftPrintTest() { tft.setTextWrap(false); tft.fillScreen(ST77XX_BLACK); tft.setCursor(0, 30); tft.setTextColor(ST77XX_RED); tft.setTextSize(1); tft.println("Hello World!"); tft.setTextColor(ST77XX_YELLOW); tft.setTextSize(2); tft.println("Hello World!"); tft.setTextColor(ST77XX_GREEN); tft.setTextSize(3); tft.println("Hello World!"); tft.setTextColor(ST77XX_BLUE); tft.setTextSize(4); tft.print(1234.567); delay(1500); tft.setCursor(0, 0); tft.fillScreen(ST77XX_BLACK); tft.setTextColor(ST77XX_WHITE); tft.setTextSize(0); tft.println("Hello World!"); tft.setTextSize(1); tft.setTextColor(ST77XX_GREEN); tft.print(p, 6); tft.println(" Want pi?"); tft.println(" "); tft.print(8675309, HEX); // print 8,675,309 out in HEX! tft.println(" Print HEX!"); tft.println(" "); tft.setTextColor(ST77XX_WHITE); tft.println("Sketch has been"); tft.println("running for: "); tft.setTextColor(ST77XX_MAGENTA); tft.print(millis() / 1000); tft.setTextColor(ST77XX_WHITE); tft.print(" seconds."); } void mediabuttons() { // play tft.fillScreen(ST77XX_BLACK); tft.fillRoundRect(25, 10, 78, 60, 8, ST77XX_WHITE); tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_RED); delay(500); // pause tft.fillRoundRect(25, 90, 78, 60, 8, ST77XX_WHITE); tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_GREEN); tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_GREEN); delay(500); // play color tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_BLUE); delay(50); // pause color tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_RED); tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_RED); // play color tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_GREEN); }

・「Adafruit ST7735 and ST7789 Library 」にあるExamplesをDisplay_Pack向けに修正したもの。
・「#ifdef PICO ... #endif」などで囲まれた部分が修正部分になる。

ビルド&書き込み

以下の手順でビルトと書き込みができる:

cd pico_proj # ツールなどのインストール(最初の1回のみ) pio run -t clean # ビルドと書き込み # bootselボタンを押しながらホストにUSB接続して # その後、bootselボタンを離すると、書き込み用ストレージが出現する pio run -t upload # この時点で書き込みが完了する

Pico_LED_SW.ino (2021/4/28)

Display_PackのLEDとSWの制御スケッチを以下に紹介する:

src/Pico_LED_SW.ino

// for pimoroni Display Pack (2021/4/28) // setup LEDs & SWs #define LED_R 6 #define LED_G 7 #define LED_B 8 #define SW_A 12 #define SW_B 13 #define SW_X 14 #define SW_Y 15 int swn = 0; int sSW_A = LOW; int sSW_B = LOW; int sSW_X = LOW; int sSW_Y = LOW; int brightness = 0; // how bright the LED is int fadeAmount = 5; // how many points to fade the LED by void setup(void) { // init LEDs (negative logic) pinMode(LED_R, OUTPUT); digitalWrite(LED_R, HIGH); pinMode(LED_G, OUTPUT); digitalWrite(LED_G, HIGH); pinMode(LED_B, OUTPUT); digitalWrite(LED_B, HIGH); //digitalWrite(LED_R, LOW); //digitalWrite(LED_G, LOW); //digitalWrite(LED_B, LOW); // setup SWs pinMode(SW_A, INPUT_PULLUP); pinMode(SW_B, INPUT_PULLUP); pinMode(SW_X, INPUT_PULLUP); pinMode(SW_Y, INPUT_PULLUP); Serial.begin(115200); Serial.print(F("LEDs and SWs Test")); } void loop() { // set the brightness switch(swn) { case 0: analogWrite(LED_R, brightness); // other LEDs off pinMode(LED_G, OUTPUT); digitalWrite(LED_G, HIGH); pinMode(LED_B, OUTPUT); digitalWrite(LED_B, HIGH); break; case 1: analogWrite(LED_G, brightness); // other LEDs off pinMode(LED_R, OUTPUT); digitalWrite(LED_R, HIGH); pinMode(LED_B, OUTPUT); digitalWrite(LED_B, HIGH); break; case 2: analogWrite(LED_B, brightness); // other LEDs off pinMode(LED_R, OUTPUT); digitalWrite(LED_R, HIGH); pinMode(LED_G, OUTPUT); digitalWrite(LED_G, HIGH); break; default: pinMode(LED_R, OUTPUT); digitalWrite(LED_R, HIGH); pinMode(LED_G, OUTPUT); digitalWrite(LED_G, HIGH); pinMode(LED_B, OUTPUT); digitalWrite(LED_B, HIGH); analogWrite(LED_R, brightness); analogWrite(LED_G, brightness); analogWrite(LED_B, 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; } sSW_A = digitalRead(SW_A); sSW_B = digitalRead(SW_B); sSW_X = digitalRead(SW_X); sSW_Y = digitalRead(SW_Y); if (sSW_A == LOW) {swn=0; Serial.println("SW_A: pressed");} if (sSW_B == LOW) {swn=1; Serial.println("SW_B: pressed");} if (sSW_X == LOW) {swn=2; Serial.println("SW_X: pressed");} if (sSW_Y == LOW) {swn=3; Serial.println("SW_Y: pressed");} do { sSW_A = digitalRead(SW_A); sSW_B = digitalRead(SW_B); sSW_X = digitalRead(SW_X); sSW_Y = digitalRead(SW_Y); delay(50); } while ((sSW_A == LOW)||(sSW_B == LOW)||(sSW_X == LOW)||(sSW_Y == LOW)) ; }

(1)スイッチ(SW_A,SW_B,SW_X,SW_Y)を押すとスイッチの状態がシリアル出力される。
(2)SW_Aを押すとLEDが赤、SW_Bを押すとLEDが緑、SW_Xを押すとLEDが青、SW_Yを押すと白に、明るさが変化しながら光る。

ただし、Arduino純正ボードライブラリ(platformio,Arduino-IDEとも)にバグがあるようで、SW_Yは動作せず、LEDの色も混じった色になり意図したものと異なる。(pinModeのbug??)

earlephilhower版Arduino-IDE(以下のjsonファイルを設定するもの)のボードライブラリは問題が無いようで、SW_Yも正常動作するし、LEDの色も混ざらない。

https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json

参考情報

Arduino-IDE関連:
Arduino-IDEでPicoを動かす

Pico-Platformio(Arduino)関連:
platformioでpicoを動かす
Official PlatformIO + Arduino IDE support for the Raspberry Pi Pico is now available!

platformio関連:
PlatformIO Core (CLI)
Arduino-IDEとPlatformioのコンパイラーの挙動の違いについて
arduinoフレームワーク用platformio.ini集
ubuntu20.04をインストールする

以上

続きを読む "Display_Packをpico_arduinoで動かす"

| | コメント (0)

2021年4月22日 (木)

platformioでpicoを動かす

2021/4/24+
arduino-frameworkの対応を追加した、

2021/4/22
初版

Pico Platformio Pico-SDK/Arduino

Pico Platformio Pico-SDK/Arduino

概要

platformioでpicoを動かす
(ホストはubuntu20.04を想定している)
platformioが既にインストールされている前提で説明する。

platformioのインストールについては以下などを参照のこと:
arduinoフレームワーク用platformio.ini集

プロジェクトの作成

プロジェクトのディレクトリを作成して、その中に以下に述べるファイルを作成する:
(このディレクトリ名は任意だが、ここでは、pico_projとする)

# platformioの環境に入っている前提 mkdir pico_proj cd pico_proj # platformio.iniを作成する gedit platformio.ini

platformio.ini

[env:raspberry-pi-pico] platform = https://github.com/Wiz-IO/wizio-pico.git ;platform = wizio-pico board = raspberry-pi-pico framework = baremetal upload_port = /media/USER/RPI-RP2/ ; directory for mass-storage monitor_port = /dev/ttyACM0 ; directory for usb-over-serial monitor_speed = 115200 board_build.bynary_type = copy_to_ram build_flags = -D PICO_STDIO_USB ; enable stdio over USB build_unflags = -D PICO_STDIO_UART ;lib_deps =

・USERは環境依存なので、自分の環境に合わせて変更すること。
・frameworkとしては、baremetal(Pico-SDK)を設定する。

テスト用プログラムを以下のように作成する:
src/main.c

/* * --------------------------------------- * Copyright (c) Sebastian Günther 2021 | * | * devcon@admantium.com | * | * SPDX-License-Identifier: BSD-3-Clause | * --------------------------------------- */ #include <stdio.h> #include <stdbool.h> #include "pico/stdlib.h" int LED_BUILTIN = 25; int LED_GREEN = 15; void setup() { stdio_init_all(); gpio_init(LED_BUILTIN); gpio_set_dir(LED_BUILTIN, GPIO_OUT); gpio_init(LED_GREEN); gpio_set_dir(LED_GREEN, GPIO_OUT); } void blink() { gpio_put(LED_BUILTIN, 1); gpio_put(LED_GREEN, 1); //sleep_ms(750); sleep_ms(200); gpio_put(LED_BUILTIN, 0); gpio_put(LED_GREEN, 0); //sleep_ms(1050); sleep_ms(200); } int main() { setup(); printf("Starting...\n"); while (true) { printf("Hello World\n"); //printf("."); blink(); } return 0; }

・「Raspberry Pico: The Simple Startup with PlatformIO 」にあるサンプルを一部修正したものになる。

ビルド&書き込み

以下の手順でビルトと書き込みができる:

cd pico_proj # ツールなどのインストール(最初の1回のみ) pio run -t clean # ビルドと書き込み # bootselボタンを押しながらホストにUSB接続して # その後、bootselボタンを離すると、書き込み用ストレージが出現する pio run -t upload # この時点で書き込みが完了する

出力例:

<省略> Archiving .pio/build/raspberry-pi-pico/sdk/libSDK.a Indexing .pio/build/raspberry-pi-pico/sdk/libSDK.a Linking .pio/build/raspberry-pi-pico/APPLICATION.elf Building .pio/build/raspberry-pi-pico/APPLICATION.bin Checking size .pio/build/raspberry-pi-pico/APPLICATION.elf DONE Advanced Memory Usage is available via "PlatformIO Home > Project Inspect" RAM: [ ] 2.2% (used 5848 bytes from 262144 bytes) Flash: [ ] 2.0% (used 41728 bytes from 2097152 bytes) Configuring upload protocol... AVAILABLE: cmsis-dap, dap, picoprobe, uf2 CURRENT: upload_protocol = uf2 Uploading... Converting to UF2 Start address: 0x10000000 FamilyID: 0xe48bff56 Output size: 84480 bytes Wrote 84480 bytes to /media/USER/RPI-RP2/APPLICATION.uf2 DONE ========================= [SUCCESS] Took 3.39 seconds =========================

・書き込み終了後、プログラムが起動する。ボード上のLEDが点滅して、
USBシリアルには「Hello World」の文字列が繰り返し出力される。

他のサンプル(morse_blinky)

morse_blinky
src/main.c

cat src/main.c // morse_blinky // 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 }; void put_morse_letter(const char *pattern) { for (; *pattern; ++pattern) { gpio_put(LED_PIN, 1); if (*pattern == '.') sleep_ms(DOT_PERIOD_MS); else sleep_ms(DOT_PERIOD_MS * 3); gpio_put(LED_PIN, 0); sleep_ms(DOT_PERIOD_MS * 1); } sleep_ms(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); } } } 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); } }

・USBシリアル経由で文字列を入力すると、それに対応したモールス信号でLEDが点滅する。

Arduino framework 対応(2021/4/24)

arduinoのframeworkとして使用する場合は以下のplatformio.iniを使用する:

platformio.ini

[env:pico] platform = https://github.com/platformio/platform-raspberrypi.git framework = arduino board = pico upload_port = /media/USER/RPI-RP2/ ; directory for mass-storage monitor_port = /dev/ttyACM0 ; directory for usb-over-serial monitor_speed = 115200 ;lib_deps =

・USERは、環境依存なので、自分の環境の合わせること。

(1)プログラム(スケッチ)のファイルタイプは.cppではなく.inoを使用すること。
(2)platformio.ini,src/main.inoを作成した後、
以下を実行してudev-ruleを登録する:(src/main.inoはダミーで良い)

# プロジェクト・ディレクトリの中で以下を実行して関係ツールをダウンロードする pio run -t clean # udev-ruleを登録する cd ~/.platformio/packages/framework-arduino-mbed sudo bash ./post_install.sh

udev-rule登録が完了して、書き込みが正常に動作した場合、
以下のような出力になる:

$ pio run -v -t upload # 詳細情報を出力するために「-v」を付けている <省略> Advanced Memory Usage is available via "PlatformIO Home > Project Inspect" RAM: [== ] 18.7% (used 50500 bytes from 270336 bytes) Flash: [ ] 3.5% (used 73048 bytes from 2097152 bytes) .pio/build/pico/firmware.elf : section size addr .boot2 256 268435456 .text 53048 268435712 .rodata 8620 268488760 .ARM.exidx 8 268497380 .ram_vector_table 192 536870912 .data 11372 536871104 .uninitialized_ram.magic_location 12 536882476 .uninitialized_data 0 536882488 .scratch_x 0 537133056 .scratch_y 0 537137152 .bss 39128 536882488 .heap 210416 536921616 .ARM.attributes 40 0 .comment 132 0 .debug_frame 5144 0 .stab 60 0 .stabstr 118 0 Total 328546 <lambda>(["upload"], [".pio/build/pico/firmware.elf"]) AVAILABLE: cmsis-dap, raspberrypi-swd, stlink BeforeUpload(["upload"], [".pio/build/pico/firmware.elf"]) Use manually specified: /media/USER/RPI-RP2/ Forcing reset using 1200bps open/close on port /media/USER/RPI-RP2/ # バグ?で間違ったシリアルポートが選択されているので、ボートがリセットできない /home/USER/.platformio/packages/tool-rp2040tools/rp2040load -v -D .pio/build/pico/firmware.elf rp2040load 1.0.1 - compiled with go1.15.8 .Loading into Flash: [ ] 0% Loading into Flash: [= ] 5% Loading into Flash: [=== ] 11% Loading into Flash: [==== ] 16% Loading into Flash: [====== ] 22% Loading into Flash: [======== ] 27% Loading into Flash: [========= ] 33% Loading into Flash: [=========== ] 39% Loading into Flash: [============= ] 44% Loading into Flash: [=============== ] 50% Loading into Flash: [================ ] 55% Loading into Flash: [================== ] 61% Loading into Flash: [=================== ] 66% Loading into Flash: [===================== ] 72% Loading into Flash: [======================= ] 78% Loading into Flash: [======================== ] 83% Loading into Flash: [========================== ] 89% Loading into Flash: [============================ ] 94% Loading into Flash: [==============================] 100% ========================= [SUCCESS] Took 2.73 seconds =========================

重要:
・現状、バグ?で、USBシリアル経由のボード・リセットができない。
そのため、書き込み前に、ボードのbootselボタンを押しながらホストのUSBに接続して、
その後、bootselボタンを離して、書き込みストレージを出現させる必要がある。
・または、以下のようにplatformio.iniを一部修正すると ボード・リセットが正常に動き、書き込みが成功するようだ。
(もしかして、これが仕様なのかも知れない)

upload_port = /dev/ttyACM0 ;upload_port = /media/USER/RPI-RP2/ ; directory for mass-storage


Arduino用デモ・スケッチ

ASCIITablePico:
src/main.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++; }

・標準のスケッチをベースにPicoボードにリセットがないので繰り返し実行するように変更したもの

Blink:
src/main.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 }

・標準のスケッチ(変更なし)

参考情報

Pico-Platformio(Pico-SDK)関連:
Raspberry Pico: The Simple Startup with PlatformIO
BAREMETAL(pico-sdk)
Examples
Raspberry Pi Pico RP2040 - PlatformIO (Pico-SDK & Arduino)

Pico-Platformio(Arduino)関連:
Official PlatformIO + Arduino IDE support for the Raspberry Pi Pico is now available!

platformio関連:
PlatformIO Core (CLI)
Arduino-IDEとPlatformioのコンパイラーの挙動の違いについて
arduinoフレームワーク用platformio.ini集
ubuntu20.04をインストールする

以上

続きを読む "platformioでpicoを動かす"

| | コメント (0)

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進ダンプ

以上

続きを読む "Arduino-IDEでPicoを動かす"

| | コメント (0)

2021年2月27日 (土)

WSL2でのplatformioやPico-SDKの利用方法

2021/4/20++
arduinoボードにリセットをかけて書き込み用ストレージを出現させるスクリプトを追加した。

2021/4/12
uf2やmbedの書き込みのドライブを自動検出に改良した。

2021/3/10
さらにextra_script.pyを改良して mbed,uf2のファイルによる書き込みも自動化した。

2021/3/8+
さらにextra_script.pyを改良して XIAO,wio-terminalの書き込みをサポートした。

2021/3/4
さらにextra_script.pyを改良して 書き込み用ストレージがないボード(UNO,M5ATOMなど)でも プログラムが書き込めるようにした。

2021/3/1
extra_script.pyを改良して uf2まで自動生成するようにした。

2021/2/27
初版

WSL2 platformio Pico-SDK

WSL2 platformio Pico-SDK

概要

WSL2(Windows Subsystem for Linux version2)でのplatformioやPico-SDKの利用方法
WSL2でplatformioやPico-SDKを利用した場合、WSL2はUSBデバイスをサポートしていないので、そのままでは、ビルドまではできるが、書き込みができない。本記事では、その解決方法について述べる。
(ホストはubuntu20.04を想定している)

基本的な考え方は、書き込み用ストレージが現れるボードに限定されるが、 書き込み用ストレージのためのファイル(.uf2または.hex)を作成して、 それをWSL2側からPowerShellを使って該当ストレージにコピーすることで 書き込みを行う。

したがって、書き込みストレージがないボード(Arduno-UNOやESP32ボードなど)は書き込めないが、 それ以外のボード(XIAO,Wio-Terminal,Nucleo,micro:bitなど)は書き込みが可能となる。

追記1:
書き込みストレージがないボード(Arduno-UNO、M5ATOM(ESP32ボード))でも、windows側の書き込みツールを利用することでプログラムが書き込めるよう extra_script.pyを改良した。(2021/3/4)

追記2:
XIAO、wio-terminalにおいて、 windows側の書き込みツール(bossac)を利用することでプログラムが書き込めるよう extra_script.pyを改良した。(2021/3/8)

追記3:
mbedボードとuf2ファイルによる書き込みをサポートしているボードにおいて 自動的に書き込むように extra_script.pyを改良した。(2021/3/10)

準備(インストール)

platformioやPico-SDKのインストールについては 以下の記事がほとんどそのまま参考になる。 (ただし、udev登録などUSB関連は除く)

arduinoフレームワーク用platformio.ini集
PicoボードにPico_SDKでC言語をビルドする

platformioの場合

ビルド時にhexファイルが必要となるので platformio.iniに以下の行を追加する:
# 任意の位置で良いが、例えば「board=」の次の行に追加する

extra_scripts = post:extra_script.py

実行するスクリプトをカレントディレクトリに 以下の内容で作成する:
extra_script.py

Import("env") # Custom HEX from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", "$BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex" ]), "Building $BUILD_DIR/${PROGNAME}.hex") )

参照:Add a new option which could generate .hex file in platformio.ini #240

ここで「pio run」の実行すると、.hexが生成される。

mbed系ボード(nucleo,micro:bitなど)は、書き込むファイルのフォーマットが.hexなので、
以下の手順で書き込みができる:

PowerShell.exe copy .pio/build/*/firmware.hex e:

ただし、「e:」は書き込みストレージのドライブ・レターなので環境に依存するので自分の環境でのドライブ・レターに置き換える。
(windows側のエクスプローラーなどで該当のドライブ・レターを確認できる)

Microchip(Almel)SAMD21/SAMD51ボード(XIAO,Wio-Terminalなど)の場合、書き込むフォーマットは、.uf2なので変換する必要がある。

このため以下の手順でツールをインストールする:

wget https://raw.githubusercontent.com/microsoft/uf2/master/utils/uf2conv.py chmod +x uf2conv.py

参照:
uf2conv -- Packing and unpacking UF2 files

XIOA(SAMD21)ボードの場合、以下のコマンドで.uf2に変換する:

./uf2conv.py .pio/build/*/firmware.hex -f 0x68ed2b88 -c -o hex2.uf2

Wio-Termial(SAMD51)ボードの場合、以下のコマンドで.uf2に変換する:

./uf2conv.py .pio/build/*/firmware.hex -f 0x55114460 -c -o hex2.uf2

他のチップに対応する場合、「-f xxxxx」のxxxxxがfamilyID(=ChipID)なので、その部分を該当IDに置き換える。
familyIDは以下を参照のこと:
Family list vs familyID

.uf2に変換後、以下の手順で書き込む:

PowerShell.exe copy hex2.uf2 e:

ただし、「e:」は書き込みストレージのドライブ・レターなので環境に依存するので自分の環境でのドライブ・レターに置き換える。
(windows側のエクスプローラーなどで該当のドライブ・レターを確認できる)

なお、以下のスクリプトで書き込みを自動化できる:
cp_wiot.sh
# SAMD51用

#!/bin/bash ./uf2conv.py .pio/build/*/firmware.hex -f 0x55114460 -c -o hex2.uf2 PowerShell.exe copy hex2.uf2 e:

注意:familyIDがチップごとに異なることに注意のこと。

Pico-SDKの場合

ビルドすると、自動的に.uf2まで作成するので、以下の手順で書き込むことができる:

PowerShell.exe copy xxxx.uf2 e:

ただし、「e:」は書き込みストレージのドライブ・レターなので環境に依存するので自分の環境でのドライブ・レターに置き換える。
(windows側のエクスプローラーなどで該当のドライブ・レターを確認できる)

extra_script.pyの改良

以下のように改良して、uf2生成までを自動化した:
extra_script.py

Import("env") board = env.GetProjectOption("board") #print("board:"+board) # set familyID(chip ID) familyID = 'undefined!' if "seeed_wio_terminal" == board: familyID = "0x55114460" if "adafruit_feather_m4" == board: familyID = "0x55114460" if "adafruit_grandcentral_m4" == board: familyID = "0x55114460" if "seeed_xiao" == board: familyID = "0x68ed2b88" if "adafruit_circuitplayground_m0" == board: familyID = "0x68ed2b88" if "nucleo_f103rb" == board: familyID = "mbed" if "nucleo_f303k8" == board: familyID = "mbed" if 'mbed' == familyID: # Custom HEX from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", " $BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex" ]), "(1)Building $BUILD_DIR/${PROGNAME}.hex") ) elif 'undefined!' != familyID: # Custom HEX from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", " $BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex" ]), "(1)Building $BUILD_DIR/${PROGNAME}.hex") ) # uf2 from HEX env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "python3 uf2conv.py $BUILD_DIR/${PROGNAME}.hex -f ", familyID, " -c -o $BUILD_DIR/${PROGNAME}.uf2" ]), "(2)Converting $BUILD_DIR/${PROGNAME}.uf2") ) # copy uf2 to current dir env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "cp $BUILD_DIR/${PROGNAME}.uf2 ." ]), "(3)Copying ${PROGNAME}.uf2 in current dir") )

以下が改良点になる:
(1)boardチェック
boardをチェックして自動的にfamilyIDを設定する。
# 定義がないboardの場合、追加する必要あり。
(2)mbed対応
boardをチェックしてmbed系ボードの場合、自動的にhexを生成する。
(2)uf2をカレントディレクトリにコピーする
書き込みドライブにコピーする際の利便性の向上

プログラミング・ヒント:
以下の部分において「 "$BUILD_DIR/${PROGNAME}.elf",」は、
「 "$BUILD_DIR/${PROGNAME}.hex",」にしたくなるが、
通常のビルド・プロセスで生成したファイルである必要がある。

# uf2 from HEX env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf",

extra_script.pyの改良(2021/3/4,2021/3/8,2021/3/10)

以下のように、さら改良して、UNO,M5ATOM,XIAO,wio-terminal,mbedボートやuf2ファイルでの書き込みするボードを書き込めるようにした:
extra_script.py

Import("env", "projenv") # access to global construction environment #print("env:") #print(dir(env)) # access to project construction environment #print("projenv:") #print(dir(projenv)) board = env.GetProjectOption("board") #print("board:"+board) ext = env.GetProjectOption("ext") print("ext:"+ext) # set familyID(chip ID) familyID = 'undefined!' if "seeed_wio_terminal" == board: familyID = "0x55114460" if "adafruit_feather_m4" == board: familyID = "0x55114460" if "adafruit_grandcentral_m4" == board: familyID = "0x55114460" if "seeed_xiao" == board: familyID = "0x68ed2b88" if "adafruit_circuitplayground_m0" == board: familyID = "0x68ed2b88" if "nucleo_f103rb" == board: familyID = "mbed" if "nucleo_f303k8" == board: familyID = "mbed" if "bbcmicrobit" == board: familyID = "mbed" if 'esp32dev' == board: # Custom BIN from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "esptool.py --chip esp32 elf2image $BUILD_DIR/${PROGNAME}.elf" ]), "(1)Building $BUILD_DIR/${PROGNAME}.bin") ) if '' != ext: env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "./"+ext ]), "(2)Doing something for ESP32 board") ) elif 'm5stick-c' == board: # Custom BIN from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "esptool.py --chip esp32 elf2image $BUILD_DIR/${PROGNAME}.elf" ]), "(1)Building $BUILD_DIR/${PROGNAME}.bin") ) if '' != ext: env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "./"+ext ]), "(2)Doing something for m5Stick-c/M5Atom board") ) if 'uno' == board: # Custom HEX from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", " $BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex" ]), "(1)Building $BUILD_DIR/${PROGNAME}.hex") ) if '' != ext: env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "./"+ext ]), "(2)Doing something for UNO board") ) # check familyID(include mbed) if 'mbed' == familyID: # Custom HEX from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", " $BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex" ]), "(1)Building $BUILD_DIR/${PROGNAME}.hex") ) if '' != ext: env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "./"+ext ]), "(2)Doing something for mbed board") ) elif 'undefined!' != familyID: # Custom BIN from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "binary", " $BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.bin" ]), "(0)Building $BUILD_DIR/${PROGNAME}.bin") ) # Custom HEX from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", " $BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex" ]), "(1)Building $BUILD_DIR/${PROGNAME}.hex") ) # uf2 from HEX env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", # "$BUILD_DIR/${PROGNAME}.hex", env.VerboseAction(" ".join([ "python3 uf2conv.py $BUILD_DIR/${PROGNAME}.hex -f ", familyID, " -c -o $BUILD_DIR/${PROGNAME}.uf2" ]), "(2)Converting $BUILD_DIR/${PROGNAME}.uf2") ) # copy uf2 to current dir env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "cp $BUILD_DIR/${PROGNAME}.uf2 ." ]), "(3)Copying ${PROGNAME}.uf2 in current dir") ) if '' != ext: env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "./"+ext ]), "(4)Doing something for uf2 board") )

動作原理:
WSL2側で書き込みに必要なファイルを作成したあと、 windows10側のc:/tempのデイレクトリに、そのファイルをコピーして PowerShell経由でwindows側の書き込みツールを起動して ボードにプログラムを書き込む。

準備として以下を実行しておく:

#WSL2側 #ファイルをwindows10側に引き渡すディレクトリを作成する mkdir /mnt/c/temp #windows10側(PowerShell側) #windows10側の書き込みツールをインストールする scoop install avrdude pio install esptool # bossacをインストールする cd $HOME mkdir msi cd msi wget https://github.com/shumatech/BOSSA/releases/download/1.9.1/bossa-x64-1.9.1.msi Start-Process -filepath "$HOME\msi\bossa-x64-1.9.1.msi" # 実行パスを設定する $Env:Path += ";C:\Program Files (x86)\BOSSA\" # 別の機能が割り当てられているaliasを削除する del alias:curl del alias:wget # curl, wgetをインストールする scoop install curl scoop install wget # その他の必要となるツールをインストールする scoop install git

・参照:WindowsコマンドラインツールScoopのすすめ(基礎編)
・注意:設定した実行パスやalias削除は、セッションが閉じると無効になるので
PowerScriptの以下の起動スクリプト

$HOME\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

の末尾に次の行を追加する。(スクリプトファイルがない場合、新規作成する)

del alias:curl del alias:wget $Env:Path += ";C:\Program Files (x86)\BOSSA\"


UNOの場合、以下のファイルをWSL2側に用意する:
platformio.ini

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:uno] platform = atmelavr board = uno extra_scripts = post:extra_script.py ext = f_UNO.sh framework = arduino #build_flags = -Dxxxx upload_protocol = arduino monitor_speed = 115200 lib_ldf_mode = deep+ #lib_deps =

f_UNO.sh

#!/bin/bash # Arduino UNO flash writing # for debug #ls .pio/build/uno/ rm /mnt/c/temp/* cp $HOME/.platformio/packages/tool-avrdude/avrdude.conf /mnt/c/temp/ cp .pio/build/uno/firmware.hex /mnt/c/temp/ PowerShell.exe avrdude -v -p atmega328p -C c:/temp/avrdude.conf -c arduino -b 115200 -D -P COM14 -U flash:w:c:/temp/firmware.hex:i exit 0

・COM14は(window10側の)通信ポートになるが環境依存なので、自分の環境での通信ポートに変更すること。
・実行属性を与えること。


M5ATOMの場合:
platformio.ini

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:esp32dev] platform = espressif32 board = m5stick-c extra_scripts = post:extra_script.py ext = f_M5ATOM.sh framework = arduino build_flags = -DM5ATOM monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = # use M5Atom lib 3113 # use "FastLED" 126

f_M5ATOM.sh

#!/bin/bash # M5ATOM flash writing # for debug #ls .pio/build/uno/ rm /mnt/c/temp/* cp $HOME/.platformio/packages/framework-arduinoespressif32/tools/sdk/bin/bootloader_dio_40m.bin /mnt/c/temp/ cp .pio/build/esp32dev/partitions.bin /mnt/c/temp/ cp $HOME/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /mnt/c/temp/ cp .pio/build/esp32dev/firmware.bin /mnt/c/temp/ PowerShell.exe esptool.py --chip esp32 --baud 1500000 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 c:/temp/bootloader_dio_40m.bin 0x8000 c:/temp/partitions.bin 0xe000 c:/temp/boot_app0.bin 0x10000 c:/temp/firmware.bin exit 0

・自動検出になっているので通信ポートの設定はない。
・実行属性を与えること。

XIAOの場合:
platformio.ini

<ヘッダー省略> [env:seeed_xiao] platform = atmelsam board = seeed_xiao extra_scripts = post:extra_script.py ext = f_XIAO.sh framework = arduino build_flags = -DXIAO upload_protocol = sam-ba monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = # Accept new functionality in a backwards compatible manner and patches olikraus/U8g2 @ ^2.28.7

f_XIAO.sh

#!/bin/bash # XIAO flash writing # for debug #ls .pio/build/seeed_xiao/ rm /mnt/c/temp/* cp .pio/build/seeed_xiao/firmware.bin /mnt/c/temp/ PowerShell.exe bossac -p COM18 -i -e -w -v -R -o 0x2000 c:/temp/firmware.bin exit 0

・COM18は(window10側の)通信ポートになるが環境依存なので、自分の環境での通信ポートに変更すること。
・実行属性を与えること。

wio-terminalの場合:
platformio.ini

<ヘッダー省略> [env:seeed_wio_terminal] platform = atmelsam board = seeed_wio_terminal extra_scripts = post:extra_script.py ext = f.WIOT.sh framework = arduino build_flags = -DWIO_TERMINAL upload_protocol = sam-ba monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = <以下、省略>

f_WIOT.sh

#!/bin/bash # wio-terminal flash writing # for debug #ls .pio/build/seeed_wio_terminal/ rm /mnt/c/temp/* cp .pio/build/seeed_wio_terminal/firmware.bin /mnt/c/temp/ PowerShell.exe bossac -p COM15 -i -e -w -v -R -o 0x4000 c:/temp/firmware.bin exit 0

・COM15は(window10側の)通信ポートになるが環境依存なので、自分の環境での通信ポートに変更すること。
・実行属性を与えること。

wio-terminalの場合(ファイルコピーによる書き込み):
platformio.ini

<ヘッダー省略> [env:seeed_wio_terminal] platform = atmelsam board = seeed_wio_terminal extra_scripts = post:extra_script.py ext = f_UF2.sh framework = arduino build_flags = -DWIO_TERMINAL upload_protocol = sam-ba monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = <以下、省略>

/***** 書き込みドライブを自動検出にしたので、以下、廃止 *****

f_UF2.sh

#!/bin/bash rm /mnt/c/temp/* cp firmware.uf2 /mnt/c/temp/ PowerShell.exe copy c:/temp/firmware.uf2 e: exit 0

・「e:」はドライブ・レターになるが環境依存なので、自分の環境のものに変更すること。
・実行属性を与えること。
***********************************************************/

// 改良版(2021/4/12)
f_UF2.sh

#!/bin/bash rm /mnt/c/temp/* cp firmware.uf2 /mnt/c/temp/ DRIVE=`PowerShell.exe get-volume|grep FAT|awk '{print $1}'` if [ "${DRIVE}" = "" ]; then echo "bootloader-mode is not activated!" exit 1 fi PowerShell.exe copy c:/temp/firmware.uf2 ${DRIVE}: exit 0

・書き込みのドライブを自動検出に改良した。
 (ただし、接続しているドライブとしてFATタイプが1台である前提)
・実行属性を与えること。

F103RBの場合(ファイルコピーによる書き込み):
platformio.ini

<ヘッダー省略> [env:nucleo_f103rb] platform = ststm32 board = nucleo_f103rb extra_scripts = post:extra_script.py ext = f_MBED.sh framework = arduino build_flags = -DNUCLEO_F103RB monitor_speed = 115200 lib_ldf_mode = deep+ upload_protocol = stlink #lib_deps =

/***** 書き込みドライブを自動検出にしたので、以下、廃止 *****

f_MBED.sh

#!/bin/bash rm /mnt/c/temp/* cp .pio/build/*/firmware.hex /mnt/c/temp/ PowerShell.exe copy c:/temp/firmware.hex e: exit 0

・「e:」はドライブ・レターになるが環境依存なので、自分の環境のものに変更すること。
・実行属性を与えること。
***********************************************************/

// 改良版(2021/4/12)
f_MBED.sh

#!/bin/bash rm /mnt/c/temp/* cp .pio/build/*/firmware.hex /mnt/c/temp/ DRIVE=`PowerShell.exe get-volume|grep FAT|awk '{print $1}'` if [ "${DRIVE}" = "" ]; then echo "MBED board is not connected!" exit 1 fi PowerShell.exe copy c:/temp/firmware.hex ${DRIVE}: exit 0

・書き込みのドライブを自動検出に改良した。
 (ただし、接続しているドライブとしてFATタイプが1台である前提)
・実行属性を与えること。

ビルド/書き込み
以下を実行する:

pio run -t clean pio run # extra_script.py(とf_xxxx.sh)のほうで書き込みを行うので「-t upload」は不要となる

対応ボードの追加:
現状は、UNO,M5ATOM,XIAO,wio-terminal,mbedボードになるが
対応ボードを追加する場合、 「extra_script.py」の変更と、実際の書き込みを実行する「f_xxxx.sh」を追加することになる。 「f_xxxx.sh」には実際の書き込みツールのコマンドラインの記述が必要となるが、 それを知るには、[pio run -v -t upload]を実行すると実際のコマンドラインが表示されるので それを参考に「f_xxxx.sh」に記述することになる。(当然のことながら、windows10側にインストールされていないツールであれば、windows10側に、そのツールをインストールする必要がある)

(参考)PowerShell.exe get-volume の出力例

raspberry-pi-picoを接続した場合: $ PowerShell.exe get-volume DriveLetter FriendlyName FileSystemType DriveType HealthStatus OperationalStatus ----------- ------------ -------------- --------- ------------ ---------------- E RPI-RP2 FAT Removable Healthy OK D Volume NTFS Fixed Healthy OK NTFS Fixed Healthy OK System NTFS Fixed Healthy OK C Windows NTFS Fixed Healthy OK micro:bitを接続した場合: $ PowerShell.exe get-volume DriveLetter FriendlyName FileSystemType DriveType HealthStatus OperationalStatus ----------- ------------ -------------- --------- ------------ ---------------- D Volume NTFS Fixed Healthy OK NTFS Fixed Healthy OK System NTFS Fixed Healthy OK C Windows NTFS Fixed Healthy OK E MICROBIT FAT Removable Healthy OK wio-terminalを接続した場合: $ PowerShell.exe get-volume DriveLetter FriendlyName FileSystemType DriveType HealthStatus OperationalStatus ----------- ------------ -------------- --------- ------------ ---------------- D Volume NTFS Fixed Healthy OK NTFS Fixed Healthy OK System NTFS Fixed Healthy OK C Windows NTFS Fixed Healthy OK E Arduino FAT Removable Healthy OK

arduinoボードをリセットするスクリプト(2021/4/20)

USBシリアルが有効のボードでシリアル経由でリセットをかけて、書き込み用ストレージを出現させるスクリプトを紹介する。(raspberry-pi-picoボードでも有効)

windows側の準備:

.wslconfigを以下のように設定する:
C:\Users\USER\.wslconfig

[wsl2] localhostForwarding=true

以下を実行する:

#以下をインストールする(scoopがインストールされている前提) scoop install python scoop install grep scoop install gawk pip install pyserial # スクリプトを置くディレクトリを作成する mkdir ¥py

以下のスクリプトを用意する:

C:¥py¥reset_arduino.py

#!/usr/bin/env python3 import sys args = sys.argv # reset arduino board via serial import serial try: arduino = serial.Serial(args[1], baudrate=1200) arduino.close() except serial.SerialException as e: #if e.errno == 13: # raise e pass

C:¥py¥reset_arduino.ps1

$env:COMPORT=(Get-WMIObject Win32_SerialPort | Select-Object DeviceID | grep COM | gawk 'END{print}') python.exe c:\py\reset_arduino.py $env:COMPORT

・複数のシリアルが接続されている場合、一番最近接続されたものが選ばれる。
状況を単純化するためにも書き込みするボードのみを接続することを進める。

WSL側:

wsl.confは以下のように設定する:
/etc/wsl.conf

[automount] enabled=true mountFsTab=true root="/mnt/" options="" crossDistro=true [network] generateHosts=true generateResolvConf=true [interop] enabled=true appendWindowsPath=true

reset_arduino.sh

#!/bin/bash PowerShell.exe C:/py/reset_arduino.ps1

・実行属性を与えること

実行例
以下を実行するとボードにリセットがかかり書き込み用ストレージが出現する。

# ボードをホストとUSBで接続する ./reset_arduino.sh # この時点で接続されているボードがリセットされ書き込み用ストレージが出現する

参考情報

WSL関連:
wsl.conf と .wslconfig
WSLのアーキテクチャ

scoop関連:
scoopインストール方法(windows10にplatformioをインストールする(scoop版))
WindowsコマンドラインツールScoopのすすめ(基礎編)
Windowsでパッケージ管理したいなら、先ずScoopより始めよ
PowerShell コンソール内で curl や wget が実行できないとお嘆きのあなたへ

書き込みツール関連:
BOSSA
AVRDUDE - AVR Downloader/UploaDEr
esptool.py
Open source version of the STMicroelectronics STlink Tools
stlink Tools Tutorial

micro:bit関連:
micro:bit Arduino/MBED開発ツール(v2)(micro:bit-v2対応,linux版)
micro:bit v2 で遊ぶ

platformio関連:

https://docs.platformio.org/en/latest/platforms/creating_board.html Installation 1.Create boards directory in core_dir if it doesn’t exist. 2.Create myboard.json file in this boards directory. 3.Search available boards via pio boards command. You should see myboard board.

PlatformIO Core (CLI)
Arduino-IDEとPlatformioのコンパイラーの挙動の違いについて
ubuntu20.04をインストールする
【小ネタ】WSL利用時のRaspberry Pi Picoへの書き込みをコマンドラインから行う

Advanced Scripting - Before/Pre and After/Post actions

以上

続きを読む "WSL2でのplatformioやPico-SDKの利用方法"

| | コメント (0)

2021年2月10日 (水)

PicoボードのMicroPythonをVS_CodeのextensionのPico-Goでプログラミングする

2021/2/9+

VS Code extension PicoGo for MicroPython

VS Code extension PicoGo for MicroPython

概要

以下のPicoボードのMicroPythonをVS_CodeのextensionのPico-Goでプログラミングする。
(ホストPCとしてはubuntuを想定している)

Raspberry Pi Pico

準備

以下のものをインストールする:

sudo apt install nodejs pip install micropy-cli pip install pylint cd ~/Downloads wget https://github.com/cpwood/Pico-Stub/archive/main.zip uzip main.zip cd Pico-Stub-main/stubs micropy stubs add micropython-rp2-1_13-290

VS_Code_extension'Pico-Go'のインストール:
VS_CodeのなかでCtrl-Pを押して
以下を実行する:

ext install ChrisWood.pico-go

参照: Pico-Go

プロジェクトの作成

以下の手順でプロジェクトを作成する:

mkdir proj cd proj micropy init # メニューが表示されるので、以下の2つを選択して改行を押す [VScode setting ...] [Pylint MicroPython setting ..] # その後、以下を選択する [rp2-micropython-1.13] # 以上でプロジェクトの雛形が作成される # MicroPythonが書き込まれたPicoボードをUSB接続する # 以下でVS Codeを起動する code .

なお、projは。任意のプロジェクト名とする。

プログラムの作成

起動しているVS_Codeで 新規ファイルとして flash.pyを作成して
以下の内容に編集する:

flash.py

from time import sleep from machine import Pin led = Pin(25, Pin.OUT) while True: led.value(1) sleep(0.1) led.value(0) sleep(0.1)

プログラムの実行

VS_Codeの最下行の[Run]をクリックすると プログラムが実行される。

もう一度、[Run]をクリックすると実行が中止される。(トグル動作)

上のやり方で、上手く実行できなかったときは 最下行の[Pico Connected]をクリックして いったん接続を切り 最下行の[Pico Disconnected]をクリックして 再度、接続する。

なお、このやり方の実行の場合、RAMでプログラムが実行される。

フラッシュへの書き込み

Picoボードに書き込む場合は、 最初に実行されるのがboot.pyなので 以下のboot.pyを作成する:

boot.py

print("boot start..") import flash

上のプログラムでは、boot.pyから flash.pyを呼び出す形で プログラムが実行される。

最下行の[Upload]をクリックすると Picoボードにカレントディレクトリにあるファイルが書き込まれる。
実行例:

Failed to read project status, uploading all files [1/5] Writing file boot.py (0kb) [2/5] Writing file dev-requirements.txt (0kb) [3/5] Writing file flash.py (0kb) [4/5] Writing file micropy.json (0kb [5/5] Writing file requirements.txt (0kb) Upload done, resetting board... OK

upload後、プログラムが自動に実行される。
実行を止めたい場合、TERMINAL画面でCtrl-Cを押す。

これで止まらない場合は、いったん、接続を切ってから 再接続して、Ctrl-Cを押す。

なお、uploadが上手く実行できなかったときは
以下を実行する:
(1)最下行メニューから[All commands]/[Pico-Go > Delete all files from boardt]を選択する。
(2)・確認のダイヤログが画面の最上行に現れるので、[Cancel][Yes]のなかから[Yes]を選択する。
(3)TERMINAL画面に「All files and directories have been deleted from the board.」が表示され
Picoボードのなかのファイルをすべて削除される。
(4)[Uplaod]をクリックする。

参照情報

micropython-pico PDF download

Pico-Go VS Code Extension
Developing for the Raspberry Pi Pico in VS Code — Getting Started
Developing for the Raspberry Pi Pico in VS Code — Start Coding!

以上

続きを読む "PicoボードのMicroPythonをVS_CodeのextensionのPico-Goでプログラミングする"

| | コメント (0)

2021年2月 7日 (日)

MicroPython/CircuitPython Performance Test

2021/2/7

MicroPython CircuitPython Performace Test (v2)

MicroPython CircuitPython Performace Test (v2)

概要

MicroPython/CircuitPython Performance Test この記事は「 MicroPython Performance Test 」を見直して新たな結果を追加した第2版にあたる。

pyborad/STM32用MicroPythonスクリプト

PerformaceTest.py

# Peformace Test import pyb def performanceTest(): millis = pyb.millis endTime = millis() + 10000 count = 0 while millis() < endTime: count += 1 print("Count: ", count) performanceTest()

ESP32/ESP8266用MicroPythonスクリプト

PerformaceTestESP32.py

# Peformace Test for ESP32 from machine import RTC rtc = RTC() rtc.datetime((2020, 2, 9, 1, 12, 48, 0, 0)) # (year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]) def performanceTest(): secs = rtc.datetime()[6] endTime = secs + 10 count = 0 while rtc.datetime()[6] < endTime: count += 1 print("Count: ", count) performanceTest()

PC/BareMetal-RpiZeo/Linux-Rpizero/Maixduino用スクリプト

PerformanceRpiZero.py

# Peformace Test RpiZero import time def performanceTest(): msec = time.ticks_ms endTime = msec() + 10000 count = 0 while msec() < endTime: count += 1 print("Count: ", count) performanceTest()

CC3200用MicroPythonスクリプト

PerformanceTestCC3200.py

# Peformace Test for CC3200 from machine import RTC rtc = RTC(datetime=(2020, 2, 9, 10, 11, 0, 0, None)) def performanceTest(): secs = rtc.now()[5] endTime = secs + 10 count = 0 while rtc.now()[5] < endTime: count += 1 print("Count: ", count) performanceTest()

CircuitPython/Python3用スクリプト

performanceTestCPY.py

# Peformace Test CircuitPython from time import monotonic_ns def performanceTest(): endTime = monotonic_ns() + 10000000000 # 10 sec count = 0 while monotonic_ns() < endTime: count += 1 print("Count: ", count) performanceTest()

XIAO CircuitPython用スクリプト

PerformanceCircuitPython_XIAO.py

# Peformace Test XIAO CircuitPython from time import monotonic def performanceTest(): endTime = monotonic() + 10.0 # 10 sec count = 0 while monotonic() < endTime: count += 1 print("Count: ", count) performanceTest()

実行例

# pyboard/STM32の場合 $ ./pyboard.py --device /dev/ttyACM0 PerformanceTest.py Count: 2825625 # ESP32/ESP866の場合 $ ./pyboard.py --device /dev/ttyUSB0 PerformanceTestESP32.py Count: 39187

結果

ボード名 M/C/P Count
F767ZI M 5,676,566
F446RE M 2,825,625
F4Disco M 2,882,769
Maixduino M 2,218,879
Pico-MP M 1,507,516
F401RE M 1,362,752
L476RG M 1,089,347
PyPortal C 474,734
Grand-Central-M4-Express C 445,404
Feather-M4-Express C 438,444
Teensy4.0 C 432,413
Pico-CPY C 341,033
XIAO C 174,388
Circuit-Playground-Express C 121,800
ESP8266 M 64,049
ESP32 M 39,187
CC3200 M 5,529
BareMetal-RpiZero M 680,525
Linux-RpiZero P 6,370,022
PC(linux) P 161,265,687
micropython-Rpi4 M 16,117,283
python3-Rpi4 P 11,359,199


M/C/Pは、pythonの種類を表し、
M:MicroPython、
C:CircuitPython、
P:Python3
を表す。

コメント

・Pico-MPは、RPI_Picoボードの MicroPython、Pico-CPYは、RPI_PicoボードのCircuitPythonを意味する。

・BareMetal-RpiZeroは、RpiZeroでのBareMetalのmicropython、 Linux-RpiZeroは、linux上でのmicropython、 PC(Linux)は、PCのLinux上でのmicropythonを意味する。

・MaixduinoはMaixduinoのmicropythonであるMaixPyを意味する。

・Teensy4.0はTeensy4.0のCircuitPythonを意味する。

・python3-Rpi4は「python3 performanceCircuitPython.py」の数字、 micropython-Rpi4は「micropython performanceCircuitPython.py」の数字を意味する。

なお、PC(linux)のCPUは、「Intel® Core™ i7-3520M CPU @ 2.90GHz × 4 )」である。

・STM32系(F7xx/F4xx/L4xx)がESP32/ESP8266に比べてダントツに速いようだ。

・Linux-RpiZeroとBareMetal-RpiZeroの数字の違いはCPUキャッシュの有効/無効の差と思われる。

・CC3200は、他のMicroPythonボードに比べて極端に遅い結果だが、省電優先設計のせいだと思われる。

・Teensy4.0のCircuitPythonはmonotonic_ns()のオーバーヘッドが大きい気がする。

・XIAOとCircuit-Playground-Expressは、同じプロセッサATSAMD21(Cortex-M0+,48MHz)にもかかわらず、性能差が出ているのは実装の違いで、XIAOのほうは、floatで動いているのに対して、Circuit-Playground-Expressのほうは、long_intで動いていることによる差が出ていると考えている。

・Pico-MP,Pico-CPYはCortex-M0であるがクロックが他のM0より高いこと(最大133Mz)と浮動小数点ライブラリが最適化されていることでM4並みの性能が出ているようだ。MP,CPYの性能差は最適化が進んでいるかどうかの差と思われる。

参照情報

PicoボードにMicropython/CircuitPythonをインストールする

RaspberryPiのpython3でCircuitPythonのAPIを使用する

XIAOにCircuitPythonをインストールする

Circuit-Playground-ExpressにCircuitPythonをインストールする

Teensy4.0にCurcuitPythonをインストールする

BareMetalのMicropythonをRaspberryPi_Zeroにインストールしてみる

NUCLEO-F767ZIにMicropythonをインストールする(v2)
Nucleo-L476RGにMicroPythonをインストールする
Nucleo-F401REにMicroPythonをインストールする
STM32F4-Discovery」にMicroPythonをインストールする
NUCLEO-F446REにMicropythonをインストールする(v2)
NUCLEO F446RE MicroPython インストール方法

CC3200 MicroPython インストール

ESP32のMicroPythonのインストール方法
ESP-WROOM-02 MicroPython インストール方法

MicroPythonのツールとしてpyboad.pyを使う
The pyboard.py tool

ESP32-DevKitC ESP-WROOM-32開発ボード
MicroPython - Quick reference for the ESP32

ampyを用いたMicroPythonのファイル操作とプログラム実行

以上

続きを読む "MicroPython/CircuitPython Performance Test"

| | コメント (0)

PicoボードにProject_Generatorを使ってpioを含むC言語をビルドする

2021/2/7

rpi Pico Project Generator for PIO

rpi Pico Project Generator for PIO

概要

以下のPicoボードにProject_Generatorを使ってpioを含むC言語をビルドする。
PicoボードにPico_SDKでC言語をビルドする」でのインストールが既に完了している前提でホストPCとしてはubuntuを想定している。

Raspberry Pi Pico

ターミナルソフト(bt)のインストール

別のターミナルソフトがインストール済みであれば特にインストールする必要はない。

以下の手順でインストールする:

mkdir bt cd bt git clone https://github.com/wtarreau/bootterm cd bootterm make sudo make install

使い方(例)

# 以下のコマンドで接続しているシリアルのデバイス名が表示される $ bt -l port | age (sec) | device | driver | description ------+------------+------------+------------------+---------------------- 0 | 2373 | ttyS4 | serial | * 1 | 332 | ttyACM0 | cdc_acm | CircuitPython CDC control # 以下のコマンドで、最近、有効化されたシリアルデバイスに接続する $ bt No port specified, using ttyACM0 (last registered). Use -l to list ports. Trying port ttyACM0... Connected to ttyACM0 at 115200 bps. Escape character is 'Ctrl-]'. Use escape followed by '?' for help.

参照:
Bootterm – a developer-friendly serial terminal program

プロジェクトを自動生成する

プログラムの雛形を自動生成できるので使ってみる。
以下の手順でgeneratorを動かす:

cd pico # 以下の1行は、言うまでもなく、一回実行すれば良い git clone https://github.com/raspberrypi/pico-project-generator.git export PICO_SDK_PATH=~/pico/pico-sdk cd pico-project-generator ./pico_project.py --gui

以上でgeneratorのGUIが起動する。

以下のようにパラメータを入力する:

(2)Project Name: 任意のプログラムを入力する(例:pio_blink) (2)Location: プロジェクトを置くディレクトリを指定する(例:~/pico_ws) (3)Feature: pioを使用するので[PIO interface]をチェックする。 (4)Console Option: コンソールをUSBシリアルにするので、以下を選択する: [Console over USB] (5)Code Option: そのままで良い。 (6)Build Option: そのままで良い。 (7)パラメータを入力したら [OK]をクリックするとプロジェクトが生成される。 (3)generatorから抜けるとき [Quit]をクリックする

CMakeList.txtを確認する

generatorにバグがあるようなので意図どおりに設定できているか確認する:

cd ~/pico_ws # 自動生成したプロジェクトを開く cd pio_blink gedit CMakeList.txt # 内容に以下が含まれていることを確認する # 存在していない場合は、追加する # 0,1が逆になっている場合は、修正する
pico_enable_stdio_usb(pio_blink 1) pico_enable_stdio_uart(pio_blink 0)

「pio_blink」のところは、設定したプロジェクト名になる。

プログラムを編集する

cd ~/pico_ws # 自動生成したプロジェクトを開く cd pio_blink gedit pio_blink.c

以下の内容になるように編集する:

// modified on 2021/2/7 /** * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ #include <stdio.h> #include "pico/stdlib.h" #include "hardware/pio.h" #include "pio_blink.pio.h" void blink_pin_forever(PIO pio, uint sm, uint offset, uint pin, uint freq); char str[10]; int main() { //setup_default_uart(); stdio_init_all(); // wait for string typed printf("Type any string to start.\n"); fflush(stdin); scanf("%s",str); // todo get free sm PIO pio = pio0; uint offset = pio_add_program(pio, &pio_blink_program); printf("Loaded program at %d\n", offset); //blink_pin_forever(pio, 0, offset, 0, 3); //blink_pin_forever(pio, 0, offset, 25, 3); // on-board LED //blink_pin_forever(pio, 0, offset, 25, 4); // on-board LED blink_pin_forever(pio, 0, offset, 25, 1); // on-board LED blink_pin_forever(pio, 1, offset, 6, 4); blink_pin_forever(pio, 2, offset, 11, 1); } void blink_pin_forever(PIO pio, uint sm, uint offset, uint pin, uint freq) { blink_program_init(pio, sm, offset, pin); pio_sm_set_enabled(pio, sm, true); printf("Blinking pin %d at freq %d\n", pin, freq); pio->txf[sm] = 24000000 / freq; }

これは提供されているサンプルを修正したものになる。

以下の部分は実際のプログラム名(pio_blink)に合わせる:

#include "pio_blink.pio.h" pio_add_program(pio, &pio_blink_program);

pioプログラムの追加

以下のファイルを同じディレクトリに追加する: pio_blink.pio

; ; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. ; ; SPDX-License-Identifier: BSD-3-Clause ; ; SET pin 0 should be mapped to your LED GPIO .program pio_blink pull block out y, 32 .wrap_target mov x, y set pins, 1 ; Turn LED on lp1: jmp x-- lp1 ; Delay for (x + 1) cycles, x is a 32 bit number mov x, y set pins, 0 ; Turn LED off lp2: jmp x-- lp2 ; Delay for the same number of cycles again .wrap ; Blink forever! % c-sdk { // this is a raw helper function for use by the user which sets up the GPIO output, and configures the SM to output on a particular pin void blink_program_init(PIO pio, uint sm, uint offset, uint pin) { pio_gpio_init(pio, pin); pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); pio_sm_config c = pio_blink_program_get_default_config(offset); sm_config_set_set_pins(&c, pin, 1); pio_sm_init(pio, sm, offset, &c); } %}

以下の部分は実際のプログラム名(pio_blink)にあわせる:

.program pio_blink pio_blink_program_get_default_config

pioヘッダーを作成する

以下の手順で *.pioから *.pio.hを作成する:

pioasm pio_blink.pio > pio_blink.pio.h

ビルド/書き込み

ここまで完了すると後は、
以下の手順でビルド/書き込みできる:

cd ~/pico_ws/pio_blink cd build make -j4 # BOOTSELボタンを押しながらPicoボードをホストPCにUSB接続する。 # BOOTSELボタンを離す。 # 書き込み用のRPI-RP2ディレクトリが現れる cp *.uf2 /media/<USER>/RPI-RP2/

以上でファームウェア(.uf2)がPicoボードに書き込まれる。
(<USER>の部分はホストの環境に合わせる)

動作確認

picocom(またはbt)を使いPicoボードとPC間でUSBシリアルで通信する。

通信例:

$ picocom -b115200 /dev/ttyACM0 <省略> # 最初に適当な文字列を入力する Loaded program at 24 Blinking pin 25 at freq 1 Blinking pin 6 at freq 4 Blinking pin 11 at freq 1

pin25はボード上のLEDなのでLEDが点滅する。 pin6,11は、ブレッドボードなどでLEDを接続してあれば 別の周期で点滅する。

参照情報

Programmable I/O with Raspberry Pi Pico

How to add a reset button to your Raspberry Pi Pico

All you need to do is to wire the GND and RUN pins together and add an extra momentary contact button to your breadboard. Pushing the button will reset the board.

Programmable I/O with Raspberry Pi Pico

Raspberry Pi Picoスタートガイド C/C++
Pico C/C++ SDK
Pico SDK docs

Raspberry Pi Pico Datasheet
RP2040 Datasheet

Raspberry Pi Pico Pinout

Ubuntu 18.04 に Cmake の Latest Release をインストールする

以上

続きを読む "PicoボードにProject_Generatorを使ってpioを含むC言語をビルドする"

| | コメント (0)

2021年2月 6日 (土)

PicoボードにProject_Generatorを使ってC言語をビルドする

2021/2/24
ソース(morse_blinky.c)修正。

2021/2/6

rpi Pico Project Generator

rpi Pico Project Generator

概要

以下のPicoボードにProject_Generatorを使ってC言語をビルドする。
PicoボードにPico_SDKでC言語をビルドする」でのインストールが既に完了している前提でホストPCとしてはubuntuを想定している。

Raspberry Pi Pico

ターミナルソフト(bt)のインストール

別のターミナルソフトがインストール済みであれば特にインストールする必要はない。

以下の手順でインストールする:

mkdir bt cd bt git clone https://github.com/wtarreau/bootterm cd bootterm make sudo make install

使い方(例)

# 以下のコマンドで接続しているシリアルのデバイス名が表示される $ bt -l port | age (sec) | device | driver | description ------+------------+------------+------------------+---------------------- 0 | 2373 | ttyS4 | serial | * 1 | 332 | ttyACM0 | cdc_acm | CircuitPython CDC control # 以下のコマンドで、最近、有効化されたシリアルデバイスに接続する $ bt No port specified, using ttyACM0 (last registered). Use -l to list ports. Trying port ttyACM0... Connected to ttyACM0 at 115200 bps. Escape character is 'Ctrl-]'. Use escape followed by '?' for help.

参照:
Bootterm – a developer-friendly serial terminal program

プロジェクトを自動生成する

プログラムの雛形を自動生成できるので使ってみる。
以下の手順でgeneratorを動かす:

cd pico # 以下の1行は、言うまでもなく、一回実行すれば良い git clone https://github.com/raspberrypi/pico-project-generator.git export PICO_SDK_PATH=~/pico/pico-sdk cd pico-project-generator ./pico_project.py --gui

以上でgeneratorのGUIが起動する。

以下のようにパラメータを入力する:

(2)Project Name: 任意のプログラムを入力する(例:morse_blinky) (2)Location: プロジェクトを置くディレクトリを指定する(例:~/pico_ws) (3)Feature: 利用する機能にチェックを入れる (4)Console Option: コンソールをUSBシリアルにするので、以下を選択する: [Console over USB] (5)Code Option: そのままで良い。 (6)Build Option: そのままで良い。 (7)パラメータを入力したら [OK]をクリックするとプロジェクトが生成される。 (3)generatorから抜けるとき [Quit]をクリックする

CMakeList.txtを確認する

cd ~/pico_ws # 自動生成したプロジェクトを開く cd morse_blinky gedit CMakeList.txt # 内容に以下が含まれていることを確認する # 存在していない場合、追加する
# enable usb output, disable uart output pico_enable_stdio_usb(morse_blinky 1) pico_enable_stdio_uart(morse_blinky 0)

「morse_blinky」のところは、設定したプロジェクト名になる。

プログラムを編集する

cd ~/pico_ws # 自動生成したプロジェクトを開く cd morse_blinky gedit morse_blinky.c

以下の内容になるように編集する:

// 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 }; void put_morse_letter(const char *pattern) { for (; *pattern; ++pattern) { gpio_put(LED_PIN, 1); if (*pattern == '.') sleep_ms(DOT_PERIOD_MS); else sleep_ms(DOT_PERIOD_MS * 3); gpio_put(LED_PIN, 0); sleep_ms(DOT_PERIOD_MS * 1); } sleep_ms(DOT_PERIOD_MS * 2); } void put_morse_str(const char *str) { for (; *str; ++str) { //if (*str >= 'A' && *str < 'Z') { if (*str >= 'A' && *str <= 'Z') { put_morse_letter(morse_letters[*str - 'A']); //} else if (*str >= 'a' && *str < 'z') { } else if (*str >= 'a' && *str <= 'z') { put_morse_letter(morse_letters[*str - 'a']); } else if (*str == ' ') { sleep_ms(DOT_PERIOD_MS * 4); } } } 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); } }

これは提供されているサンプルを変更したものになる。

ビルド/書き込み

以下の手順でビルド/書き込みできる:

cd ~/pico_ws/morse_blinky cd build make -j4 # BOOTSELボタンを押しながらPicoボードをホストPCにUSB接続する。 # BOOTSELボタンを離す。 # 書き込み用のRPI-RP2ディレクトリが現れる cp *.uf2 /media/<USER>/RPI-RP2/

以上でファームウェア(.uf2)がPicoボードに書き込まれる。
(<USER>の部分はホストの環境に合わせる)

なお、ソースを修正する場合、以下のようにする:

gedit ../morse_blinky.c

動作確認

picocom(またはbt)を使いPicoボードとPC間でUSBシリアルで通信する。

通信例:

$ picocom -b115200 /dev/ttyACM0 <省略> # 最初に適当な文字を入力する morse: adf # 以降、入力した文字列のモールス信号がボード上のLEDで点滅する Enter String for Morse morse: kool Enter String for Morse morse: pool Enter String for Morse

参照情報

How to add a reset button to your Raspberry Pi Pico
All you need to do is to wire the GND and RUN pins together and add an extra momentary contact button to your breadboard. Pushing the button will reset the board.

Programmable I/O with Raspberry Pi Pico

Raspberry Pi Picoスタートガイド C/C++
Pico C/C++ SDK
Pico SDK docs

Raspberry Pi Pico Datasheet
RP2040 Datasheet

Raspberry Pi Pico Pinout

Ubuntu 18.04 に Cmake の Latest Release をインストールする

以上

続きを読む "PicoボードにProject_Generatorを使ってC言語をビルドする"

| | コメント (0)

2021年2月 4日 (木)

PicoボードにPico_SDKでC言語をビルドする

2021/2/23+
openocdのudev登録を追加。
gdbの実行例を追加。

2021/2/17
必要なライブラリのインストールの追加。

2021/2/4
初版

rpi Pico SDK C/C++

rpi Pico SDK C/C++

概要

以下のPicoボードにPico_SDKでC言語をビルドする。
(ホストPCとしてはubuntuを想定している)

Raspberry Pi Pico

事前準備

以下の手順でツールをインストールする:

sudo apt update sudo apt install gcc-arm-none-eabi build-essential sudo apt install curl git picocom # udevのrulesを登録する curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/master/scripts/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules sudo udevadm control --reload-rules sudo usermod -a -G dialout $USER sudo usermod -a -G plugdev $USER # 必要なライブラリのインストール sudo apt install libusb-dev sudo apt install libusb-1.0-0-dev # ビルド時にエラーになったのでcmake最新版をインストールする # 古いcmakeを削除する sudo apt remove cmake mkdir ~/cmake_latest cd ~/cmake_latest wget https://github.com/Kitware/CMake/releases/download/v3.17.1/cmake-3.17.1.tar.gz tar zxvf cmake-3.17.1.tar.gz cd cmake-3.17.1/ ./bootstrap make sudo make install # gdbのインストール sudo apt install gdb-multiarch

Pico_SDKの準備

以下の手順で必要なものをインストールする:

# pico SDK のダウンロード mkdir ~/pico git clone -b master https://github.com/raspberrypi/pico-sdk.git cd pico-sdk git submodule update --init # picotoolのインストール cd ~/pico git clone https://github.com/raspberrypi/picotool.git cd picotool mkdir build cd build export PICO_SDK_PATH=../../pico-sdk cmake .. make sudo cp picotool /usr/local/bin/ # elf2uf2のインストール # (sdkの環境のまま使用するときは不要) cd ~/pico cd pico-sdk/tools/elf2uf2 mkdir build cd build export PICO_SDK_PATH=../../../../pico-sdk cmake .. make sudo cp elf2uf2 /usr/local/bin/ # pioasmのインストール # (sdkの環境のまま使用するときは不要) cd ~/pico cd pico-sdk/tools/pioasm mkdir build cd build export PICO_SDK_PATH=../../../../pico-sdk cmake .. make sudo cp pioasm /usr/local/bin/

以下を.bashrcを登録する:

export PICO_SDK_PATH=~/pico/pico-sdk

サンプルプログラムのダウンロード

以下の手順でダウンロードする:

cd ~/pico git clone -b master https://github.com/raspberrypi/pico-examples.git

サンプルプログラム(blink)のビルド

cd ~/pico cd pico-examples mkdir build cd build export PICO_SDK_PATH=../../pico-sdk cmake .. cd blink make -j4 # ビルド結果を確認する ls CMakeFiles blink.bin blink.elf blink.hex cmake_install.cmake Makefile blink.dis blink.elf.map blink.uf2 elf2uf2

別のサンプル(hello_workd)のビルド

cd ~/pico cd pico-examples # すでにあるbuildをいったん削除する rm -rf build/ mkdir build cd build export PICO_SDK_PATH=../../pico-sdk cmake .. cd hello_world make -j4 # この例では2つのビルド結果ができるので確認する # その1: ls serial/ CMakeFiles hello_serial.bin hello_serial.elf.map Makefile hello_serial.dis hello_serial.hex cmake_install.cmake hello_serial.elf hello_serial.uf2 # その2: ls usb/ CMakeFiles hello_usb.bin hello_usb.elf.map Makefile hello_usb.dis hello_usb.hex cmake_install.cmake hello_usb.elf hello_usb.uf2

他のサンプルも上の手順で「cd hello_world」のところをビルドしたい サンプルのディレクトリに置き換えて実行すればビルドできる。

ビルドしたファームウェアの確認

以下のやり方でファームウェアの内容を確認できる:

$ picotool info firmware.uf2 File firmware.uf2: Program Information name: MicroPython version: de1239b6a features: USB REPL thread support frozen modules: _boot, rp2, ds18x20, onewire, uasyncio, uasyncio/core, uasyncio/event, uasyncio/funcs, uasyncio/lock, uasyncio/stream

ビルドしたファームウェアの書き込み

以下の手順で書き込む:(ディレクトリ位置は例)

# BOOTSELボタンを押しながらPicoボードをホストPCにUSB接続する。 # BOOTSELボタンを離す。 # 書き込み用のRPI-RP2ディレクトリが現れる cd build cd hello_world sudo cp usb/hello_usb.uf2 /media/<USER>/RPI-RP2/

以上でファームウェア(.uf2)がPicoボードに書き込まれる。
(<USER>の部分はホストの環境に合わせる)

動作確認

picocomを使いPicoボードとPC間でUSBシリアルで通信する。
通信例:

$ picocom -b115200 /dev/ttyACM0 <省略> Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! <省略>

プロジェクトを自動生成する

プログラムの雛形を自動生成できるので使ってみる。
以下の手順でgeneratorを動かす:

cd pico git clone https://github.com/raspberrypi/pico-project-generator.git cd pico-project-generator ./pico_project.py --gui

以上でgeneratorのGUIが起動する。

以下のようにパラメータを入力する:

(2)Project Name: 任意のプログラムを入力する(例:mycode) (2)Location: プロジェクトを置くディレクトリを指定する(例:~/pico_ws) (3)Feature: 利用する機能にチェックを入れる (4)Console Option: arduinoボード同様にコンソールをUSBシリアルにしたい場合、以下を選択する: [Console over USB] (5)Code Option: そのままで良い。 (6)Build Option: そのままで良い。 (7)パラメータを入力したら [OK]をクリックするとプロジェクトが生成される。 (3)generatorから抜けるとき [Quit]をクリックする

ビルド/書き込み 以下の手順でビルドできる:(例)

cd ~/pico_ws/mycode cd build make cp mycode.uf2 /media/<USER>/RPI-RP2

この場合、ソースは~/pico_ws/mycodeにある。

実際には、ここにある雛形のソース(mycode.c)を編集してプログラムする。

picoprobe

PICOボードをデバッグ(picoprobe)ボードにするためのファームウェアが提供されているので、それをビルドする:

build

export PICO_SDK_PATH=~/pico/pico-sdk cd ~/pico git clone https://github.com/raspberrypi/picoprobe.git cd picoprobe mkdir build cd build cmake .. make -j4 # PICOボードに書き込む sudo cp picoprobe.uf2 /media/<USER>/RPI-RP2/

以上で、PICOボードが以下の機能をもつデバッグボードになる。

  1. CDC UART (USBシリアル)
  2. SWD probe

picoprobe対応のOpenOCDのビルド

cd ~/pico sudo apt install automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev git clone https://github.com/raspberrypi/openocd.git --branch picoprobe --depth=1 cd openocd ./bootstrap ./configure --enable-picoprobe make -j4 sudo make install

openocdのudev登録
以下の手順で登録する:

echo 'ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE="0666"' | sudo tee /etc/udev/rules.d/99-picoprobe.rules sudo udevadm trigger

この登録がないと一般ユーザーとしてのopenocdを起動した場合「Error: libusb_open() failed with LIBUSB_ERROR_ACCESS」のエラーが出る。

起動方法

openocd -f interface/picoprobe.cfg -f target/rp2040.cfg -s tcl Open On-Chip Debugger 0.10.0+dev-g14c0d0d-dirty (2021-02-01-08: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 : Listening on port 6666 for tcl connections Info : Listening on port 4444 for telnet connections Info : clock speed 5000 kHz Info : DAP init failed # ターゲットボードを接続していないのでDAPでエラーになっている # Connect GDB as you usually would with # target remote localhost:3333

ドキュメントの起動方法はミス・スペルがあったので注意のこと。

実際にターゲットボードと接続したときのgdbでの実行例

#別のterminalで以下を実行してopenocdを起動する(サーバーとして動作する) openocd -f interface/picoprobe.cfg -f target/rp2040.cfg -s tcl #もう一つのterminalで以下を実行する: $ cd ~/pico/pico-examples/build/blink $ gdb-multiarch blink.elf GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from blink.elf... # 以下でopenocdと接続する (gdb) target remote :3333 Remote debugging using :3333 0x100009ce in sleep_ms () (gdb) mon reset init 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 (gdb) load Loading section .boot2, size 0x100 lma 0x10000000 Loading section .text, size 0x2608 lma 0x10000100 Loading section .rodata, size 0xd8 lma 0x10002708 Loading section .binary_info, size 0x1c lma 0x100027e0 Loading section .data, size 0x99c lma 0x100027fc Start address 0x10000104, load size 12696 Transfer rate: 7 KB/sec, 2539 bytes/write. # mainにブレークポイントを設定する (gdb) b main Breakpoint 1 at 0x1000037c # 実行する (gdb) c Continuing. Note: automatically using hardware breakpoints for read-only addresses. target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00 # 以下のようにブレークする Thread 1 hit Breakpoint 1, 0x1000037c in main () # さらに実行する (gdb) c Continuing. ^Ctarget halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00 Thread 1 received signal SIGINT, Interrupt. 0x100009ce in sleep_ms () <省略>

なお、targetボードには、あらかじめblink.uf2を書き込んでおく。

DebugボードとTargetボードの接続方法:
(1)DebuggerボードUSBコネクタ側 上面左側

Pin Target側Pin
GP0 NC
GP1 NC
GND GND
GP2 SWCLK
GP3 SWDIO
GP4(TX) GP1(RX)
GP5(RX) GP0(TX)


(2)DebuggerボードUSBコネクタ側 上面右側

Pin Target側Pin
VBUS(5V) NC
VSYS(IN 1.8V-5.5V) NC
GND GND
3V3EN NC
3V3(OUT) VSYS


(1) NC: None Connection
(2) VBUS(5V):
・USBコネクタの5Vに接続されているのでUSBコネクタで給電している場合、5Vが出力される。
・USBホストモードで使用する際は、ここに5Vを給電する。
(3) 配線状況:
TargetボードはDebugボードから給電される配線になっている。
したがって、USBコネクタとPCを接続するのはDebugボードのみになる。

参照情報

How to add a reset button to your Raspberry Pi Pico
All you need to do is to wire the GND and RUN pins together and add an extra momentary contact button to your breadboard. Pushing the button will reset the board.

Programmable I/O with Raspberry Pi Pico

Raspberry Pi Picoスタートガイド C/C++
Pico C/C++ SDK
Pico SDK docs

Raspberry Pi Pico Datasheet
RP2040 Datasheet

Pico Pinout

Ubuntu 18.04 に Cmake の Latest Release をインストールする

Ubuntu 20.04のPCでRaspberry Pi Picoを2台使ってOpenOCDによるデバッグ

以上

続きを読む "PicoボードにPico_SDKでC言語をビルドする"

| | コメント (2)

2021年2月 3日 (水)

PicoボードにMicropython/CircuitPythonをインストールする

2021/2/3

rpi Pico MicroPython/CircuitPython Install

rpi Pico MicroPython/CircuitPython Install

概要

以下のPicoボードにMicropython/CircuitPythonをインストールする方法について記載する。
(ホストPCとしてはubuntuを想定している)

Raspberry Pi Pico

MicroPytho PreBuild

プリビルドしたファームウェアを使う場合
以下を手順でファームウェアをダウンロードする:

cd ~/Downloads wget https://www.raspberrypi.org/documentation/pico/getting-started/static/5d8e777377e8dbe23cf36360d6efc727/pico_micropython_20210121.uf2

このファームウェアを「ビルドしたファームウェアの書き込み」の手順で書き込む。

ソースからビルドする場合、以降の手順でビルドする。

事前準備

以下の手順でツールをインストールする:

sudo apt update sudo apt install gcc-arm-none-eabi build-essential # ビルド時にエラーになったのでcmake最新版をインストールする # 古いcmakeを削除する sudo apt remove cmake mkdir ~/cmake_latest cd ~/cmake_latest wget https://github.com/Kitware/CMake/releases/download/v3.17.1/cmake-3.17.1.tar.gz tar zxvf cmake-3.17.1.tar.gz cd cmake-3.17.1/ ./bootstrap make sudo make install

該当ツールのインストール

以下の手順でインストールする:

# pico SDK のダウンロード mkdir ~/pico git clone -b master https://github.com/raspberrypi/pico-sdk.git cd pico-sdk git submodule update --init # picotoolのインストール cd ~/pico git clone https://github.com/raspberrypi/picotool.git cd picotool mkdir build cd build export PICO_SDK_PATH=../../pico-sdk cmake .. make sudo cp picotool /usr/local/bin/ # elf2uf2のインストール cd ~/pico cd pico-sdk/tools/elf2uf2 mkdir build cd build export PICO_SDK_PATH=../../../../pico-sdk cmake .. make sudo cp elf2uf2 /usr/local/bin/ # pioasmのインストール cd ~/pico cd pico-sdk/tools/pioasm mkdir build cd build export PICO_SDK_PATH=../../../../pico-sdk cmake .. make sudo cp pioasm /usr/local/bin/

MicroPython Build

以下の手順でビルドする:

cd ~/pico git clone -b pico https://github.com/raspberrypi/micropython.git cd micropython git submodule update --init -- lib/pico-sdk cd lib/pico-sdk git submodule update --init cd ../.. make -C mpy-cross cd ports/rp2 make clean make ls build CMakeCache.txt elf2uf2 firmware.elf.map frozen_mpy CMakeFiles firmware.bin firmware.hex generated Makefile firmware.dis firmware.uf2 genhdr cmake_install.cmake firmware.elf frozen_content.c pico_sdk

この時点でfirmware.*がビルドされる。 実際にPicoボードで書き込むのは、firmware.uf2になる。

ビルドしたファームウェアの確認

以下のやり方でファームウェアの内容を確認できる:

$ picotool info firmware.uf2 File firmware.uf2: Program Information name: MicroPython version: de1239b6a features: USB REPL thread support frozen modules: _boot, rp2, ds18x20, onewire, uasyncio, uasyncio/core, uasyncio/event, uasyncio/funcs, uasyncio/lock, uasyncio/stream

ビルドしたファームウェアの書き込み

以下の手順で書き込む:

# BOOTSELボタンを押しながらPicoボードをホストPCにUSB接続する。 # 接続後、BOOTSELボタンを離す。 cd build sudo cp firmwre.uf2 /media/<USER>/RPI-RP2

以上でfirmwareがボードに書き込まれる。
(<USER>の部分はホストの環境に合わせる)

動作確認(REPL)

picocomを使いボードとシリアルで通信する。
以下、通信例:

$ picocom /dev/ttyACM0 -b115200 MPY: soft reboot MicroPython de1239b6a on 2021-01-24; Raspberry Pi Pico with RP2040 Type "help()" for more information. >>> import os >>> os.uname() (sysname='rp2', nodename='rp2', release='1.13.0', version='de1239b6a on 2021-01-24 (GNU 6.3.1 MinSizeRel)', machine='Raspberry Pi Pico with RP2040') >>> >>> import gc >>> gc.collect() >>> gc.mem_free() 187904

オンライン・ヘルプ表示:

>>> help() Welcome to MicroPython! For online help please visit https://micropython.org/help/. For access to the hardware use the 'machine' module. RP2 specific commands are in the 'rp2' module. Quick overview of some objects: machine.Pin(pin) -- get a pin, eg machine.Pin(0) machine.Pin(pin, m, [p]) -- get a pin and configure it for IO mode m, pull mode p methods: init(..), value([v]), high(), low(), irq(handler) machine.ADC(pin) -- make an analog object from a pin methods: read_u16() machine.PWM(pin) -- make a PWM object from a pin methods: deinit(), freq([f]), duty_u16([d]), duty_ns([d]) machine.I2C(id) -- create an I2C object (id=0,1) methods: readfrom(addr, buf, stop=True), writeto(addr, buf, stop=True) readfrom_mem(addr, memaddr, arg), writeto_mem(addr, memaddr, arg) machine.SPI(id, baudrate=1000000) -- create an SPI object (id=0,1) methods: read(nbytes, write=0x00), write(buf), write_readinto(wr_buf, rd_buf) machine.Timer(freq, callback) -- create a software timer object eg: machine.Timer(freq=1, callback=lambda t:print(t)) Pins are numbered 0-29, and 26-29 have ADC capabilities Pin IO modes are: Pin.IN, Pin.OUT, Pin.ALT Pin pull modes are: Pin.PULL_UP, Pin.PULL_DOWN Useful control commands: CTRL-C -- interrupt a running program CTRL-D -- on a blank line, do a soft reset of the board CTRL-E -- on a blank line, enter paste mode For further help on a specific object, type help(obj) For a list of available modules, type help('modules') >>> help('modules') __main__ framebuf uasyncio/__init__ uio _boot gc uasyncio/core uos _onewire machine uasyncio/event urandom _rp2 math uasyncio/funcs uselect _thread micropython uasyncio/lock ustruct _uasyncio onewire uasyncio/stream usys builtins rp2 ubinascii utime ds18x20 uarray ucollections Plus any modules on the filesystem >>> >>> >>>

MicroPython demo scripts

blink.py

from time import sleep from machine import Pin led = Pin(25, Pin.OUT) while True: led.value(1) sleep(0.1) led.value(0) sleep(0.1)

neopixel_ring.py

# Example using PIO to drive a set of WS2812 LEDs. import array, time from machine import Pin import rp2 # Configure the number of WS2812 LEDs. NUM_LEDS = 24 #16 PIN_NUM = 6 brightness = 0.2 @rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) def ws2812(): T1 = 2 T2 = 5 T3 = 3 wrap_target() label("bitloop") out(x, 1) .side(0) [T3 - 1] jmp(not_x, "do_zero") .side(1) [T1 - 1] jmp("bitloop") .side(1) [T2 - 1] label("do_zero") nop() .side(0) [T2 - 1] wrap() # Create the StateMachine with the ws2812 program, outputting on pin sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM)) # Start the StateMachine, it will wait for data on its FIFO. sm.active(1) # Display a pattern on the LEDs via an array of LED RGB values. ar = array.array("I", [0 for _ in range(NUM_LEDS)]) ########################################################################## def pixels_show(): dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)]) for i,c in enumerate(ar): r = int(((c >> 8) & 0xFF) * brightness) g = int(((c >> 16) & 0xFF) * brightness) b = int((c & 0xFF) * brightness) dimmer_ar[i] = (g<<16) + (r<<8) + b sm.put(dimmer_ar, 8) time.sleep_ms(10) def pixels_set(i, color): ar[i] = (color[1]<<16) + (color[0]<<8) + color[2] def pixels_fill(color): for i in range(len(ar)): pixels_set(i, color) def color_chase(color, wait): for i in range(NUM_LEDS): pixels_set(i, color) time.sleep(wait) pixels_show() time.sleep(0.2) def wheel(pos): # Input a value 0 to 255 to get a color value. # The colours are a transition r - g - b - back to r. if pos < 0 or pos > 255: return (0, 0, 0) if pos < 85: return (255 - pos * 3, pos * 3, 0) if pos < 170: pos -= 85 return (0, 255 - pos * 3, pos * 3) pos -= 170 return (pos * 3, 0, 255 - pos * 3) def rainbow_cycle(wait): for j in range(255): for i in range(NUM_LEDS): rc_index = (i * 256 // NUM_LEDS) + j pixels_set(i, wheel(rc_index & 255)) pixels_show() time.sleep(wait) BLACK = (0, 0, 0) RED = (255, 0, 0) YELLOW = (255, 150, 0) GREEN = (0, 255, 0) CYAN = (0, 255, 255) BLUE = (0, 0, 255) PURPLE = (180, 0, 255) WHITE = (255, 255, 255) COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE) print("fills") for color in COLORS: pixels_fill(color) pixels_show() time.sleep(0.2) print("chases") for color in COLORS: color_chase(color, 0.01) print("rainbow") rainbow_cycle(0)

pioで正確なタイミングを作っているせいか 今までのやり方のものよりも、安定して光る印象がある。

pio_blink.py

import time from rp2 import PIO, asm_pio from machine import Pin # Define the blink program. It has one GPIO to bind to on the set instruction, which is an output pin. # Use lots of delays to make the blinking visible by eye. @asm_pio(set_init=rp2.PIO.OUT_LOW) def blink(): wrap_target() set(pins, 1) [31] nop() [31] nop() [31] nop() [31] nop() [31] set(pins, 0) [31] nop() [31] nop() [31] nop() [31] nop() [31] wrap() # Instantiate a state machine with the blink program, at 1000Hz, with set bound to Pin(25) (LED on the rp2 board) sm = rp2.StateMachine(0, blink, freq=1000, set_base=Pin(25)) # Run the state machine for 3 seconds. The LED should blink. sm.active(1) #time.sleep(3) time.sleep(10) sm.active(0)

pio実装によるblinkになる。

pwn_fade.py

# Example using PWM to fade an LED. import time from machine import Pin, PWM # Construct PWM object, with LED on Pin(25). pwm = PWM(Pin(25)) # Set the PWM frequency. pwm.freq(1000) # Fade the LED in and out a few times. duty = 0 direction = 1 while True: for _ in range(8 * 256): duty += direction if duty > 255: duty = 255 direction = -1 elif duty < 0: duty = 0 direction = 1 pwm.duty_u16(duty * duty) time.sleep(0.001)

Performance Test for MicroPython

# Peformace Test import time def performanceTest(): msec = time.ticks_ms endTime = msec() + 10000 count = 0 while msec() < endTime: count += 1 print("Count: ", count) performanceTest()

以下が出力される:
Count: 1507516

thonny(pyhton用エディタ)

言うまでもなく、通常のエディタを使ってプログラムすることが可能だが、ここでは専用のエディタをインストールして使用してみる。

以下の手順でインストールする:

bash <(curl -s https://thonny.org/installer-for-linux) # ディスクトップにアイコンができる

起動/設定:

# 起動 # thonnyアイコンをクリックする # 設定 (1)実行後、picoボードをPCにUSB接続する (2)Tools/Options/Interpreterを選択する [Which interpreter or device should Thonny use for running your code?] のプルダウンメニューから以下を選ぶ: 「MicroPyton(Raspberry Pi Pico」 (3)「Port」のプルダウンメニューから実際に接続しているポート(/dev/ttyACM0など)を選択する

CircuitPythonダウンロード&書き込み

以下を手順でファームウェアをダウンロードする:

cd ~/Downloads wget https://downloads.circuitpython.org/bin/raspberry_pi_pico/en_US/adafruit-circuitpython-raspberry_pi_pico-en_US-6.2.0-beta.1.uf2

このファームウェアを「ビルドしたファームウェアの書き込み」の手順で書き込む。

REPL(CircuitPython)

Press any key to enter the REPL. Use CTRL-D to reload. Adafruit CircuitPython 6.2.0-beta.1 on 2021-01-27; Raspberry Pi Pico with rp2040 >>> soft reboot Auto-reload is on. Simply save files over USB to run them or enter REPL to disable. code.py output: Hello World! Code done running. Press any key to enter the REPL. Use CTRL-D to reload. Adafruit CircuitPython 6.2.0-beta.1 on 2021-01-27; Raspberry Pi Pico with rp2040 >>> import os >>> os.uname() (sysname='rp2040', nodename='rp2040', release='6.2.0', version='6.2.0-beta.1 on 2021-01-27', machine='Raspberry Pi Pico with rp2040') >>> list(5 * x + y for x in range(10) for y in [4, 2, 1]) [4, 2, 1, 9, 7, 6, 14, 12, 11, 19, 17, 16, 24, 22, 21, 29, 27, 26, 34, 32, 31, 39, 37, 36, 44, 42, 41, 49, 47, 46] >>> import gc >>> gc.collect() >>> gc.mem_free() 220640 >>> >>> import board >>> dir(board) ['__class__', 'A0', 'A1', 'A2', 'GP0', 'GP1', 'GP10', 'GP11', 'GP12', 'GP13', 'GP14', 'GP15', 'GP16', 'GP17', 'GP18', 'GP19', 'GP2', 'GP20', 'GP21', 'GP22', 'GP25', 'GP26', 'GP26_A0', 'GP27', 'GP27_A1', 'GP28', 'GP28_A2', 'GP3', 'GP4', 'GP5', 'GP6', 'GP7', 'GP8', 'GP9', 'LED']
>>> help() Welcome to Adafruit CircuitPython 6.2.0-beta.1! Please visit learn.adafruit.com/category/circuitpython for project guides. To list built-in modules please do `help("modules")`. >>> help("modules") __main__ collections microcontroller storage _bleio digitalio micropython struct _pixelbuf displayio msgpack supervisor adafruit_bus_device errno neopixel_write sys analogio fontio os terminalio array framebufferio pwmio time binascii gamepad random touchio bitbangio gc re ulab board io rp2pio usb_hid builtins json sdcardio usb_midi busio math sharpdisplay vectorio Plus any modules on the filesystem >>>

CircuitPython demo scripts

blink.py

# blink for CircuitPython from time import sleep import board import digitalio led = digitalio.DigitalInOut(board.LED) led.direction = digitalio.Direction.OUTPUT while True: led.value = True sleep(0.1) led.value = False sleep(0.1)

Performance Test for CircuitPython

# Peformace Test CircuitPython from time import monotonic_ns def performanceTest(): endTime = monotonic_ns() + 10000000000 # 10 sec count = 0 while monotonic_ns() < endTime: count += 1 print("Count: ", count) performanceTest()

以下が出力される:
Count: 341033

参照情報

Raspberry Pi Picoスタートガイド C/C++
Pico C/C++ SDK
Pico SDK docs

Pico Python SDK

Pico Pinout

Ubuntu 18.04 に Cmake の Latest Release をインストールする

NUCLEO-F767ZIにMicropythonをインストールする(v2)

MicroPython Performance Test

以上

続きを読む "PicoボードにMicropython/CircuitPythonをインストールする"

| | コメント (0)