編集履歴一覧に戻る
moruxaのアイコン画像

moruxa が 2024年01月30日22時02分27秒 に編集

初版

タイトルの変更

+

SPRESENSEによるパリピ神棚

タグの変更

+

LovyanGFX

+

SP_Audio

+

SPRESENSE

+

VSCode

+

PlatformIO

+

ILI9341

+

SK6812

+

Neopixel

メイン画像の変更

メイン画像が設定されました

記事種類の変更

+

製作品

ライセンスの変更

+

(MIT) The MIT License

本文の変更

+

# デモ動画 @[youtube](https://youtu.be/Oy4uKDyWqh0?feature=shared) # 経緯 [2023年 SPRESENSE™ 活用コンテスト](https://elchika.com/promotion/spresense2023/)に応募するにあたり、「パリピ神棚」というコンセプトを掲げました。そして、紆余曲折の末に出来上がったものがこちらです。 ![キャプションを入力できます](https://camo.elchika.com/4790e2c1b74419655a57ddda84b2d8861e1ef722/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f39353433373162332d363031622d343039622d396462642d3761363934393061306562642f39646137343038662d316338342d346363382d386131652d393862663438393036633832/) ちなみに裏側はこうなってます。 ![キャプションを入力できます](https://camo.elchika.com/1ab0ddad3c90161caa588191d2b41af84cd8bd56/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f39353433373162332d363031622d343039622d396462642d3761363934393061306562642f66336130626134312d386265302d346165352d616261342d333931393532333337333937/) # 謝辞 ソニーセミコンダクタソリューションズさん、今回もチャレンジしがいのあるコンテストを企画していただきありがとうございました。🙇 また、SPRESENSE関連製品各種をモニター提供していただきありがとうございました。🙇 本作品には下記のすばらしいライブラリ等を使用させていただきました。 [LovyanGFX(超高速なグラフィックスライブラリ)](https://github.com/lovyan03/LovyanGFX) [SP_Audio(オーディオライブラリ)](https://github.com/baggio63446333/SP_Audio) [MM-S50MV 用 Arduinoライブラリ](https://github.com/Interested-In-Spresense/MM-S50MV) [nepils(NeoPixelライブラリ)](https://github.com/KotaMeiwa/nepils) [PlatformIO integration for Sony CXD5602GG Spresense boards ](https://github.com/maxgerhardt/platform-sonyspresense) これらのライブラリ等のおかげで開発が捗りました。 本当にありがとうございました。🙇🙇🙇 # 部品 下記はハードウェア部品です。 | 品名 | 入手先 | |:---:|:---| | Spresense メインボード | モニター提供品 | | Spresense 拡張ボード | モニター提供品 | | Spresense HDRカメラボード | モニター提供品 | | ILI9341搭載2.8インチTFT液晶 MSP2807 | モニター提供品 | | TOFセンサー MM-S50MV | モニター提供品 | | 9軸 加速度計・ジャイロ・コンパスセンサ (BMI270・AK09918) Addon ボード | モニター提供品 | | SK6812使用マイコン内蔵フルカラーテープLED 1m 60LED IP20 | モニター提供品 | | スイッチングACアダプター 5V4A AD-A50P400 | 秋月電子 | | ブレッドボード用2.1mm標準DCジャックDIP化キット | 秋月電子 | | ミニ・ブレッドボード | 秋月電子 | | ジャンパーワイヤ各種 | 秋月電子 | | サーボ | 秋月電子 | | パッシブスピーカー | セリア | | 推しを祀る神棚 | メルカリ | | 越前かにめしの空き容器 | 食品館あおば初山店 | 下記はソフトウェア部品です。(microSDカードのルートフォルダに配置) | ファイル名 | 内容 | |:---:|:---| | 1.bmp | ビットマップ(大吉) | | 2.bmp | ビットマップ(中吉) | | 3.bmp | ビットマップ(小吉) | | 4.bmp | ビットマップ(末吉) | | 5.bmp | ビットマップ(吉) | | 6.bmp | ビットマップ(凶) | | 7.bmp | ビットマップ(大凶) | | zinja-ne.wav | 音声ファイル([©もみじば 「神社の音」より](https://music.storyinvention.com/zinja-ne/)) | | BIN/WAVDEC | DSP Codec バイナリ | | cnn.nnb | DNNRT機能の学習データ(今後使いたい) | ※例によってビットマップはペイントで手作りしました。音声ファイルはAudacityで編集しました。 # 設計図 - 下記はSPRESENSE拡張ボードとLCD、NeoPixelの配線図です。 ![キャプションを入力できます](https://camo.elchika.com/525caa65635ca88426fe4f816ae747e994860638/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f39353433373162332d363031622d343039622d396462642d3761363934393061306562642f63636635323834612d663062352d346537392d393331342d303363323337343031633066/) - 下記はLCDとのピン接続(SPI)です。 | SPRESENSE拡張ボード側 | LCD側 | |:---:|:---| | AREF | VCC | | GND | GND | | D10 | CS | | D15 | RESET | | D14 | DC | | D11 | SDI(MOSI) | | D13 | SCK | | 3.3V | LED | | D12 | SDO(MISO) | - 下記はNeoPixelとのピン接続(PWM)です。VDD(赤)とVSS(黒)はACアダプター接続です。 | SPRESENSE拡張ボード側 | NeoPixel側 | |:---:|:---| | D06 | DIN(緑) | - TOFセンサーはSPRESENSE本体にAdd-onボード接続(SPI)です。 # 反省文(ポエム) 前回の反省から、今回は「SPRESENSEではじめるローパワーエッジAI 」と「はじめての「SonyNNC」改訂版」の二冊を入手しました。 ![キャプションを入力できます](https://camo.elchika.com/cab8f8eb381741deb6e83a655982750ace7038ae/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f39353433373162332d363031622d343039622d396462642d3761363934393061306562642f39633331616662632d393333662d343666382d393061622d363761336531643936336530/) ![キャプションを入力できます](https://camo.elchika.com/d2d2395510c0089efc6320335e14acf83a01474d/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f39353433373162332d363031622d343039622d396462642d3761363934393061306562642f63343839373466312d373932382d346132322d626130622d643334376236326263626435/) これらの資料によって、Spresenseのポテンシャルを最大限引き出すことができるようになり、カメラ映像から柏手(かしわで)を認識できるようになるはず・・・ ・・・だったのですが、いかんせん業務多忙につきカメラAIの実装は間に合いませんでした。🤣🤣🤣 しかし、次回のコンテストには、いよいよ「カメラAIをインターフェース」とした作品を提出できる予感がしています・・・!! ちなみに今回は、Arduino IDEではなくPlatformIOでビルドできるようになったので断然開発作業が捗りました。 Arduino IDEだとビルドの度に2~3分ぐらいかかるところ、PlatformIOならば1分かからずにアップロードまで終わります。 この勢いに乗ってSpresense SDKが使えるようになると、より開発が捗る気がしますね・・・!! ということで、moruxa先生の次回作にご期待ください・・・!!(今度こそ・・・今度こそ・・・) # ソースコード ```arduino(PlatformIO):main.cpp #define LGFX_AUTODETECT #define LGFX_USE_V1 #include <SDHCI.h> SDClass SD; #include "LGFX_SPRESENSE_sample.hpp" #include <SP_AudioPlayer.h> #include <MM-S50MV.h> #include <Adafruit_NeoPixel_Spresense.h> static LGFX lcd; SP_AudioPlayer player; const uint16_t NUM_PIXELS = 60; const uint16_t PIN = 6; Adafruit_NeoPixel_Spresense strip(NUM_PIXELS, PIN); int cnt = 0; int wait = 500; int remain = 1; void disp(int n) { static LGFX_Sprite canvas(&lcd); char buf[8]; snprintf(buf,8,"/%d.bmp",n+1); canvas.createFromBmpFile(SD, buf); canvas.pushRotateZoom(120, 160, 0.f, 1.0, 1.0); } void setup(void) { Serial.begin(115200); randomSeed(analogRead(0)); /* Initialize Player */ player.begin(); player.volume(80); /* 120 ~ -1020(?) */ // player.setFs(44100); /* Change from the default 48kHz to 44.1kHz */ player.setBitlen(16); /* same as the default */ player.setChannel(2); /* same as the default */ lcd.init(); lcd.startWrite(); lcd.clear(TFT_BLACK); //lcd.clear(TFT_WHITE); lcd.setColorDepth(16); // LCDを16bitカラーモードに設定する。 lcd.setSwapBytes(true); // バイト順変換を有効にする。 lcd.invertDisplay(false); lcd.setRotation(2); MMS50MV.begin(); MMS50MV.skip(256); delay(500); MMS50MV.set(MMS50MV_CMD_MODE, MMS50MV_MODE_SYNC); // sync mode. delay(500); MMS50MV.skip(256); MMS50MV.sync(); // sync. MMS50MV.set(MMS50MV_CMD_MODE, MMS50MV_MODE_NOMAL); // normal mode. delay(500); MMS50MV.set(0x10, 0); // 256frames/s delay(500); MMS50MV.skip(256); strip.begin(); strip.setBrightness(50); strip.show(); cnt = 4; wait=250; } void disp2(int n){ lcd.setCursor(0, 20); lcd.setTextColor(TFT_BLACK, TFT_WHITE); lcd.setFont(&fonts::Font2); lcd.setTextSize(2); lcd.printf("%2d\n", n); } // Input a value 0 to 255 to get a color value. // The colours are a transition r - g - b - back to r. uint32_t Wheel(byte WheelPos) { WheelPos = 255 - WheelPos; if(WheelPos < 85) { return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } if(WheelPos < 170) { WheelPos -= 85; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } WheelPos -= 170; return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); } void loop(void) { int dis = MMS50MV.get(); if (dis < 500) { cnt--; lcd.setCursor(100, 140); lcd.setTextColor(TFT_WHITE, TFT_BLACK); lcd.setFont(&fonts::Font4); lcd.setTextSize(4); lcd.printf("%d\n", cnt); } else { if (cnt < 4) lcd.clear(TFT_BLACK); cnt = 4; } if (cnt == 0) { cnt = 4; player.wavplay("/mnt/sd0/zinja-ne.wav", false); for (int i = 0; i < 30; i++) { disp(i % 7); //disp2(i); for(int x=0; x<strip.numPixels(); x++) { strip.setPixelColor(x, Wheel((x+i*8) & 255)); } strip.show(); delay(i*i); } disp(random(0, 6)); remain = 20; } delay(wait); if (remain > 0) { remain--; //disp2(remain); if (remain == 0){ for(int x=0; x<strip.numPixels(); x++) { strip.setPixelColor(x, 0); } strip.show(); lcd.clear(TFT_BLACK); } } } ``` ```arduino(PlatformIO):LGFX_SPRESENSE_sample.hpp #pragma once #define LGFX_USE_V1 #include <LovyanGFX.hpp> // SPRESENSEでLovyanGFXを独自設定で利用する場合の設定例 /* このファイルを複製し、新しい名前を付けて、環境に合わせて設定内容を変更してください。 作成したファイルをユーザープログラムからincludeすることで利用可能になります。 複製したファイルはライブラリのlgfx_userフォルダに置いて利用しても構いませんが、 その場合はライブラリのアップデート時に削除される可能性があるのでご注意ください。 安全に運用したい場合はバックアップを作成しておくか、ユーザープロジェクトのフォルダに置いてください。 //*/ /// 独自の設定を行うクラスを、LGFX_Deviceから派生して作成します。 class LGFX : public lgfx::LGFX_Device { /* クラス名は"LGFX"から別の名前に変更しても構いません。 AUTODETECTと併用する場合は"LGFX"は使用されているため、LGFX以外の名前に変更してください。 また、複数枚のパネルを同時使用する場合もそれぞれに異なる名前を付けてください。 ※ クラス名を変更する場合はコンストラクタの名前も併せて同じ名前に変更が必要です。 名前の付け方は自由に決めて構いませんが、設定が増えた場合を想定し、 例えば SPRESENSE でSPI接続のILI9341の設定を行った場合、 LGFX_SPRESENSE_SPI_ILI9341 のような名前にし、ファイル名とクラス名を一致させておくことで、利用時に迷いにくくなります。 //*/ // 接続するパネルの型にあったインスタンスを用意します。 //lgfx::Panel_GC9A01 _panel_instance; //lgfx::Panel_GDEW0154M09 _panel_instance; //lgfx::Panel_HX8357B _panel_instance; //lgfx::Panel_HX8357D _panel_instance; //lgfx::Panel_ILI9163 _panel_instance; lgfx::Panel_ILI9341 _panel_instance; //lgfx::Panel_ILI9342 _panel_instance; //lgfx::Panel_ILI9481 _panel_instance; //lgfx::Panel_ILI9486 _panel_instance; //lgfx::Panel_ILI9488 _panel_instance; //lgfx::Panel_IT8951 _panel_instance; //lgfx::Panel_SH110x _panel_instance; // SH1106, SH1107 //lgfx::Panel_SSD1306 _panel_instance; //lgfx::Panel_SSD1327 _panel_instance; //lgfx::Panel_SSD1331 _panel_instance; //lgfx::Panel_SSD1351 _panel_instance; // SSD1351, SSD1357 //lgfx::Panel_SSD1963 _panel_instance; //lgfx::Panel_ST7735 _panel_instance; //lgfx::Panel_ST7735S _panel_instance; //lgfx::Panel_ST7789 _panel_instance; //lgfx::Panel_ST7796 _panel_instance; // SPIバスのインスタンスを用意します。 lgfx::Bus_SPI _bus_instance; // SPIバスのインスタンス public: // コンストラクタを作成し、ここで各種設定を行います。 // クラス名を変更した場合はコンストラクタも同じ名前を指定してください。 LGFX(void) { { // バス制御の設定を行います。 auto cfg = _bus_instance.config(); // バス設定用の構造体を取得します。 cfg.spi_mode = 3; // SPI通信モードを設定 (0 ~ 3) cfg.freq_write = 30000000; // 送信時のSPIクロック cfg.freq_read = 16000000; // 受信時のSPIクロック cfg.pin_dc = 14; // SPIのD/Cピン番号を設定 (-1 = disable) cfg.spi_port = 4; // Arduino拡張ボードの場合は 4 _bus_instance.config(cfg); // 設定値をバスに反映します。 _panel_instance.setBus(&_bus_instance); // バスをパネルにセットします。 } { // 表示パネル制御の設定を行います。 auto cfg = _panel_instance.config(); // 表示パネル設定用の構造体を取得します。 cfg.pin_cs = 10; // CSが接続されているピン番号 (-1 = disable) HW CSピンの場合は-1を指定 cfg.pin_rst = 15; // RSTが接続されているピン番号 (-1 = disable) cfg.pin_busy = -1; // BUSYが接続されているピン番号 (-1 = disable) // ※ 以下の設定値はパネル毎に一般的な初期値が設定されていますので、不明な項目はコメントアウトして試してみてください。 cfg.panel_width = 240; // 実際に表示可能な幅 cfg.panel_height = 320; // 実際に表示可能な高さ cfg.offset_x = 0; // パネルのX方向オフセット量 cfg.offset_y = 0; // パネルのY方向オフセット量 cfg.offset_rotation = 0; // 回転方向の値のオフセット 0~7 (4~7は上下反転) cfg.dummy_read_pixel = 8; // ピクセル読出し前のダミーリードのビット数 cfg.dummy_read_bits = 1; // ピクセル以外のデータ読出し前のダミーリードのビット数 cfg.readable = true; // データ読出しが可能な場合 trueに設定 cfg.invert = false; // パネルの明暗が反転してしまう場合 trueに設定 cfg.rgb_order = false; // パネルの赤と青が入れ替わってしまう場合 trueに設定 cfg.dlen_16bit = false; // データ長を16bit単位で送信するパネルの場合 trueに設定 cfg.bus_shared = true; // SDカードとバスを共有している場合 trueに設定(drawJpgFile等でバス制御を行います) // 以下はST7735やILI9163のようにピクセル数が変更できるドライバでのみ設定してください。 // cfg.memory_width = 240; // ドライバICがサポートしている最大の幅 // cfg.memory_height = 320; // ドライバICがサポートしている最大の高さ _panel_instance.config(cfg); } setPanel(&_panel_instance); // 使用するパネルをセットします。 } }; ```