以下の内容はhttps://gijin77.blog.jp/archives/cat_428510.htmlより取得しました。


◆M5Stack Tab5 で「radiko」の無料枠(三時間)を聞いてみました。

 radiko_tab5_1

1.「radiko」の無料枠
 ①Radikoの無料範囲はどこまで?
  ※ 無料の機能では、あなたが今いるエリアで現在放送されているラジオ局の番組は
   聴くことができます。

 ②Radikoは無料で何時間聴けるか?
 ※ 無料の機能では、あるひとつの番組を選んで、その番組を再生し始めてから
  24時間以内であれば、合計3時間まで聴くことができます。

 ➂神奈川県での「radiko」は、下記の15局が受信できます。 
  No.0 ID: TBS , name: TBSラジオ
  No.1 ID: QRR , name: 文化放送
  No.2 ID: LFR , name: ニッポン放送
  No.3 ID: RN1 , name: ラジオNIKKEI第1
  No.4 ID: RN2 , name: ラジオNIKKEI第2
  No.5 ID: INT , name: interfm
  No.6 ID: FMT , name: TOKYO FM
  No.7 ID: FMJ , name: J-WAVE
  No.8 ID: JORF , name: ラジオ日本
  No.9 ID: BAYFM78 , name: BAYFM78
  No.10 ID: NACK5 , name: NACK5
  No.11 ID: YFM , name: FMヨコハマ
  No.12 ID: IBS , name: LuckyFM 茨城放送
  No.13 ID: JOAK , name: NHKラジオ第1(東京)
  No.14 ID: JOAK-FM , name: NHK-FM(東京)
  station_MAX = 15

 先人の方のサイトを参考にM5Stack Tab5に移植修正してradikoを聞くことが出来るように
 なりました。感謝です。
 下記のサイトに詳しく説明されています。
  Radiko(ESP32S3編)

2.まずは音声出力用のライブラリとして、下記をインストールします。
 ①下記より「zip」ファイルをダウンロードするかライブラリマネージャーで検索して
  インストールします。
  ESP32-audioI2S-master : 3.4.2

 ②インストール出来たら「radiko」を聞くためにライブラリを修正します。
 
 ➂ライブラリフォルダの「libraries\ESP32-audioI2S-master\src\Audio.cpp」を
  エデッタで開きます。

 ④627行当たりに追加修正します。
 
 627://2025/11/08 追加修正
    628:       if(authLen > 0) {
    629:        if(user == "-") {
    630:      rqh.append("X-Radiko-AuthToken: ");
    631:          rqh.append(pwd);
    632:        } else {
    633:      rqh.append("Authorization: Basic ");
    634:           rqh.append(authorization.get());
    635:        }
    636:           rqh.append("\r\n"); 
    637:       }
    638:      
    639:
  640:/*
    641:    if(authLen > 0) {  rqh.append("Authorization: Basic ");
    642:                       rqh.append(authorization.get());
    643:                       rqh.append("\r\n"); }
    644:*/
     
   ⑤あと「tab5」の音声出力に必要な「examples\ES8388\」フォルダ内の次の二つを
    スケッチのフォルダにコピーします。   
    「libraries\ESP32-audioI2S-master\examples\ES8388\ES8388.cpp」
    「libraries\ESP32-audioI2S-master\examples\ES8388\ES8388.h」
   
   ⑥このままだとコンパイルエラーが発生しましたので、エラー箇所をコメントアウトしました。
    *取り敢えずの対処です。
    152行から157行をコメントアウトします。
    
 151:            /* set up MCLK) */
    152:    /*  #ifdef FUNC_GPIO0_CLK_OUT1
 153:          PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U,             FUNC_GPIO0_CLK_OUT1);
    154:        #endif
    156:          WRITE_PERI_REG(PIN_CTRL, 0xFFF0);
    157:    */
    158:    }    
    
  以上で準備OKです。
  
3.開発環境 2025/11/12時点
  ①Windows11 X64 Pro 25H2 
  ②Arduino IDE 2.3.6
  ➂ESP32ボードバージョンV3.3.4
  ④M5STACK Tab5 ボードバージョンV3.2.4
  ⑤M5GFX ライブラリv0.2.17
  ⑥bb_captouch ライブラリv1.3.1
  ⑦ESP32-audioI2S-master v3.4.2
  ⑧efont_Unicode_Font_Data v1.0.9
  ⑨その他のライブラリもインストールが必要

4.スケッチ及びコンパイル時の設定
 ①ボード設定「M5Stack -> M5Tab5」
 ②コンパイル時の設定
 tab5_radioko_設定

 ➂WiFiの設定を自分用に書き換えます。
  53:// WiFi設定
  54:const char* ssid     = "IO_Net_2G"; //自分用に変更
  55:const char* password = "1234567890"; //自分用に変更

 ④LCD表示用のライブラリは、「M5GFX」を使用していますが、書式として
  「Arduino_GFX_Library」に準拠するように変更しています。

  59:M5GFX tft;
  60:LGFX_Device* gfx = &tft;  // ← これで gfx->begin() の形式が使える

 ⑤今回GUIにバックグランドのイメージデータを使用して
  その上にラジコ局名、WiFi接続状況、時計表示をしています。
 
 ⑥スケッチ構成(zipファイルにて)
  (1)「tab5_radiko.ino」--本体スケッチ
  (2)「img_radiko.h」------画像データ
  (3)「ES8388.h」----------tab5 オーディオチップ用ドライバ
  (4)「ES8388.cpp」-------tab5 オーディオチップ用ドライバ
  
  (保障無しの自己責任で)  tab5_radiko.zip

5.実際の実行の様子
 ①「FMヨコハマ」を再生中
 radiko_tab5_1


 ②停止中
 radiko_tab5_2


6.他のボードについてもインストール済みです。
 ①「JC3248W535」
 radiko_JC3248W535

 ②「ESP32-4848S040」
 radiko_ESP32-4848S040

 ➂「freenove-media-kit-3.5」
 radiki_media_kit

 ④「ES3C28P」
 radiko_ES3C28P

 順次、ブログに記事を追加いたします。

以上


ブログトップへ

◆M5Stack Tab5 でWiFiがArduino IDE環境で使えるようになったのでインターネットラジオを
 作ってみました。
 tab5_radio2

 「M5Unified」を使うとMP3データを扱う時にドライバの競合によるエラーでリブートを
 繰り返す事象が発生しました。
 
 対策①「M5Unified」を使わず音出しが出来るようにしました。
 対策② 同じくタッチスクリーが使えるようににしました。
     これについては、下記ブログ内記事を参照して下さい。
     ・M5Stack Tab5 で「M5Unified」無しでタッチスクリーンを試してみた
      
1.対策①について最も苦労しました。
 ①Tab5で音出ししている「ES8388」のドライバをIDE環境で探す事から始めました。
  色々探していて、M5Stack オーディオモジュールで「ES8388」が使用されているのが
  分かりました。これ用のドライバで実験しましたら音を出すことが出来ました。
  下記参照
  (1)スイッチサイエンスのURL
   M5Stack オーディオモジュール(STM32G030)

  (2)本家のURL
   Module Audio

 ②ドライバを下記よりダウンロードしZIPファイルでライブラリにインストールします。
   M5モジュールオーディオ

2.参考資料等
 ①「M5Stack Tab5」について回路図等詳しくは、
   下記ブログ内記事の最後の方を参照して下さい。
  ・M5Stack TAB5 ArduinoIDE M5GFX RTC 環境でニキシー管時計もどきを表示してみた

 ②M5StackのI2Cアドレスは、下記で分かります。
  M5StackデバイスのI2Cアドレス(7ビット)

3.開発環境 2025/08/04時点
  ①Windows11 X64 Pro 24H2 
  ②Arduino IDE 2.3.6
  ➂ESP32ボードバージョンV3.3.0
  ④M5STACK Tab5 ボードバージョンV3.2.2
  ⑤M5GFX ライブラリv0.2.9
  ⑥bb_captouch ライブラリv1.3.1

4.スケッチ及びコンパイル時の設定
 ①ボード設定「M5Stack -> M5Tab5」
 ②コンパイル時設定
 tab5_ide

 ➂LCD表示用のライブラリは、「M5GFX」を使用していますが、書式として
  「Arduino_GFX_Library」に準拠するように変更しています。

 5:#include <M5GFX.h>
 
 59:M5GFX tft;
 60:LGFX_Device* gfx = &tft;  // ← これで gfx->begin() の形式が使える

 ④今回GUIに1280x720のバックグランドのイメージデータを使用して
  その上にラジオ局名、再生中データ、WiFi接続状況、時計表示をしています。

 ⑤デバッグ時にタッチ操作の範囲を確認する為、枠を表示して確認しました。
  真ん中のでっかい再生ボタンは、今回使用していません。
  次に、MP3プレイヤーを作るときに使おうと思っています。
 tab5_radio1
 
 ⑥スケッチ構成(zipファイルにて)
  (1)「tab5_inet_radio.ino」--本体スケッチ
  (2)「img_radio.h」---画像データ
  (保障無しの自己責任で)  tab5_inet_radio.zip

5.実際の実行の様子
 
 


以上


ブログトップへ

◆M5Stack Tab5 で「M5Unified」無しでタッチスクリーンを試してみました。

 tab5_touch_demo
 以前下記ボードで三種のライブラリで試験しましたが、その中のbb_captouchを
 使いました。
 下記ブログ内記事を参照して下さい。
 ・JC1060P470C(ESP32P4 ESP32C6 搭載) でタッチスクリーンを試してみた

1.タッチの仕様
 ①静電容量方式
 ②インターフェースは、「I2C」でアドレスは、「0x14」
 ➂解像度 1280 x 720

2.参考資料等
 ①「M5Stack Tab5」について回路図等詳しくは、下記ブログ内記事を参照して下さい。
 ・M5Stack TAB5 ArduinoIDE M5GFX RTC 環境でニキシー管時計もどきを表示してみた
 
3.開発環境 2025/07/30時点
  ①Windows11 X64 Pro 24H2 
  ②Arduino IDE 2.3.6
  ➂ESP32ボードバージョンV3.3.0
  ④M5STACK Tab5 ボードバージョンV3.2.2
  ⑤M5GFX ライブラリv0.2.9
  ⑥bb_captouch ライブラリv1.3.1  「ライブラリマネージャーでインストールします。」

4.スケッチ及びコンパイル時の設定
 ①ボード設定「M5Stack -> M5Tab5」
 ②コンパイル時設定
 tab5_ide

 ➂LCD表示用のライブラリは、「M5GFX」を使用していますが、書式として
  「Arduino_GFX_Library」に準拠するように変更しています。

 6:#include <M5GFX.h>
 7:
 8:M5GFX tft;
 9:LGFX_Device* gfx = &tft;  // ← これで gfx->begin() の形式が使える

 ④スケッチ例「tab5_BBCapTouch_test.ino」
 
//tab5_BBCapTouch_test.ino
//V2025/07/30 M5Stack Tab5 1280x720 by JK1VCk
//blog URL:https://gijin77.blog.jp/archives/45237682.html

//***************************************************************************
#include <M5GFX.h>

M5GFX tft;
LGFX_Device* gfx = &tft;  // ← これで gfx->begin() の形式が使える

#define GFX_BL 22 // LCD バックライト
//***************************************************************************

#include <bb_captouch.h>
#include <Wire.h>

//GT911 I2C adress 0x14
//PI4IOE5V6408 P5 TOUCH_RST
//https://docs.m5stack.com/ja/core/Tab5 //GPIO割当

#define TOUCH_SDA 31
#define TOUCH_SCL 32
#define TOUCH_INT 23
#define TOUCH_RST -1

BBCapTouch bbct;

//***************************************************************************
int32_t w, h, n, n1, cx, cy, cx1, cy1, cn, cn1; //画面サイズ等の各種データ
//***************************************************************************

void setup(){
  Serial.begin(115200);
  while (!Serial); 
  Serial.println("\n\nM5Stack Tab5 BBCapTouch test start\n");
  if (!gfx->begin()) {
    Serial.println("gfx->begin() failed!");
  } else {
    Serial.println("gfx->begin() OK!!");
  }
  
  gfx->setRotation(3);
  w = gfx->width();
  h = gfx->height();
  n = min(w, h);
  n1 = n - 1;
  cx = w / 2;
  cy = h / 2;
  cx1 = cx - 1;
  cy1 = cy - 1;
  cn = min(cx1, cy1);
  cn1 = cn - 1;

  pinMode(GFX_BL, OUTPUT);
  digitalWrite(GFX_BL, HIGH); //バックライトON
  
// Init touch device *********************
  bbct.init(TOUCH_SDA, TOUCH_SCL, TOUCH_RST, TOUCH_INT);
  int iType = bbct.sensorType();
  Serial.printf("iType=%d \n",iType); 

  gfx->fillScreen(BLACK); 
  gfx->setTextSize(6);
  gfx->setTextColor(GREEN);
  gfx->setCursor(0,0);
  gfx->println("touch test Start By JK1VCK"); 
}
void loop() {
  bool touched;
  uint16_t touchX, touchY,cox,coy;
  w=gfx->width();
  h=gfx->height();
  int r=gfx->getRotation();
  TOUCHINFO ti;
  if (bbct.getSamples(&ti)) {
    ti.x[0] = map(ti.x[0], 0, 1280, 0, w - 1);  // X軸を0〜1280にマッピング
    ti.y[0] = map(ti.y[0], 0, 720, 0, h - 1);  // y軸を0〜720にマッピング
    cox=ti.x[0];
    coy=ti.y[0];
    switch (r) {
      case 1:
        touchY=h-cox;touchX=coy;break;
      case 2:
        touchX=w-cox;touchY=h-coy;break;
      case 3:
        touchY=cox;touchX=w-coy;break;
      default:
        touchX=cox;touchY=coy;break;
    }
    Serial.printf("x=%d,y=%d \r\n",touchX,touchY);
    gfx->fillRect(touchX,touchY,5,5, RED);
    if(touchX>1200){ //画面右端タッチにて画面クリア
      gfx->fillScreen(BLACK);
    }
  }
  delay(10);
}


5.実際の実行の様子
 ①タッチされたところに点を表示するプログラムとなっております。
 ②試しに「へへののもへじ」をタッチしてみました。
 tab5_touch_demo

以上


ブログトップへ

◆遂にM5Stack Tab5 ArduinoIDE 環境でWiFiが使えるようになりました。
 環境は、下記の通りです。(2025/07/18時点)
  ①Windows11 X64 Pro 24H2 
  ②Arduino IDE V2.3.6
  ➂ESP32ボードバージョンV3.2.1
  ④M5StackボードバージョンV3.2.2
  ⑤M5GFX バージョンV0.2.9
  ⑥M5Unified バージョンV0.2.7

1.スケッチは、下記に示します。
 
//tab5_M5GFX_wifi_Scan.ino
//V1 /2025/05/18 By JK1VCK <M5GFX.h>使用
//blog URL:https://gijin77.blog.jp/archives/45137181.html
//tab5 esp32p4 Flash Size:"16MB" Partition Scheme:16M Flash(3MB APP..) 
//     PSRAM : en USB_CDC Ob Boot : en  
//     UPload Mode : Hardware CDC...

#include <WiFi.h>
#include <M5GFX.h>
#include <M5Unified.h>

M5GFX tft;

#define GFX_BL 22

void setup() {
  Serial.begin(115200);
  delay(1000);
  pinMode(GFX_BL, OUTPUT);digitalWrite(GFX_BL, HIGH); //バックライトON  
  tft.begin();
  tft.setRotation(3);tft.fillScreen(BLACK);
  tft.setCursor(0,2);tft.setTextColor(GREEN);tft.setTextSize(5);
  tft.drawRect(0,0,tft.width()-1,tft.height()-1,YELLOW);//枠表示
 
  Serial.println("WiFi Scan / M5GFX_Library Start");  
  tft.println("WiFi Scan / M5GFX_Library Start");  
  // Set WiFi to station mode and disconnect from an AP if it was previously connected.
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  Serial.println("Setup done");
  tft.println("Setup done");
  delay(2000);
}

void loop() {
  tft.fillScreen(BLACK);tft.setCursor(0,2);
  tft.drawRect(0,0,tft.width()-1,tft.height()-1,YELLOW);//枠表示
  tft.setTextSize(4);tft.setTextColor(GREEN);
  Serial.println("WiFi Scan start");tft.println("WiFi Scan start");
  //WiFi.scanNetworks will return the number of networks found.
  int n = WiFi.scanNetworks();
  Serial.println("WiFi Scan done");tft.println("WiFi Scan done");
  if (n == 0) {
    Serial.println("no networks found");tft.println("no networks found");
  } else {
    Serial.printf("\n %d networks found\n",n);tft.printf("\n %d networks found\n",n);
    tft.setTextSize(3);tft.setTextColor(CYAN);
    Serial.println(" No| SSID                 | MAC アドレス       | RSSI | CH | Encryption");
    tft.println(" No| SSID                 | MAC address        | RSSI | CH | Encryption");
    for (int i = 0; i < n; ++i) {
      // Print SSID and RSSI for each network found
      tft.setTextColor(ORANGE);
      
      Serial.printf(" %2d| %-20.20s | %-18.18s | %4ld | %2ld | ", i + 1,WiFi.SSID(i).c_str(),WiFi.BSSIDstr(i).c_str(),WiFi.RSSI(i),WiFi.channel(i));
      tft.printf(" %2d| %-20.20s | %-18.18s | %4ld | %2ld | ", i + 1,WiFi.SSID(i).c_str(),WiFi.BSSIDstr(i).c_str(),WiFi.RSSI(i),WiFi.channel(i));      switch (WiFi.encryptionType(i)) {
        case WIFI_AUTH_OPEN:            Serial.print("open");     tft.print("open"); break;
        case WIFI_AUTH_WEP:             Serial.print("WEP");      tft.print("WEP");break;
        case WIFI_AUTH_WPA_PSK:         Serial.print("WPA");      tft.print("WPA"); break;
        case WIFI_AUTH_WPA2_PSK:        Serial.print("WPA2");     tft.print("WPA2"); break;
        case WIFI_AUTH_WPA_WPA2_PSK:    Serial.print("WPA+WPA2"); tft.print("WPA+WPA2"); break;
        case WIFI_AUTH_WPA2_ENTERPRISE: Serial.print("WPA2-EAP"); tft.print("WPA2-EAP"); break;
        case WIFI_AUTH_WPA3_PSK:        Serial.print("WPA3");     tft.print("WPA3"); break;
        case WIFI_AUTH_WPA2_WPA3_PSK:   Serial.print("WPA2+WPA3");tft.print("WPA2+WPA3"); break;;
        case WIFI_AUTH_WAPI_PSK:        Serial.print("WAPI");     tft.print("WAPI"); break;
        default:                        Serial.print("unknown");  tft.print("unknown");
      }                                                                 
      Serial.println();tft.println();
      delay(10);
    }
  }
 
  Serial.println("");tft.println("");
  // Delete the scan result to free memory for code below.
  WiFi.scanDelete();
  // Wait a bit before scanning again.
  delay(20000);
}


  写真は、WiFiスキャンの様子です。
 m5_tab5_wifi

これで色々遊べます。めでたしめでたし

以上


ブログトップへ

◆以前からTAB5で「Xiaozhi」を動かそうと思い色々調べていましたら、
 本日、VSCode(ESP-IDF)環境で「xiaozhi-esp32-v174」をTAB5用に
 コンパイルが出来て書き込むことが出来ました。
 先人の方に、感謝です。

 tab5_小智_2

1.構築方法
 ①下記サイトからソース一式をダウンロードします。
  6/5の時点では、エラーで実行できませんでしたが、本日ダウンロード
  したバージョンは、見事に動作しました。素晴らしい!
  xiaozhi-esp32

 ②コンパイルするにあたって、ESP-IDFの環境を構築して下さい。
 *私は、Visial Studio Codeをインストールしました。
  でも、初めてでGUI環境ではまだビルド出来ていません。
  今回は、パワーシェル内でビルドしました。
 VSCODE

 ➂次は、解凍して、"xiaozhi-esp32-main\main\boards\m5stack-tab5"フォルダ内
  の「sdkconfig.tab5」を「xiaozhi-esp32-main」フォルダ内に「sdkconfig」として
  コピーします。

 ④idf.py set-target esp32p4    *ターゲットをESP32P4へ設定
 
 ⑤idf.py build           *ビルド
 
 ⑥idf.py -p COM10 flash monitor *書き込み&モニター
 
 以上でコンパイル&書き込みできました。
 

2.再起動させて、後はWiFiの設定等実施します。
 この辺については、下記ブログ内記事を参照して下さい。
 ・小智「XiaoZhi」を ATOMS3/ESP32S3 にて 日本語 で話してみた
 
 ①今回デバイスの登録時に下記の画面が出て来ました。
  その内、商用化されるのでしょうか。

 tab5_登録画面

 ②無事登録出来て、デバイスのバージョンが、!.7.4となっていて日々アップデートが
  進んでいるようです。
 tab5_v174
3.実際の様子

 


以上
 

ブログトップへ

◆M5Stack TAB5 ArduinoIDE M5GFX RTC RX8130環境でニキシー管時計もどきと
 パタパタ時計もどきを表示してみました。
 最初WiFi経由のNTPで時間を取得使用としましたが、ArduinoIDEではまだWiFiがサポート
 されていなくてRTCからの時間取得で時計を表示しました。

 *ニキシー管時計もどき
 tab5_nixie
 *パタパタ時計もどき
 tab5_flip

 ◆動作状況
 
 
 *ニキシー管時計もどきについては、下記ブログ内記事も参照して下さい。

 *パタパタ時計もどきについては、下記ブログ内記事も参照して下さい。
 ・数種のLCD付ESP32ボードで「パタパタ時計もどき」を表示させてみた


1.開発環境 2025/05/22時点
  ①Windows11 X64 Pro 24H2 
  ②Arduino IDE 2.3.6
  ➂ESP32ボードバージョンV3.2.0

2.概要
 ①LCDの描画は、M5GFXライブラリで出来ました。
 ②TAB5搭載RTCのライブラリは、ArtronShop_RX8130CEを使いました。
 (ライブラリマネージャーで検索してインストールしました。)
 ➂ニキシー管時計のイメージデータは、以前から使っていたものを使用しました。

3.スケッチについて
 ①RTCに時刻をセットするスケッチ「set_time.ino」
  (1) RTCにセットしたい時刻に、スケッチを修正します。(書き込む30秒後の時刻)
  (2) スケッチをESP32P4に書き込み、セット時刻まで待ち「Enter」押下します。
   *30秒操作が無ければRTCに書き込まずに(4)へ進みます。
  (3) するとRTCにセットされ「loop」で読み込まれます。
  (4) 時刻が有っていれば終了。狂っていれば①に戻ります。

//set_time.ino
//2025/05/23 By JK1VCK ニキシー管&パタパタ時計 RTC RX8130CE対応版
//blog URL:https://gijin77.blog.jp/archives/44667829.html

//ボード:"ESP32P4 Dev Module"
//USB CDC On Boot: "Enabled"
//Flash Size: "16MB (128Mb)"
//Partition Scheme: "16M Flash (3MB APP/9.9MB FATFS)"
//PSRAM: "Enabled"
//USB Mode: "Hardware CDC and JTAG"

#include <Arduino.h>
#include <ArtronShop_RX8130CE.h>
#include <Wire.h>
#include <time.h>

ArtronShop_RX8130CE rtc(&Wire);

// 曜日を文字列に変換
const char* wday_str(int wday) {
  const char* wd[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  if (wday >= 0 && wday <= 6) return wd[wday];
  return "???";
}

void setup() {
  Serial.begin(115200);
  Wire.begin(31,32);

  while (!rtc.begin()) {
    Serial.println("RX8130CE init error !");
    delay(1000);
  }
  Serial.println("Press any key in 5 seconds to set RTC...");
  unsigned long start = millis();
  while (millis() - start < 30000) {
    if (Serial.available()) {
      Serial.read(); // consume
  // 必要に応じて初期設定(例:RTCに時刻をセット)

      struct tm t;
      t.tm_year = 2025 - 1900;
      t.tm_mon = 4; // 5月(0起点)
      t.tm_mday = 22;
      t.tm_hour = 16;
      t.tm_min = 44;
      t.tm_sec = 0;

      time_t tt = mktime(&t); // 曜日も自動で計算される
      localtime_r(&tt, &t);   // tm_wday にも反映される

      rtc.setTime(t);
      break;
    }
  }
}

void loop() {
  struct tm t;
  if (rtc.getTime(&t)) {
    Serial.printf(
      "Datetime: %02d:%02d:%02d %d/%d/%d (%s)\n",
      t.tm_hour, t.tm_min, t.tm_sec,
      t.tm_mday, t.tm_mon + 1, t.tm_year + 1900,
      wday_str(t.tm_wday)
    );
  } else {
    Serial.println("Get time from RTC fail !");
  }
  delay(1000);
}
 
 ②スケッチ内でニキシー管/パタパタ時計を選択できるようにしました。
  *下記の三つのファイルは、サイズが大きいためzipファイルでダウンロード
  (1)tab5_nixie_flip_clock_V3.ino   *ニキシー管/パタパタ時計スケッチ
  (2)img_nixie_tube.h      *ニキシー管時計のイメージファイル
  (3)img_flip.h          *パタパタ時計のイメージファイル

  (保障無しの自己責任で)  tab5_nixie_flip_clock_V3.zip

 ➂ニキシー管/パタパタ時計の選択は、下記の部分を修正してコンパイル&
  書き込みます。
 
 tab5_nixie_flip_clock_V3.ino
 23://************************************************************
 24:int flip_flg=1;   //パタパタ時計=1 ニキシー管=0
 25:uint16_t d_color=WHITE; //コロン等カラー
 26:#define GFX_BL 22 //バックライト制御用GPIO番号
 27://************************************************************

 ④2025/5/31追記
  又は、loopの最後の部分「disp_colon(0)」の後112行に下記を追記すれば10分毎に
  ニキシー管/パタパタ時計を交互に表示出来ます。

   disp_colon(0);//コロン消灯
    if (((n_minute%10)==0)&&(n_second==0)) {//10分毎に反転
      tft.fillScreen(BLACK);
      bday=bh1=bh0=bm1=bm0=bs1=bs0=99;
      flip_flg=!flip_flg;
      if (flip_flg) d_color=WHITE; else d_color=ORANGE;
    }

 ⑤IDEの設定(下記を選択して書き込みます。)

 //ボード:"ESP32P4 Dev Module"
 //ポート: "COM13"

 //USB CDC On Boot: "Enabled"
 //CPU Frequency: "360MHz"
 //Core Debug Level: "None"
 //USB DFU On Boot: "Disabled"
 //Erase All Flash Before Sketch Upload: "Disabled"
 //Flash Frequency: "80MHz"
 //Flash Mode: "QIO"
 //Flash Size: "16MB (128Mb)"
 //JTAG Adapter: "Disabled"
 //USB Firmware MSC On Boot: "Disabled"
 //Partition Scheme: "16M Flash (3MB APP/9.9MB FATFS)"
 //PSRAM: "Enabled"
 //Upload Mode: "UARTO / Hardware CDC"
 //Upload Speed: "921600"
 //USB Mode: "Hardware CDC and JTAG"

 TAB5_IDE_設定


4.このあと、TAB5のデモに戻すには下記を参照して戻す事が出来ます。
 TAB5工場出荷時のデモに戻す方法

5.参考URL
 ①M5Stack Tab5 ドキュメント
 ②M5Unifiedライブラリ
 ➂M5GFXライブラリ
 ④M5GFX API
 ⑤M5GFXライブラリの使い方
 ⑥RTC RX8130ライブラリ
 ⑦M5Stack Tab5 回路図 PDF
 ⑧M5Stack Tab5 ピンマップ
 ⑧M5Stack Tab5レビュー – パート1:ESP32-P4とESP32-C6 5インチ
  IoT開発キットの開封、分解、そして初試用

 ⑨M5Stack Tab5レビュー – パート2:ESP-IDFフレームワークとArduino IDEを
  使用したESP32-P4ファームウェア開発入門


6.参考分解内部写真
 *ESP32C6との接続用シリアル端子が、内部にパッドで有りました。
 TAB5内部写真


以上


ブログトップへ

◆unit MIDIを入手したのでM5StampS3を使ってUSB MIDI I/Fのキーボードデータを
 DIN-MIDI OUT/INへの変換アダプタを作ってみました。
 USBのキーボードから変換器でDINにしてunit MIDIのDIN入力に繋いでいます。

 usb-din-midi変換1
 usb-din-midi変換3

1.開発環境 2024/11/28時点
 ①Windows11 X64 Pro 24H2 
 ②Arduino IDE 2.3.2(2.3.3はフリーズするのでバージョンを落として使っています)
 ➂ESP32ボードバージョンV3.0.7(esp32s3dev)
 ④M5Stack Arduino ボードバージョンV2.08(M5Stamp-S3)

2.変換アダプタ回路図
 usb-din変換アダプタ3

3.USB-MIDIをESP32S3で読み込むための準備
 ①スケッチ例を下記よりダウンロードします。
  esp32-usb-host-demos
  解凍後、「esp32-usb-host-demos-main\examples\usbhmidi\usbhmidi.ino」
  を別フォルダにコピペして使っています。
  そこに、「esp32-usb-host-demos-main」のフォルダにある二つのファイル
  「show_desc.hpp」usbhhelp.hpp」をコピペします。

  *ESP32S3Debkit用
  フォルダ1
  *M5Stamps3用
  フォルダ2

 ②USB-DIN変換用のスケッチです。先人のスケッチを修正しています。
  *ESP32S3用とM5STAMPS3用とは//コメントで変更しています。
  *他のESP32S3ボードを使用する場合、ここのDIN用シリアルポート番号を
   変更すれば、いけると思います。
  ◆当然ながらスケッチは、保障無しの自己責任で参考程度にお願いします。

************************************************************************************************
161: //Serial2.begin(31250,SERIAL_8N1,18,17); //RXD=18 TXD=17 ESP32S3 Devkit
162: Serial2.begin(31250,SERIAL_8N1,15,13);//RXD:15 TXD:13 M5STAMPS3
163:  delay(500);
164; usbh_setup(show_config_desc_full);
165: //Serial.println("ESP32S3 MIDI USB-IN -> DIN-OUT & DIN-IN -> USB-OUT");
166: Serial.println("M5STAMP MIDI USB-IN -> DIN-OUT & DIN-IN -> USB-OUT");
*************************************************************************************************

/*m5stamp_midi.ino
 * MIT License
 *Copyright (c) 2021 touchgadgetdev@gmail.com
 *2024/11/24 modify By JK1VCK
*/
#include <usb/usb_host.h>
#include "show_desc.hpp"
#include "usbhhelp.hpp"

bool isMIDI = false;
bool isMIDIReady = false;

const size_t MIDI_IN_BUFFERS = 8;
const size_t MIDI_OUT_BUFFERS = 8;
usb_transfer_t *MIDIOut = NULL;
usb_transfer_t *MIDIIn[MIDI_IN_BUFFERS] = {NULL};
// USB MIDI Event Packet Format (always 4 bytes)
//
// Byte 0 |Byte 1 |Byte 2 |Byte 3
// -------|-------|-------|------
// CN+CIN |MIDI_0 |MIDI_1 |MIDI_2
//
// CN = Cable Number (0x0..0xf) specifies virtual MIDI jack/cable
// CIN = Code Index Number (0x0..0xf) classifies the 3 MIDI bytes.
// See Table 4-1 in the MIDI 1.0 spec at usb.org.
//
static void midi_transfer_cb(usb_transfer_t *transfer) {
  ESP_LOGI("", "midi_transfer_cb context: %d", transfer->context);
  if (Device_Handle == transfer->device_handle) {
    int in_xfer = transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK;
    if ((transfer->status == 0) && in_xfer) {
      uint8_t *const p = transfer->data_buffer;
      for (int i = 0; i < transfer->actual_num_bytes; i += 4) {
        if ((p[i] + p[i+1] + p[i+2] + p[i+3]) == 0) break;
        ESP_LOGI("", "midi: %02x %02x %02x %02x",p[i], p[i+1], p[i+2], p[i+3]);
        Serial.printf("USB MIDI-IN: %02X %02X %02X %02X ",p[i], p[i+1], p[i+2], p[i+3]);
        Serial.printf("DIN MIDI-OUT: %02X %02X %02X\n", p[i+1], p[i+2], p[i+3]);
        Serial2.write(p[i+1]);
        Serial2.write(p[i+2]);
        Serial2.write(p[i+3]);
      }
      esp_err_t err = usb_host_transfer_submit(transfer);
      if (err != ESP_OK) {
        ESP_LOGI("", "usb_host_transfer_submit In fail: %x", err);
      }
    } else {
      ESP_LOGI("", "transfer->status %d", transfer->status);
    }
  }
}

void check_interface_desc_MIDI(const void *p) {
  const usb_intf_desc_t *intf = (const usb_intf_desc_t *)p;
  // USB MIDI
  if ((intf->bInterfaceClass == USB_CLASS_AUDIO) &&
      (intf->bInterfaceSubClass == 3) &&
      (intf->bInterfaceProtocol == 0))
  {
    isMIDI = true;
    ESP_LOGI("", "Claiming a MIDI device!");
    esp_err_t err = usb_host_interface_claim(Client_Handle, Device_Handle,
        intf->bInterfaceNumber, intf->bAlternateSetting);
    if (err != ESP_OK) ESP_LOGI("", "usb_host_interface_claim failed: %x", err);
  }
}

void prepare_endpoints(const void *p) {
  const usb_ep_desc_t *endpoint = (const usb_ep_desc_t *)p;
  esp_err_t err;
  // must be bulk for MIDI
  if ((endpoint->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK) != USB_BM_ATTRIBUTES_XFER_BULK) {
    ESP_LOGI("", "Not bulk endpoint: 0x%02x", endpoint->bmAttributes);
    return;
  }
  if (endpoint->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) {
    for (int i = 0; i < MIDI_IN_BUFFERS; i++) {
      err = usb_host_transfer_alloc(endpoint->wMaxPacketSize, 0, &MIDIIn[i]);
      if (err != ESP_OK) {
        MIDIIn[i] = NULL;
        ESP_LOGI("", "usb_host_transfer_alloc In fail: %x", err);
      } else {
        MIDIIn[i]->device_handle = Device_Handle;
        MIDIIn[i]->bEndpointAddress = endpoint->bEndpointAddress;
        MIDIIn[i]->callback = midi_transfer_cb;
        MIDIIn[i]->context = (void *)i;
        MIDIIn[i]->num_bytes = endpoint->wMaxPacketSize;
        esp_err_t err = usb_host_transfer_submit(MIDIIn[i]);
        if (err != ESP_OK) {
          ESP_LOGI("", "usb_host_transfer_submit In fail: %x", err);
        }
      }
    }
  } else {
    err = usb_host_transfer_alloc(endpoint->wMaxPacketSize, 0, &MIDIOut);
    if (err != ESP_OK) {
      MIDIOut = NULL;
      ESP_LOGI("", "usb_host_transfer_alloc Out fail: %x", err);
      return;
    }
    ESP_LOGI("", "Out data_buffer_size: %d", MIDIOut->data_buffer_size);
    MIDIOut->device_handle = Device_Handle;
    MIDIOut->bEndpointAddress = endpoint->bEndpointAddress;
    MIDIOut->callback = midi_transfer_cb;
    MIDIOut->context = NULL;
//    MIDIOut->flags |= USB_TRANSFER_FLAG_ZERO_PACK;
  }
  isMIDIReady = ((MIDIOut != NULL) && (MIDIIn[0] != NULL));
}

void show_config_desc_full(const usb_config_desc_t *config_desc) {
  // Full decode of config desc.
  const uint8_t *p = &config_desc->val[0];
  uint8_t bLength;
  for (int i = 0; i < config_desc->wTotalLength; i+=bLength, p+=bLength) {
    bLength = *p;
    if ((i + bLength) <= config_desc->wTotalLength) {
      const uint8_t bDescriptorType = *(p + 1);
      switch (bDescriptorType) {
        case USB_B_DESCRIPTOR_TYPE_DEVICE:
          ESP_LOGI("", "USB Device Descriptor should not appear in config");
          break;
        case USB_B_DESCRIPTOR_TYPE_CONFIGURATION:
          show_config_desc(p);
          break;
        case USB_B_DESCRIPTOR_TYPE_STRING:
          ESP_LOGI("", "USB string desc TBD");
          break;
        case USB_B_DESCRIPTOR_TYPE_INTERFACE:
          show_interface_desc(p);
          if (!isMIDI) check_interface_desc_MIDI(p);
          break;
        case USB_B_DESCRIPTOR_TYPE_ENDPOINT:
          show_endpoint_desc(p);
          if (isMIDI && !isMIDIReady) {
            prepare_endpoints(p);
          }
          break;
        case USB_B_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
          ESP_LOGI("", "USB device qual desc TBD");// Should not be in config?
          break;
        case USB_B_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION:
          ESP_LOGI("", "USB Other Speed TBD");// Should not be in config?
          break;
        case USB_B_DESCRIPTOR_TYPE_INTERFACE_POWER:
          ESP_LOGI("", "USB Interface Power TBD");// Should not be in config?
          break;
        default:
          ESP_LOGI("", "Unknown USB Descriptor Type: 0x%x", *p);
          break;
      }
    }
    else {
      ESP_LOGI("", "USB Descriptor invalid");
      return;
    }
  }
}

void setup() {
  Serial.begin(115200);
  //Serial2.begin(31250,SERIAL_8N1,18,17); //RXD=18 TXD=17 ESP32S3 Devkit
  Serial2.begin(31250,SERIAL_8N1,15,13);//RXD:15 TXD:13 M5STAMPS3
  delay(500);
  usbh_setup(show_config_desc_full);
  //Serial.println("ESP32S3 MIDI USB-IN -> DIN-OUT & DIN-IN -> USB-OUT");
  Serial.println("M5STAMP MIDI USB-IN -> DIN-OUT & DIN-IN -> USB-OUT");
}
int ct=0;
uint8_t data[5]={1,2,3,4,5};
void loop() {
uint8_t wk;
  usbh_task();
  if (Serial2.available()) {// DIN MIDIからメッセージを取得
    wk=Serial2.read();      //Serial.printf("ct:%d %02x ",ct,wk);
    if ((wk & 0x80)) ct=0;
    data[ct]=wk;
    ct++;
    if (ct>2) {
      ct=0;
      Serial.print("DIN MIDI-IN: ");
      for(int i=0;i<3;i++) {
        Serial.printf("%02X ",data[i]);
      }
      if (isMIDIReady) {
        ESP_LOGI("", "MIDI send 4 bytes");
        MIDIOut->num_bytes = 4;
        uint8_t *const p = MIDIOut->data_buffer;
        p[0]=(data[0]&0xF0)>>4;
        for(int i=0;i<3;i++) {
          p[i+1]=data[i];
        }
        Serial.print(" USB MIDI-OUT: ");
        for(int i=0;i<4;i++) {
          Serial.printf("%02X ",p[i]);
        }
        esp_err_t err = usb_host_transfer_submit(MIDIOut);
        if (err != ESP_OK) {
          ESP_LOGI("", "usb_host_transfer_submit Out fail: %x", err);
        } else {
          Serial.printf(" USB OUT OK\n");
        }
      } else {
        Serial.println();
      }
    }
  }  
}


4.実行例
 最初は、二つ変換アダプタを作り、相互接続して実験しました。
 下記ブログ内記事を参照してみて下さい。

 ◆トラブル
 ①DINコネクタの4,5番ピンの単純な裏表の勘違いで動作せず分かるまで
  大変でした。
 ②その後、データのサイズが、USBから入出力データが、4バイトで
  DINへのデータが3バイトと違っていたので同じく分かるまで大変でした。

 ◆最後、両方向の変換がうまくいき、音が出た時は感激しました。
  カシオのLK-223を繋ぐと鍵盤からの入力と音源への出力と分離して
  入出力出来ました。

 下図は、デバッグ用に付けたシリアル出力です。
 USB---DINOK

4.DIN MIDIで流れるデータの方式について
 ①詳しくは、下記を参照して下さい。
  M I D I 1.0 規格書

 ②概略を下記に示します。(ChatGPTより)

 ## **1. データの基本構造**
 MIDIデータは**1バイト(8ビット)単位**で送信されます。
 1バイトは以下の形式で構成されています:

 ### **1.1 ステータスバイト**
  **最上位ビット (MSB)**: 常に `1`。
  **下位7ビット**: メッセージの種類やチャネル番号を指定。

 | ステータスバイト | 機能                        
 |--------------------------|-----------------------------------------------
 |     `1000xxxx`        | ノートオフメッセージ 
 |     `1001xxxx`        | ノートオンメッセージ 
 |     `1010xxxx`        | ポリフォニック・アフタータッチ
 |     `1011xxxx`        | コントロールチェンジ  
 |     `1100xxxx`        | プログラムチェンジ 
 |     `1101xxxx`        | チャネル・アフタータッチ 
 |     `1110xxxx`        | ピッチベンド  
 |     `1111xxxx`        | システムメッセージ  
 |--------------------------|-----------------------------------------------
  `xxxx` はチャネル番号(0~15、16チャネル対応)。

 ### **1.2 データバイト**
  **最上位ビット (MSB)**: 常に `0`。
  **下位7ビット**: 各メッセージに必要な追加データ。

 例:
 * ノートオンメッセージには「音のピッチ」と「ベロシティ」が含まれる。
 * コントロールチェンジには「コントローラ番号」と「値」が含まれる。

 ## **2. 主なメッセージの種類**
 以下は、DIN MIDIでやり取りされる代表的なメッセージです。

 ### **2.1 ノートオン/ノートオフ**
  **目的**: ノート(音符)を演奏開始・停止。
  **フォーマット**:
   *ノートオン: `1001cccc`(チャネル番号を含む) + `0kkkkkkk`(ノート番号)
   + `0vvvvvvv`(ベロシティ)
 *ノートオフ: `1000cccc`(チャネル番号を含む) + `0kkkkkkk`(ノート番号)
   + `0vvvvvvv`(ベロシティ)

 | 項目                | 内容                             
 |--------------------|------------------------------------------
 | ノート番号     | 0~127(中央Cは60)
 | ベロシティ     | 0~127(0はノートオフ扱い)
 |--------------------|------------------------------------------


 ### **2.2 コントロールチェンジ**
 **目的**: 音量、パンニング、モジュレーションなどのパラメータを変更。
 **フォーマット**:
  `1011cccc`(チャネル番号を含む) + `0ccccccc`(コントローラ番号) + `0vvvvvvv`(値)

 | コントローラ番号 | 機能例 
 |--------------------------|--------------------------
 | 1                            | モジュレーション 
 | 7                            | メイン音量 
 | 10                          | パンニング 
 | 64                          | ダンパーペダル
 |--------------------------|--------------------------

 ### **2.3 ピッチベンド**
 **目的**: 音程を滑らかに変更。
 **フォーマット**:
  `1110cccc`(チャネル番号を含む) + `0vvvvvvv`(LSB) + `0vvvvvvv`(MSB)

 | 項目                 | 内容 
 |---------------------|--------------------------
 | 範囲                 | -8192~8191         
 | デフォルト値   | 0(中央値)          
 |---------------------|--------------------------
 
 ### **2.4 プログラムチェンジ**
 **目的**: 音色(プログラム)の切り替え。
 **フォーマット**:
  `1100cccc`(チャネル番号を含む) + `0ppppppp`(プログラム番号)

 | 項目                   | 内容  
 |-----------------------|------------------------------
 | プログラム番号  | 0~127(音色番号)
 |-----------------------|------------------------------

 ### **2.5 システムメッセージ**
 **目的**: グローバルな操作(全チャネルに影響)。
 **例**:
  **システムリアルタイムメッセージ**: MIDIクロック(テンポ同期)やスタート/ストップ。
  **システムエクスクルーシブ (SysEx)**: メーカー固有の機能。

 ## **3. 伝送方式**
 DIN MIDIでは、以下の方式でデータが送信されます。

 ### **3.1 物理規格**
 **ケーブル**: 5ピンDINケーブル(通常、ピン2がGND、ピン4とピン5がデータ用)。
 **伝送速度**: 31.25 kbps (非同期)。
 **信号レベル**: 電圧範囲は約5V。

 ### **3.2 データ伝送**
 *MIDIデータはシリアル通信方式で1バイトずつ送信。
 *スタートビット、8ビットデータ(LSB先行)、ストップビットで構成されます。

 | 項目                  | 内容          
 |----------------------|-----------------------
 | スタートビット | 1ビット (0固定) 
 | データビット     | 8ビット  
 | ストップビット | 1ビット (1固定) 
 |----------------------|-----------------------

 ### **3.3 データの順序**
 送信されるデータの順序は以下の通り:
 1. ステータスバイト(メッセージタイプとチャネル)
 2. データバイト(必要に応じて1~2バイト)

例:
  ノートオン (チャネル1、ノート60、ベロシティ127):  
   `10010000`(ステータスバイト)  
   `00111100`(ノート番号60)  
   `01111111`(ベロシティ127)

 ## **4. まとめ**
 DIN MIDIはシンプルかつ堅牢なプロトコルで、音楽デバイス間のコミュニケーションを
 標準化しています。シリアル通信を利用し、音符の演奏、音色の変更、コントローラの
 操作、テンポ同期など、幅広い音楽情報をリアルタイムで伝送可能です。
 
以上 入出力共にうまく変換出来ました。

◆もう一台、作る予定だったので、基板を発注してみました。
 下記ブログ内記事を参照してみてください。
 ・Kicad で書いて JLCPCB へ基板を発注してみた






ブログトップへ

◆震度計に興味が有ってネットで先人の情報を検索していて、簡単にM5Stick C Plusへ
 移植できそうな下記サイトが見つかりました。先人に感謝です。
 震度計測の仕組みなど詳しく説明されています。
 M5Atom Matrix"だけ"で作る簡易震度測定システム

 添付図は、ambientに送っていた10月14日19:46の横須賀での震度情報です。
 気象庁の発表は、横須賀は震度2でしたが、我が家のモニターは、1.7を記録していました。
 参考程度には、なるみたいです。
 2024_10_14_19_46_1_7

1.上記サイトよりスケッチをダウンロードさせてもらい、「M5Stick C Plus」用に
 移植しました。
 また、無料のクラウトサービス「Ambient」へデータを記録するように追加しました。
 ◆「Ambient」については、下記ブログ内記事も参照してみてください。
 ・ESP32でBME280,AHT10,HW390,CDSを使い気象モニターを作ってみた
 
2.スケッチは、下記のようなことを改修しました。
 ①「M5Stick C Plus」を起動させると、センサーが安定するまで一定時間待ちます。

 284:  delay(20000); //センサーが安定するまで20秒待つ

 ②その後、5秒間隔で震度の計算をします。
 *オリジナルは、バッファサイズが1024で10秒間隔でした。
 *色々追加したためメモリ不足でコンパイルエラーとなった為、512にして有ります。
 *今後の課題です。
 
    54:  #define FFT_SAMPLES 512 //1024

 ➂「Ambient」への送信は、
  1.震度の変化が「±0.2」変化した時、
  2.1分経過した時
  にするようにしています。
  *データ量が多くならないようして、約2日間記録できるようにしました。

  194:  m_ct++;
  195:  int sa=b_shindo-shindo;
  196:  if ((abs(sa) >= 0.2)||(m_ct>12)) { //差が0.2以上か1分間隔でambientに送信
  197:  m_ct=0;

 ④最大値をリセットしたい時には、「A」釦を圧下しますとESP32がリセットされます。

  290:  M5.update();
  291:  if(M5.BtnA.wasPressed()){
  292:    ESP.restart();
  293:  }
 
 ⑤LCDの輝度をリセット後2分間で、暗くしています。

  295:  if (lcd_of) {
  296:    if (t > (stt+(120*1000000))) { //2分後輝度を落とす
  297:      M5.Axp.ScreenBreath(10);  //LCDの輝度調整
  298:      lcd_of=0;
  299:    }
  300:  }

 ⑥震度のオフセットを「2.3」マイナスして「震度情報」としています。
 *これは、先人のスケッチで揺れていない時、「2.3」表示していた為です。

  149:  if (shindo >= 2.3) shindo=shindo-2.3; //震度のオフセットの調整
  150:  else shindo=0.0;

 ⑦WiFiのSSIDとpassword&AmbientのchannelIdとwriteKeyを自分用に修正します。
 
   23:  const char* ssid  PROGMEM    = "yourssid";
   24:  const char* password PROGMEM = "yourpasswd";
   25:
   26: const unsigned int channelId PROGMEM = xxxxx;
   27: const char* writeKey PROGMEM = "xxxxxxxxxxxxxxx8";

3.開発環境 2024/10/18時点
  ①Windows11 X64 Pro 24H2 
  ②Arduino IDE 2.3.3
  ➂M5Stack ArduinoボードバージョンV2.0.8

4.スケッチは、下記に示します。 
 (保障無しの自己責任で)  m5stickcp_sindokei.ino

5.動作状況
 ①リセット後安定するまで
 ①起動直後待機時

 ②起動直後、安定した状態
 ②起動直後

 ➂試験的に振動を与えた時(2.4)
 ➂試験1

 ④試験的に振動を与えた時(1.1)
 ④試験2

 ⑤2分後に輝度を落とした状態
 ⑤2分後


以上


ブログトップへ

◆M5StickC,Plus,Plus2,M5StackGLAYで「パタパタ時計もどき」を表示させてみました。
 先日LCD付ESP32ボードで作ったものの続きです。
 スケッチは、先日の物にM5用のパラメータを追記しました。
 下記ブログ内記事を参照して下さい。
 ・数種のLCD付ESP32ボードで「パタパタ時計もどき」を表示させてみた

 m5_StickC

1.M5の種類(サイズ、解像度、ドライバIC、バックライト制御、名前)
 ①2インチ   w320 x h240 ILI9342 GPIO32 M5Stack BASIC/GLAY
 ②1.14インチ w240 x h135 ST7789  GPIO27 M5StickCPlus2
 ➂1.14インチ w240 x h135 ST7789  AXP192 M5StickCPlus
 ④0.96インチ w160 x h80  ST7735  AXP192 M5StickC

2.バックライトの制御方法
 ①M5StickC,M5StickCPlusは、電源管理IC「AXP192」の「LDO2」ピンで制御しています。
  今回M5.LCDライブラリを使用せず「Arduino_GFX_Library」のみで行っているために
  特別に初期設定で直接制御しました。
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 #include <Wire.h>
 #include <AXP192.h>
 AXP192 power;  // AXP192オブジェクトを作成

 #define GFX_EXTRA_PRE_INIT()
    {
       Wire.begin(21, 22);  // I2Cの初期化 (SDA, SCL)
       power.begin(true);   // AXP192の初期化 LDO2をONにしてLCDバックライトを点灯
       power.SetLDO2(3000); // 3.0Vに設定 (通常のLCDバックライトの電圧は3.3V)
    }
 ---------------------------------------------------------------------------------------------------------------

 ②M5StickCPlus2は、普通にバックライトLEDをGPIO327ピンで制御しています。 
  それとバッテリー時電源ONを保持する為に、初期設定でGPIO4ピン(HOLD)を
  「HIGH」に制御しました。
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 #define GFX_EXTRA_PRE_INIT()
    {
       pinMode(4, OUTPUT);
       digitalWrite(4 ,HIGH);
    }
 ---------------------------------------------------------------------------------------------------------------

 ➂M5Stack BASIC/GLAYは、普通にバックライトLEDをGPIO32ピンで制御しています。 

2.開発環境 2024/07/18時点
  ①Windows11 X64 Pro 23H2 
  ②Arduino IDE 2.3.2
  ➂ESP32ボードバージョンV3.0.2
  ④Arduino_GFX_Library v1.4.7
  ⑤ボードの選択は、
   *それぞれ、M5Core,M5StickC-Plus.M5StickC-Plus,M5StickC
   *M5StickCPlus2は、無かったのでM5StickC-Plusを使用
  ⑥コンパイル時のAPPサイズ
   *機種によってはPartion Scheme」->Defaut から->No OTA(2MB APP)にしました。 

3.スケッチとイメージファイル
    (保障無しの自己責任で)  FlipClockV2.zip

 ①先日のものに、M5関連を追記したのと、1秒毎にLEDを点滅させるようにしました。
 *点滅がうっとうしい場合、定義の時に、LEDON時も消灯に定義します。
  #define LEDON    HIGH ◆LEDの配線によりH/Lを指定します。
  #define LEDOFF   LOW

4.パタパタ時計実行の様子
 

以上


ブログトップへ

◆M5StickC Plusのバッテリーが不良の為、ちょっと容量は小さいものに交換しました。
 その時、無理な力が掛ったのかも知れませんが液晶表示がおかしくなりました。(故障)
 他の機能は、良さそうなので液晶を交換してみることにしました。
 M5C_P_液晶故障

 液晶の仕様は、下記の通りなので「Aliexpress」で検索してみました。
 TFTコントローラー ST7789
 液晶サイズ    1.14 インチ
 画面サイズ    135×240
 
1.検索の結果、下記ストアの液晶がヒットしました。
  IPS 1.14 Inch HD TFT LCD Screen SPI Interface Colorful Screen 135X240 Resolution Full View Display ST7789 Driver
  
 m5stickc_plus_lcd

 ①パラメーター:
  1>.製品名: 1.14インチLCDディスプレイ135*240 ips
  2>.material: ipsカラーディスプレイ画面
  3>.resolution: 135*240
  4>.driverチップ: st7789
  5>.表示サイズ: 1.14インチ
  6>.表示領域: 14.864*24.912mm
  7>.パネルサイズ: 17.6*31.0*1.6mm
  8>.interfaceタイプ: 4ピンspi
  9>.作業電圧: 3.3v
 10>.ピン: 0.5 8ピン
 11>.view: フル視野角ディスプレイ
 12>.動作温度範囲:-20 ℃ 〜70 ℃
 13>.作業湿度範囲: 5%-95% rh
 
 ②ピン定義:
 1>.pin-1: LEDA
 2>.pin-2: GND
 3>.pin-3: RESET
 4>.pin-4: RS
 5>.pin-5: SDA
 6>.pin-6: SCL
 7>.pin-7: VDD
 8>.pin-8: CS

 ◆早速注文しました。

2.交換は、液晶が届いてから。「2024/06/03 注文」
 ◆分解方法などは、下記ブログ内記事を参照して下さい。
 ・M5StickC Plus の バッテリー交換 分解 について

3.「2024/06/20」にLCDが到着したので交換しました。
 ①交換前
 cp_lcd-1

 ②LCDのフラットケーブルの外し方
 cp_lcd-3

 ➂交換後の新旧LCD
 cp_lcd-2

 ④LCD交換後、確認の為ファクトリーテストを書き込み見事LCDが復活しました。
 cp_lcd-4

 ⑤組み込んだ後の最後の確認。めでたしめでたし。
 cp_lcd-5


以上

ブログトップへ

◆ESP32(M5STickC) Arduino IDE 2.3.2 でPS4コントローラを使う事が出来きました。
 開発環境 2024/05/22時点
 ①Arduino IDE 2.3.2
 ②Windows11 X64 Pro 23H2 
 ➂PS4Controller 1.0.8
 ps4_car

1.まずは、PS4コントローラ用のライブラリをインストールします。
 ①ライブラリマネージャーで「PS4」と検索し、PS4Controllerを
  インストールします。
 PS4Controller108
  
2.PS4コントローラは、接続先(ESP32)のBluetoothのMac Addressを記憶しなくては、
  なりません。
 ①ESP32のBluetoothのMac Addressを調べるため、下記のスケッチを書き込み、
  メモしておきます。
 ◆ESP32 ボードバージョンが3.0.5の場合、下記を一行追加しないとコンパイルエラーと
  なります。(2024/11/16追記)

#include "esp_mac.h"  
void setup(void) {
  Serial.begin(115200);
  delay(2000);
  Serial.println("-----------------------------");
  uint8_t btmac[6];
  esp_read_mac(btmac, ESP_MAC_BT);
  Serial.printf("[Bluetooth] Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", btmac[0], btmac[1], btmac[2], btmac[3], btmac[4], btmac[5]);
}

void loop() {
}

 ②実行例
 cplus_btmacadrs

3.PS4コントローラに、Mac Addressを記憶させるためのソフトを下記サイトで
  ダウンロードします。 (Windows用
  SixaxisPairTool 0.3.12024/05/22時点
 
 SixaxisPairTool-1
 SixaxisPairTool-2

 ①ダウンロードしたらインストールします。
 ②PS4コントローラをMicroUSBケーブルでPCに繋ぎます
 ➂SixaxisPairToolを実行し、<2.①>でメモしたMac Addressを入力し
  「Update」をクリックし書き換えます。
 (最初の実行時かなり時間がかかりました。) 
 BT_MAC_SET

4.サンプルプログラムを実行してみます。
 ①「PS4ReceiveData.ino」実行し各ボタンの動きを確認出来ました。

 ②「PS4SendData.ino」は、LEDをレインボーカラーにしたり
  バイブレーターを制御出来たりしました。

以上 色々なコントロールに活用出来るようになりました。


ブログトップへ

◆M5AtomS3の128x128のLCDにefont を使い漢字を表示してみました。
 M5StickCPlusには、efont用ライブラリが有りますが、M5AtomS3用は
 無かったので以前ESP32用に作ったものが有ったので流用しました。

 詳しくは、下記ブログ内記事を参照して下さい。
 ・ESP32 にて efont を使い SSD1306 OLED に漢字を表示してみた

1.試験用のスケッチは下記に示します。 
//atoms3_efont.ino
//V2024/04/17 by JK1VCK
//blog URL:http://gijin77.blog.jp/archives/40506691.html

#include <M5AtomS3.h>
#include "efontEnableJaMini.h"
//#include "efontEnableJa.h"
#include "efont.h"

//#define EFONT_DEBUG
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

//efont 文字列を表示する
//**********************************************************************************************
void printEfont(int16_t x,int16_t y,int16_t txtsize,uint16_t color,uint16_t bgcolor,char *str) {
  int posX = x;
  int posY = y;
  int16_t textsize = txtsize;
  uint16_t textcolor = color;
  uint16_t textbgcolor = bgcolor;
  byte font[32];
  while( *str != 0x00 ){
    // 改行処理
    if( *str == '\n' ){
      // 改行
      posY += 16 * textsize;
      posX += 16 * textsize;
      str++;
      continue;
    }
    // フォント取得
    uint16_t strUTF16;
    str = efontUFT8toUTF16( &strUTF16, str );
    getefontData( font, strUTF16 );
    // 文字横幅
    int width = 16 * textsize;
    if( strUTF16 < 0x0100 ){
      // 半角
      width = 8 * textsize;
    }

#ifdef EFONT_DEBUG
    Serial.printf( "str : U+%04X\n", strUTF16 );
#endif

    // 背景塗りつぶし
    M5.Lcd.fillRect(posX, posY, width, 16 * textsize, textbgcolor);
    // 取得フォントの確認
    for (uint8_t row = 0; row < 16; row++) {
      word fontdata = font[row*2] * 256 + font[row*2+1];
      for (uint8_t col = 0; col < 16; col++) {

#ifdef EFONT_DEBUG
        Serial.write( ( (0x8000 >> col) & fontdata ) ? "#" : " " );
#endif

        if( (0x8000 >> col) & fontdata ){
          int drawX = posX + col * textsize;
          int drawY = posY + row * textsize;
          if( textsize == 1 ){
            M5.Lcd.drawPixel(drawX, drawY, textcolor);
          } else {
            M5.Lcd.fillRect(drawX, drawY, textsize, textsize, textcolor);
          }
        }
      }

#ifdef EFONT_DEBUG
        Serial.write( "\n" );
#endif

    }
    // 描画カーソルを進める
    posX += width;
    // 折返し処理
    if( SCREEN_WIDTH <= posX ){ 
      posX = 0;
      posY += 16 * textsize;
    }
  }
  // カーソルを更新
  M5.Lcd.setCursor(posX, posY);
}

void setup() {
auto cfg = M5.config();
  M5.begin(cfg);
  Serial.begin(115200); // シリアル通信初期設定
  delay(1000);        // シリアル接続待ち
  Serial.println("AtomS3 eFont Test!"); // シリアル出力
  M5.Lcd.setRotation( 3 );
  M5.Lcd.clear();
}

void loop() {
  M5.Lcd.clear();
  printEfont(1,10,1,GREEN, BLACK,(char *)"1倍角 こんにちは");
  printEfont(1,28,1,GREEN, BLACK,(char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ123456");
  delay(5000);
  M5.Lcd.clear();  
  printEfont(1,1,2,GREEN, BLACK,(char *)"2倍角 こんにちは");
  delay(5000);
  M5.Lcd.clear();  
  printEfont(1,1,3,GREEN, BLACK,(char *)"3倍角 こんにちは");
  delay(5000);
}


2.実行画面

 s3_efont-3

 s3_efont-2

 s3_efont-1

以上

ブログトップへ

◆先人のサイトよりweb radioをダウンロードしてM5Stavk Basicに
 インストールしてみました。
 M5Stack_Basic_WebRadio

 詳しくは、下記サイトを参照して下さい。
 M5Stack WebRadio Stereo

 音の出力は、PCM5102 audio decoding moduleを使いました。
 下記で購入
 PCM5102 audio decoding module
 
以上


ブログトップへ

◆M5Stack用CardKBの代わりに市販のUSBキーボードとAtomS3を
 使い、USBからI2Cに変換して繋いでみました。
 M5Stack-CardKB-UsbKB-2

1.CardKBについては、下記を参照
  CardKB v1.1

2.I2Cのマスター側(M5Stack Basic)のスケッチは、下記ののままで動作します。
  CardKB.ino

3.USBUSBキーボードをAtomS3に繋ぐには、下記ブログ内記事を参照して下さい。
  ・AtomS3にUSB Keyboardを繋いでみた

4.本題は、AtomS3にてI2Cのスレーブで動くようにすることです。
 ①まず、I2Cの動きを理解する為に、下記サイトを参照し、二つのESP32で実験し、
  上手く動きました。
  【コード付き】I2Cの Master / Slave 間の通信をESP32を2個使って試す

 esp32-i2c-test

 esp32-i2c-test2

 ②次にAtomS3のグローブ端子を使いI2Cスレーブで動くようにします。
  1.GPIO番号は、G2,G1なので、それをSDA,SCLに設定する必要があります。
 AtomS3-i2c端子

   ここではまりました。
   Wire.begin(SDA,SCL);で設定できません。
  2.ライブラリのソースを眺めて
   Wire.setPins(SDA_PIN, SCL_PIN);を発見
   これで、G2,G1をSDA,SCLに出来ました。
  3.I2Cのアドレスは、0x5FとCardKBと同じにします。
 ➂後は、マスターからの要求に対して1バイトのAsciiコードを返すように
  します。

 ④テストするにあたって、グローブ端子の信号を見るため中継用の
  道具を作り、オシロで信号を見ながら動作を確認しました。
 i2c-test1

 i2c-test2
  
5.出来上がったスケッチ例です。保障無しの自己責任で。
 ①atoms3_usb_host_keybord_to_i2c.ino
 ◆USBキーボードから一文字入力が有れば、液晶に表示し、
  マスターからのリクエストで一文字I2C出力します。

//atoms3_usb_host_keybord_to_i2c.ino v20230706
//http://gijin77.blog.jp/archives/37426889.html
//USBキーボードをカードキーボードに変換(CardKB v1.1)

#include <M5AtomS3.h>
#include "EspUsbHost.h"
#include <Wire.h>

#define SDA_PIN 2 
#define SCL_PIN 1

uint8_t keyPressed=0;
uint8_t KEY=0;

class MyEspUsbHost : public EspUsbHost {
  void onKeyboardKey(uint8_t ascii, uint8_t keycode, uint8_t modifier) {
    KEY=ascii;keyPressed=1;
    if (' ' <= ascii && ascii <= '~') {
      M5.Lcd.printf("%c", ascii);
    } else if (ascii == '\r') {
      M5.Lcd.println();
    }
  };
};

MyEspUsbHost usbHost;

void requestEvent() {
  if (keyPressed == 1) {
    Wire.write(KEY);
    keyPressed = 0;
  } else {
    Wire.write(0);
  }
}


void setup() {
  M5.begin(true, false, false, false);  // Init M5AtomS3
  M5.Lcd.setRotation( 3 );
  M5.Lcd.clear();
  M5.Lcd.setTextSize(2);
  M5.Lcd.println("EspUsbHostKeybord to I2C" );

  usbHost.begin();
  usbHost.setHIDLocal(HID_LOCAL_Japan_Katakana);

  Wire.onRequest(requestEvent);
  Wire.setPins(SDA_PIN, SCL_PIN);
  Wire.begin(0x5f);

}

void loop() {
  M5.update();  // Read the press state of the key
  if (M5.Btn.wasReleased() || M5.Btn.pressedFor(1000)) {
    M5.Lcd.clear();
    M5.Lcd.setCursor(0,0);
  }
  usbHost.task();

}

 atoms3-i2c
  

 AtomS3Liteでも表示なしで使えます。
 ②atoms3lite_usb_host_keybord_to_i2c.ino
 ◆USBキーボードから一文字入力が有れば、青色LEDを一瞬点灯し、
  マスターからのリクエストで一文字I2C出力します。
//atoms3lite_usb_host_keybord_to_i2c.ino v20230706
//http://gijin77.blog.jp/archives/37426889.html
//USBキーボードをカードキーボードに変換(CardKB v1.1)

#include <FastLED.h>
#include <M5AtomS3.h>
#include "EspUsbHost.h"
#include <Wire.h>

#define SDA_PIN 2 
#define SCL_PIN 1

#define PIN_SW     41   // 本体釦 atoms3lite
#define PIN_LED    35   // 本体フルカラーLEDの使用端子(G21)
#define NUM_LEDS   1    // 本体フルカラーLEDの数

uint8_t keyPressed=0;
uint8_t KEY=0;
CRGB leds[NUM_LEDS];

class MyEspUsbHost : public EspUsbHost {
  void onKeyboardKey(uint8_t ascii, uint8_t keycode, uint8_t modifier) {
    KEY=ascii;keyPressed=1;
    leds[0] = CRGB(0, 0, 255); 
    FastLED.show();
    delay(100);
    leds[0] = CRGB(0, 0, 0); 
    FastLED.show();
  };
};

MyEspUsbHost usbHost;

void requestEvent() {
  if (keyPressed == 1) {
    Wire.write(KEY);
    keyPressed = 0;
  } else {
    Wire.write(0);
  }
}

void setup() {
  M5.begin(true, false, false, false);  // Init M5AtomS3
  FastLED.addLeds<WS2812B, PIN_LED, GRB>(leds, NUM_LEDS);
  for( int i=0;i<2;i++) {
    leds[0] = CRGB(255, 0, 0);   // 白色(赤, 緑, 青)※3色それぞれの明るさを0〜255で指定
    FastLED.show();
    delay(1000);
    leds[0] = CRGB(0, 255, 0);   // 白色(赤, 緑, 青)※3色それぞれの明るさを0〜255で指定
    FastLED.show();
    delay(1000);
    leds[0] = CRGB(0, 0, 255);   // 白色(赤, 緑, 青)※3色それぞれの明るさを0〜255で指定
    FastLED.show();
    delay(1000);
  }
  leds[0] = CRGB(0, 0, 0); 
  FastLED.show();
  
  usbHost.begin();
  usbHost.setHIDLocal(HID_LOCAL_Japan_Katakana);

  Wire.onRequest(requestEvent);
  Wire.setPins(SDA_PIN, SCL_PIN);
  Wire.begin(0x5f);

}

void loop() {
  usbHost.task();

}

 Atoms3lite-i2c

◆CardKBの代わりをUSBキーボードで実現出来ました。

以上

ブログトップへ

◆AtomS3のUSB HOST機能を使ってUSBキーボードを繋いでみました。
 atoms3_kbd-1

1.AtomS3の使い方などは、下記のサイトが参考になります。
 ①AtomS3の使い方、端子配列、開発環境、サンプルプログラムで詳しく紹介
 ②AtomS3の便利な使い方、日本語表示、並列処理、PWM、カウントダウンタイマ

2.AtomS3のUSB HOST機能については下記を参照しました。
 ◆EspUsbHost
  ①上記よりzipファイルをダウンロードし、
   Arduino IDEに「ZIP形式のライブラリをインストール」として登録します。
  ◆直接ライブラリマネージャーで検索してインストールするとコンパイル時
   エラーとなりました。
 ②サンプルをシリアル出力ではなくAtomS3の液晶画面に表示するように変更しました。

3.確認環境 2022/07/03時点
  ①Arduino IDE 1.8.19
  ②Windows11 X64 Pro 21H2 
  ➂ボード M5Stack バージョン2.0.7
  ④ライブラリ M5AtomS3 バージョン0.0.3
  ⑤ライブラリ EspUsbHost バージョン1.0.1

4.スケッチについて
 ①キーボードを押すたびにアスキー文字で1文字づつ画面に表示していきます。
 ②リターンを押すと改行します。
 ➂画面いっぱいになったら画面外に表示されていると思います。
 ④ここで、画面SWを押すと、画面をクリアして最初から表示していきます。
 ◆カーソル位置の制御などは、していませんので追加すれば良いと思います。

 ④短いソースなのでここに貼り付けます。保障無しの自己責任で。
 「atoms3_usb_host_keybord.ino」
//atoms3_usb_host_keybord.ino v20230703
//http://gijin77.blog.jp/archives/37402177.html
#include <M5AtomS3.h>
#include "EspUsbHost.h"

class MyEspUsbHost : public EspUsbHost {
  void onKeyboardKey(uint8_t ascii, uint8_t keycode, uint8_t modifier) {
    if (' ' <= ascii && ascii <= '~') {
      M5.Lcd.printf("%c", ascii);
    } else if (ascii == '\r') {
      M5.Lcd.println();
    }
  };
};

MyEspUsbHost usbHost;

void setup() {
  M5.begin(true, false, false, false);  // Init M5AtomS3
  M5.Lcd.setRotation( 3 );
  M5.Lcd.clear();
  M5.Lcd.setTextSize(2);
  M5.Lcd.println("EspUsbHostKeybord" );

  usbHost.begin();
  usbHost.setHIDLocal(HID_LOCAL_Japan_Katakana);
}

void loop() {
  M5.update();  // Read the press state of the key
  if (M5.Btn.wasReleased() || M5.Btn.pressedFor(1000)) {
    M5.Lcd.clear();
    M5.Lcd.setCursor(0,0);
  }
  usbHost.task();
}



4.コンパイルについて
 ①IDEで「ツール」「ボード」「M5Stack Arduino」「M5Stack ATOMS3」とボードを選択します。
 IDE_ボード選択

 ②続いて「ツール」「USB Mode」「USB-OTG(TinyUSB)」と設定します。
 IDEボード設定USB

 ➂同じく「シリアルポート」「COM17(ESP32S3 Dev Module」と設定します。
  COM番号は、環境により番号が変わっていると思います。私の場合は17でした。
 IDEボード設定COM

 ④リセットボタンを2秒以上押し、書き込みモードにしてから書き込みます。
  この時、リセットボタンの下で緑のLEDが一瞬光ります。

 ⑤「→」でコンパイルし、書き込みます。

 ◆コンパイル時に下記エラーが、発生しましたので該当のライブラリ部分を
 コメントアウトしました。  色々調べましたが原因が、分かりません。
 お分かりの方は、ご教示お願いします。
  
 C:\Users\yoshito\Documents\Arduino\libraries\M5AtomS3\src\M5AtomS3.cpp:20:9:
  error: 'USBSerial' was not declared in this scope
         USBSerial.begin(115200);
         ^~~~~~~~~

   *****\libraries\M5AtomS3\src\M5AtomS3.cppの下記を部分をコメントアウトします。
 18:/*
 19:    if (USBSerialEnable) {
 20:        USBSerial.begin(115200);
 21:        USBSerial.flush();
 22:        delay(1200);
 23:        USBSerial.println("M5AtomS3 initializing...OK");
 24:    }
 25:*/

5.キーボードを繋いでの動作試験
 ①書き込みが終わったら、一回電源を切ります。(USBケーブルを抜く)
 ②USB-OTG対応のType-C=>Type-Aの変換コネクタを使いUSBキーボードを接続します。
   ◆100均でも売っています。
 ➂AtomS3の5Vピンに外部電源を供給します。
 atoms3_kbd-2

  ④ATOMS3のピンアサイン
 atoms3ピンアサイン

以上

ブログトップへ

◆先日AtomS3Liteを使いスーファミのコントローラをUSB化しました。
 今回は、WiiControllerをAtomS3LiteでUSB化しました。
 atoms3_wii-1

 ①AtomS3 Liteについては、下記が参考となります。
 AtomS3 Liteの使い方、端子配列、初期設定をサンプルプログラムで詳しく紹介
 ②WiiControllerについては、下記が参考となります。
 Wiiリモコン拡張コントローラープロトコル解析
 ➂以前 raspi picoでのwii関連ブログ内記事も参照してみて下さい。
 ・pico-sdk (vsc) で Wii classic controller を使ってみた

1. WiiコントローラとAtomS3Liteとの配線とフォーマット
 ①下記のように配線します。
 wii-1
  
  ②Wiiコントローラのフォーマット
 wii-2

 ➂Wiiコントローラ釦bit配列
 wii-3
2.配線の様子
 ◆今回Wiiのモーションコントローラのジャンク品のコネクタを使い
  それにAtomS3Liteを載せました。
 ①分解後のモーションコントローラ(コネクタだけ残し他の基板は撤去)
 atoms3_wii-2
 
 ②AtomS3Lite接続用ピンヘッダの基板を作成
 atoms3_wii-3

 ➂コネクタ部分の拡大
 atoms3_wii-4
 
 ④コネクタとピンヘッダの半田付け
 atoms3_wii-5

 ⑤組み込み後の完成写真
 atoms3_wii-6
 
3.スケッチは、先日SFC用に作ったものをWiiコントローラ用に改修しました。
 ◆Wiiコントローラ部のプログラムは、下記を参考にコピペ修正しました。
  (先人に感謝です。)
  Wii Classic Controller

 (保障無しの自己責任で)  atoms3_wii_gamepad.ino

4.gamepadの確認方法やスケッチのコンパイル方法は、下記ブログ内を参照して下さい。
 ①・STAMPS3を使いスーファミのコントローラをUSB化してPCで使ってみた
 ②・AtomS3Liteを使いPSXコントローラをUSB化してPCで使ってみた
 ➂・AtomS3Liteを使いスーファミのパチスロコントローラを専用USB化してみた

以上

ブログトップへ

◆先日M5STAMPS3を使いスーファミのコントローラをUSB化しました。
 今回は、これのパチスロコントローラをAtomS3Liteで専用のUSBゲームパッド
 にしました。また、操作のBET、レバー、ストップ釦を自動化してみました。

 AtomS3 Liteについては、下記が参考となります。
 AtomS3 Liteの使い方、端子配列、初期設定をサンプルプログラムで詳しく紹介
 
 北斗の拳2_pad
 
1.パチスロコントローラを分解し、中にAtomS3Liteを埋め込みます。
  SFC用コネクタのケーブルを内部で切断して、基板に直接半田付けします。

ピン番号  名前   説明           GPIO番号 ケーブルの色
 --
  | 1 |   VCC    +3.3Vの電源  3.3V    白
  | 2 |   Clock  クロック    5    黄
  | 3 |   Latch  ラッチ     6       橙
  | 4 |   Data   シリアルデータ 7       赤
  ===
  | 5 |   N/A    未使用          -
  | 6 |   N/A    未使用          -
  | 7 |   GND    GND         GND    茶
  \__/
  


 ①分解後のコントローラの中の写真
 コントローラ-1

 ②コントローラの中にatomS3用基板の取付状態
 コントローラ-2

 ➂コントローラの表から基板の取付状態
 コントローラ-3

 ④コントローラの表から基板にatomS3を取り付けた状態
  (atomS3いつでも外せる用に外からアクセスできるようにしました。)
 コントローラ-4

2.スケッチ
 先日stampS3で作ったものをAtomS3に改修しました。
 ①パチスロ用ですので、今回自動モードを追加しました。
  AtomS3の釦を押すことで、BET,レバー,ストップ釦左、中、右の
  順で1秒間隔で押してくれます。
  (保障無しの自己責任で)  atoms3_sfc_gamepad.ino

3.gamepadの確認方法やスケッチのコンパイル方法は、下記ブログ内を参照して下さい。

 ①・AtomS3Liteを使いPSXコントローラをUSB化してPCで使ってみた
 ②・STAMPS3を使いスーファミのコントローラをUSB化してPCで使ってみた

以上

ブログトップへ

◆先日SFCのコントローラをUSB化してPCで使えたので、今回PS2の
 コントローラをUSB化してみました。
 下記ブログ内記事を参照して下さい。

 変換には、M5Stack ATOMS3 Liteを使いました。
 M5Stack ATOMS3 Liteについては、下記が参考となります。
 AtomS3 Liteの使い方、端子配列、初期設定をサンプルプログラムで詳しく紹介

1.PS2コントローラとの接続
 先日、ジャンクPS1からコントローラのソケットを確保していましたので
 そちらとAtomS3を配線しました。

 ①AtomS3とPSXコントローラとの接続

 atoms3 GPIO No.| PSX Controller Pin No.
 ---------------+------------------------
   G5    | Pin 1 Data
   G6    | Pin 2 Command
   5V    | Pin 3 9V for Motor (Optional)
   GND   | Pin 4 GND
   3V3          | Pin 5 VCC (3.3V)
   G7            | Pin 6 SEL1 (PAD1)
   G8            | Pin 7 Clock
                 | Pin 8 N/C
   G38          | Pin 9 ACK

   G39          | Pin 6 SEL2 (PAD2)

 ②実際の配線写真
 atoms3_psx
 
 ➂半田面の写真
 atoms3_psx-2
 ④AtomS3の端子配列
 ATOMS3端子配列

2.SCPH-1200コントローラとのやり取り時の波形とデータ
 ①デジタルモード時
 SCPH-1200デジタル.

 ②アナログモード時
 SCPH-1200アナログ

 ➂データ形式
 ◆下記サイトを参照しSCPH-1200用に編集
 プレイステーション・PAD/メモリ・インターフェースの解析
 寺川氏によるデュアルショック(SCPH-1200)の解析

 SCPH-1200

3.スケッチ
  ◆現時点でアナログモードでスティックの値が、正確ではないようです。
  使う場合は、再検討が必要です。
 (保障無しの自己責任で)  psx_usb_gamepad.ino

4.win11でのgamepadの確認方法やコンパイル方法などは、
  下記ブログ内記事を参照して下さい。
  あとボード設定でatoms3を選択してください。
 ・STAMPS3を使いスーファミのコントローラをUSB化してPCで使ってみた

以上

ブログトップへ

◆先日PS2エミュレータソフト「PCSX2」をWin11 PCにインストールして
 パチスロゲームを普通のコントローラでやっていました。
 下記ブログ内記事参照
 ・Win11 PCで【PS2エミュレータ】「PCSX2」を動かしてみた
 
◆ここからが、本題 
 リサイクルショップを探索していたら、スーパーファミコン(SFC)用の
 パチスロコントローラがあったので使えそうなので購入しました。
 でも、直接PCには繋がりません。
 なので、SFC-USB変換器をM5STAMPS3で作ってみました。
 M5STAMPS3については、下記が参考になります。
 M5StampS3の使い方、端子配列、初期設定、サンプルプログラムで詳しく紹介

1.ESP32S3は、OTGモードのUSBが使える事が、分かりそれでSFC-USB変換器が
 実現出来そうです。

 ◆現時点の環境
  ①OS:Win11 Pro X64 22H2
  ②IDE:Arduino IDE 1.8.19
  ➂ボード:M5Stack V2.07 


 ①SFCコントローラの仕様は、以前調査済みでしたので今回すんなり活きました。
 ②ESP32S3のUSBライブラリに「gamepad」が有るのが分かりました。
 ➂SFCコントローラから釦情報を読み取り「gamepad」ライブラリに渡します。
 
2.まずは試作段階として下写真のようにバラックで仮配線しました。
 ①接続写真
 stamps3接続

 SFCコントローラ対応 GPIOピン番号
 ◆注意事項:現在試験的に(ピン配列の関係で)VCCに5Vを与えていますが、
  Dataにも5Vレベルで
帰ってきています。
   ESP32S3は、3.3Vの論理レベルで動作するマイクロコントローラです。
  したがって、5VのレベルをそのままESP32S3の入力ピンに与えると、
  正常に動作しない可能性があります。
  ESP32S3の仕様では、入力ピンの最大電圧は3.6Vまでとされています。
   よって、長期的に使う場合は、ピン配列を工夫してVCCに3.3Vで与える
  方が良いと思います。

 ピン番号  名前   説明       GPIO番号
 --
  | 1 |   VCC    +5Vの電源   5V
  | 2 |   Clock  クロック    9
  | 3 |   Latch  ラッチ     7
  | 4 |   Data   シリアルデータ 5
  ===
  | 5 |   N/A    未使用        -
  | 6 |   N/A    未使用        -
  | 7 |   GND    GND        GND
  \__/

 ②SFCコントローラ釦bit配列
 bit 対応するボタン
 0   B
 1  Y
 2  Select
 3  Start
 4  ↑(Up)
 5  ↓(Down)
 6  ←(Left)
 7  →(Right)
 8  A
 9  X
 10   L
 11   R
 12 なし
 13 なし
 14 なし
 15 なし

 ➂SFCとの信号波形
 stamps3オシロ波形

3.PCでのgamepadの接続確認テスト方法
 ①コントロールパネルを開きます。
 ②「デバイスとプリンター」を開きます。
 gamepad-2

 ➂「その他のデバイスを表示」を開きます
 gamepad-3

 ④「その他のデバイスとプリンターの設定」を開きます
 gamepad-4

 ⑤うまくプログラムが動いていると「STAMP_S3」のアイコンが表示されています。
 gamepad-5

 ⑥「STAMP_S3」アイコンを右クリックし、「ゲームコントローラーの設定」を開きます。 
 gamepad-6
 
 ⑦「STAMP_S3」を選択後「プロパティ」を開きます。
 gamepad-7

 ⑧「STAMP_S3」のプロパティが開き、各ボタンの状態が赤印で表示されます。
  ◆画面は、レバーの「UP」の状態
 gamepad-8

3.プログラムは、「gamepad」ライブラリのサンプルにSFCコントローラからの
  釦読取部分を追加しました。
 ◆プログラムの概要説明
 ①SFCコントローラからの釦読取部
 ②「gamepad」ライブラリ  
 ➂WS2812のLEDを点灯させる部分
  
  詳しくは、下記ソースコメント欄を参照
  (保障無しの自己責任で)  esp32s3_sfc_gamepad.ino

4.Arduino IDEでの書き込みについて
 ①ボードの選択画面
  「M5Stack Arduino」 -->「 STAMPS3」 を選択
 arduinoIDE-1


 ②USBコネクタをUSB-OTGにするための選択
  「USB Mode」-->「USB OTG(TinyUSB)」を選択
 arduinoIDE-2


 ➂シリアルの選択
  「COM6(ESP32S3 Dev Module」を選択
  (ESP32S3のCOMを選択します。私の場合はCOM6でした。)
 arduinoIDE-3

 ④「→」アイコンをクリックして書き込みます。
  一回OTGモードで書き込みますと、次に書き込むときは、
  「G00」を押しながら電源を入れると書き込みモードとなります。

5.実際に北斗の拳のエミュレータの動作画面
 北斗の拳画面

6.これからやる事
 1.コントローラを仮付からコネクタに付け替える
 2.PS2のコントローラも変換できるようにする
 上記の為に、リサイクルショップでコントローラのソケットの
 部品取り用にジャンクのSFCとPS1をゲットしてきました。

 ◆PSX版の変換器も作ってみました。下記ブログ内参照
 ・AtomS3を使いPSXコントローラをUSB化してPCで使ってみた


 ①スーパーファミコンのジャンク300円
 sfc

 ②プレイステーション1のジャンク100円
 ps1

 ➂ばらして、コネクタだけ取り出しました。
 sfc_ps1コネクタ

 ④SFCのコネクタに配線しました。
 STAMPS3_SFC

 ⑤M5STAMPS3で、プログラムの書き換えが便利になるように「RESET SW」と
 「G00 SW」を付けました。
 これまで、電源のoff/onでの操作でしたが、これによって電源は入れたままで
 SWの操作で出来るようになりました。
 「G00 SW」を押しながら「RESET SW」で、プログラムモードとなります。
 STAMPS3_RESET_SW

 
以上


ブログトップへ

◆M5Stack,M5StickC,M5StickCPlusをM5StackからESP-NOWを
 使って指示し、画像を同期をとって表示してみました。

 

1.まずM5Stackシリーズに画像を表示するのに下記を参考にしました。
  M5StickC PLUSで画像を表示してみた

 1.表示用の画像を画像ソフトで作ります。
  表示ピクセルは、機種に合わせます。
  ・M5Stack      320x240 2枚 (st_10.jpg st_11.jpg)
  ・M5StickC     80x160 2枚 (c_10.jpg c_20.jpg)
  ・M5StickCPlus 240x135 2枚 (左 cp_10.jpg cp_11.jpg )
  ・M5StickCPlus 240x135 2枚 (右 cp_20.jpg cp21.jpg )
 2023あけおめ1

 2012あけおめ2

 2.出来た画像をヘッダーファイルに変換します。
  下記サイトで画像ファイルを変換出来ます。
  画像データImageData化

  ◆M5Stack用の例です。
 画像変換サイト

 ①変換する画像ファイルを指定します。「st_10.jpg」
 ②変換するデータ名を指定します。「img_st10」
 ➂データ形式を指定します。
  ここは、ディフォルトのまま「16Bit RGB565」
 ④送信をクリックします。
 ⑤出力データを全選択します。
 ⑥Ctrl_Cで、コピーします。
 ⑦テキストエデッタを起動し、ペーストします。
 ⑧名前を付けて保存します。「st_10.h」

 ◆順次変換します。
 ・M5Stack      320x240 2枚 (st_10.h  ,st_11.h img_st11)
 ・M5StickC     80x160 2枚 (c_10.h img_c10 ,c_20.h img_c20)
 ・M5StickCPlus 240x135 2枚 (左 cp_10.h img_10 ,cp_11.h img_11 )
 ・M5StickCPlus 240x135 2枚 (右 cp_20.h img_20 ,cp_21.h img_21)

2.動作概要
 ①同期をとるのに下記を参考にESP-NOWを使いました。
  M5StickCでESP-NOW その1

 ②切替指示は、M5Stackからのみにしました。
  ・A釦を押すたびに切替え指示。
  ・B釦を押すと2秒毎に自動で切替え指示。
  ・C釦で自動切替え停止。

 ➂他の4台は、指示に従って画像を切替えて表示します。
    
3.スケッチは、各々コンパイルして、書き込みます。
 ◆画像用のヘッダファイルは、「1」で作ったものを使用します。
  スケッチと同じフォルダにヘッダファイルも保存します。

 ◆例 M5Stack用
 M5Stack

 ◆下記の各スケッチには、画像のヘッダファイルは含まれていません。
 ①M5Stack用
  (保障無しの自己責任で)  m5s2_2023.ino
 
 ②M5StickC用
  (保障無しの自己責任で)  m5c2_2023.ino

 ➂M5StickCPlusは、右、左用に別々です。
  ・左用をコンパイルする時、4行目で#define LCPを指定します。
  ・右用をコンパイルする時、4行目で#define LCPをコメントアウトします。
  (保障無しの自己責任で)  om5cp_2023.ino

以上



ブログトップへ

◆M5STAMP Picoで表示部の無い小型のインターネットラジオを作ってみました。
 IRリモコン操作、ブラウザ操作(スマホ,iPadなどでも)で音量、選局等が出来ます。
 *起動時に音声合成によるIPアドレスを読み上げる様にしました。(2022/10/12)
 m-1

 以前作った「多機能インターネットラジオ」からLCD及びタッチパネル
 無しのバージョンです。
 なので、「TFT_eSPI」「efont」のライブラリは、必要有りません。
 下記ブログ内記事を参照して「AUDIO_I2S」「IRリモコン」
 ライブラリをインストールして下さい。
 ・ESP32-3248S035 で 多機能インターネットラジオ を作ってみた
 
1.実態配線図

 m30

2.パソコンweb上の操作画面
 ①シリアルモニタに表示されるIPアドレスにアクセスします。
 *起動時にIPアドレスを読み上げますのでシリアルモニタを使えない
  環境でもアクセスできます。

  表示部が無いので、再生中曲名をブラウザ上に表示するように
  しました。30秒毎更新します。
 m-31

 ②スマホからの操作画面
 i-34

 ➂iPadからの操作画面
 i-33


 ④あとIRリモコンでも同様の操作が出来ます。

4.最後に次のスケッチをコンパイル・インストールします。
  (保障無しの自己責任で)  M5STAMP_iradio2.ino

  ①本体SWで消音できます。
  ②LEDは、再生中青色表示で消音時滅灯、スリーブ時赤色となります。
  ➂起動時に音声合成によるIPアドレスを読み上げる様にしました。
   (2022/10/12)


以上


ブログトップへ

◆M5StickC Plus の バッテリーの不良等に対処する為にAXP192の情報を
 表示させてみました。
 元のスケッチは、M5StickC用のスケッチ例AXP192を参照しています。
 
1.下記のスケッチをM5StickC Plusに書き込みます。
   (保障無しの自己責任で)  M5StickC_Plus_battery_info.ino

2.実際に動かしてバッテリー情報を表示させています。
 ①上側は、バッテリー動作中
 ②下側は、充電中
m5-30

 
3.バッテリー不良でここに来られた方は、下記ブログ内記事も参照して下さい。
  ・M5StickC Plus の バッテリー交換 分解 について

以上


ブログトップへ

1.分解手順
 ①まずは、六角レンチで二本のビスを外します。
m5-1

 ②液晶側ケースは、簡単に外れます。
m5-2

 ➂本体と裏側ケースは接着剤で止めてあり慎重にこじ開けます。
  この時、ブザーが裏側ケースに接着してあり細い線で
  繋がっていますので、切らないよう慎重に開けます。
 (そう言いながら一本切れてしまいました。後で半田付けしました。)
m5-3
 ➂-2 裏ケースと本体は、ピンソケットにラベルがくっついていて中々外れなかった
 ので、前もってラベルを剥がしておくとスムースに外れると思われます。
 (下記黄色枠の部分)
m5-21

 ④何とかバッテリーが外せるまで分解出来ました。
m5-4

 ⑤バッテリーは、赤2本、黒1本で本体に半田付けされています。
  2本は、簡単に取れそうですが、拡張端子に繋がっている方は
  アプローチが難しそうです。
m5-5

 ⑥組むときは、下図、黄色線のように配線にしたいと思っています。
m5-20

2.バッテリーの交換
 ①使えそうなバッテリーを入手し、交換しようと思っています。
  120mAh 3.7V 25mm x 14mm x 4.5mm (451425)
m5-7

 ②バッテリーを外して、充電モジュールに繋いで充電してみました。
m5-8

 ➂外す前は、0.4V位でしたが、
m5-9

 ④充電後3.84Vに復活しました。
m5-10

 ⑤なので再度組み上げて、バッテリーテストプログラムを書き込んでみました所
  普通にバッテリーで動くようになりました。写真の上のM5StickC Plusです。
  下のM5StickC Plusは、同じくバッテリー不良の物で、電源に繋いでも電圧が
  出ていません。
  ◆バッテリーテストプログラムは、下記を参考に次の3行をM5StickC Plus用に
  書き換えて使用しました。

  ◆修正箇所
    1:#include <M5StickCPlus.h>
    9:#define DISP_BRIGHTNESS_MIN 10
  60:  M5.Lcd.setRotation(3);

m5-11

 ⑥同じ現象なので、今回は分解しないでそのまま拡張端子のBAT,GNDに
  充電モジュールを繋いでみました所、見事復活しました。
 (本体が壊れるかも知れませんので覚悟のうえで実行しました。)
m5-12

 ⑦2台とも100%まで充電しバッテリーだけで動かしたところ10分から15分位
  動作しました。
  当然バッテリーは、へたっていますが、このまま使うことにしました。
m5-13

 ◆使えそうなバッテリーが入手出来たら交換しようと思っています。

 ◆後さらに詳しくバッテリー情報を表示させてみました。
 下記、ブログ内記事も参照してみてください。
 ・M5StickC Plus の バッテリー 情報 の 表示

3.バッテリーを交換しました。「2024/066/03(月) 追記
 ①容量は、少ないですが中に入るバッテリーが入手出来ましたので
  交換しました。(120mAh-->100mAh)
(ショック:交換の際かと思われるのですが液晶が壊れてしまいました。)
  詳しくは、下記ブログ内記事を参照して下さい。
 ・M5StickC Plus の 液晶 が壊れたので交換してみた

 M5C_P_バッテリ交換


以上



ブログトップへ

 ◆M5Stamp C3 が届きました。
  その中にカードが入っていたのですが、何に使えるのでしょうか?
  RFIDと書いてあるので何か情報が入っているのでしょうか?
m5stampc3rfid


①回路図
c3回路図


②ピンアサイン
m5c3PinMap

➂ArduinoIDEでM5Stamp C3を使うには、
 arduino-esp32のバージョンを2.0.1-RC1にする必要が有りました。
 espressif / arduino-esp32


④ファイル->環境設定->追加のボードマネージャのURLに下記を追加しました。
 https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
c3board

⑤詳しくは、下記で
 M5Stamp C3 ドキュメント


ブログトップへ

◆M5Stackを使い音声と7セグ表示で測定値を教えてくれる
 「トーキングテスター」を作ってみました。(その1)

S__44556302



◆測定項目は、ボタンBにて、操作し、
 電圧、電流、抵抗、ロジックを切り替え、
 音声出力と7セグ表示させます。
 その1は、電圧測定のみ)

◆測定モードは、ボタンCにて操作し、
 手動測定、自動測定、リピート測定としました。
 ①手動測定・・・・ ボタンAを押したとき測定し出力。
 ②自動測定・・・・ 値の変化があった時、測定し出力。
 ③リピート測定・・ 3,5,7,15,31秒間隔でリピート測定し出力。

◆ハードは、出来る限りシンプルにしました。
 (その1は、抵抗2本とコンデンサ1個、ピンヘッダ)

1.準備
①まず最初に、M5Stackで喋らせるためには、音声合成機能を準備します。
  下記URLを参考に、導入し、
  サンプル発生までが出来ていること前提としています。
 *デモ版の為、ナ、マ行が「ヌ」と発音します。

  「AquesTalk-ESP32 Ver.2.0」を使う

 ダウンロード:SampleTTS.zip

②トーキングテスターは、上記「SampleTTS.ino」を改造します。

③M5Stackの標準のアナログ入力を使って、(GPIO36,35,26)
  電圧、電流、抵抗測定及びロジックテスター作ります。

④アナログ入力については、色々誤差などが有り大変でした。

⑤詳しくは、下記URLが大変参考になり、ありがとうございました。

   ESP32のアナログポートの特性調査-入力感度特性

2.電圧測定について

①ADコンバータのアッテネータの設定を選びます。
 ブログのの内容と実際試してみて、「ADC_11db」を選びました。

以下ブログより抜粋(先人の方に感謝です。)
***********************************************************
  //  analogSetAttenuation(ADC_0db); //アッテネーターを設定
  //  analogSetAttenuation(ADC_2_5db);
  //  analogSetAttenuation(ADC_6db);
  //  analogSetAttenuation(ADC_11db);
***********************************************************
  データーシートのリンクがすぐに出てこないのですが、
  ADCのキャリブレーション方法について書いてある資料には、
  誤差が少ない範囲として、
  Atten0 (0dB)は、  100-950mV
  Atten1 (-2.5dB)は、100-1250mV
  Atten2 (-6dB)は、  150-1750mV
  Atten3 (-11dB)は、 150-2450mV
  となっていて、下の方もダメと書いてありましたorz
************************************************************

②上記より電圧測定範囲を1.2V~27V未満としました。

③電圧測定の入力部分は、抵抗分圧で10倍としました。
 手持ち部品の関係で2MΩと220KΩとしましたが、
 出来れば割り切れる1.8MΩと200KΩが良いです。

 入 力◎-----2MΩ----+->GPIO36(ADC)
              l
    GND◎-+-220KΩ--+
               l         l
               +-0.1uF----+-->GND

④AD変換後の電圧値の算出に
  「(float)ad*3.3/4096.0*10.0」
  ・最後の10.0は、入力抵抗の分圧の分です。
  の式を使って測定値を出していましたが、
  テスター値との乖離があまりにもあり、使えませんでした。

⑤採用したのは、大まかな実測値と計算にて電圧値を算出しました。
 結果、ほぼテスターと同じ様な値となりました。
 ・実測は、2V~27Vまで、1V間隔でAD変換値を記録し、vtblという
  配列に保存しました。2V以下は0.1V間隔でltblに保存しました。
 ・基本値は、配列の位置とし、1Vの間は、1V間の差分を10で割り、
  加算しました。

    計算式の概略
   ad=analogRead(AD_IN);
           for (i=0;i<28;i++) {
             if ((vtbl[i]<=ad)&&(ad<vtbl[i+1])) break;
           }
           v2=vtbl[i+1];
           v1=vtbl[i];
           v3=((ad-v1)/((v2-v1)/10.0))/10.0;
          adt=i+v3;

  シリアル出力
   ad=1076 i=10 v1=1060 v2=1182 v3=0.131148 adt=10.13 
   10.13ボルト.

   ad :AD変換値
   adt:測定電圧値(計算結果)

  以上により、ほぼテスター値とほぼ同じくらいの制度となりました。

3.電流測定、抵抗測定、ロジック測定について

  その1は、抵抗2本とコンデンサ1個の簡易版とし
  電圧測定のみとします。

4.測定値の7セグ表示について

①LCDの表示は、7セグメント表示が、かっこいいかなと色々検索してみましたら

    M5.Lcd.drawString("V",140,200,4);
    M5.Lcd.drawString(String(dt,2),x,80,7);     <--の最後の数値を「7」にすることで
                     7セグ表示出来ました。隠しコマンドかな

*ライブラリの使用例ではサイズとなっている。
  M5.Lcd.drawString("文字列", X, Y, {size}) 指定位置に文字列を表示

5.スケッチについて
 
**整理中

以上

 

ブログトップへ

・M5StickC で 接触確認アプリ (COCOA) の数を数えてみた。

◆下記参考URLよりAtom から M5StickCに変更。
◆釦Aでリスタート出来るように追加した。
◆バッテリー電圧の表示を追加した。

◆参考URL
M5 Atom Matrixで新型コロナウイルス接触確認アプリが周囲に何個あるか数えてみる


◆下記は、スーパーでのカウント数です。

4900


◆下記は、自宅にて
S__44122132


◆スケッチ例(cocoaM5StickC.ino)

#include <M5StickC.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

#define LED 10
int scanTime = 4; //BLEスキャン間隔
BLEScan* pBLEScan;

// 接触確認アプリのUUID
const char* uuid = "0000fd6f-0000-1000-8000-00805f9b34fb";
int deviceNum = 999;

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
       if(advertisedDevice.haveServiceUUID()){
            if(strncmp(advertisedDevice.getServiceUUID().toString().c_str(),uuid, 36) == 0){
                int rssi = advertisedDevice.getRSSI();
                Serial.print("RSSI: ");
                Serial.println(rssi);
                Serial.print("ADDR: ");
                Serial.println(advertisedDevice.getAddress().toString().c_str());
                Serial.println("Found!");
                deviceNum++;
            }
        }

    }
};

void disp(){    
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(10,20);M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(GREEN);M5.Lcd.print("COCOA");  
  if (deviceNum>9) M5.Lcd.setCursor(5,60); else M5.Lcd.setCursor(25,60);
  if (deviceNum>99) M5.Lcd.setTextSize(4); else M5.Lcd.setTextSize(6);
  M5.Lcd.setTextColor(WHITE);M5.Lcd.printf("%d", deviceNum);
  M5.Lcd.setCursor(0,120);M5.Lcd.setTextSize(1);
  M5.Lcd.setTextColor(CYAN);M5.Lcd.printf("BtnA=Restart");  
  M5.Lcd.setCursor(0,140);M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(GREEN);M5.Lcd.printf("Bt%3.1fV\n", M5.Axp.GetBatVoltage());
}

void Task1(void *pvParameters) {
  // loop()内に書くとボタン圧下が取れないのでマルチスレッド化してある
  while(1) {
    deviceNum = 0;
    BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
    disp();
    Serial.print("Devices found: ");
    Serial.println(deviceNum);
    Serial.println("Scan done!");
    pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory
  }
}

void setup() {
  M5.begin();
  Serial.begin(115200);
  Serial.println("Program Start...");
  pinMode(LED, OUTPUT);
  M5.Lcd.setRotation( 0 );
  M5.Lcd.fillScreen(GREEN);
  for(int i=0;i<3;i++) {
    digitalWrite(LED,LOW);delay(500);
    digitalWrite(LED,HIGH);delay(500);
  }
  disp();
  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);  // less or equal setInterval value
  xTaskCreatePinnedToCore(Task1,"Task1", 4096, NULL, 3, NULL, 1);
}

void loop() {
  M5.update();
    if ( M5.BtnA.wasReleased() ) {
    // ボタンを押すとリスタート
      esp_restart();
    }
 }

************************************
*4秒周期の数と電源on(リスタート)からの
 トータルの数を表示するように追加修正


cocoa07074995

◆経過時間追加
S__44171275


◆スケッチ例(cocoaM5StickC_2.ino)
次の項目を追加修正した。
①スタートからのトータル表示
 (マックアドレスをチェックして違うものだけカウント)
②ボタンAでリスタート
③ボタンBで電源OFF
④スタートからの経過時間を表示

#include <M5StickC.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

#define LED 10
int scanTime = 4; //BLEスキャン間隔
BLEScan* pBLEScan;

// 接触確認アプリのUUID
const char* uuid = "0000fd6f-0000-1000-8000-00805f9b34fb";
int deviceNum = 0;
int cocoa = 999;
int skip_flg=0;
int hh=0;
int mm=0;
int ss=0;
unsigned long otime;

char  cocoa_buf[500][18] = {"01:23:45:57:89:ab","40:00:31:92:29:5a","01:23:45:57:89:ab","40:00:31:92:29:5a"};
char  c_buf[18] = "01:23:45:57:89:ab";

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
       if(advertisedDevice.haveServiceUUID()){
            if(strncmp(advertisedDevice.getServiceUUID().toString().c_str(),uuid, 36) == 0){
                int rssi = advertisedDevice.getRSSI();
                Serial.printf("RSSI: %d \n",rssi);
                strcpy(c_buf, advertisedDevice.getAddress().toString().c_str());
                Serial.printf("ADDR: %s \n",c_buf);
                Serial.println("Found!");
                cocoa++;
                skip_flg=0;
                for(int i=0;i<=deviceNum;i++) {
                  if (strcmp(cocoa_buf[i],c_buf)==0) {
                    skip_flg=1;
                    break;  
                  }
                }
                if (skip_flg==0) {
                  strcpy(cocoa_buf[deviceNum], c_buf);
                  deviceNum++;
                }
            }
        }

    }
};
void jikan(){
  otime = millis()/1000;
  ss=int(otime%60);
  mm=int((otime/60)%60);
  hh=int(otime/3600);
}
void disp(){    
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(10,5);M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(GREEN);M5.Lcd.print("COCOA");  
  if (cocoa>9) M5.Lcd.setCursor(5,40); else M5.Lcd.setCursor(25,40);
  if (cocoa>99) M5.Lcd.setTextSize(4); else M5.Lcd.setTextSize(6);
  M5.Lcd.setTextColor(WHITE);M5.Lcd.printf("%d", cocoa);
  M5.Lcd.setCursor(0,90);M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(YELLOW);M5.Lcd.printf("T=%d", deviceNum);
  M5.Lcd.setCursor(0,110);M5.Lcd.setTextSize(1);jikan();
  M5.Lcd.setTextColor(GREEN);M5.Lcd.printf("Time=%02d:%02d:%02d",hh,mm,ss);  
  M5.Lcd.setCursor(0,120);M5.Lcd.setTextSize(1);
  M5.Lcd.setTextColor(CYAN);M5.Lcd.printf("BtnA=Restart");  
  M5.Lcd.setCursor(0,130);M5.Lcd.setTextSize(1);
  M5.Lcd.setTextColor(CYAN);M5.Lcd.printf("BtnB=PowerOff");  
  M5.Lcd.setCursor(0,146);M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(GREEN);M5.Lcd.printf("Bt%3.1fV\n", M5.Axp.GetBatVoltage());
}

void Task1(void *pvParameters) {
  // loop()内に書くとボタン圧下が取れないのでマルチスレッド化してある
  while(1) {
    cocoa=0;
    BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
    disp();
    Serial.printf("Devices found: %d Total: %d \n",cocoa,deviceNum);
    for (int i = 0; i < deviceNum; i++){
      Serial.printf("%03d=%s \n",i+1,cocoa_buf[i]);
    }
    Serial.println("Scan done!");   
    pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory
  }
}

void setup() {
  M5.begin();
  Serial.begin(115200);
  Serial.println("Program Start...");
  pinMode(LED, OUTPUT);
  M5.Lcd.setRotation( 0 );
  M5.Lcd.fillScreen(GREEN);
  for(int i=0;i<3;i++) {
    digitalWrite(LED,LOW);delay(500);
    digitalWrite(LED,HIGH);delay(500);
  }
  disp();
  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);  // less or equal setInterval value
  xTaskCreatePinnedToCore(Task1,"Task1", 4096, NULL, 3, NULL, 1);
}

void loop() {
  M5.update();
  if ( M5.BtnB.wasReleased() ) {
    // ボタンを押すとパワーオフ
      M5.Axp.PowerOff();
  }
  if ( M5.BtnA.wasReleased() ) {
    // ボタンを押すとリスタート
      esp_restart();
  }
}


ブログトップへ


以前作っていた、バランスロボットをついに立たせることが出来ました。




S__43638798

S__43638800

S__43638801


ハードは、下記のサイトを参考にしました。
M5StickC バランスロボ

ソフトは、下記のサイトを参考にしました。
実質500円&100Stepで作る超簡単「 ゆるメカトロ的 M5StickC 倒立振子」

M5StickCはMadgwickフィルタで倒立振子の夢を見るか?


■スケッチ

#include <M5StickC.h>

//PIDパラメータ調整
#define OFFSET             90.0                    // 重心 後方-←90°→+前方
#define COEF_P             35.0                    // Propotional
#define COEF_I             1.5                     // Integral
#define COEF_D             50.0                    // Differential

//Motor
#define LED_PIN            10                      // 内蔵LED

#define MOTOR_R 0x65 //A0=low, A1=open
#define MOTOR_L 0x63 //A0=high, A1=open


//MPU6886 https://github.com/m5stack/M5StickC/blob/master/src/utility/MPU6886.h
#define MPU6886_AFS        M5.MPU6886.AFS_2G       // Ascale [g]      (±2,4,8,16)
#define MPU6886_GFS        M5.MPU6886.GFS_1000DPS  // Gscale [deg/s]  (±250,500,1000,200)
#define DPS                1000                    // Gscale [deg/s]
#define CALIBRATION_COUNT  1000

//Function
#define min(a,b)           ((a) < (b) ? (a) : (b))
#define max(a,b)           ((a) > (b) ? (a) : (b))

//キャリブレ結果
double offsetX;              //Gyro X
float  base_angle;           //Accl X
//ローテーション結果
float dpsX;                  //Gyro X
float angleX;                //Accl X
//積分
double gyro_angle_x = 0;
float  preInterval  = 0;

// I2Cドライバー
void drvMotor(byte adr, int16_t pwr) { //pwr -255 to 255
  byte dir, st;
  if (pwr < 0) dir = 2;
  else dir =1;
  byte ipower=(byte) (abs(pwr)/4); //
  if (ipower == 0) dir=3; //brake

  //constrain(x, a, b) xがa以上b以下のときはxがそのまま返ります。xがaより小さいときはa、bより大きいときはbが返ります。
  ipower = constrain (ipower, 0, 63);
  st = drv8830read(adr);
  if (st & 1) drv8830write(adr, 0, 0);
  drv8830write(adr, ipower, dir);
}

void drv8830write(byte adr, byte pwm, byte ctrl) {
  Wire.beginTransmission(adr);
  Wire.write(0);
  Wire.write(pwm*4+ctrl);
  Wire.endTransmission(true);
}

int drv8830read(byte adr) {
  Wire.beginTransmission(adr);
  Wire.write(1);
  Wire.endTransmission(false);
  Wire.requestFrom((int)adr, (int)1, (int)1);
  return Wire.read();
}


void setup() {
  //初期化
  M5.begin();
  M5.Lcd.setRotation(1);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.println("<B-Robot v1>");
  //Motor設定
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);

// I2C設定
  Wire.begin(0, 26, 400000); //SDA, SCL
//  Wire.setClock(50000);
  drvMotor(MOTOR_R,0);
  drvMotor(MOTOR_L,0);

  //MPU設定
  M5.MPU6886.Init();
  M5.MPU6886.SetGyroFsr(MPU6886_GFS);
  M5.MPU6886.SetAccelFsr(MPU6886_AFS);
  delay(1000);

  //キャリブレーション
  calibration();
//  base_angle-=1.5;
//  offsetX+=0.6;

  M5.Lcd.setRotation(2);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 140);
  M5.Lcd.printf("BT%3.1fV\n", M5.Axp.GetBatVoltage());
  face();
}

void loop() {
  static  int   Duty;
  float         power, powerP, powerD;
  static float  powerI = 0;
  double        angle;

  //MPUローテーション
  calcRotation();
  //モーター制御
  angle = angleX;
  M5.Lcd.setCursor(0, 0);
  if ((base_angle>=0)&&(base_angle<=1.0)) {
    M5.Lcd.setTextColor(GREEN);
  } else {
    M5.Lcd.setTextColor(RED);
  }
  M5.Lcd.printf(">%3.1f", base_angle);

  if ((angle - OFFSET > -20) && (angle - OFFSET < 20)) {    // 30度以下だけモーター駆動
    powerP = (angle - OFFSET ) / 90;                        // angle=0~180  → -1~1
    powerI += powerP;
    powerD = dpsX / DPS;                                    // 角速度 → -1~1
    power = powerP * COEF_P + powerI * COEF_I + powerD * COEF_D;
    power = max(-1, min(1, power));                         // -1~1
    //モーター駆動
    Duty = (int)(255* power );
    drvMotor(MOTOR_R,Duty);
    drvMotor(MOTOR_L,Duty);
    digitalWrite(LED_PIN, HIGH);
  } else {                                                  // 転倒したら停止
    drvMotor(MOTOR_R,0);
    drvMotor(MOTOR_L,0);
    powerI = 0;
    digitalWrite(LED_PIN, LOW);
  }
  M5.update();
  if (M5.BtnA.wasReleased()) {
    M5.Lcd.fillScreen(GREEN);
    ESP.restart();
    while (true) ;
  }
}

//キャリブレーション関数
void calibration() {
  float raw_gyro_x, raw_gyro_y, raw_gyro_z;
  float raw_acc_x, raw_acc_y, raw_acc_z;
  float acc_x = 0, acc_y = 0, acc_z = 0;
  offsetX = 0;
  for (int i = 0; i < CALIBRATION_COUNT; i++) {
    M5.MPU6886.getGyroData(&raw_gyro_x, &raw_gyro_y, &raw_gyro_z);
    M5.MPU6886.getAccelData(&raw_acc_x, &raw_acc_y, &raw_acc_z);
    //ベースプログラムとM5StickCの組付け位置の違いによる座標系変換含む
    offsetX += -raw_gyro_x;
    acc_x   += -raw_acc_x;
    acc_y   +=  raw_acc_y;
    acc_z   += -raw_acc_z;
  }
  //gyro offset
  offsetX /= CALIBRATION_COUNT;
  //加速度から角度を算出
  acc_x   /= CALIBRATION_COUNT;
  acc_y   /= CALIBRATION_COUNT;
  acc_z   /= CALIBRATION_COUNT;
  base_angle = (atan2(acc_y, acc_z + abs(acc_x)) * 360 / 2.0 / PI) + 180;
}

//MPUローテーション関数
void calcRotation() {
  float raw_acc_x, raw_acc_y, raw_acc_z, raw_t, raw_gyro_x, raw_gyro_y, raw_gyro_z ;
  float acc_angle_x;
  M5.MPU6886.getGyroData(&raw_gyro_x, &raw_gyro_y, &raw_gyro_z);
  M5.MPU6886.getAccelData(&raw_acc_x, &raw_acc_y, &raw_acc_z);
  //ベースプログラムとM5StickCの組付け位置の違いによる座標系変換
  raw_gyro_x *= -1;
  raw_acc_x  *= -1;
  raw_acc_z  *= -1;
  //
  acc_angle_x = (atan2(raw_acc_y, raw_acc_z + abs(raw_acc_x)) * 360 / 2.0 / PI) + 180;
  dpsX = raw_gyro_x - offsetX;
  //積分
  float now_time = millis();
  float interval = now_time - preInterval;  //前回からの経過時間
  preInterval = now_time;
  gyro_angle_x += dpsX * (interval * 0.000999999);
  //相補フィルター
  angleX = (0.996 * gyro_angle_x) + (0.004 * acc_angle_x) + base_angle;
}

void face(){
 int x0=10;
 int y0=40;
 int w0=25;
 int h0=10;
 int col=TFT_ORANGE;
 M5.Lcd.fillRect(x0,y0,w0,h0,col);
 M5.Lcd.fillRect(x0+35,y0,w0,h0,col);
 M5.Lcd.fillCircle(x0+12,y0+25, 7,col);
 M5.Lcd.fillCircle(x0+12,y0+25, 5,BLACK);
 M5.Lcd.fillCircle(x0+48,y0+25, 7,col);
 M5.Lcd.fillCircle(x0+48,y0+25, 5,BLACK);
 M5.Lcd.fillTriangle(x0+30,y0+25, 30,90,50,90,col);
 M5.Lcd.fillRect(20,y0+60,40,15,col);
}


ブログトップへ


・最近の新型コロナの影響で非接触型の温度計を作ってみました。
 毎日の体温の目安になるのではと思っています。

■画面の説明
上から
①周囲温度
②ターゲット温度
③MIN,MAX温度
④釦Aを押したときのターゲット温度(Hold)

*釦Bを押すとリスタートし、データをクリア出来ます。


S__43614232


S__43614231


mlx90615


■使用部品
①M5StickC
②MLX90615センサー(アマゾン)
③ピンヘッダ、ピンソケット(手持ちの部品)


■ライブラリは、下記のものを使いましたが、そのままではエラーが発生しましたので
ヘッダーファイルを編集しました。

MLX90615:Melexis MLX90615赤外線温度センサー用の最小限のArduinoライブラリ

下記の三つのファイルを同じフォルダに保存してコンパイルしました。
mlx90615.ino
mlx90615.h
mlx90615.cpp

■スケッチ

//mlx90615.ino

// 2020/03/06 Yoshito Hashiguchi

#include <M5StickC.h>
#include <Wire.h>
#include "mlx90615.h"

MLX90615 mlx;

float maxtemp=0.0;
float mintemp=100.0;
float hold=0.0;
float objtemp=0.0;
float ambitemp=0.0;

void setup() {

  Serial.begin(115200);
  M5.begin();
  M5.Lcd.setRotation(0);
  M5.Lcd.fillScreen(BLACK);

  Wire.begin(0, 26, 400000); //SDA, SCL
  Serial.println("Melexis MLX90615 infra-red temperature sensor");
  Serial.print("Sensor ID number = ");
  Serial.println(mlx.get_id(), HEX);
}

int ct=0;

void loop() {

  M5.update();
  if ( M5.BtnA.wasPressed() ) {
    hold=mlx.get_object_temp();
  }
  if ( M5.BtnB.wasPressed() ) {
    esp_restart();
  }
  ct++;
  if (ct>100) {
    ambitemp=mlx.get_ambient_temp();
    objtemp=mlx.get_object_temp();
    if (mintemp>objtemp) mintemp=objtemp;
    if (maxtemp<objtemp) maxtemp=objtemp;
    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.setCursor(0,0);
    M5.Lcd.setTextSize(1);M5.Lcd.setTextColor(GREEN); 
    M5.Lcd.printf("ambient temp\n");
    M5.Lcd.setTextSize(3);M5.Lcd.setTextColor(WHITE);   
    M5.Lcd.printf("%3.1f\n",ambitemp);
    M5.Lcd.setTextSize(1);M5.Lcd.setTextColor(GREEN); 
    M5.Lcd.printf("\nterget  temp\n");
    M5.Lcd.setTextSize(3);M5.Lcd.setTextColor(WHITE);   
    M5.Lcd.printf("%3.1f\n",objtemp);
    M5.Lcd.setTextSize(1);M5.Lcd.setTextColor(CYAN);  
    M5.Lcd.printf("\nBtnB=Restart\n");
    M5.Lcd.setTextColor(GREEN); 
    M5.Lcd.printf("Battery:%3.1fV\n", M5.Axp.GetBatVoltage());

    M5.Lcd.setTextSize(1);M5.Lcd.setTextColor(GREEN);  
    M5.Lcd.printf("\n min   max\n"); 
    M5.Lcd.setTextSize(1);M5.Lcd.setTextColor(WHITE);   
    M5.Lcd.printf(" %3.1f  %3.1f\n",mintemp,maxtemp);
    
    M5.Lcd.setTextSize(1);M5.Lcd.setTextColor(CYAN);   
    M5.Lcd.printf("\nBtnA = hold\n");
    M5.Lcd.setTextSize(3);M5.Lcd.setTextColor(WHITE);     
    M5.Lcd.printf("%3.1f\n",hold);

 
    ct=0;
  }
  delay(10);
}

■ヘッダーファイル

//mlx90615.h

#ifndef __MLX90615_H__
#define __MLX90615_H__

#include "Wire.h"

// default MLX90615 I2C address
#define MLX90615_I2C_ADDR 0x5B

// ROM - ID number
#define MLX90615_REG_ID_LOW 0x1E
#define MLX90615_REG_ID_HIGH 0x1F
// RAM - ambient temperature register
#define MLX90615_REG_TEMP_AMBIENT 0x26
// RAM - object temperature register 
#define MLX90615_REG_TEMP_OBJECT 0x27

class MLX90615 {
 public:
  MLX90615(uint8_t i2c_addr = MLX90615_I2C_ADDR);
  void begin();
  uint32_t get_id();
  float get_object_temp();
  float get_ambient_temp();

 private:
  uint8_t i2c_addr_;
  uint16_t read_word16(uint8_t reg);
};
#endif // __MLX90615_H__

■C++ソースファイル

//mlx90615.cpp

#include "mlx90615.h"

MLX90615::MLX90615(uint8_t i2c_addr) {
  i2c_addr_ = i2c_addr;
}

void MLX90615::begin() {
  Wire.begin();
}

uint32_t MLX90615::get_id() {
uint32_t id;
id = read_word16(MLX90615_REG_ID_LOW);
id |= (uint32_t)read_word16(MLX90615_REG_ID_HIGH) << 16;
return id;
}

float MLX90615::get_ambient_temp() {
  float temp;
  temp = read_word16(MLX90615_REG_TEMP_AMBIENT) * 0.02 - 273.15;
  return temp;
}

float MLX90615::get_object_temp() {
  float temp;
  temp = read_word16(MLX90615_REG_TEMP_OBJECT) * 0.02 - 273.15;
  return temp;
}

uint16_t MLX90615::read_word16(uint8_t reg) {
  uint16_t data;
  Wire.beginTransmission(i2c_addr_);
  Wire.write(reg);
  Wire.endTransmission(false);
  Wire.requestFrom(i2c_addr_, (uint8_t)3);
  data = Wire.read();       // read low byte
  data |= Wire.read() << 8; // read high byte
  Wire.read(); // read and discard PEC (packet error code)
  return data;
}






ブログトップへ

・M5StickC FM90 BD6211 バッテリー を使って倒立振子を作ってみました。

■最初M5StickCのバッテリーだけで実験していたのですが、直ぐに切れてしまい
 面倒だったので、バッテリーを積んでみました。









br-1


br-2


■使用部品
①M5StickC
②ギヤードモーター FM90(秋月)
③タイヤ FS90R対応用(秋月)
④フルブリッジドライバ 7V BD6211F-D2(秋月)
⑤SOP8P DIP変換基板(秋月)
⑥バッテリー3.7V 1600mAh(中古モバイルバッテリー部品取り)
 ・バッテリーは、HAT端子に接続
⑦3Dプリンタ作成ケース
⑧その他配線部品等


参考は、下記URL


この中のパラーメータ変更
//PIDパラメータ調整
#define OFFSET 86.0  //91.5=>86.0 // 重心 後方-←90°→+前方
#define COEF_D 55.0 //50  ->55   // Differential

  //キャリブレーション
  calibration();
  base_angle-=1.2; //追加調整
  offsetX+=0.6;          //追加調整


ブログトップへ

・M5StickC 搭載 BeetleC に近接センサ「APDS9930」を取付し、
 PS3のコントローラで遊んでみました。
 まだまだ、スピードが出すぎて、コントロールは難しいです。






APDS9930


◆下記ブログ内リンクを参照
  ・ESP32 (M5StickC) で PS3 の コントローラ を使う



ブログトップへ

・M5StickC 搭載 web 操縦 リモコンカーを作ってみました。

前方衝突防止にAPDS9930近接センサーを搭載しました。
約10cmに壁があると停止又はバックするようにしました。
動画は、デモモードで自動で動いています。




wificar2




wificar3



ブログトップへ

・M5StickC を使って WiFi 操縦 ミニカーを作ってみました。

S__41738280

S__41738281


前面に近接センサーを付け、追突を防止しようと考えました。
そのため、前後で i2c を 2チャンネル 使う方がスマートにできそうです。

最初は、「M5StickC非公式日本語リファレンス」を参照して
下記のスケッチでテストしましたが、ダメでした。
..

M5.begin();
Wire.begin(32, 33); //SDA,SCL
Wire1.begin(0, 26); //SDA,SCL
...

色々テストしていて、理由は、分かりませんが、
一応両方動くようになりました。

Wire1.begin(SDA,SCL)は、使わないで
1.setup()の初期化の時に、それぞれWire.begin(32,33)/(0,26)を設定
2.loop()の中では、近接センサを呼び出す前に都度Wire.begin(32,33);設定
3.終わったらWire.begin(0,26);を再設定する
void setup() {
.......
M5.begin();
Wire.begin(32, 33); //SDA,SCL
// Initialize APDS-9930 (configure I2C and initial values)
if ( apds.init() ) {
Serial.println(F("APDS-9930 initialization complete"));
} else {
Serial.println(F("Something went wrong during APDS-9930 init!"));
}
Wire.begin(0, 26); //SDA,SCL
Wire.setClock(50000);
drvMotorL(0);drvMotorR(0); // STOP
.......
}
void loop(){
.....
Wire.begin(32, 33); //SDA,SCL
if ( !apds.readProximity(proximity_data) ) {
Serial.println("Error reading proximity value");
} else {
Serial.print("Proximity: ");
Serial.println(proximity_data);
}
if (proximity_data>500) {
x=0;y=0;
}
Wire.begin(0, 26); //SDA,SCL
.....
}




ブログトップへ



以上の内容はhttps://gijin77.blog.jp/archives/cat_428510.htmlより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14