こんにちは、あろっちです。
Adafruit QT Py RP2040を入手したので試してみました。
特徴
- Seeeduino XIAO、Adafruit QT Py(SAMDベースモデル)互換のピン配置/形状
- USB Type-C
- RGB NeoPixel LED内蔵
- STEMMA QT/Qwiicコネクタ搭載
- リセットボタン
- ブートローダーセレクトボタン
スペックはこんな感じです。
MCU | RP2040 デュアルコア ARM Cortex M0+プロセッサ、最大動作周波数 133 MHz |
フラッシュメモリ | 8MB (Raspberry Pi Pico、Seeed XIAO RP2040は2MB) |
GPIO | 13 ・11xブレイクアウト(11xディジタル&PWM, 4xアナログ対応(12bit ADC)) ・2xQT |
サイズ | 21.8×17.8×5.8mm |
本記事はArduino(C/C++)で試してみます。
ちなみに、開発環境としてVS Codeを使うこともできたりします。
PlatformIO IDEでの開発について記事を書きました。
Adafruit QT Py RP2040に似たようなマイコンにSeeed XIAO RP2040があります。そちらについても記事を書いていますので、よろしければご覧ください。
Seeed XIAO BLE nRF52840 / Sense(参考サイト)
RP2040搭載ボードまとめ記事(参考サイト)
ピン配列
GPIOとの対応を記載します。
ピン | GPIO |
A0 | 29/ADC3 |
A1 | 28/ADC2 |
A2 | 27/ADC1 |
A3 | 26/ADC0 |
SDA | 24 |
SCL | 25 |
TX | 20 |
RX | 5 |
SCK | 6 |
MISO | 4 |
MOSI | 3 |
NEOPIXEL POWER | 11 |
NEOPIXEL | 12 |
BUTTON | 21 |
QT
ピン | GPIO |
SDA1 | 22 |
SCL1 | 23 |
NeoPixelを使用するには
NeoPixelを使用する場合、電源であるGPIO11をHIGHに引き上げる必要があります。
pinMode(11, OUTPUT);
digitalWrite(11, HIGH);
Raspberry Pi Pico/RP2040ボード(earlephilhower版) Adafruit QT Py RP2040ボードでは、定数(NEOPIXEL_POWER)が定義されているので、この定数を使って次のようにHIGHにできます。
pinMode(NEOPIXEL_POWER, OUTPUT);
digitalWrite(NEOPIXEL_POWER, HIGH);
参考
Arduino IDEの設定
ボードは、RP2040のearlephilhowerボードを使用します。
このボードを使用するには、以下の設定を行います。
Arduino IDEから[ファイル] > [環境設定]の画面を開き、[追加のボードマネージャのURL:]のボックス(赤枠の箇所)に以下のURLを入力し、[OK]をクリックします。
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
[ツール] > [ボード] > [ボードマネージャ]を開き、検索ボックスにrp2040と入力し、Raspberry Pi Pico/RP2040ボードをインストールします。
ボードは、[ツール] > [ボード] > [Raspberry Pi RP2040 Boards(Ver)] > [Adafruit QT Py RP2040]を選択します。(画像の赤枠参照)
NeoPixelをLチカしてみる
Adafruit QT Py RP2040の内蔵LEDはNeoPixel。せっかくなので、カラフルにLチカしてみましょう。
#include <Adafruit_NeoPixel.h>
#define LED_POWER 11
#define LED_PIN 12
#define COLOR_REPEAT 2
Adafruit_NeoPixel pixels(1, LED_PIN);
uint8_t color = 0, count = 0;
uint32_t colors[] = {pixels.Color(255, 0, 0), pixels.Color(0, 255, 0), pixels.Color(0, 0, 255), pixels.Color(255, 255, 255)};
const uint8_t COLORS_LEN = (uint8_t)(sizeof(colors) / sizeof(colors[0]));
void setup() {
pinMode(LED_POWER, OUTPUT);
digitalWrite(LED_POWER, HIGH);
pixels.begin(); // initialize the pixel
}
void loop() {
pixels.setPixelColor(0, colors[color]);
pixels.show();
delay(1000);
pixels.clear();
pixels.show();
delay(1000);
count++;
if(count >= COLOR_REPEAT) {
count = 0;
color++;
if(color >= COLORS_LEN) {
color = 0;
}
}
}
こんな感じで光ります。
NeoPixelをレインボーに光らせてみる
このスケッチもAdafruit NeoPixelライブラリを使っています。
#include <Adafruit_NeoPixel.h>
#define LED_POWER 11
#define LED_PIN 12
#define MAX_BRIGHTNESS 255
Adafruit_NeoPixel pixels(1, LED_PIN);
int rgbValues[] = {MAX_BRIGHTNESS, 0, 0}; // 0=Red, 1=Green and 2=Blue
int upIndex = 0, downIndex = 1;
void setup()
{
pinMode(LED_POWER, OUTPUT);
digitalWrite(LED_POWER, HIGH);
pixels.begin(); // initialize the pixel
}
void loop()
{
rgbValues[upIndex] += 1;
rgbValues[downIndex] -= 1;
if (rgbValues[upIndex] > MAX_BRIGHTNESS)
{
rgbValues[upIndex] = MAX_BRIGHTNESS;
upIndex = upIndex + 1;
if (upIndex > 2)
{
upIndex = 0;
}
}
if (rgbValues[downIndex] < 0)
{
rgbValues[downIndex] = 0;
downIndex = downIndex + 1;
if (downIndex > 2)
{
downIndex = 0;
}
}
pixels.setPixelColor(0, pixels.Color(MAX_BRIGHTNESS - rgbValues[0], MAX_BRIGHTNESS - rgbValues[1], MAX_BRIGHTNESS - rgbValues[2]));
pixels.show();
delay(5);
}
こんな感じで光ります。思ったより明るくて眩しいです。
一撃入魂
BOOTボタンを押すと、1/2でレインボーに光るというスケッチです。
ルール
チャンスは1回、ボタン押下時に抽選
あえてボタン入力の受付は1回のみとしてみました。
再チャレンジしたい場合は、リセットボタンを押してみてください。
RGB LEDの状態について
ボタン入力受付は、白点滅
抽選演出は、赤で表現
抽選結果は、当選時 > レインボー、落選時 > フェードアウト
#include <Adafruit_NeoPixel.h>
#define BTN 21
#define LED_POWER 11
#define LED_PIN 12
#define TOGGLE_PERIOD (1000u)
#define LED_STAND_BY_COLOR 0xffffff
#define LED_READY_COLOR 0xff0000
Adafruit_NeoPixel pixels(1, LED_PIN);
uint8_t rgbValues[7][3] = {
{255, 0, 0}, {255, 165, 0}, {255, 255, 0}, {0, 128, 0}, {0, 255, 255}, {0, 0, 255}, {128, 0, 128}};
int16_t randNumber;
int16_t brightness = 0;
int16_t fadeAmount = 10;
void toggleLED_nb(void)
{
static bool toggle = true;
static auto lastToggle = millis(); // saved between calls
auto now = millis();
if (now - lastToggle > TOGGLE_PERIOD)
{
if (toggle)
{
pixels.setPixelColor(0, LED_STAND_BY_COLOR);
pixels.setBrightness(18);
pixels.show();
}
else
{
pixels.clear();
pixels.show();
}
toggle = !toggle;
lastToggle = now;
}
}
void readyLED()
{
for (uint8_t i = 0; i < 3; i++)
{
brightness = 0;
pixels.clear();
pixels.show();
delay(100);
for (uint8_t j = 0; j < (100 / fadeAmount); j++)
{
pixels.setPixelColor(0, LED_READY_COLOR);
pixels.setBrightness(brightness);
pixels.show();
brightness = brightness + fadeAmount;
delay(80);
}
delay(1000);
}
brightness = 150;
pixels.setPixelColor(0, LED_READY_COLOR);
pixels.setBrightness(brightness);
pixels.show();
delay(3000);
}
void successLED()
{
for (uint8_t i = 0; i < 8; i++)
{
for (uint8_t j = 0; j < 7; j++)
{
pixels.setPixelColor(0, pixels.Color(rgbValues[j][0], rgbValues[j][1], rgbValues[j][2]));
pixels.setBrightness(18);
pixels.show();
delay(50);
}
}
}
void failureLED()
{
while (0 < brightness)
{
pixels.setPixelColor(0, LED_READY_COLOR);
pixels.setBrightness(brightness);
pixels.show();
brightness = brightness - fadeAmount;
delay(80);
}
pixels.clear();
pixels.show();
delay(200);
pixels.setPixelColor(0, LED_READY_COLOR);
pixels.setBrightness(10);
pixels.show();
delay(150);
}
void setup()
{
pinMode(BTN, INPUT_PULLUP);
pinMode(LED_POWER, OUTPUT);
digitalWrite(LED_POWER, HIGH);
pixels.begin();
while (digitalRead(BTN) == HIGH)
{
toggleLED_nb();
delay(10);
}
// 抽選
randomSeed(analogRead(A2));
randNumber = (int16_t)random(0xffff + 1);
readyLED();
if (randNumber < 0)
{
// おめでとう
successLED();
}
else
{
// 残念
failureLED();
}
pixels.clear();
pixels.show();
}
void loop()
{
}
落選時
当選時
STEMMA QT/Qwiicコネクタを試してみました
QTコネクタが搭載されているので、試してみました。
Lチカ
GroveのLEDモジュールを使ってLチカしてみました。
QTコネクタとGroveモジュールの接続にはGroveアダプタケーブルを使います。
Groveアダプタケーブルはスイッチサイエンスさんで入手しました。
#define LED 23
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED as an output.
pinMode(LED, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
QTコネクタのGPIO 23のオン/オフでLチカできます。
RGB LEDテープを光らせてみる
Grove – WS2813搭載防水RGB LEDテープ1m(60LED)を光らせてみました。
https://www.seeedstudio.com/Grove-WS2813-RGB-LED-Strip-Waterproof-60-LED-m-1m.html
QTとRGB LEDテープのGroveコネクタを接続するのにGrove – Qwiicハブを使用しました。
https://www.seeedstudio.com/Grove-Qwiic-Hub-p-4531.html
スケッチはAdafruit NeoPixelライブラリのスケッチ例「strandtest」を使っています。
[スケッチ例] > [Adafruit NeoPixel] > [strandtest]
LED_PINとLED_COUNTを以下のように修正しました。
// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN 23
// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 60
Seeeduino XIAO 拡張ボードを試してみました
Adafruit QT Py RP2040は、Seeeduino XIAO互換ということで、Seeeduino XIAO 拡張ボードという便利なボードが使えます。
※現在、秋月電子通商、マルツオンラインなどで入手できそうです。
Seeeduino XIAO 拡張ボードは、以下のような豊富なインターフェースが備わっています。
- OLEDディスプレイ
- RTC
- 拡張可能なメモリスペース
- パッシブブザー
- ユーザーボタン
- Groveコネクタ
- オンボードバッテリー管理チップなど
ちなみにSeeeduino XIAOも保有していて、なにか試したい時によく使うボードですね。
OLEDディスプレイを表示してみる
スケッチ例を使った表示方法を紹介します。
ボード搭載のOLEDディスプレイは、0.96インチ(128×64)、制御IC: SSD1306、通信: I2Cのものです。
単体でもよく見かけるポピュラーなOLEDディスプレイですね。
事前にライブラリマネージャから、Adafruit SSD1306ライブラリをインストールしておきます。
スケッチ例から、[Adafruit SSD1306] > [ssd1306_128x64_i2c]を選択します。
#define OLED_RESET 4
#define SCREEN_ADDRESS 0x3D
を
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
に変更し、スケッチを書き込みます。
以下、抜粋です。
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
こんな感じで、表示されます。
ちなみに、Seeeduino XIAOでもこのスケッチを書き込めば同じように表示されます。
パッシブブザーでメロディを鳴らしてみる
メロディは、恥ずかしながらオリジナルだったりします。
int duration = 250;
int pin = A3;
void do1(int k) {
tone(pin, 261, k);
delay(k);
noTone(pin);
}
void re(int k) {
tone(pin, 293, k);
delay(k);
noTone(pin);
}
void mi(int k) {
tone(pin, 329, k);
delay(k);
noTone(pin);
}
void fa(int k) {
tone(pin, 349, k);
delay(k);
noTone(pin);
}
void so(int k) {
tone(pin, 391, k);
delay(k);
noTone(pin);
}
void ra(int k) {
tone(pin, 440, k);
delay(k);
noTone(pin);
}
void si(int k) {
tone(pin, 494, k);
delay(k);
noTone(pin);
}
void do2(int k) {
tone(pin, 523, k);
delay(k);
noTone(pin);
}
void logo1() {
mi(duration / 2);
mi(duration / 2);
mi(duration / 2);
mi(duration / 2);
mi(duration / 2);
mi(duration / 2);
delay(duration * 2);
so(duration * 2);
so(duration * 2);
do2(duration * 2);
}
void logo2() {
so(duration);
delay(duration);
do2(duration);
ra(duration);
si(duration);
delay(duration);
ra(duration);
so(duration);
so(duration);
do2(duration);
delay(duration);
si(duration);
do2(duration);
}
void title() {
re(duration);
do1(duration);
re(duration * 2);
mi(duration * 2);
fa(duration * 2);
ra(duration);
ra(duration);
so(duration * 2);
re(duration * 2);
mi(duration * 2);
ra(duration);
ra(duration);
so(duration * 2);
re(duration * 2);
mi(duration * 2);
fa(duration * 2);
}
void mainbgm() {
so(duration);
delay(duration);
do2(duration);
ra(duration);
si(duration);
delay(duration);
ra(duration);
so(duration);
so(duration);
do2(duration);
delay(duration);
si(duration);
do2(duration * 2);
delay(duration * 2);
so(duration);
delay(duration);
do2(duration);
delay(duration);
ra(duration);
ra(duration);
si(duration);
delay(duration);
so(duration);
do2(duration);
delay(duration);
si(duration);
do2(duration * 2);
delay(duration * 2);
}
void setup() {
do1(duration);
re(duration);
mi(duration);
fa(duration);
so(duration);
ra(duration);
si(duration);
do2(duration);
delay(2000);
logo1();
delay(2000);
logo2();
delay(2000);
title();
delay(2000);
mainbgm();
delay(2000);
}
void loop() {
}
ちなみにSeeeduino XIAOやSeeed XIAO RP2040でも鳴らせます。
PWMでオーディオ再生してみました
ライブラリを作ってみました。
ダウンロード&インストール方法は以下の記事をご参照ください。
スケッチ例 typewriter
スケッチ例はそのまま書き込めばOKです。
まとめ
Adafruit QT Py RP2040は、小さくて高性能。今では、お気に入りのマイコンの一つです。
当ブログのマイコン記事です。ぜひご覧ください。
コメント