« プログラミング言語RustをXIAOで動かす | トップページ | XIAOボードでTinyGOを動かす »

2020年6月10日 (水)

開発ツールPlatformIOをcliで使う(Seeeduino-XIAO版)

2020/6/10

PlatformIO cli XIAO

PlatformIO cli XIAO

概要

開発ツールPlatformIOをcli(comand line interface)で使う(Seeeduino-XIAO版)。VisualCodeのプラグインとしてPlatformIOを使用することができるが、ここでは、cliとしての使い方について記する。 (ホストPCとしてはubuntuを想定している)

PlatformIOのインストール

python3 -m venv pio_env source pio_env/bin/activate pip3 install platformio インストール後も、本ツールを使用する場合 同じディレクトリで以下を実行する: source pio_env/bin/activate # 「source」は、「.」でも良い

準備

以下を実行して、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

過去に設定してあったとしても、rulesが更新されている場合があるので、再設定したほうが良い。特にXIAOのような比較的新しいボードでは必須のような気がする。

テスト用プロジェクト xiao_sample を作成/実行する

#ターゲットボードのtarget名を検索する # (ここではxiaoを検索する) pio boards | grep -i xiao #出力例: seeed_xiao SAMD21G18A 48MHz 256KB 32KB Seeeduino XIAO .... #target名として「seeed_xiao」が判明した # プロジェクト xiao_sample のディレクトリを作成する mkdir xiao_sample cd xiao_sample # 以下を実行して必要なファイルを作成する pio init --board seeed_xiao # platformをupdateする # (updateしないとコンパイルエラーが出るようなのでupdateは必須となる) pio platform update nano 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:seeed_xiao] platform = atmelsam board = seeed_xiao framework = arduino upload_protocol = sam-ba
# テスト用のblink.inoを作成する nano src/blink.ino 以下のように編集する:
void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { digitalWrite(LED_BUILTIN, HIGH); delay(1000); digitalWrite(LED_BUILTIN, LOW); delay(1000); }

続き:

# build pio run # ボードをホストPCに接続する # build&upload(flash) pio run -t upload # buildしないで書き込む場合は以下を実行する: pio run -t nobuild -t upload -v # -v は、詳細を表示するオプション # 以上で、基本的な操作としては完了となる

オンボードのLEDが点滅すれば動作としてはOKとなる。

これ以降、別のプログラムを動かすときは xiao_sampleのディレクトリをまるごと コピーして別のプロジェクトのディレクトリを作り そこにプログラム(.ino)を置く。

例:

cp xiao_sample xiao_proj01 cd xiao_proj01 ...

外部ライブラリのインストール方法

# 外部ライブラリを検索する # (ここでは例として「neopixel」を検索する) 「platformio lib neopixel」のキーワードでwebで検索する。 以下が見つかったので、これをインストールしてみる https://platformio.org/lib/show/28/Adafruit%20NeoPixel Installtion方法が以下になっているのが分かる: 「pio lib install "Adafruit NeoPixel"
# "Adafruit NeoPixel"(#ID: 28)をインストールする # 以下を実行する: pio lib install 28 # または、以下を実行する: pio lib install "Adafruit NeoPixel" webにあるサンプルstrandtest.inoを動かしてみる:

src/starndtest.ino

// A basic everyday NeoPixel strip test program. // NEOPIXEL BEST PRACTICES for most reliable operation: // - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections. // - MINIMIZE WIRING LENGTH between microcontroller board and first pixel. // - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR. // - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS // connect GROUND (-) first, then +, then data. // - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip, // a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED. // (Skipping these may work OK on your workbench but can fail in the field) #include <Adafruit_NeoPixel.h> #ifdef __AVR__ #include <avr/power.h> // Required for 16 MHz Adafruit Trinket #endif // Which pin on the Arduino is connected to the NeoPixels? // On a Trinket or Gemma we suggest changing this to 1: #define LED_PIN 6 // How many NeoPixels are attached to the Arduino? #define LED_COUNT 60 // Declare our NeoPixel strip object: Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); // Argument 1 = Number of pixels in NeoPixel strip // Argument 2 = Arduino pin number (most are valid) // Argument 3 = Pixel type flags, add together as needed: // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) // NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) // NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products) // setup() function -- runs once at startup -------------------------------- void setup() { // These lines are specifically to support the Adafruit Trinket 5V 16 MHz. // Any other board, you can remove this part (but no harm leaving it): #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000) clock_prescale_set(clock_div_1); #endif // END of Trinket-specific code. strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) strip.show(); // Turn OFF all pixels ASAP strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255) } /*** // loop() function -- runs repeatedly as long as board is on --------------- void loop() { // Fill along the length of the strip in various colors... colorWipe(strip.Color(255, 0, 0), 50); // Red colorWipe(strip.Color( 0, 255, 0), 50); // Green colorWipe(strip.Color( 0, 0, 255), 50); // Blue // Do a theater marquee effect in various colors... theaterChase(strip.Color(127, 127, 127), 50); // White, half brightness theaterChase(strip.Color(127, 0, 0), 50); // Red, half brightness theaterChase(strip.Color( 0, 0, 127), 50); // Blue, half brightness rainbow(10); // Flowing rainbow cycle along the whole strip theaterChaseRainbow(50); // Rainbow-enhanced theaterChase variant } ***/ // Some functions of our own for creating animated effects ----------------- // Fill strip pixels one after another with a color. Strip is NOT cleared // first; anything there will be covered pixel by pixel. Pass in color // (as a single 'packed' 32-bit value, which you can get by calling // strip.Color(red, green, blue) as shown in the loop() function above), // and a delay time (in milliseconds) between pixels. void colorWipe(uint32_t color, int wait) { for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip... strip.setPixelColor(i, color); // Set pixel's color (in RAM) strip.show(); // Update strip to match delay(wait); // Pause for a moment } } // Theater-marquee-style chasing lights. Pass in a color (32-bit value, // a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms) // between frames. void theaterChase(uint32_t color, int wait) { for(int a=0; a<10; a++) { // Repeat 10 times... for(int b=0; b<3; b++) { // 'b' counts from 0 to 2... strip.clear(); // Set all pixels in RAM to 0 (off) // 'c' counts up from 'b' to end of strip in steps of 3... for(int c=b; c<strip.numPixels(); c += 3) { strip.setPixelColor(c, color); // Set pixel 'c' to value 'color' } strip.show(); // Update strip with new contents delay(wait); // Pause for a moment } } } // Rainbow cycle along whole strip. Pass delay time (in ms) between frames. void rainbow(int wait) { // Hue of first pixel runs 5 complete loops through the color wheel. // Color wheel has a range of 65536 but it's OK if we roll over, so // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time // means we'll make 5*65536/256 = 1280 passes through this outer loop: for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) { for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip... // Offset pixel hue by an amount to make one full revolution of the // color wheel (range of 65536) along the length of the strip // (strip.numPixels() steps): int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels()); // strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or // optionally add saturation and value (brightness) (each 0 to 255). // Here we're using just the single-argument hue variant. The result // is passed through strip.gamma32() to provide 'truer' colors // before assigning to each pixel: strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue))); } strip.show(); // Update strip with new contents delay(wait); // Pause for a moment } } // Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames. void theaterChaseRainbow(int wait) { int firstPixelHue = 0; // First pixel starts at red (hue 0) for(int a=0; a<30; a++) { // Repeat 30 times... for(int b=0; b<3; b++) { // 'b' counts from 0 to 2... strip.clear(); // Set all pixels in RAM to 0 (off) // 'c' counts up from 'b' to end of strip in increments of 3... for(int c=b; c<strip.numPixels(); c += 3) { // hue of pixel 'c' is offset by an amount to make one full // revolution of the color wheel (range 65536) along the length // of the strip (strip.numPixels() steps): int hue = firstPixelHue + c * 65536L / strip.numPixels(); uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB strip.setPixelColor(c, color); // Set pixel 'c' to value 'color' } strip.show(); // Update strip with new contents delay(wait); // Pause for a moment firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames } } } // loop() function -- runs repeatedly as long as board is on --------------- void loop() { // Fill along the length of the strip in various colors... colorWipe(strip.Color(255, 0, 0), 50); // Red colorWipe(strip.Color( 0, 255, 0), 50); // Green colorWipe(strip.Color( 0, 0, 255), 50); // Blue // Do a theater marquee effect in various colors... theaterChase(strip.Color(127, 127, 127), 50); // White, half brightness theaterChase(strip.Color(127, 0, 0), 50); // Red, half brightness theaterChase(strip.Color( 0, 0, 127), 50); // Blue, half brightness rainbow(10); // Flowing rainbow cycle along the whole strip theaterChaseRainbow(50); // Rainbow-enhanced theaterChase variant }

参照エラー(関数未定義エラー)が出たので、 関数定義の並びをオリジナルから変えた。 接続は、D6をneopixelsのDIN,3V3をVCCに、GNDをGNDに接続した。

続き:
ビルド/書き込み/実行:

# build/flash/exec pio run -t upload

ファイル位置

# buildの結果である firmware.* は以下にある: $ ls .pio/build/seeed_xiao/firmware.* .pio/build/seeed_xiao/firmware.bin .pio/build/seeed_xiao/firmware.elf # インストールした外部ライブラリは以下にある: $ ls .pio/libdeps/seeed_xiao/Adafruit\ NeoPixel_ID28/ Adafruit_NeoPixel.cpp COPYING examples Adafruit_NeoPixel.h README.md keywords.txt CONTRIBUTING.md esp8266.c library.properties # examplesは以下にある: $ ls .pio/libdeps/seeed_xiao/Adafruit\ NeoPixel_ID28/examples/ RGBWstrandtest StrandtestBLE simple_new_operator StrandtestArduinoBLE buttoncycler strandtest StrandtestArduinoBLECallback simple strandtest_wheel

以降、サンプルプログラム:

USBserial

USBシリアルとして動作するプログラム:
src/USBserial.ino

void setup() { Serial.begin(115200); Serial1.begin(115200); } void loop() { if (Serial.available()) { char c = (char)Serial.read(); Serial1.write(c); } if (Serial1.available()) { char c = (char)Serial1.read(); Serial.write(c); } }

D6(TX),D7(RX)を相手のRX,TXに、それぞれ接続する。(GND同士も接続する)

Fading

src/fading.ino

/* Fading This example shows how to fade an LED using the analogWrite() function. The circuit: - LED attached from digital pin 9 to ground. created 1 Nov 2008 by David A. Mellis modified 30 Aug 2011 by Tom Igoe This example code is in the public domain. http://www.arduino.cc/en/Tutorial/Fading */ int ledPin = 13; //9; // LED connected to digital pin 9 void setup() { // nothing happens in setup } void loop() { // fade in from min to max in increments of 5 points: for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) { // sets the value (range from 0 to 255): analogWrite(ledPin, fadeValue); // wait for 30 milliseconds to see the dimming effect delay(30); } // fade out from max to min in increments of 5 points: for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) { // sets the value (range from 0 to 255): analogWrite(ledPin, fadeValue); // wait for 30 milliseconds to see the dimming effect delay(30); } }

オンボードのLEDで少しづつ光の強さを変えながら光る。

AnalogInput

src/AnalogInput.ino

/* Analog Input Demonstrates analog input by reading an analog sensor on analog pin 0 and turning on and off a light emitting diode(LED) connected to digital pin 13. The amount of time the LED will be on and off depends on the value obtained by analogRead(). The circuit: * Potentiometer attached to analog input 0 * center pin of the potentiometer to the analog pin * one side pin (either one) to ground * the other side pin to +5V * LED anode (long leg) attached to digital output 13 * LED cathode (short leg) attached to ground * Note: because most Arduinos have a built-in LED attached to pin 13 on the board, the LED is optional. Created by David Cuartielles modified 30 Aug 2011 By Tom Igoe This example code is in the public domain. http://arduino.cc/en/Tutorial/AnalogInput */ int sensorPin = A0; // select the input pin for the potentiometer int ledPin = 13; // select the pin for the LED // Pin 13: Arduino has an LED connected on pin 13 // Pin 11: Teensy 2.0 has the LED on pin 11 // Pin 6: Teensy++ 2.0 has the LED on pin 6 // Pin 13: Teensy 3.0 has the LED on pin 13 int sensorValue = 0; // variable to store the value coming from the sensor void setup() { // declare the ledPin as an OUTPUT: pinMode(ledPin, OUTPUT); } void loop() { // read the value from the sensor: sensorValue = analogRead(sensorPin); // turn the ledPin on digitalWrite(ledPin, HIGH); // stop the program for <sensorValue> milliseconds: delay(sensorValue); // turn the ledPin off: digitalWrite(ledPin, LOW); // stop the program for for <sensorValue> milliseconds: delay(sensorValue); }

AOの入力値により、LEDの点滅周期が変化する。A0をGNDに落とすと点滅ではなく常に光る状態になる。

ASCIITable

src/ASCIITalbe.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(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 == '~') { // This loop loops forever and does nothing while (true) { continue; } } // go on to the next character thisByte++; }

「piccom /dev/ttyACM0 -b115200」で通信ソフトを起動すると、ASCIIテーブルが表示される。

blink3led

src/blink3led.ino

void setup() { pinMode(LED_BUILTIN, OUTPUT); pinMode(PIN_LED2, OUTPUT); pinMode(PIN_LED3, OUTPUT); } void loop() { digitalWrite(LED_BUILTIN, HIGH); digitalWrite(PIN_LED2, HIGH); digitalWrite(PIN_LED3, HIGH); delay(1000); digitalWrite(LED_BUILTIN, LOW); digitalWrite(PIN_LED2, LOW); digitalWrite(PIN_LED3, LOW); delay(1000); }

オンボードの3つのLEDが点滅する。緑色のLEDは通電表示なので点滅ではなく常に光っている。

bootloader-mode

通常(/dev/ttyACM0が見えているとき)は、ツール側で自動的にresetしているので気にする必要はないが、(既に書き込んであるプログラムによっては)/dev/ttyACM0が見えない状況になり、ツール側で自動的にresetできなくなる。(=書き込みが失敗する)
その場合はRSTピンを2度(GNDと)ショートすることで XIAOにfirmwareを書き込めるモードになる。これを「bootloader mode」といい、このモードでは、USBストレージとしてArduinoディレクトリが現れる。
なお、/dev/ttyACM0が見えていても、resetができずに、書き込みが失敗することがあるようだ。そのときも、上と同様にresetを2度、行なう。

補足:「stty -F /dev/ttyACM0」を実行することでボードをリセットしているようだが詳細は不明。

参考情報

Seeeduino XIAO

XIAO Schematic
XIAO Pinout

Arduino Nano Pinout

PlatformIO Core (CLI)

Seeeduino XIAO Get Started By Nanase
コインサイズ Arduino互換機 Seeeduino XIAO を使ってみた

以上

|

« プログラミング言語RustをXIAOで動かす | トップページ | XIAOボードでTinyGOを動かす »

linux」カテゴリの記事

PlatformIO」カテゴリの記事

Arduino」カテゴリの記事

XIAO」カテゴリの記事

コメント

コメントを書く



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




« プログラミング言語RustをXIAOで動かす | トップページ | XIAOボードでTinyGOを動かす »