2025年4月5日土曜日

M5Stamp PicoでLチカ(WS2812)

Aliexpressで面白うそうなLEDモジュールを見つけたので、M5Stamp PicoでLチカ 第2弾をしました。なお、このLEDモジュールはアマゾンでも販売していました

このLEDモジュールはWS2812 5050を8個搭載しており、1本のデータ信号でこれらを制御することが出来ます。それにより1モジュール1ピンとなるため、GPIOピンの節約が出来そうです。今回もナイトライダー風にしますが、折角なのでパターン違いで2モジュール制御したいと思います。回路は非常に簡単です


本モジュールの制御には、Adafruit_NeoPixelライブラリを使用しました。ArduinoIDEのライブラリマネージャーで簡単に追加できます

  1. // LED 制御(WS2812B)
  2. #include <M5unified .h>
  3. #include <dafruit_NeoPixel.h>
  4. #define PIN1 18 // LEDのデータを接続するGPIO
  5. #define PIN2 19 // LEDのデータを接続するGPIO
  6. #define LED_NUM 8 // 接続LED数(4の倍数)
  7. #define LED_MSK (LED_NUM/2) -1
  8. #define LED_DLY 50 // 点灯時間
  9. #define MAX_LED 128 // 明るさ
  10. // LED config
  11. Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(LED_NUM, PIN1, NEO_GRB + NEO_KHZ800);
  12. Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(LED_NUM, PIN2, NEO_GRB + NEO_KHZ800);
  13. void setup() {
  14. auto cfg = M5.config();
  15. M5.begin(cfg);
  16. // LED setup
  17. strip1.begin();
  18. strip2.begin();
  19. }
  20. int z = 0;
  21. void loop() {
  22. int x = 0;
  23. int y = 0;
  24. for (int i = 0; i < LED_NUM; i++ ){
  25. // LED1 設定
  26. strip1.clear(); // LED1 消灯
  27. x = i & LED_MSK;
  28. y = ~x & (LED_NUM-1);
  29. strip1.setPixelColor(x, strip1.Color(0, MAX_LED, 0));
  30. strip1.setPixelColor(y, strip1.Color(0, MAX_LED, 0));
  31. strip1.show();
  32. // LED2 設定
  33. strip2.clear(); // LED2 消灯
  34. if ((z % 2) == 0) {
  35. strip2.setPixelColor((i), strip2.Color(0, MAX_LED, 0));
  36. } else {
  37. strip2.setPixelColor(((LED_NUM-1)-i), strip2.Color(0, MAX_LED, 0));
  38. }
  39. strip2.show();
  40. delay(LED_DLY);
  41. }
  42. z++;
  43. }

13行目、14行目のAdafruit_NeoPixel宣言は、モジュール内のLED総数、割当てピン、蘇秦データのカラー順序(今回はRGB)、駆動周波数は800KHzで設定しています

22行目、23行目の.begin()でGPIOの出力設定が行われます

25行目、43行目の.clean()で全てのLEDを消灯しています

38,39行目、45,47行目の.setPixelColor()で表示するLEDとカラー(RGB順)を設定します(今回は緑色にしています)

なお、strip1はLED 0 → 3、LED 7 → 4の順で2個づつ表示、strip2はLED 0 → 7 → 0の順で表示しています

カラー設定値を半分にして明るさが変わるか試しましたが、これでも眩しいです


次は何をしてみようかな...

iOS 18.4 リリース

 iOS 18.4に合わせて、watchOS 11.4がリリースされました

なお、Apple Watch Series 6 以降が対象になります

アップデートには、以下の新機能と機能改善、およびバグ修正が含まれます:

  • Matter対応のロボット掃除機をホームアプリで操作でき、シーンやオートメーションに追加することもできます。
  • 消音モードで睡眠/起床アラームを強化するオプション
  • 文字盤の切り替え時に文字盤の選択が応答しなくなる問題

Apple セキュリティアップデートを確認すると以下のセキュリティアップデート内容が記載されています

AirDrop

CVE-2025-24097: Ron Masas of BREAKPOINT.SH

Audio

CVE-2025-24244: Hossein Lotfi (@hosselot) of Trend Micro Zero Day Initiative

CVE-2025-24243: Hossein Lotfi (@hosselot) of Trend Micro Zero Day Initiative

Authentication Services

CVE-2025-30430: Dominik Rath

CVE-2025-24180: Martin Kreichgauer of Google Chrome

BiometricKit

CVE-2025-24237: Yutong Xiu

Calendar

CVE-2025-30429: Denis Tokarev (@illusionofcha0s)

CVE-2025-24212: Denis Tokarev (@illusionofcha0s)

CoreAudio

CVE-2025-24163: Google Threat Analysis Group

CVE-2025-24230: Hossein Lotfi (@hosselot) of Trend Micro Zero Day Initiative

CoreMedia

ACVE-2025-24190: Hossein Lotfi (@hosselot) of Trend Micro Zero Day Initiative

CoreMedia Playback

CVE-2025-30454: pattern-f (@pattern_F_)

CoreServices

CVE-2025-31191: Jonathan Bar Or (@yo_yo_yo_jbo) of Microsoft, and an anonymous researcher

CoreText

CVE-2025-24182: Hossein Lotfi (@hosselot) of Trend Micro Zero Day Initiative

curl

CVE-2024-9681

Focus

CVE-2025-30439: Andr.Ess

CVE-2025-24283: Kirin (@Pwnrin)

Foundation

CVE-2025-30447: LFY@secsys from Fudan University

ImageIO

CVE-2025-24210: Anonymous working with Trend Micro Zero Day Initiative

IOGPUFamily

CVE-2025-24257: Wang Yu of Cyberserval

Kernel

CVE-2025-30432: Michael (Biscuit) Thomas - @biscuit@social.lol

libarchive

CVE-2024-48958

libnetcore

CVE-2025-24194: an anonymous researcher

libxml2

CVE-2025-27113

CVE-2024-56171

libxpc

CVE-2025-24178: an anonymous researcher

CVE-2025-31182: Alex Radocea and Dave G. of Supernetworks, 风沐云烟(@binary_fmyy) and Minghao Lin(@Y1nKoc)

CVE-2025-24238: an anonymous researcher

Maps

CVE-2025-30470: LFY@secsys from Fudan University

NetworkExtension

CVE-2025-30426: Jimmy

Power Services

CVE-2025-24173: Mickey Jin (@patch1t)

Safari

CVE-2025-24113: @RenwaX23

CVE-2025-30467: @RenwaX23

CVE-2025-24167: Syarif Muhammad Sajjad

Security

CVE-2025-30471: Bing Shi, Wenchao Li, Xiaolong Bai of Alibaba Group, Luyi Xing of Indiana University Bloomington

Share Sheet

CVE-2025-30438: Halle Winkler, Politepix theoffcuts.org

Shortcuts

CVE-2025-30433: Andrew James Gonzalez

Siri

CVE-2025-31183: Kirin (@Pwnrin), Bohdan Stasiuk (@bohdan_stasiuk)

CVE-2025-24217: Kirin (@Pwnrin)

CVE-2025-24214: Kirin (@Pwnrin)

WebKit

CVE-2025-24264: Gary Kwong, and an anonymous researcher

CVE-2025-24216: Paul Bakker of ParagonERP

CVE-2025-24213: Google V8 Security Team

CVE-2025-24209: Francisco Alonso (@revskills), and an anonymous researcher

CVE-2025-30427: rheza (@ginggilBesel)

CVE-2025-30425: an anonymous researcher


スマホ・携帯ランキング 

2025年4月4日金曜日

iOS 18.4リリース

先日、iOS 18.4がリリースされました

対象デバイスは、iPhone XS以降, iPad(7代目), iPad mini(5代目以降), iPad Air(3代目), iPad Pro(13インチ、12.9インチ 3代目以降、11インチ 初代以降)になります

アップデート内容は、以下の様になっています。なお、英語でのリリース情報でしたので、日本語に翻訳しています

Apple lntelligence(iPhone16全モデル、iPhone15 Pro、iPhone15 Pro Max)

  • 優先通知は通知の最上部に表示され、すぐに注意を払う必要がある重要な通知をハイライトします。
  • lmage Playgroundの追加スタイルオプションにSketchが追加されました。
  • Apple lntelligence機能は、英語(インド、シンガポール)、フランス語(フランス、カナダ)、ドイツ語(ドイツ)、イタリア語(イタリア)、日本語(日本)、韓国語(韓国)、ポルトガル語(ブラジル)、簡体字中国語、スペイン語(スペイン、ラテンアメリカ、米国)を含む、8つの追加言語と2つの追加英語ロケールに対応しています。

Apple Vision Proアプリ

  • 新しいApple Vision Proアプリケーションは、Apple Vision Proを搭載しているユーザー向けに自動的に起動し、新しいコンテンツや空間体験の発見、デバイスに関する情報への素早いアクセスをサポートします。

Apple News+

  • 世界有数のレシピ出版社のレシピがApple News+に登場
  • レシピカタログでは、ブラウズや検索でぴったりの料理を見つけて、保存したレシピに保存できます。
  • クッキングモードでは、ステップバイステップの指示に簡単に従うことができます。
  • フードセクションでは、レストラン、キッチンのコツ、健康的な食事などに関する記事も楽しめます。

Photos 

  • Photosのライブラリビューで、アルバムに含まれていないアイテムや、MacまたはPCから同期されたアイテムの表示/非表示を切り替える新しいフィルタ。
  • Photosの"メディアの種類"および"ユーティリティ"コレクションのアイテムの順序を変更。
  • すべてのコレクションで一貫したフィルタリングオプション。
  • Photosで更新日順にアルバムを並べ替えるオプション。
  • Photosの設定で、"最近閲覧した"コレクションと"最近共有した"コレクションを無効にする機能。。
  • Photos設定で"Face IDを使用"が有効になっている場合、MacまたはPCへのインポート時に非表示の写真が除外されます。

このアップデートには、以下の機能強化とバグ修正も含まれています:

  • 絵文字キーボードに、オブジェクト、植物、スマイリーフェイスを含む8つの新しい絵文字が追加されました。
  • Safariの最近の検索候補により、新しいクエリを開始する際に以前の検索トピックにすばやく戻ることができます。
  • セットアップアシスタントは、保護者が家族の子供のためにチャイルドアカウントを作成するために必要な手順を合理化し、あとでチャイルドアカウントの設定を完了したい場合は、子供に適したデフォルト設定を有効にします。
  • 子どもがアプリをアンインストールし、再インストールしても、Screen Timeアプリの制限は継続されます。
  • App Storeにはユーザーレビューの要約が含まれているため、他のユーザーからの有益な情報を一目で得ることができます。
  • 進行状況を失うことなく、App Storeでアプリのダウンロードやアップデートを一時停止したり再開したりできます。
  • ポッドキャスト用の新しいウィジェットには、お気に入りの番組を追跡するためのフォロー中の番組ウィジェットや、最新のエピソード、保存済み、ダウンロード済みなどの最もよく使用するセクションにアクセスできるライブラリウィジェットが含まれます。
  • アンビエントミュージックは、コントロールセンターから即座に音楽を再生する機能を提供し、日常生活のためのサウンドトラックを提供する手作りのプレイリストのセットへのアクセスを提供します。
  • Apple Fitness+コレクションをライブラリに追加できるようになりました。
  • Matter対応のロボット掃除機をホームアプリで操作でき、シーンやオートメーションに追加することもできます。
  • バングラ語、グジャラート語、カンナダ語、マラヤーラム語、マラーティー語、オディア語、パンジャブ語、タミル語、テルグ語、ウルドゥー語を含む10の新しいシステム言語に対応。
原文:

Apple lntelligence (All iPhone 16 models, iPhone 15 Pro, iPhone 15 Pro Max)

  • Priority notifications appear at the top of your notifications, highlighting important notifications that may require your immediate attention
  • Sketch is now available as an additional style optionin in lmage Playground, allowing you to create gorgeous sketch drawings
  • Apple lntelligence features support 8 additional languages and 2 additional English locales, including English (lndia, Singapore), French (France, Canada), German (Germany), ltalian (ltaly), Japanese (Japan), Korean (South Korea), Portuguese (Brazil), Sim plified Chinese, and Spanish (Spain, Latin America, US)

Apple Vision Pro App

  • The new Apple Vision Pro app, automatically in stalled for users with Apple Vision Pro, helps you discover new content, spatial experiences, and quickly access information about your device

Apple News+

  • Recipes from some of the world's best recipe publishers are now available on Apple News+
  • Recipe Catalog allows you to browse or search to find the perfect dish and save it to your Saved Recipes
  • Cooking mode lets you easily follow step- by- step directio ns
  •   The Food section also includes stories about restaurants, kitchen tips, healthy eating, and more 

Photos 

  • New filters to show or hide items that are not contained in an album, or synced froma Mac or PC,in the Library view in Photos
  • Reorder items in the Media Types and Utilities collections in Photos
  • Consistent filtering options in all collections, including the ability to sort by oldest or newest first in Photos
  • Option to sort albums by Date Modified in Photos
  • Ability to disable "Recently Viewed" and "Recently Shared" collections in Photos Settings
  • Hidden photos are no longer in cluded for import to Mac or a PC if Use Face ID is enabled in Photos settings

This update also includes the following enhancements and bug fixes:

  • 8 new emoji including objects, plants, and a smiley face are now available in the emoji keyboard
  • Safari recent search suggestions help you quickly get back to previous search topics when starting a new query
  • Setup Assistant streamlines steps parents need to take to create a Child Account for a kid in their family, and enables child-appropriate default settings if parents prefer to complete setting up a Child Account later
  • Screen Time App Limits persist even after a child uninstalls and reinstalls an app
  • App Storeincludes summariesforuser reviews so you can get helpfulinsights from other users at a glance
  • Pause and resume of an app download or update on App Store without losing progress
  • New widgets for Podcasts including a Followed Shows  widget to track your favorite shows and a Library widget to get to your most used sections, such as Latest Episodes, Saved, and Downloaded
  • Ambient Music offers the ability to instantly play music from Control Center, giving access to a set of hand-curated playlists that offer soundtracks for daily life
  • Apple Fitness+ Collections can now be added to Library
  • Matter-compatible robot vacuum cleaners can be controlled in the Home app as well as be added to scenes and automatlons
  • Support for 10 new system languages including Bangla, Gujarati, Kannada, Malayalam, Marathi, Odia, Punjabi, Tamil, Telugu, and Urdu

Apple セキュリティアップデートを確認すると以下のセキュリティアップデート内容が記載されています

Accessibility

CVE-2025-24202: Zhongcheng Li from IES Red Team of ByteDance

Accounts

CVE-2025-24221: Lehan Dilusha @zorrosign Sri Lanka, and an anonymous researcher

AirDrop

CVE-2025-24097: Ron Masas of BREAKPOINT.SH

Audio

CVE-2025-24244: Hossein Lotfi (@hosselot) of Trend Micro Zero Day Initiative

CVE-2025-24243: Hossein Lotfi (@hosselot) of Trend Micro Zero Day Initiative

Authentication Services

CVE-2025-30430: Dominik Rath

CVE-2025-24180: Martin Kreichgauer of Google Chrome

BiometricKit

CVE-2025-24237: Yutong Xiu

Calendar

CVE-2025-30429: Denis Tokarev (@illusionofcha0s)

CVE-2025-24212: Denis Tokarev (@illusionofcha0s)

CoreAudio

CVE-2025-24163: Google Threat Analysis Group

CVE-2025-24230: Hossein Lotfi (@hosselot) of Trend Micro Zero Day Initiative

CoreMedia

CVE-2025-24211: Hossein Lotfi (@hosselot) of Trend Micro Zero Day Initiative

CVE-2025-24190: Hossein Lotfi (@hosselot) of Trend Micro Zero Day Initiative

CoreMedia Playback

CVE-2025-30454: pattern-f (@pattern_F_)

CoreServices

CVE-2025-31191: Jonathan Bar Or (@yo_yo_yo_jbo) of Microsoft, and an anonymous researcher

CoreText

CVE-2025-24182: Hossein Lotfi (@hosselot) of Trend Micro Zero Day Initiative

curl

CVE-2024-9681

DiskArbitration

CVE-2025-30456: Gergely Kalman (@gergely_kalman)

Focus

CVE-2025-30439: Andr.Ess

CVE-2025-24283: Kirin (@Pwnrin)

Foundation

CVE-2025-30447: LFY@secsys from Fudan University

Handoff

CVE-2025-30463: mzzzz__

ImageIO

CVE-2025-24210: Anonymous working with Trend Micro Zero Day Initiative

IOGPUFamily

CVE-2025-24257: Wang Yu of Cyberserval

Journal

CVE-2025-30434: Muhammad Zaid Ghifari (Mr.ZheeV) and Kalimantan Utara

Kernel

CVE-2025-30432: Michael (Biscuit) Thomas - @biscuit@social.lol

libarchive

CVE-2024-48958

libnetcore

CVE-2025-24194: an anonymous researcher

libxml2

CVE-2025-27113

CVE-2024-56171

libxpc

CVE-2025-24178: an anonymous researcher

CVE-2025-31182: Alex Radocea and Dave G. of Supernetworks, 风沐云烟(@binary_fmyy) and Minghao Lin(@Y1nKoc)

CVE-2025-24238: an anonymous researcher

Maps

CVE-2025-30470: LFY@secsys from Fudan University

MobileLockdown

CVE-2025-24193: Florian Draschbacher

NetworkExtension

CVE-2025-30426: Jimmy

Photos

CVE-2025-30428: Jax Reissner

CVE-2025-30469: Dalibor Milanovic

Power Services

CVE-2025-24173: Mickey Jin (@patch1t)

RepairKit

CVE-2025-24095: Mickey Jin (@patch1t)

Safari

CVE-2025-24113: @RenwaX23

CVE-2025-30467: @RenwaX23

CVE-2025-31192: Jaydev Ahire

CVE-2025-24167: Syarif Muhammad Sajjad

Security

CVE-2025-30471: Bing Shi, Wenchao Li, Xiaolong Bai of Alibaba Group, Luyi Xing of Indiana University Bloomington

Share Sheet

CVE-2025-30438: Halle Winkler, Politepix theoffcuts.org

Shortcuts

CVE-2025-30433: Andrew James Gonzalez

Siri

CVE-2025-31183: Kirin (@Pwnrin), Bohdan Stasiuk (@bohdan_stasiuk)

CVE-2025-24217: Kirin (@Pwnrin)

CVE-2025-24214: Kirin (@Pwnrin)

CVE-2025-24205: YingQi Shi(@Mas0nShi) of DBAppSecurity's WeBin lab and Minghao Lin (@Y1nKoc)

CVE-2025-24198: Richard Hyunho Im (@richeeta) with routezero.security

Web Extensions

CVE-2025-31184: Alexander Heinrich (@Sn0wfreeze), SEEMOO, TU Darmstadt & Mathy Vanhoef (@vanhoefm) and Jeroen Robben (@RobbenJeroen), DistriNet, KU Leuven

Web Extensions

CVE-2025-24192: Vsevolod Kokorin (Slonser) of Solidlab

WebKit

CVE-2025-24264: Gary Kwong, and an anonymous researcher

CVE-2025-24216: Paul Bakker of ParagonERP

CVE-2025-24213: Google V8 Security Team

CVE-2025-24209: Francisco Alonso (@revskills), and an anonymous researcher

CVE-2025-24208: Muhammad Zaid Ghifari (Mr.ZheeV) and Kalimantan Utara

CVE-2025-30427: rheza (@ginggilBesel)

CVE-2025-30425: an anonymous researcher

なおアップデートファイルの大きさは、iOS 18.3.2をインストールしているiPhone 11 proで3.26GB、iPhone 11で3.24GBになります


スマホ・携帯ランキング











2025年3月31日月曜日

M5Stamp Picoを買っちゃった

M5StickC Plus2を弄ってみて、玩具などの改造など色々と使い道ありそうです。そこで、組み込みし易そうな、M5Stamp Pico Mateを購入してみました。このサイズであれば、ゴチゾウからはみ出さずに出来そうな気がしますが、バッテリーや液晶などを考えると難しいかな...

内容物は本体、端子引き出し用のジャンパ端子、シール、六角レンジとなっています。サクッとジャンパ端子を半田付けして使用しみます。

なお、ArduinoIDEはM5StickC Plus2で設定していますので、ライブラリインストールのみで使用できました

とりあえず、初めに行うのはLチカと勝手に決めてGPIOにLEDを接続して試します(普通はオンボードのLEDだとは主マスが、きっと使う機会は少ないのでGPIO経由で試します)。あと、LED 1個じゃつまらないのでナイトライダー風にします


  1. // LED 制御(PWM)
  2. #include <M5unified .h>
  3. #define LED_NUM 6
  4. #define LED_DLY 50
  5. #define MAX_LED 256
  6. #define LOW_LED 64
  7. byte leds [LED_NUM] = {26, 18, 19, 21, 22, 25};
  8. byte pwmchs [LED_NUM] = {1, 2, 3, 4, 5, 6};
  9. void setup() {
  10. auto cfg = M5.config();
  11. M5.begin(cfg);
  12. // set pin to OUTPUT & LED off
  13. for (byte i = 0 ; i < LED_NUM ; i++) {
  14. pinMode(leds[i], OUTPUT);
  15. ledcSetup(pwmchs[i], 12000, 8); //周波数:12KHz、分解能:8ビット
  16. ledcAttachPin(leds[i], pwmchs[i]);
  17. }
  18. }
  19. void loop() {
  20. int y = 0;
  21. // 左から右
  22. for (int i = 0; i < LED_NUM*2-1; i++ ){
  23. if ((i % 2) == 0) {
  24. ledcWrite(pwmchs[y], MAX_LED); // 100%(3.3V)
  25. delay(LED_DLY);
  26. ledcWrite(pwmchs[y], 0); // 0%(0V)
  27. } else {
  28. ledcWrite(pwmchs[y], LOW_LED); // 25%(0.9V)
  29. ledcWrite(pwmchs[y+1], LOW_LED); // 25%(0.9V)
  30. delay(LED_DLY);
  31. ledcWrite(pwmchs[y], 0); // 0%(0V)
  32. ledcWrite(pwmchs[y+1], 0); // 0%(0V)
  33. y++;
  34. }
  35. }
  36. for (int i = LED_NUM*2-3; i >= 0; i-- ){
  37. if ((i % 2) == 0) {
  38. ledcWrite(pwmchs[y], MAX_LED); // 100%(3.3V)
  39. delay(LED_DLY);
  40. ledcWrite(pwmchs[y], 0); // 0%(0V)
  41. } else {
  42. ledcWrite(pwmchs[y], LOW_LED); // 25%(0.9V)
  43. ledcWrite(pwmchs[y-1], LOW_LED); // 25%(0.9V)
  44. delay(LED_DLY);
  45. ledcWrite(pwmchs[y], 0); // 0%(0V)
  46. ledcWrite(pwmchs[y-1], 0); // 0%(0V)
  47. y--;
  48. }
  49. }
  50. }

なお、残像を残すようにするため、ループ変数 iから変数 yを作成しています(変数 iが偶数の時はLED 1個を最大輝度、基数の時はLED 2個を25%輝度)

書き込みにはStamp ISPを使用しています(ドライバはCH9102_VCP_SER_Windowsを使用)。なお、LED点灯だけであれば5Vが無くても動作するようです。とりあえず、無事に動作しました



PWM制御で作成していますが、本来はGPIOをアンログ出力(dacWrite)を使用すると思いますが、将来的にモーターを制御したいと思いますのでPWM制御にしています

2025年3月27日木曜日

mini MAG LITE(2AA)のLED化

作業机の引き出しを整理していたところ、mini MAG LITE用のLEDモジュールが出てきました。記憶が定かではありませんが、20年位前に友人からジャンクとして貰って、後回しで引き出しに放り込んでいたんだと思います

LEDの横が溶けており修理した後がありますが、よく見ると足が折れています。ま、ダメ元と言うことでいいやと思い、手持ちのLEDと変えてみました


何とかLED交換できましたが、パターンのランドもダメになっており半田で無理やり繋いでいます(LEDを取り外した際の写真は撮り忘れ...ランドが剥がれたので焦ってしまいました)。これで点くのかとドキドキしながら、装着してみたところ無事に点灯しました

やはり電球と比べると明るいです。写真では青っぽく見えますが、白色LEDを使用しています。これでしばらく使用しみます

ま、3Vで点灯するLEDもありますので、電球の代わりに付け替える方法もあるんですがね

2025年3月25日火曜日

デジタルゴチゾウを作ってみよう:ハードウェア編

前回の記事でソフトウェアの準備が出来ましたので、今度はハードウェア面を作成します

最初にヒダカヒロジさんの「デジタルゴチゾウをつくる | MUDAなことをしよう。」サイトを参考にしてか回路を作成します。当初は、サイズが小さい点からMCP4661を単体で購入して作成するつもりでしたが、部品サイトを検索しても見つからなかったため同じモジュールを使用することにしました。なので、ヒダカヒロジさんの紹介している回路と全く同じ構成になりますので、回路詳細は「デジタルゴチゾウをつくる | MUDAなことをしよう。」サイトをご覧ください

上側の6角形にした基板には、M5STICKC Plus2を接続するためのピンヘッダーを搭載しています。下側のピンヘッダはゴチゾウ側の基板、およびスイッチを接続します。配線が切れない様にホットボンドで固定してあります

さて、ケースですが我が家には3Dプリンタはありません。たとえ、合ったとしてもデータが作れないので、ゴチゾウを切った貼ったして加工しました。途中で、タイクーンはてれびくんの付録ゴチゾウだったことを思い出し、違うのを試用すればよかったと後悔することになりました

ゴチゾウ側の基板からの配線になります。こちらも断線防止のためにホットボンドで固定しています。ゴチゾウの下部スイッチは再利用して、中にマイクロスイッチ(uxcell 20pcs 4mm x 2mm SPST 瞬間押しボタン パネルPCB)を付けています。なお、株スイッチは奥まで押し込まれますので、それに合わせてください(スイッチを貼り付けるためにスイッチの出っ張りを切り落としています)


で、組み立てるとこんな感じになります。ホットボンドやレジンで補強しまくっています

ピンヘッダーに合わせて、M5STICKC Plus2を刺すことができます

この状態でガヴベルトに接続してテストを行いました。特に高さがありませので、動作テストとベルトとの干渉をチェックしています(少し余裕があるていどで使用できます)

ここで、我が家のちびちゃんにみつかりました。遊びたいオーラ出しまくりですが、M5STICKC Plus2が不安定なので渡せません。急いで上部を作成することにしました

いらない穴をふさいで、スクリーン用の穴を空けて、次は細かい傷を消そうというところで、ちびちゃんの玩具になりました。とりあえず、不安定では無いのでちびちゃんが遊んでも簡単には壊れないと思います

とりあえず、動作画面を載せておきます




レジェンドライダーを選択した時は、ライダーズクレストが表示されます

強奪されたので、これで完成にしました。気が向いたら細かい傷取りや塗装もしたいと思ってます...

2025年3月24日月曜日

デジタルゴチゾウを作ってみよう:ソフトウェア編

現在、我が家のちびちゃんは仮面ライダーガヴにはまっており、色々なゴチゾウに興味があります。一時期よりは手に入るようになりましたが、それでも手に入らない物もありますよね

そんな中、X(旧Twitter)を眺めていたところヒダカヒロジさんの投稿でデジタルゴチゾウが紹介されていました。早速、リンク先の「デジタルゴチゾウをつくる | MUDAなことをしよう。」を拝見したところ、スケッチ(ソースコードをこういう風に言うらしい)を含む制作過程がすべて紹介されていました。

M5STAMP製品どころかArduinoも使用したことありませんが、ここまで情報があればきっと作ることが出来ると見切り発車で~す

ヒダカヒロジさんは、ヴァレンバスターをターゲットにしていますので横向き使用となっておりますが、我が家ではガヴドライバでの使用を想定しています。そのため、ヒダカヒロジさんのソースコードから下記内容を変更しています

  1. 縦型表示
    • select_gochizou 関数内の画面サイズ、およびsetup 関数内のsetRotation()の設定値を変更
    • 各種描画位置、サイズを変更
  2. ゴチゾウのカテゴリ、名称の日本語表示
    ちびちゃんはまだ読めませんが、今後の勉強もかねて
    • M5Unified.h をインクルードし、setup 関数内でsetTextFontでgfxJapanGothic_8 フォントを設定
      縦型、日本語化に伴い、このサイズを選択しています
  3. カテゴリアイコンをゴチゾウ画像化
    ちびちゃんにはこちらの方が判りますので...
    • 85x85 の画像データを作成し、こちらのサイトからバイナリ化してimg_icon.hを作成しています
  4. ゴチゾウの目を丸型化
    横幅が狭いので変更。ま、こっちの方が好みなんですけど
    • ヒダカヒロジさんの瞳作成を参考にし、縦型変更に伴うサイズ、位置設定を変更してます
    • 瞳を閉じている目、初期状態の目も描画で作成したので、img_gochizou.hは使用してません
    • 白目の部分は黒めにしています(ゴチゾウのイメージカラーで白がいるため)
  5. デバッグモードを追加
    描画動作のデバッグの容易化のため
    • 4項のデバッグのため、ボタンBの設定を拡張スイッチと同様の内容に変更
    • デバッグモード時、I2C アクセスは行わない様になっています
  6. その他
    • 75x75でライダーズクレスト画像を作成し、img_crest.hに設定
    • サポートゴチゾウを増やしています(クレーンの丈さんの調査結果を参考にしました)
    • ブンブンジャー選択時もクレスト画像を表示っするようにしています

完成したソースコードは以下になります:

  1. #include <M5StickCPlus2.h>
  2. #include "M5Unified.h" // 日本語フォントを使用するために追加
  3. #include "MCP4661_asukiaaa.hpp"
  4. #include "img_icon.h"
  5. #include "img_crest.h"
  6. #include "Wire.h"
  7. #define PIN_SW 25 // Extra SW
  8. #define ON LOW
  9. #define OFF HIGH
  10. uint8_t sw = OFF;
  11. uint8_t prev_sw = OFF;
  12. #define STATE_INIT 0
  13. #define STATE_GOCHIZOU 1
  14. #define STATE_CHANGE 2
  15. #define STATE_FINISH 3
  16. uint8_t state = STATE_INIT;
  17. uint8_t prev_state = STATE_INIT;
  18. #define STATE_FINISH_TO_CHANGE_TIME_MS 10000
  19. unsigned long state_change_point_ms = 0;
  20. // #define debug // I2C 通信オフ
  21. void change_state(uint8_t new_state){
  22. state = new_state;
  23. Serial.print(F("State: "));
  24. switch(state){
  25. case STATE_INIT: Serial.println(F("INIT")); break;
  26. case STATE_GOCHIZOU: Serial.println(F("GOCHIZOU")); break;
  27. case STATE_CHANGE: Serial.println(F("CHANGE")); break;
  28. case STATE_FINISH: Serial.println(F("FINISH")); break;
  29. default: ;
  30. }
  31. }
  32. MCP4661_asukiaaa::Core potentio(&Wire, MCP4661_asukiaaa::DeviceAddress::A0H_A1H_A2H);
  33. #define R_VALUE_MAX 256
  34. int RrA_value = 0;
  35. int RrB_value = 0;
  36. // 257ステップで100kΩなので、1ステップあたり0.389Ω。
  37. #define R_62K 162 // 145 ~ 179
  38. #define R_47K 121 // 114 ~ 132
  39. #define R_39K 102 // 95 ~ 108
  40. #define R_30K 78 // 74 ~ 82
  41. #define R_24K 63 // 60 ~ 65
  42. #define R_20K 52 // 50 ~ 54
  43. #define R_16K 42 // 39 ~ 44
  44. #define R_12K 31 // 29 ~ 32
  45. #define R_10K 26 // 25 ~ 27
  46. #define R_8_2K 21 // 20 ~ 22
  47. #define R_6_8K 17 // 17 ~ 18
  48. #define R_5_6K 14 // 14 ~ 15
  49. void printLogAboutWrite(Stream* serial, uint8_t channel, uint16_t valWrote, int result) {
  50. serial->print("write " + String(valWrote) + " for wiper" + String(channel) +
  51. " ");
  52. serial->println(result == 0 ? "succeeded"
  53. : "failed by error " + String(result));
  54. }
  55. #define CATEGORY_GUMMY 0
  56. #define CATEGORY_SNACK 1
  57. #define CATEGORY_CHOCOLATE 2
  58. #define CATEGORY_MARSHMALLOW 3
  59. #define CATEGORY_CANDY 4
  60. #define CATEGORY_RAMUNE 5
  61. #define CATEGORY_POPCORN 6
  62. #define CATEGORY_RICE_CRACKER 7
  63. #define CATEGORY_JELLY 8
  64. #define CATEGORY_MACARON 9
  65. #define CATEGORY_DONUT 10
  66. #define CATEGORY_CARAMEL 11
  67. #define CATEGORY_COOKIE 12
  68. #define CATEGORY_PUDDING 13
  69. #define CATEGORY_CAKE 14
  70. #define CATEGORY_SPECIAL 15
  71. #define CATEGORY_LEGEND_RIDER 16
  72. #define CATEGORY_SUPER_SENTAI 17
  73. #define CATEGORY_SWEETS 18
  74. typedef struct {
  75. char* name_1; // 全角 8文字
  76. char* name_2; // 全角 8文字
  77. uint32_t color; // 0x000000Uの形で表現
  78. uint16_t r_A;
  79. uint16_t r_B;
  80. } gochizou;
  81. #define C_BLACK 0x000000U
  82. #define C_NAVY 0x000080U
  83. #define C_DARKGREEN 0x008000U
  84. #define C_DARKCYAN 0x008080U
  85. #define C_MAROON 0x800000U
  86. #define C_PURPLE 0x800080U
  87. #define C_OLIVE 0x808000U
  88. #define C_LIGHTGREY 0xC0C0C0U
  89. #define C_DARKGREY 0x808080U
  90. #define C_BLUE 0x0000FFU
  91. #define C_GREEN 0x00FF00U
  92. #define C_CYAN 0x00FFFFU
  93. #define C_RED 0xFF0000U
  94. #define C_MAGENTA 0xFF00FFU
  95. #define C_YELLOW 0xFFFF00U
  96. #define C_WHITE 0xFFFFFFU
  97. #define C_ORANGE 0xFFA500U
  98. #define C_GREENYELLOW 0xADFF2FU
  99. #define C_PINK 0xFFC0CBU
  100. #define C_BROWN 0x964B00U
  101. #define C_GOLD 0xFFD700U
  102. #define C_SILVER 0xC0C0C0U
  103. #define C_SKYBLUE 0x87CEEBU
  104. #define C_VIOLET 0xB42EE2U
  105. gochizou selected_gochizou = {"ポッピンググミ", NULL, C_PURPLE, R_62K, R_62K};
  106. gochizou gochizou_gummy[] = {
  107. {"ポッピンググミ", NULL, C_PURPLE, R_62K, R_62K}, //017
  108. {"キッキンググミ", NULL, C_ORANGE, R_62K, R_47K}, //018
  109. {"パンチンググミ", NULL, C_SKYBLUE, R_62K, R_39K}, //019
  110. {"フィッシンググミ", NULL, C_CYAN, R_62K, R_30K}, //020
  111. {"アメージンググミ", NULL, C_PURPLE, R_62K, R_24K}, //021
  112. {"スパーキンググミ", NULL, C_DARKGREY, R_62K, R_20K} //022
  113. };
  114. gochizou gochizou_snack[] = {
  115. {"ザクザクチップス", NULL, C_YELLOW, R_62K, R_16K}, //023
  116. {"ヒリヒリチップス", NULL, C_RED, R_62K, R_8_2K}, //026
  117. {"ショットスナック", NULL, C_YELLOW, R_24K, R_10K}, //073
  118. {"スパイクスナック", NULL, C_YELLOW, R_24K, R_8_2K}, //074
  119. {"ショットスナック", "技:シュート", C_YELLOW, R_20K, R_47K}, //078
  120. {"スパイクスナック", "技:ニードル", C_YELLOW, R_20K, R_39K}, //079
  121. {"ポテトチェーン", NULL, C_YELLOW, R_20K, R_16K}, //083
  122. {"シールドスナック", NULL, C_YELLOW, R_20K, R_12K}, //084
  123. {"ポテトチェーン", "技:ストーム", C_YELLOW, R_20K, R_10K}, //085
  124. {"シールドスナック", "技:アタック", C_YELLOW, R_20K, R_8_2K}, //086
  125. };
  126. gochizou gochizou_chocolate[] = {
  127. {"チョコダン", NULL, C_RED, R_62K, R_6_8K}, //027
  128. {"チョコドン", "技:バースト", C_BROWN, R_62K, R_5_6K}, //028
  129. {"チョコT", NULL, C_DARKGREEN, R_47K, R_47K}, //030
  130. {"チョコホネ" , NULL, C_DARKGREEN, R_47K, R_39K}, //031
  131. {"チョコルド", NULL, C_DARKGREY, R_47K, R_30K}, //032
  132. {"チョコルド", "技:アタック", C_DARKGREY, R_47K, R_24K}, //033
  133. {"チョコスタ" , NULL, C_BROWN, R_20K, R_62K}, //077
  134. {"チョコホネ", "技:ウォール", C_DARKGREEN, R_20K, R_30K}, //080
  135. {"チョコスタ", "技:シュート", C_BROWN, R_20K, R_20K} //082
  136. };
  137. gochizou gochizou_marshmallow[] = {
  138. {"フワマロ", NULL, C_CYAN, R_47K, R_20K}, //034
  139. {"マルマロ", NULL, C_PINK, R_47K, R_16K} //035
  140. };
  141. gochizou gochizou_candy[] = {
  142. {"ブルキャン", NULL, C_MAGENTA, R_47K, R_12K}, //036
  143. {"グルキャン", NULL, C_SKYBLUE, R_47K, R_10K}, //037
  144. {"バクキャン", NULL, C_YELLOW, R_47K, R_8_2K}, //038
  145. {"もふパチ", NULL, C_PURPLE, R_39K, R_30K}, //044
  146. {"もふパチ", "技:スパーキング", C_PURPLE, R_30K, R_16K} //059
  147. };
  148. gochizou gochizou_ramune[] = {
  149. {"バブルラムネ", "技:ショック", C_SKYBLUE, R_47K, R_6_8K}, //039
  150. {"バブルラムネ", NULL, C_SKYBLUE, R_47K, R_5_6K} //040
  151. };
  152. gochizou gochizou_popcorn[] = {
  153. {"ポップバーン", NULL, C_SKYBLUE, R_39K, R_16K}, //047
  154. {"ポップバーン", "技:バーン", C_SKYBLUE, R_30K, R_8_2K} //062
  155. };
  156. gochizou gochizou_rice_cracker[] = {
  157. {"ビュンベイ", NULL, C_RED, R_39K, R_10K}, //049
  158. {"ビュンベイ", "技:ローリング", C_RED, R_30K, R_5_6K} //064
  159. };
  160. gochizou gochizou_jelly[] = {
  161. {"ぷるゼリー", NULL, C_MAGENTA, R_39K, R_8_2K}, //050
  162. {"ぷるゼリー", "技:ショット", C_MAGENTA, R_24K, R_62K} //065
  163. };
  164. gochizou gochizou_macaron[] = {
  165. {"エレガンマカロン", NULL, C_PINK, R_39K, R_6_8K}, //051
  166. {"エレガンマカロン", "技:アタック", C_PINK, R_24K, R_47K}, //066
  167. };
  168. gochizou gochizou_donut[] = {
  169. {"ドーマル", NULL, C_SKYBLUE, R_39K, R_5_6K}, //052
  170. {"ドーマル", "技:ショット", C_SKYBLUE, R_24K, R_39K} //067
  171. };
  172. gochizou gochizou_caramel[] = {
  173. {"キャラメルメル", NULL, C_GOLD, R_30K, R_62K}, //053
  174. {"キャラメルメル", "技:マジック", C_GOLD, R_24K, R_30K} //068
  175. };
  176. gochizou gochizou_cookie[] = {
  177. {"クッキッキー", NULL, C_BLUE, R_30K, R_47K}, //054
  178. {"クッキッキー", "技:ラッシュ", C_BLUE, R_24K, R_24K} //069
  179. };
  180. gochizou gochizou_pudding[] = {
  181. {"どっプリン", NULL, C_ORANGE, R_30K, R_30K}, //056
  182. {"どっプリン", "技:インパクト", C_ORANGE, R_24K, R_16K} //071
  183. };
  184. gochizou gochizou_cake[] = {
  185. {"ケーキング", NULL, C_WHITE, R_5_6K, R_39K}, //151
  186. {"ブッシュ", "ドノエル", C_GREEN, R_5_6K, R_30K} //152
  187. };
  188. gochizou gochizou_special[] = {
  189. {"スペシャル", NULL, C_WHITE, R_16K, R_62K}, //089
  190. {"おめでとう", NULL, C_WHITE, R_16K, R_47K}, //090
  191. {"クリスマス", NULL, C_GREEN, R_16K, R_39K}, //091
  192. {"ハッピー", "ニューイヤー", C_RED, R_16K, R_30K}, //092
  193. {"ミュージック", NULL, C_WHITE, R_16K, R_24K}, //093
  194. {"おめでとう", "誕生日Ver.", C_WHITE, R_16K, R_20K} //094
  195. };
  196. gochizou gochizou_legend_rider[] = {
  197. {"クウガ", NULL, C_RED, R_16K, R_16K}, //095
  198. {"アギト", NULL, C_GOLD, R_16K, R_12K}, //096
  199. {"竜騎", NULL, C_RED, R_16K, R_10K}, //097
  200. {"ファイズ", NULL, C_RED, R_16K, R_8_2K}, //098
  201. {"ブレード", NULL, C_BLUE, R_16K, R_6_8K}, //099
  202. {"響", NULL, C_PURPLE, R_16K, R_5_6K}, //100
  203. {"カブト", NULL, C_RED, R_12K, R_62K}, //101
  204. {"電王", NULL, C_RED, R_12K, R_47K}, //102
  205. {"キバ", NULL, C_RED, R_12K, R_39K}, //103
  206. {"ディケード", NULL, C_MAGENTA, R_12K, R_30K}, //104
  207. {"ダブル", NULL, C_PURPLE, R_12K, R_24K}, //105
  208. {"オーズ", NULL, C_GREEN, R_12K, R_20K}, //106
  209. {"フォーゼ", NULL, C_WHITE, R_12K, R_16K}, //107
  210. {"ウィザード", NULL, C_RED, R_12K, R_12K}, //108
  211. {"鎧武", NULL, C_ORANGE, R_12K, R_10K}, //109
  212. {"ドライブ", NULL, C_RED, R_12K, R_8_2K}, //110
  213. {"ゴースト", NULL, C_ORANGE, R_12K, R_6_8K}, //111
  214. {"エグゼイド", NULL, C_PURPLE, R_12K, R_5_6K}, //112
  215. {"ビルド", NULL, C_RED, R_10K, R_62K}, //113
  216. {"ジオウ" , NULL, C_PURPLE, R_10K, R_47K}, //114
  217. {"ゼロワン", NULL, C_YELLOW, R_10K, R_39K}, //115
  218. {"セイバー", NULL, C_RED, R_10K, R_30K}, //116
  219. {"リバイ", "REVICE", C_PINK, R_10K, R_24K}, //117
  220. {"バイス", "REVICE", C_PINK, R_10K, R_20K}, //118
  221. {"ギーツ", NULL, C_WHITE, R_10K, R_16K}, //119
  222. {"タイクーン", "GEATS", C_GREEN, R_10K, R_12K}, //120
  223. {"バッファ", "GEATS", C_PURPLE, R_10K, R_10K}, //121
  224. {"ナーゴ", "GEATS", C_GOLD, R_10K, R_8_2K}, //122
  225. {"ガッチャード", NULL, C_SKYBLUE, R_10K, R_6_8K}, //123
  226. {"レジェンド", "GOTCHARD", C_GOLD, R_10K, R_5_6K}, //124
  227. {"マジェード", "GOTCHARD", C_WHITE, R_8_2K, R_62K}, //125
  228. {"ジーン", "GEATS", C_BLUE, R_8_2K, R_47K}, //126
  229. {"ヴァルバラド", "GOTCHARD", C_PURPLE, R_8_2K, R_39K}, //127
  230. {"1号", NULL, C_GREEN, R_8_2K, R_30K}, //128
  231. {"バルカン", "ZERO-ONE", C_BLUE, R_8_2K, R_24K}, //129
  232. {"ブレイズ", "SABER", C_BLUE, R_8_2K, R_20K}, //130
  233. {"ライブ", "REVICE", C_GOLD, R_8_2K, R_16K}, //131
  234. {"ガヴ", NULL, C_PURPLE, R_5_6K, R_24K}, //153
  235. {"Nextライダー", NULL, C_GREEN, R_5_6K, R_20K}, //154
  236. {"Newヒーロー", NULL, C_GREEN, R_5_6K, R_16K}, //155
  237. {"仮面ライダー", NULL, C_GREEN, R_5_6K, R_12K} //156
  238. };
  239. gochizou gochizou_super_sentai[] = {
  240. {"戦隊", NULL, C_RED, R_8_2K, R_12K}, //132
  241. {"ヒーロー", NULL, C_RED, R_8_2K, R_10K}, //133
  242. {"爆上戦隊", "ブンブンジャー", C_RED, R_8_2K, R_8_2K} //134
  243. };
  244. gochizou gochizou_sweets[] = {
  245. {"おやつ", NULL, C_WHITE, R_24K, R_6_8K}, // 078
  246. {"おかし", NULL, C_WHITE, R_24K, R_5_6K}, // 079
  247. {"??????", NULL, C_WHITE, R_20K, R_24K},
  248. {"??????", NULL, C_WHITE, R_8_2K, R_6_8K},
  249. {"??????", NULL, C_WHITE, R_8_2K, R_5_6K},
  250. {"??????", NULL, C_WHITE, R_6_8K, R_62K},
  251. {"??????", NULL, C_WHITE, R_6_8K, R_47K},
  252. {"??????", NULL, C_WHITE, R_6_8K, R_39K},
  253. {"??????", NULL, C_WHITE, R_6_8K, R_30K},
  254. {"??????", NULL, C_WHITE, R_6_8K, R_24K},
  255. {"??????", NULL, C_WHITE, R_6_8K, R_20K},
  256. {"??????", NULL, C_WHITE, R_6_8K, R_16K},
  257. {"??????", NULL, C_WHITE, R_6_8K, R_12K},
  258. {"??????", NULL, C_WHITE, R_6_8K, R_10K},
  259. {"??????", NULL, C_WHITE, R_6_8K, R_8_2K},
  260. {"??????", NULL, C_WHITE, R_6_8K, R_6_8K},
  261. {"??????", NULL, C_WHITE, R_6_8K, R_5_6K},
  262. {"??????", NULL, C_WHITE, R_6_8K, R_62K},
  263. {"??????", NULL, C_WHITE, R_6_8K, R_47K},
  264. {"??????", NULL, C_WHITE, R_6_8K, R_39K},
  265. {"??????", NULL, C_WHITE, R_6_8K, R_30K},
  266. {"??????", NULL, C_WHITE, R_6_8K, R_24K},
  267. {"??????", NULL, C_WHITE, R_6_8K, R_20K},
  268. {"??????", NULL, C_WHITE, R_6_8K, R_16K},
  269. {"??????", NULL, C_WHITE, R_6_8K, R_12K},
  270. {"??????", NULL, C_WHITE, R_6_8K, R_10K},
  271. {"??????", NULL, C_WHITE, R_6_8K, R_8_2K},
  272. {"??????", NULL, C_WHITE, R_6_8K, R_6_8K},
  273. {"??????", NULL, C_WHITE, R_6_8K, R_5_6K},
  274. {"??????", NULL, C_WHITE, R_5_6K, R_62K},
  275. {"??????", NULL, C_WHITE, R_5_6K, R_47K}
  276. };
  277. int8_t gochizou_index = 0;
  278. uint8_t gochizou_category = CATEGORY_GUMMY;
  279. uint8_t gochizou_category_size = sizeof(gochizou_gummy) / sizeof(gochizou);
  280. void change_gochizou_category(){
  281. // カテゴリー順を編集しやすいよう、この形にする
  282. switch(gochizou_category){
  283. case CATEGORY_GUMMY:
  284. gochizou_category = CATEGORY_SNACK;
  285. gochizou_category_size = sizeof(gochizou_snack) / sizeof(gochizou);
  286. break;
  287. case CATEGORY_SNACK:
  288. gochizou_category = CATEGORY_CHOCOLATE;
  289. gochizou_category_size = sizeof(gochizou_chocolate) / sizeof(gochizou);
  290. break;
  291. case CATEGORY_CHOCOLATE:
  292. gochizou_category = CATEGORY_MARSHMALLOW;
  293. gochizou_category_size = sizeof(gochizou_marshmallow) / sizeof(gochizou);
  294. break;
  295. case CATEGORY_MARSHMALLOW:
  296. gochizou_category = CATEGORY_CANDY;
  297. gochizou_category_size = sizeof(gochizou_candy) / sizeof(gochizou);
  298. break;
  299. case CATEGORY_CANDY:
  300. gochizou_category = CATEGORY_RAMUNE;
  301. gochizou_category_size = sizeof(gochizou_ramune) / sizeof(gochizou);
  302. break;
  303. case CATEGORY_RAMUNE:
  304. gochizou_category = CATEGORY_POPCORN;
  305. gochizou_category_size = sizeof(gochizou_popcorn) / sizeof(gochizou);
  306. break;
  307. case CATEGORY_POPCORN:
  308. gochizou_category = CATEGORY_RICE_CRACKER;
  309. gochizou_category_size = sizeof(gochizou_rice_cracker) / sizeof(gochizou);
  310. break;
  311. case CATEGORY_RICE_CRACKER:
  312. gochizou_category = CATEGORY_JELLY;
  313. gochizou_category_size = sizeof(gochizou_jelly) / sizeof(gochizou);
  314. break;
  315. case CATEGORY_JELLY:
  316. gochizou_category = CATEGORY_MACARON;
  317. gochizou_category_size = sizeof(gochizou_macaron) / sizeof(gochizou);
  318. break;
  319. case CATEGORY_MACARON:
  320. gochizou_category = CATEGORY_DONUT;
  321. gochizou_category_size = sizeof(gochizou_donut) / sizeof(gochizou);
  322. break;
  323. case CATEGORY_DONUT:
  324. gochizou_category = CATEGORY_CARAMEL;
  325. gochizou_category_size = sizeof(gochizou_caramel) / sizeof(gochizou);
  326. break;
  327. case CATEGORY_CARAMEL:
  328. gochizou_category = CATEGORY_COOKIE;
  329. gochizou_category_size = sizeof(gochizou_cookie) / sizeof(gochizou);
  330. break;
  331. case CATEGORY_COOKIE:
  332. gochizou_category = CATEGORY_PUDDING;
  333. gochizou_category_size = sizeof(gochizou_pudding) / sizeof(gochizou);
  334. break;
  335. case CATEGORY_PUDDING:
  336. gochizou_category = CATEGORY_CAKE;
  337. gochizou_category_size = sizeof(gochizou_cake) / sizeof(gochizou);
  338. break;
  339. case CATEGORY_CAKE:
  340. gochizou_category = CATEGORY_SPECIAL;
  341. gochizou_category_size = sizeof(gochizou_special) / sizeof(gochizou);
  342. break;
  343. case CATEGORY_SPECIAL:
  344. gochizou_category = CATEGORY_LEGEND_RIDER;
  345. gochizou_category_size = sizeof(gochizou_legend_rider) / sizeof(gochizou);
  346. break;
  347. case CATEGORY_LEGEND_RIDER:
  348. gochizou_category = CATEGORY_SUPER_SENTAI;
  349. gochizou_category_size = sizeof(gochizou_super_sentai) / sizeof(gochizou);
  350. break;
  351. case CATEGORY_SUPER_SENTAI:
  352. //gochizou_category = CATEGORY_SWEETS;
  353. //gochizou_category_size = sizeof(gochizou_sweets) / sizeof(gochizou);
  354. gochizou_category = CATEGORY_GUMMY;
  355. gochizou_category_size = sizeof(gochizou_gummy) / sizeof(gochizou);
  356. break;
  357. /*
  358. case CATEGORY_SWEETS:
  359. gochizou_category = CATEGORY_GUMMY;
  360. gochizou_category_size = sizeof(gochizou_gummy) / sizeof(gochizou);
  361. break;
  362. */
  363. default:
  364. ;
  365. }
  366. gochizou_index = 0;
  367. }
  368. void select_gochizou(){
  369. if(gochizou_index >= gochizou_category_size){
  370. gochizou_index = 0;
  371. }else if(gochizou_index < 0){
  372. gochizou_index = gochizou_category_size - 1;
  373. }
  374. switch(gochizou_category){
  375. case CATEGORY_GUMMY: selected_gochizou = gochizou_gummy[gochizou_index]; break;
  376. case CATEGORY_SNACK: selected_gochizou = gochizou_snack[gochizou_index]; break;
  377. case CATEGORY_CHOCOLATE: selected_gochizou = gochizou_chocolate[gochizou_index]; break;
  378. case CATEGORY_MARSHMALLOW: selected_gochizou = gochizou_marshmallow[gochizou_index]; break;
  379. case CATEGORY_CANDY: selected_gochizou = gochizou_candy[gochizou_index]; break;
  380. case CATEGORY_RAMUNE: selected_gochizou = gochizou_ramune[gochizou_index]; break;
  381. case CATEGORY_POPCORN: selected_gochizou = gochizou_popcorn[gochizou_index]; break;
  382. case CATEGORY_RICE_CRACKER: selected_gochizou = gochizou_rice_cracker[gochizou_index]; break;
  383. case CATEGORY_JELLY: selected_gochizou = gochizou_jelly[gochizou_index]; break;
  384. case CATEGORY_MACARON: selected_gochizou = gochizou_macaron[gochizou_index]; break;
  385. case CATEGORY_DONUT: selected_gochizou = gochizou_donut[gochizou_index]; break;
  386. case CATEGORY_CARAMEL: selected_gochizou = gochizou_caramel[gochizou_index]; break;
  387. case CATEGORY_COOKIE: selected_gochizou = gochizou_cookie[gochizou_index]; break;
  388. case CATEGORY_PUDDING: selected_gochizou = gochizou_pudding[gochizou_index]; break;
  389. case CATEGORY_CAKE: selected_gochizou = gochizou_cake[gochizou_index]; break;
  390. case CATEGORY_SPECIAL: selected_gochizou = gochizou_special[gochizou_index]; break;
  391. case CATEGORY_LEGEND_RIDER: selected_gochizou = gochizou_legend_rider[gochizou_index]; break;
  392. case CATEGORY_SUPER_SENTAI: selected_gochizou = gochizou_super_sentai[gochizou_index]; break;
  393. case CATEGORY_SWEETS: selected_gochizou = gochizou_sweets[gochizou_index]; break;
  394. default: ;
  395. }
  396. }
  397. M5Canvas canvas_0(&StickCP2.Display); // スプライト1
  398. M5Canvas canvas_1(&StickCP2.Display); // スプライト2
  399. #define DISP_WIDTH 135
  400. #define DISP_HEIGHT 240
  401. #define SWEETS_ICON_WIDTH 85
  402. #define SWEETS_ICON_HEIGHT 85
  403. #define EYE_X 35
  404. #define EYE_Y 140
  405. void update_disp_gochizou_name(){
  406. if(gochizou_category == CATEGORY_LEGEND_RIDER){
  407. // ダブルとビルドのみ、上下で帯の色を変える
  408. switch(gochizou_index){
  409. case 10: StickCP2.Display.fillRect(0, 0, DISP_WIDTH, 25, C_GREEN); break; // W
  410. case 18: StickCP2.Display.fillRect(0, 0, DISP_WIDTH, 25, C_BLUE); break; // Build
  411. default: StickCP2.Display.fillRect(0, 0, DISP_WIDTH, 25, selected_gochizou.color);
  412. }
  413. }else{
  414. StickCP2.Display.fillRect(0, 0, DISP_WIDTH, 25, selected_gochizou.color);
  415. }
  416. StickCP2.Display.fillRect(0, 215, DISP_WIDTH, 25, selected_gochizou.color);
  417. StickCP2.Display.fillRect(0, 130, DISP_WIDTH, 85, TFT_BLACK);
  418. if(selected_gochizou.name_2 == NULL){
  419. StickCP2.Display.setCursor(0,170);
  420. StickCP2.Display.print(selected_gochizou.name_1);
  421. }else{
  422. StickCP2.Display.setCursor(0,150);
  423. StickCP2.Display.print(selected_gochizou.name_1);
  424. StickCP2.Display.setCursor(0,185);
  425. StickCP2.Display.print(selected_gochizou.name_2);
  426. }
  427. }
  428. void update_disp_gochizou_category(){
  429. StickCP2.Display.fillRect(0, 25, DISP_WIDTH, 105, C_BLACK);
  430. switch(gochizou_category){
  431. case CATEGORY_GUMMY: StickCP2.Display.drawPng((std::uint8_t*)gummy, 12425, 25, 35); break;
  432. case CATEGORY_SNACK: StickCP2.Display.drawPng((std::uint8_t*)snack, 14633, 25, 35); break;
  433. case CATEGORY_CHOCOLATE: StickCP2.Display.drawPng((std::uint8_t*)chocolate, 12294, 25, 35); break;
  434. case CATEGORY_MARSHMALLOW: StickCP2.Display.drawPng((std::uint8_t*)marshmallow, 10978, 25, 35); break;
  435. case CATEGORY_CANDY: StickCP2.Display.drawPng((std::uint8_t*)candy, 11478, 25, 35); break;
  436. case CATEGORY_RAMUNE: StickCP2.Display.drawPng((std::uint8_t*)ramune, 14219, 25, 35); break;
  437. case CATEGORY_POPCORN: StickCP2.Display.drawPng((std::uint8_t*)popcorn, 13037, 25, 35); break;
  438. case CATEGORY_RICE_CRACKER: StickCP2.Display.drawPng((std::uint8_t*)rice_cracker, 12937, 25, 35); break;
  439. case CATEGORY_JELLY: StickCP2.Display.drawPng((std::uint8_t*)jelly, 15142, 25, 35); break;
  440. case CATEGORY_MACARON: StickCP2.Display.drawPng((std::uint8_t*)macaron, 12466, 25, 35); break;
  441. case CATEGORY_DONUT: StickCP2.Display.drawPng((std::uint8_t*)donut, 15886, 25, 35); break;
  442. case CATEGORY_CARAMEL: StickCP2.Display.drawPng((std::uint8_t*)caramel, 12346, 25, 35); break;
  443. case CATEGORY_COOKIE: StickCP2.Display.drawPng((std::uint8_t*)cookie, 12419, 25, 35); break;
  444. case CATEGORY_PUDDING: StickCP2.Display.drawPng((std::uint8_t*)pudding, 15329, 25, 35); break;
  445. case CATEGORY_CAKE: StickCP2.Display.drawPng((std::uint8_t*)cake, 9209, 25, 35); break;
  446. case CATEGORY_SPECIAL: StickCP2.Display.drawPng((std::uint8_t*)special, 12475, 25, 35); break;
  447. case CATEGORY_LEGEND_RIDER: StickCP2.Display.drawPng((std::uint8_t*)rider, 2467, 25, 35); break;
  448. case CATEGORY_SUPER_SENTAI: StickCP2.Display.drawPng((std::uint8_t*)sentai, 5287, 25, 35); break;
  449. //case CATEGORY_SWEETS:
  450. // break;
  451. default: ;
  452. }
  453. }
  454. void show_gochizou_face_init(){
  455. canvas_0.fillSprite(C_WHITE);
  456. canvas_1.fillSprite(C_WHITE);
  457. // 右目
  458. canvas_0.fillCircle(EYE_X-4, EYE_Y+5, 28, C_BLACK);
  459. canvas_0.fillCircle(EYE_X, EYE_Y, 21, C_SILVER);
  460. if(gochizou_category == CATEGORY_LEGEND_RIDER){
  461. // ダブルとビルドのみ、左右で目の色を変える
  462. switch(gochizou_index){
  463. case 10: canvas_0.fillCircle(EYE_X, EYE_Y, 15, C_GREEN); break;
  464. case 18: canvas_0.fillCircle(EYE_X, EYE_Y, 15, C_BLUE); break;
  465. default: canvas_0.fillCircle(EYE_X, EYE_Y, 15, selected_gochizou.color);
  466. }
  467. }else{
  468. canvas_0.fillCircle(EYE_X, EYE_Y, 15, selected_gochizou.color);;
  469. }
  470. // 左目
  471. canvas_0.fillCircle(DISP_WIDTH - EYE_X+4, EYE_Y+5, 28, C_BLACK);
  472. canvas_0.fillCircle(DISP_WIDTH - EYE_X, EYE_Y, 21, C_SILVER);
  473. canvas_0.fillCircle(DISP_WIDTH - EYE_X, EYE_Y, 15, selected_gochizou.color);
  474. // 両ハイライト
  475. canvas_0.fillCircle(EYE_X+7, EYE_Y-7, 5, C_WHITE);
  476. canvas_0.fillCircle(DISP_WIDTH - EYE_X-7, EYE_Y-7, 5, C_WHITE);
  477. canvas_0.pushSprite(0,0);
  478. // 目を閉じる方は準備だけ
  479. canvas_1.fillCircle(EYE_X-4, EYE_Y+5, 28, C_BLACK);
  480. canvas_1.fillCircle(EYE_X-4, EYE_Y+5, 26, C_WHITE);
  481. // 左目
  482. canvas_1.fillCircle(DISP_WIDTH - EYE_X+4, EYE_Y+5, 28, C_BLACK);
  483. canvas_1.fillCircle(DISP_WIDTH - EYE_X+4, EYE_Y+5, 26, C_WHITE);
  484. }
  485. void show_gochizou_face_change(){
  486. canvas_0.fillSprite(C_WHITE);
  487. canvas_1.fillSprite(C_WHITE);
  488. // 右目
  489. canvas_0.fillCircle(EYE_X-4, EYE_Y+5, 28, C_BLACK);
  490. canvas_0.fillCircle(EYE_X, EYE_Y, 21, C_SILVER);
  491. if(gochizou_category == CATEGORY_LEGEND_RIDER){
  492. // ダブルとビルドのみ、左右で目の色を変える
  493. switch(gochizou_index){
  494. case 10: canvas_0.fillCircle(EYE_X, EYE_Y, 15, C_GREEN); break;
  495. case 18: canvas_0.fillCircle(EYE_X, EYE_Y, 15, C_BLUE); break;
  496. default: canvas_0.fillCircle(EYE_X, EYE_Y, 15, selected_gochizou.color);
  497. }
  498. }else{
  499. canvas_0.fillCircle(EYE_X, EYE_Y, 15, selected_gochizou.color);;
  500. }
  501. canvas_0.fillCircle(EYE_X, EYE_Y, 6, C_SILVER);
  502. canvas_0.fillCircle(EYE_X, EYE_Y, 2, C_BLACK);
  503. // 左目
  504. canvas_0.fillCircle(DISP_WIDTH - EYE_X+4, EYE_Y+5, 28, C_BLACK);
  505. canvas_0.fillCircle(DISP_WIDTH - EYE_X, EYE_Y, 21, C_SILVER);
  506. canvas_0.fillCircle(DISP_WIDTH - EYE_X, EYE_Y, 15, selected_gochizou.color);
  507. canvas_0.fillCircle(DISP_WIDTH - EYE_X, EYE_Y, 6, C_SILVER);
  508. canvas_0.fillCircle(DISP_WIDTH - EYE_X, EYE_Y, 2, C_BLACK);
  509. // 両まぶた
  510. canvas_0.fillTriangle(EYE_X-24, EYE_Y-26, EYE_X+26, EYE_Y+5, EYE_X+26, EYE_Y-26, C_WHITE);
  511. canvas_0.fillTriangle(DISP_WIDTH - EYE_X+24, EYE_Y-26, DISP_WIDTH - EYE_X-26, EYE_Y+5, DISP_WIDTH - EYE_X-26, EYE_Y-26, C_WHITE);
  512. // 両ハイライト
  513. canvas_0.fillCircle(EYE_X-7, EYE_Y+9, 5, C_WHITE);
  514. canvas_0.fillCircle(DISP_WIDTH - EYE_X+7, EYE_Y+9, 5, C_WHITE);
  515. // canvas_0.drawPng((std::uint8_t*)gochizou_init, 548, 0, 0);
  516. if(gochizou_category == CATEGORY_LEGEND_RIDER){
  517. switch(gochizou_index){
  518. case 0: canvas_0.drawPng((std::uint8_t*)kuuga, 2136, 30, 50); break;
  519. case 1: canvas_0.drawPng((std::uint8_t*)agito, 1897, 30, 50); break;
  520. case 2: canvas_0.drawPng((std::uint8_t*)ryuki, 2100, 30, 50); break;
  521. case 3: canvas_0.drawPng((std::uint8_t*)faiz, 1884, 30, 50); break;
  522. case 4: canvas_0.drawPng((std::uint8_t*)blade, 1357, 30, 50); break;
  523. case 5: canvas_0.drawPng((std::uint8_t*)hibiki, 2128, 30, 50); break;
  524. case 6: canvas_0.drawPng((std::uint8_t*)kabuto, 2654, 30, 50); break;
  525. case 7: canvas_0.drawPng((std::uint8_t*)deno, 3238, 30, 50); break;
  526. case 8: canvas_0.drawPng((std::uint8_t*)kiva, 2509, 30, 50); break;
  527. case 9: canvas_0.drawPng((std::uint8_t*)decade, 1612, 30, 50); break;
  528. case 10: canvas_0.drawPng((std::uint8_t*)w, 1535, 30, 50); break;
  529. case 11: canvas_0.drawPng((std::uint8_t*)ooo, 4088, 30, 50); break;
  530. case 12: canvas_0.drawPng((std::uint8_t*)fourze, 4203, 30, 50); break;
  531. case 13: canvas_0.drawPng((std::uint8_t*)wizard, 4437, 30, 50); break;
  532. case 14: canvas_0.drawPng((std::uint8_t*)gaim, 2921, 30, 50); break;
  533. case 15: canvas_0.drawPng((std::uint8_t*)drive, 1850, 30, 50); break;
  534. case 16: canvas_0.drawPng((std::uint8_t*)ghost, 2158, 30, 50); break;
  535. case 17: canvas_0.drawPng((std::uint8_t*)exaid, 2450, 30, 50); break;
  536. case 18: canvas_0.drawPng((std::uint8_t*)build, 1963, 30, 50); break;
  537. case 19: canvas_0.drawPng((std::uint8_t*)zio, 2045, 30, 50); break;
  538. case 20: canvas_0.drawPng((std::uint8_t*)zeroone, 2182, 30, 50); break;
  539. case 21: canvas_0.drawPng((std::uint8_t*)saber, 2461, 30, 50); break;
  540. case 22: canvas_0.drawPng((std::uint8_t*)revice, 2183, 30, 50); break;
  541. case 23: canvas_0.drawPng((std::uint8_t*)revice, 2183, 30, 50); break;
  542. case 24: canvas_0.drawPng((std::uint8_t*)geats, 2640, 30, 50); break;
  543. /*
  544. case 25: canvas_0.drawPng((std::uint8_t*)geats, 2640, 30, 50); break;
  545. case 26: canvas_0.drawPng((std::uint8_t*)geats, 2640, 30, 50); break;
  546. case 27: canvas_0.drawPng((std::uint8_t*)geats, 2640, 30, 50); break;
  547. */
  548. case 28: canvas_0.drawPng((std::uint8_t*)gotchard, 2453, 30, 50); break;
  549. case 29: canvas_0.drawPng((std::uint8_t*)legend, 3035, 30, 50); break;
  550. case 30: canvas_0.drawPng((std::uint8_t*)majede, 2743, 30, 50); break;
  551. // case 31: canvas_0.drawPng((std::uint8_t*)geats, 2640, 30, 50); break;
  552. case 32: canvas_0.drawPng((std::uint8_t*)valvarad, 2630, 30, 50); break;
  553. case 33: canvas_0.drawPng((std::uint8_t*)ichigo, 3302, 30, 50); break;
  554. /*
  555. case 34: canvas_0.drawPng((std::uint8_t*)zeroone, 2182, 30, 50); break;
  556. case 35: canvas_0.drawPng((std::uint8_t*)saber, 2461, 30, 50); break;
  557. case 36: canvas_0.drawPng((std::uint8_t*)revice, 2183, 30, 50); break;
  558. */
  559. case 37: canvas_0.drawPng((std::uint8_t*)gavv, 2121, 30, 50); break;
  560. /*
  561. case 38: canvas_0.drawPng((std::uint8_t*)raider, 2467, 30, 50); break;
  562. case 39: canvas_0.drawPng((std::uint8_t*)raider, 2467, 30, 50); break;
  563. case 40: canvas_0.drawPng((std::uint8_t*)raider, 2467, 30, 50); break;
  564. */
  565. default: ;
  566. }
  567. } else if(gochizou_category == CATEGORY_SUPER_SENTAI){
  568. switch(gochizou_index){
  569. //case 0: canvas_0.drawPng((std::uint8_t*)sentai, 5287, 30, 50); break;
  570. //case 1: canvas_0.drawPng((std::uint8_t*)sentai, 5287, 30, 50); break;
  571. case 2: canvas_0.drawPng((std::uint8_t*)boonboom, 3597, 30, 50); break;
  572. default: ;
  573. }
  574. }
  575. canvas_0.pushSprite(0,0);
  576. // 目を閉じる方は準備だけ
  577. canvas_1.fillCircle(EYE_X-4, EYE_Y+5, 28, C_BLACK);
  578. canvas_1.fillCircle(EYE_X-4, EYE_Y+5, 26, C_WHITE);
  579. // 左目
  580. canvas_1.fillCircle(DISP_WIDTH - EYE_X+4, EYE_Y+5, 28, C_BLACK);
  581. canvas_1.fillCircle(DISP_WIDTH - EYE_X+4, EYE_Y+5, 26, C_WHITE);
  582. // canvas_1.drawPng((std::uint8_t*)gochizou_blink, 1070, 0, 0);
  583. if(gochizou_category == CATEGORY_LEGEND_RIDER){
  584. switch(gochizou_index){
  585. case 0: canvas_1.drawPng((std::uint8_t*)kuuga, 2136, 30, 50); break;
  586. case 1: canvas_1.drawPng((std::uint8_t*)agito, 1897, 30, 50); break;
  587. case 2: canvas_1.drawPng((std::uint8_t*)ryuki, 2100, 30, 50); break;
  588. case 3: canvas_1.drawPng((std::uint8_t*)faiz, 1884, 30, 50); break;
  589. case 4: canvas_1.drawPng((std::uint8_t*)blade, 1357, 30, 50); break;
  590. case 5: canvas_1.drawPng((std::uint8_t*)hibiki, 2128, 30, 50); break;
  591. case 6: canvas_1.drawPng((std::uint8_t*)kabuto, 2654, 30, 50); break;
  592. case 7: canvas_1.drawPng((std::uint8_t*)deno, 3238, 30, 50); break;
  593. case 8: canvas_1.drawPng((std::uint8_t*)kiva, 2509, 30, 50); break;
  594. case 9: canvas_1.drawPng((std::uint8_t*)decade, 1612, 30, 50); break;
  595. case 10: canvas_1.drawPng((std::uint8_t*)w, 1535, 30, 50); break;
  596. case 11: canvas_1.drawPng((std::uint8_t*)ooo, 4088, 30, 50); break;
  597. case 12: canvas_1.drawPng((std::uint8_t*)fourze, 4203, 30, 50); break;
  598. case 13: canvas_1.drawPng((std::uint8_t*)wizard, 4437, 30, 50); break;
  599. case 14: canvas_1.drawPng((std::uint8_t*)gaim, 2921, 30, 50); break;
  600. case 15: canvas_1.drawPng((std::uint8_t*)drive, 1850, 30, 50); break;
  601. case 16: canvas_1.drawPng((std::uint8_t*)ghost, 2158, 30, 50); break;
  602. case 17: canvas_1.drawPng((std::uint8_t*)exaid, 2450, 30, 50); break;
  603. case 18: canvas_1.drawPng((std::uint8_t*)build, 1963, 30, 50); break;
  604. case 19: canvas_1.drawPng((std::uint8_t*)zio, 2045, 30, 50); break;
  605. case 20: canvas_1.drawPng((std::uint8_t*)zeroone, 2182, 30, 50); break;
  606. case 21: canvas_1.drawPng((std::uint8_t*)saber, 2461, 30, 50); break;
  607. case 22: canvas_1.drawPng((std::uint8_t*)revice, 2183, 30, 50); break;
  608. case 23: canvas_1.drawPng((std::uint8_t*)revice, 2183, 30, 50); break;
  609. case 24: canvas_1.drawPng((std::uint8_t*)geats, 2640, 30, 50); break;
  610. /*
  611. case 25: canvas_1.drawPng((std::uint8_t*)geats, 2640, 30, 50); break;
  612. case 26: canvas_1.drawPng((std::uint8_t*)geats, 2640, 30, 50); break;
  613. case 27: canvas_1.drawPng((std::uint8_t*)geats, 2640, 30, 50); break;
  614. */
  615. case 28: canvas_1.drawPng((std::uint8_t*)gotchard, 2453, 30, 50); break;
  616. case 29: canvas_1.drawPng((std::uint8_t*)legend, 3035, 30, 50); break;
  617. case 30: canvas_1.drawPng((std::uint8_t*)majede, 2743, 30, 50); break;
  618. // case 31: canvas_1.drawPng((std::uint8_t*)geats, 2640, 30, 50); break;
  619. case 32: canvas_1.drawPng((std::uint8_t*)valvarad, 2630, 30, 50); break;
  620. case 33: canvas_1.drawPng((std::uint8_t*)ichigo, 3302, 30, 50); break;
  621. /*
  622. case 34: canvas_1.drawPng((std::uint8_t*)zeroone, 2182, 30, 50); break;
  623. case 35: canvas_1.drawPng((std::uint8_t*)saber, 2461, 30, 50); break;
  624. case 36: canvas_1.drawPng((std::uint8_t*)revice, 2183, 30, 50); break;
  625. */
  626. case 37: canvas_1.drawPng((std::uint8_t*)gavv, 2121, 30, 50); break;
  627. /*
  628. case 38: canvas_1.drawPng((std::uint8_t*)raider, 2467, 30, 50); break;
  629. case 39: canvas_1.drawPng((std::uint8_t*)raider, 2467, 30, 50); break;
  630. case 40: canvas_1.drawPng((std::uint8_t*)raider, 2467, 30, 50); break;
  631. */
  632. default: ;
  633. }
  634. } else if (gochizou_category == CATEGORY_SUPER_SENTAI){
  635. switch(gochizou_index){
  636. //case 0: canvas_1.drawPng((std::uint8_t*)sentai, 5287, 30, 50); break;
  637. //case 1: canvas_1.drawPng((std::uint8_t*)sentai, 5287, 30, 50); break;
  638. case 2: canvas_1.drawPng((std::uint8_t*)boonboom, 3597, 30, 50); break;
  639. default: ;
  640. }
  641. }
  642. }
  643. void show_gochizou_face_finish(){
  644. // 天使の輪を描く
  645. canvas_0.fillSprite(C_WHITE);
  646. canvas_1.fillSprite(C_WHITE);
  647. // 右目
  648. canvas_0.fillCircle(EYE_X-4, EYE_Y+5, 28, C_BLACK);
  649. canvas_0.fillCircle(EYE_X, EYE_Y, 21, C_SILVER);
  650. if(gochizou_category == CATEGORY_LEGEND_RIDER){
  651. // ダブルとビルドのみ、左右で目の色を変える
  652. switch(gochizou_index){
  653. case 10: canvas_0.fillCircle(EYE_X, EYE_Y, 15, C_GREEN); break;
  654. case 18: canvas_0.fillCircle(EYE_X, EYE_Y, 15, C_BLUE); break;
  655. default: canvas_0.fillCircle(EYE_X, EYE_Y, 15, selected_gochizou.color);
  656. }
  657. }else{
  658. canvas_0.fillCircle(EYE_X, EYE_Y, 15, selected_gochizou.color);;
  659. }
  660. // 左目
  661. canvas_0.fillCircle(DISP_WIDTH - EYE_X+4, EYE_Y+5, 28, C_BLACK);
  662. canvas_0.fillCircle(DISP_WIDTH - EYE_X, EYE_Y, 21, C_SILVER);
  663. canvas_0.fillCircle(DISP_WIDTH - EYE_X, EYE_Y, 15, selected_gochizou.color);
  664. // 両ハイライト
  665. canvas_0.fillCircle(EYE_X+7, EYE_Y-7, 5, C_WHITE);
  666. canvas_0.fillCircle(DISP_WIDTH - EYE_X-7, EYE_Y-7, 5, C_WHITE);
  667. canvas_0.fillEllipse(DISP_WIDTH/2, 70, 50, 30, C_GOLD);
  668. canvas_0.fillEllipse(DISP_WIDTH/2, 67, 40, 20, C_WHITE);
  669. canvas_0.pushSprite(0,0);
  670. // 目を閉じる方は準備だけ
  671. canvas_1.fillCircle(EYE_X-4, EYE_Y+5, 28, C_BLACK);
  672. canvas_1.fillCircle(EYE_X-4, EYE_Y+5, 26, C_WHITE);
  673. // 左目
  674. canvas_1.fillCircle(DISP_WIDTH - EYE_X+4, EYE_Y+5, 28, C_BLACK);
  675. canvas_1.fillCircle(DISP_WIDTH - EYE_X+4, EYE_Y+5, 26, C_WHITE);
  676. canvas_1.fillEllipse(DISP_WIDTH/2, 70, 50, 30, C_GOLD);
  677. canvas_1.fillEllipse(DISP_WIDTH/2, 67, 40, 20, C_WHITE);
  678. }
  679. uint8_t blink_state = 0;
  680. unsigned long prev_eye_change_point_ms = 0;
  681. void update_face(unsigned long now_ms){
  682. // 状態遷移時
  683. switch(prev_state){
  684. case STATE_INIT:
  685. if(state == STATE_GOCHIZOU){
  686. show_gochizou_face_init();
  687. }
  688. break;
  689. case STATE_GOCHIZOU:
  690. if(state == STATE_INIT){
  691. update_disp_gochizou_name();
  692. update_disp_gochizou_category();
  693. }else if(state == STATE_CHANGE){
  694. show_gochizou_face_change();
  695. }
  696. break;
  697. case STATE_CHANGE:
  698. if(state == STATE_INIT){
  699. update_disp_gochizou_name();
  700. update_disp_gochizou_category();
  701. }else if(state == STATE_FINISH){
  702. show_gochizou_face_change();
  703. }
  704. break;
  705. case STATE_FINISH:
  706. if(state == STATE_INIT){
  707. update_disp_gochizou_name();
  708. update_disp_gochizou_category();
  709. }else if(state == STATE_CHANGE){
  710. show_gochizou_face_finish();
  711. }
  712. break;
  713. default:
  714. ;
  715. }
  716. // 時間経過時
  717. if(state == STATE_GOCHIZOU || state == STATE_CHANGE){
  718. // まばたき動作
  719. switch(blink_state){
  720. case 0:
  721. if(now_ms - prev_eye_change_point_ms >= 3000){
  722. canvas_1.pushSprite(0,0); // 目を閉じる
  723. blink_state++;
  724. prev_eye_change_point_ms = now_ms;
  725. }
  726. break;
  727. case 1:
  728. if(now_ms - prev_eye_change_point_ms >= 100){
  729. canvas_0.pushSprite(0,0); // 目を開く
  730. blink_state++;
  731. prev_eye_change_point_ms = now_ms;
  732. }
  733. break;
  734. case 2:
  735. if(now_ms - prev_eye_change_point_ms >= 5000){
  736. canvas_1.pushSprite(0,0); // 目を閉じる
  737. blink_state++;
  738. prev_eye_change_point_ms = now_ms;
  739. }
  740. break;
  741. case 3:
  742. if(now_ms - prev_eye_change_point_ms >= 100){
  743. canvas_0.pushSprite(0,0); // 目を開く
  744. blink_state++;
  745. prev_eye_change_point_ms = now_ms;
  746. }
  747. break;
  748. case 4:
  749. if(now_ms - prev_eye_change_point_ms >= 7000){
  750. canvas_1.pushSprite(0,0); // 目を閉じる
  751. blink_state++;
  752. prev_eye_change_point_ms = now_ms;
  753. }
  754. break;
  755. case 5:
  756. if(now_ms - prev_eye_change_point_ms >= 100){
  757. canvas_0.pushSprite(0,0); // 目を開く
  758. blink_state++;
  759. prev_eye_change_point_ms = now_ms;
  760. }
  761. break;
  762. case 6:
  763. if(now_ms - prev_eye_change_point_ms >= 100){
  764. canvas_1.pushSprite(0,0); // 目を閉じる
  765. blink_state++;
  766. prev_eye_change_point_ms = now_ms;
  767. }
  768. break;
  769. case 7:
  770. if(now_ms - prev_eye_change_point_ms >= 100){
  771. canvas_0.pushSprite(0,0); // 目を開く
  772. blink_state = 0;
  773. prev_eye_change_point_ms = now_ms;
  774. }
  775. break;
  776. default:
  777. ;
  778. }
  779. }
  780. }
  781. void setup(void)
  782. {
  783. auto cfg = M5.config();
  784. StickCP2.begin(cfg);
  785. Wire.end();
  786. Wire.begin(0, 26); //G0. G26 I2C port
  787. Serial.begin(115200);
  788. // 省電力化のため、CPU周波数を少し落とす場合に有効化。最大240MHz。
  789. setCpuFrequencyMhz(160);
  790. pinMode(PIN_SW, INPUT_PULLUP); // 入力として使用する
  791. gpio_pulldown_dis(GPIO_NUM_36); // 使用しないのでフローティング入力設定
  792. gpio_pullup_dis(GPIO_NUM_36); // 使用しないのでフローティング入力設定
  793. StickCP2.Display.setBrightness(5);
  794. StickCP2.Display.setRotation(2); // 画面向き
  795. StickCP2.Display.setTextSize(2); // フォントサイズ
  796. StickCP2.Display.setTextFont(&fonts::lgfxJapanGothic_8); // フォント
  797. update_disp_gochizou_name();
  798. update_disp_gochizou_category();
  799. // ゴチゾウの表情用スプライトの準備
  800. canvas_0.createSprite(DISP_WIDTH, DISP_HEIGHT);
  801. canvas_1.createSprite(DISP_WIDTH, DISP_HEIGHT);
  802. }
  803. void loop(void)
  804. {
  805. StickCP2.update();
  806. sw = digitalRead(PIN_SW);
  807. unsigned long now_ms = millis();
  808. if(prev_sw == OFF && sw == ON){
  809. switch(state){
  810. case STATE_INIT:
  811. StickCP2.Speaker.tone(5000, 50);
  812. change_gochizou_category();
  813. select_gochizou();
  814. update_disp_gochizou_category();
  815. update_disp_gochizou_name();
  816. break;
  817. case STATE_GOCHIZOU:
  818. change_state(STATE_CHANGE);
  819. break;
  820. case STATE_CHANGE:
  821. change_state(STATE_FINISH);
  822. state_change_point_ms = now_ms;
  823. break;
  824. case STATE_FINISH:
  825. break;
  826. default:
  827. ;
  828. }
  829. }
  830. if(StickCP2.BtnA.wasClicked()){
  831. StickCP2.Speaker.tone(5000, 50);
  832. switch(state){
  833. case STATE_INIT:
  834. gochizou_index++;
  835. select_gochizou();
  836. update_disp_gochizou_name();
  837. break;
  838. case STATE_GOCHIZOU:
  839. break;
  840. case STATE_CHANGE:
  841. case STATE_FINISH:
  842. default:
  843. ;
  844. }
  845. }
  846. if(StickCP2.BtnB.wasClicked()){
  847. switch(state){
  848. case STATE_INIT:
  849. StickCP2.Speaker.tone(5000, 50);
  850. change_gochizou_category();
  851. select_gochizou();
  852. update_disp_gochizou_category();
  853. update_disp_gochizou_name();
  854. break;
  855. case STATE_GOCHIZOU:
  856. change_state(STATE_CHANGE);
  857. break;
  858. case STATE_CHANGE:
  859. change_state(STATE_FINISH);
  860. state_change_point_ms = now_ms;
  861. break;
  862. case STATE_FINISH:
  863. break;
  864. default:
  865. ;
  866. }
  867. }
  868. if(StickCP2.BtnA.wasHold()){
  869. switch(state){
  870. case STATE_INIT:
  871. // 抵抗値をセットする
  872. int result_a, result_b;
  873. #ifndef debug
  874. result_a = potentio.writeWiperRAM(0, selected_gochizou.r_A);
  875. printLogAboutWrite(&Serial, 0, selected_gochizou.r_A, result_a);
  876. result_b = potentio.writeWiperRAM(1, selected_gochizou.r_B);
  877. printLogAboutWrite(&Serial, 1, selected_gochizou.r_B, result_b);
  878. #else
  879. result_a = 0;
  880. result_b = 0;
  881. #endif
  882. if(result_a == 0 && result_b == 0){
  883. StickCP2.Speaker.tone(4000, 50);
  884. delay(50);
  885. StickCP2.Speaker.tone(6000, 50);
  886. change_state(STATE_GOCHIZOU);
  887. }
  888. break;
  889. case STATE_GOCHIZOU:
  890. case STATE_CHANGE:
  891. case STATE_FINISH:
  892. change_state(STATE_INIT);
  893. break;
  894. default:
  895. ;
  896. }
  897. }
  898. // 時間経過処理
  899. if(state == STATE_FINISH && now_ms - state_change_point_ms >= STATE_FINISH_TO_CHANGE_TIME_MS){
  900. change_state(STATE_CHANGE);
  901. }
  902. update_face(now_ms);
  903. prev_sw = sw;
  904. prev_state = state;
  905. delay(10);
  906. }

完成したスケッチをArduino IDEでコンパイルと検証を行って見たいと思います。その前に準備として、MCP4661_asukiaaaをArduino IDEにインストールしました(関連ライブラリとして、wire_asukiaaa 1.1.13もインストールされました)

コンパイルしたところ、エラーが発生しました

  1. IIn file included from c:\Users\********\Documents\Arduino\libraries\wire_asukiaaa\src/wire_asukiaaa.h:3,
  2. from c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp:3,
  3. from C:\Tools\M5StickCPlus2\gochizou\gochizou.ino:3:
  4. c:\Users\********\Documents\Arduino\libraries\wire_asukiaaa\src/wire_asukiaaa.hpp:8:35: error: 'TwoWire' was not declared in this scope
  5. typedef PeripheralHandlerTemplate<TwoWire> PeripheralHandler;
  6. ^~~~~~~
  7. c:\Users\********\Documents\Arduino\libraries\wire_asukiaaa\src/wire_asukiaaa.hpp:8:35: note: suggested alternative: 'TwoWire_h'
  8. typedef PeripheralHandlerTemplate<TwoWire> PeripheralHandler;
  9. ^~~~~~~
  10. TwoWire_h
  11. c:\Users\********\Documents\Arduino\libraries\wire_asukiaaa\src/wire_asukiaaa.hpp:8:42: error: template argument 1 is invalid
  12. typedef PeripheralHandlerTemplate<TwoWire> PeripheralHandler;
  13. ^
  14. In file included from C:\Tools\M5StickCPlus2\gochizou\gochizou.ino:3:
  15. c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp:131:3: error: 'TwoWire' does not name a type; did you mean 'TwoWire_h'?
  16. TwoWire* wire;
  17. ^~~~~~~
  18. TwoWire_h
  19. c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp:133:15: error: expected ')' before '*' token
  20. Core(TwoWire* wire, uint8_t address) : wire(wire), address(address) {}
  21. ~ ^
  22. )
  23. c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp: In member function 'int MCP4661_asukiaaa::Core::writeToRegister(uint8_t, uint16_t, uint8_t)':
  24. c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp:189:5: error: 'wire' was not declared in this scope
  25. wire->beginTransmission(address);
  26. ^~~~
  27. c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp:189:5: note: suggested alternative: 'Core'
  28. wire->beginTransmission(address);
  29. ^~~~
  30. Core
  31. c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp: In member function 'int MCP4661_asukiaaa::Core::readFromRegister(uint8_t, uint16_t*, uint8_t)':
  32. c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp:199:9: error: 'wire' was not declared in this scope
  33. wire, address, buildFirstByte(registerAddress, command, 0), bytes, 2);
  34. ^~~~
  35. c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp:199:9: note: suggested alternative: 'Core'
  36. wire, address, buildFirstByte(registerAddress, command, 0), bytes, 2);
  37. ^~~~
  38. Core
  39. C:\Tools\M5StickCPlus2\gochizou\gochizou.ino: At global scope:
  40. C:\Tools\M5StickCPlus2\gochizou\gochizou.ino:38:84: error: no matching function for call to 'MCP4661_asukiaaa::Core::Core(TwoWire*, const uint8_t&)'
  41. MCP4661_asukiaaa::Core potentio(&Wire, MCP4661_asukiaaa::DeviceAddress::A0H_A1H_A2H);
  42. ^
  43. In file included from C:\Tools\M5StickCPlus2\gochizou\gochizou.ino:3:
  44. c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp:129:7: note: candidate: 'constexpr MCP4661_asukiaaa::Core::Core(const MCP4661_asukiaaa::Core&)'
  45. class Core {
  46. ^~~~
  47. c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp:129:7: note: candidate expects 1 argument, 2 provided
  48. c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp:129:7: note: candidate: 'constexpr MCP4661_asukiaaa::Core::Core(MCP4661_asukiaaa::Core&&)'
  49. c:\Users\********\Documents\Arduino\libraries\MCP4661_asukiaaa\src/MCP4661_asukiaaa.hpp:129:7: note: candidate expects 1 argument, 2 provided
  50. exit status 1
  51. Compilation error: no matching function for call to 'MCP4661_asukiaaa::Core::Core(TwoWire*, const uint8_t&)'
エラーメッセージから検索しましたが、さっぱり判りません。そもそもToWireってM5STAMPの標準関数では無いの?!っという疑問しかわきませんでした。記述内容をチェックしても原因が判りません

問題の切り分けのためにMCP4661_asukiaaa.hppにM5StickCPlus2.hのインクルード文を追加したところ同じエラーが発生、さらにwire_asukiaaa.hppにも追加してもエラーが発生しました。
この現象から、ToWireが定義されているwire.hが参照されていないのではなりました。

慣れている人であれば対策を知っているかと思いますが、初めて使用した私からするとこれまたサッパリです。なので、全てのヘッダファイルをローカルにコピーして、インクルード文をローカル参照にすることでコンパイルが正常に終了しました。簡単に書いていますが、一晩悩みましたよ

2025年3月18日火曜日

M5StickC Plus2の開発環境準備

先日、あるものを作りたくなり、その準備のためにM5StickC Plus2を購入しました


この製品は、M5Stackテクノロジー社のマイコンボードで、CPU:ESP32-PICO-V3-02、フラッシュメモリ:8MB、さらにバッテリーを搭載ています

これの開発環境としてはいくつかありますが、今回は手軽そうなArduinoIDEを使用することにしました

最初にArduinoIDEをダウンロードします。ArduinoIDEのサイトに移動して、Download Optionから使用しているOSにあったファイルをダウンロードします。今回は「Windows win 10 and newer, 64bit」を選択しました


ダウンロードは、寄付または無償でダウンロードすることが出来ます。無償で行う場合は、「JUST DOWNLOAD」をクリックします

ダウンロードが完了したらインストーラを起動し、指示に従ってインストールします

次にArduinoIDEをM5StickC Plus2に合わせて設定します

ファイルメニューの基本設定を開きます(最初は英語設定なので、File → Preferences)


下記設定を行います

  • エディタ言語(Language):日本語
  • 配色テーマ(Theme):Dark(お好みで)
  • 追加のボードマネージョーのURL(Additional boards Maneger URLs)に下記サイトを追加
    https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
ボードマネージャーを開き、M5Stackをインストールします

ボードマネージャーのインストールが完了すると、ターゲットボードの設定にM5StickC Plus2が表示されます


M5StickC Plus2に必要な下記ライブラリをライブラリマネージャーでインストールします
  • M5StickCPlus2
  • M5Unified


これで、ArduinoIDEの設定は完了になります

最後にM5StickC Plus2に書き込むためのUSBドライバをインストールします。インストーラーは、M5Stackのサイトからリンクされています


M5StickC Plus2の場合、「FTDI Drivers」になります。リンク先サイトから赤丸箇所をクリックするとダウンロードできます

ドライバのインストールを行えば、準備完了になります

2025年3月14日金曜日

iOS 18.3.2リリース

iOS 18.3.2がリリースされました

対象デバイスは、iPhone XS以降, iPad(7代目), iPad mini(5代目以降), iPad Air(3代目), iPad Pro(13インチ、12.9インチ 3代目以降、11インチ 初代以降)になります

アップデート内容は、以下の様になっています

このアップデートには重要なバグ修正とセキュリティアップデートが含まれ、一部のストリーミングコンテンツを再生できなくなることがある問題に対応しています。

Apple セキュリティアップデートを確認すると以下のセキュリティアップデート内容が記載されています

WebKit

WebKit Bugzilla: 285858 

CVE-2025-24201: Apple

なおアップデートファイルの大きさは、iOS 18.3.1をインストールしているiPhone 11 proで433.6MB、iPhone 11で418.7MBになります


スマホ・携帯ランキング

2025年2月18日火曜日

Xiaomi Smart Band 8 Active の液晶が割れた。じゃ、分解だな

 家人が使用して言えるXiaomi Smart Band 8 Activeの液晶が割れてしまいました

ま、価格も安いし捨ててしまおうかと思いましたが、折角なので分解してみることにしました。早速、ホットマットで液晶を温めてフラットスパッジャーで外します(外すと言うよりは割っているに近かったです)

液晶のフラットケーブルは、メイン基板の裏側で接続されていますので、メイン基板を外す必要があります。赤丸のネジを3本外し、ピンセットなどで下側の樹脂製のカバーを外します。なお、下側には充電用のマグネットがありますので、ネジを外す際に若干抵抗があります

ネジと樹脂カバーを外すとこんな感じになります。プラ製のオープナーでバッテリーと一緒にメイン基板を外します(両面テープが無いか不安でしたが、簡単に外れました)

メイン基板の裏側です。写真右側のシールを剥がすと液晶を外すことが出来ます

液晶の裏側はこんな感じになっています。ガラス面が割れているので、セロテープで飛散防止しています。おかげで、印刷してある文字が読みにくくなりました

で、分解はここまでになります。これで終わりと思いましたが、折角なので交換液晶が無いかAliexpressで探してみました。残念ながら、Smart Band 8 Activeで検索しても交換用液晶は出てきませんでした(Smart Band 無印はたくさん出てきます)。そこで、今度は液晶サイズ(1.47インチ)から検討して、Xiaomi-Redmi Band 2が同じサイズで使えそうです

割れた液晶のケーブルに印刷されたシルクも同じそうなので、物は試しと購入してみました。購入後に気が付きましたが、アマゾンでもこの液晶は購入可能みたいです(ちょっち高い)

で、早速交換してみるとピッタリサイズで使用可能です

タッチパネルも問題なく使用可能です。残念ながら、液晶固定用の専用テープは無かったので1mm の両面テープで張り付けています(防水、強度にはかなり不安があります)。ま、割れて時間がたっているので、使用する予定もないので気にしないことにしました

おまけ:メイン基板を外した後のケースはこんな感じになっています