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


◆以前このボードを解析し、LCDの表示方法等が分かりましたので、気象ステーション
 にしてみました。
 c3_tenki_2

 解析内容等については、下記ブログ内記事を参照して下さい。
  ・doit-ai-02-kit-lcd を解析し「xiaozhi V1.8.2」を入れてみた

1.今回の気象ステーションは、以前下記ブログ内の記事の移植です。
  *天気予報のAPI取得等下記を参照して下さい。
  ・ESP32 で 天気予報/温湿度 などを ビデオ 出力してみた(その2)

2.スケッチについて
  (保障無しの自己責任で)  c3_tenkiv2.zip

3.動作画面
 ①天気表示が文字で詳しく表示(10秒毎に①と②を交互に表示)
 c3_tenki_1
 
 ②天気表示が図形表示と温度を表示
 c3_tenki_2
 
 ➂おまけとしてストップウォッチ機能を作ってみました。
  *電源投入時「VOL+(上側)」釦を押して「電源(中央)」釦を押します。
  *その後「VOL-(下側)」釦を押しスタートします。
  *「VOL+(上側)」釦を押すとリセットします。
  c3_tenki_3

以上


ブログトップへ

◆JC1060P470 (ESP32P4) ボードに「xiaozhi-ベトナム版 v2.0.5.06」を入れてみました。
 ベトナム版は、
 ①待機中に時刻、天気予報を表示出来ます。
 ②音楽再生時にスペクトラムレベルを表示出来ます。
 ➂SDカード内の音楽とビデオの再生が出来ます。
 ソースは、下記でダウンロードします。
 TienHuyIoT/xiaozhi-esp32_vietnam

 ④xiaozhi-vnについては、ブログ内下記記事も参照してみて下さい。
 ・ES3C28P HU-086 (ESP32S3) に xiaozhi ベトナム 版をを入れてみた

 ⑤JC1060P470の回路図やGPIO等については、ブログ内下記記事も参照してみて下さい。
 ・JC1060P470C(ESP32P4 ESP32C6 搭載) を使ってみた


 JC1060P470 に対応するにあたり、色々大変でしたが、カメラを除きほぼ全ての機能を
 実装する事が出来ました。
 ①マイク入力&音出し(ES8311対応)
 ②LCD表示(JD9165対応)
 ➂SDカード認識(SDSPIモード)
 ④タッチ操作(GT911対応)
 ⑤バッテリー表示(power_manager)
 ⑥カメラ(未実装)

1.動作写真
 ①待機時(時刻&天気予報表示)
 待機画面
 
 ②SDカード内音楽再生
 SD音楽再生
 
 ➂SDカード内ビデオ(AVI)再生
 SDビデオ再生

 ④会話中
 会話中

2.コードのサイズが大きくなったため、パーティションテーブルを編集しました。
 "\xiaozhi_vn_0322\partitions\v2\16m.csv"の中のota_o,ota_1のサイズを0x500000に
 編集します。

 # ESP-IDF Partition Table
 # Name,   Type, SubType, Offset,  Size, Flags
 nvs,          data, nvs,      0x9000,     0x4000,
 otadata,    data, ota,      0xd000,     0x2000,
 phy_init,    data, phy,     0xf000,      0x1000,
 ota_0,       app,  ota_0,  0x20000,   0x500000,
 ota_1,       app,  ota_1,         ,          0x500000,
 assets,     data, spiffs,          ,          5M

3.ボードは、カスタムボードを追加しないで、JC1060P470
   (ESP32P4 7インチLCDのボード)  に似た「waveshare-p4-wifi6-touch-lcd-7b」を
 編集しました。
 下記にzipファイルとして保存してあります。
 (保障無しの自己責任で)  jc1060p470_xiaozhi_vn.zip

 解凍すると下記のファイルが展開されます。
 zip中身


 ①"\xiaozhi_vn_0322\main\boards\waveshare-p4-wifi6-touch-lcd-7b"内に
 上記zipファイルを解凍しボード内のファイルをコピーします。
 board

 *下記②から⑦のファイルは、解凍後のファイルを上書きするか編集して下さい。
 ②"\xiaozhi_vn_0322\main\features\weather\weather_ui.cc"を
  上書きします。

 ➂"\xiaozhi_vn_0322\main\features\weather\weather_service.ccを
  下記の通り編集します。
 weather_service_cc

 ④"\xiaozhi_vn_0322\main\features\weather\weather_config.hを
  下記の通り編集します。
 weather_config_h

 ⑤"\xiaozhi_vn_0322\main\boards\common\sdspi.cc"を
  下記の通り編集します。
 sdspi_cc

 ⑥"\xiaozhi_vn_0322\main\idf_component.yml"を
  下記の通り編集します。
 idf_component_yml

 ⑦"\xiaozhi_vn_0322\main\Kconfig.projbuild"を
  下記の通り編集します。
 Kconfig_projbuild

4.ビルド&フラッュします。
 >Remove-Item Env:IDF_TARGET *おまじない
 >idf.py fullclean
 >idf.py set-target esp32p4
 >idf.py menuconfig

 Xiaozhi Assistant  --->
   *日本語を選択する
    Default Language (Chinese)  --->       (X) Japanese
   *ボードに合わせて選択する
    Board Type(Espressif ESP-P4-Function-EV-Board)
     ---> Waveshare ESP32-P4-WIFI6-Touch-LCD-7B
   *タッチパネルを有効にする
     (X)Enable Touch Panel
   *SDカードを有効にする。(SDSPIモード)
     (X)Enable SD Card
          SD Card Interface Type (SDMMC Interface)  ---> (X)SPI Interface    
   *待機画面で気象情報を表示するよう[*]チェックする
   (X)Enable Weather Feature (Idle Display for LCD) 
   *ライン形式の表示を選択する
    Select display style (Enable default message style)  ---> (X) Enable WeChat Message Style 

  Component config --->
   *天気予報用フォントを追加する
    LVGL configuration ---> Font usage ---> 
      Enable built-in fonts --->(X) Enable Montserrat 20 にチェックを入れる。
   *PSRAMの設定
    ESP PSRAM  ---> [*] Support for external PSRAM
     PSRAM config  --->
       (4096)Maximum malloc() size, in bytes, to always put in internal memor (4096->0)にする
   *SDカードで長いファイル名を許可
    FAT Filesystem support  ---> (2) Number of volumes
     Long filename support (No long filenames)  ---> (X) Long filename buffer in heap
   *Stackサイズを増やす
    ESP System Settings  --->(6144) Event loop task stack size (6144へ変更)

  ESC ESC (Y) *設定を保存する

 >idf.py build
 *シリアルポートを設定する
 >idf.py -p COM7 flash monitor

 >idf.py merge-bin  *必要に応じて一つのファイルに纏める
***************************************************
ターゲットが切り替わらない時のおまじない
 現在のターゲット確認:
 >echo $Env:IDF_TARGET

 環境変数を手動クリア
 >Remove-Item Env:IDF_TARGET

 >idf.py set-target esp32p4 *ターゲットを指定する
***************************************************
以上

 

今日はここまで

ブログトップへ

◆XH-S3E-AI MINI ESP32-S3-N16R8 ボードに使われていない18ピン半田パッドが、有ったので
 拡張出来るようにGPIOのピンアサインを調べてみました。
 このボードは、マイク、スピーカ付きで「xiaozhi-esp32」が動くコスパの良いボードです。
 ①解析後の確認中(順次GPIOでLチカ)
 xh-s3e-ai拡張全体
 ②購入時の状態
 xh-s3e-ai裏

 ➂コネクタ取り付け後の状態
 xh-s3e-ai拡張
 
1.解析にあたって半田パッドに18ピンのコネクタを半田付けし、リボンケーブルで引き出し
 2.54DIP化基板に接続し、ESP32S3と導通試験をしました。
 これらは、下記で入手しました。
 ①MINI ESP32-S3-N16R8 開発ボード Xiaozhi Ai 音声対話ロボットモジュール
  0.96 インチ OLED スクリーンタイプ C


 ②10個 0.5mmピッチ下クラムシェルソケット FPC FFC フラットケーブルコネクタ 18P
 
 ➂5 個 FPC FFC リボンフレキシブルフラットケーブル 18ピン ピッチ0.5mm Aタイプ 10cm

 ④1 個 FPC/FFC アダプタボード 0.5mm 2.54mmコネクタ複列ストレート針 18ピン

 18pコネクタ他
 ⑤ブレッドボード用変換アダプタ(自作)
 変換アダプタ

2.解析結果(間違っているかも知れませんが)
  1:GND
  2:3.3V
  3:GPIO9
  4:GPIO10
  5:GPIO11
  6:GPIO12
  7:GND
  8:GPIO18
  9:GPIO8
 10:GPIO13
 11:GPIO14
 12:GPIO21
 13:GND
 14:GND
 15:3.3V
 16:3.3V
 17:NC
 18:GND

 xh-s3e-ai_GPIO

3.実際にLCDを繋いでテストしてみました。
 lcd_test
 lcd_testG

//xh_s3e_ai_lcd_test.ino
//V2026/03/12 by JK1VCK
//blog URL:https://gijin77.blog.jp/archives/46838549.html

#include <Arduino_GFX_Library.h>

#define TFT_CS   8
#define TFT_RST  9 
#define TFT_DC   10 
#define TFT_MOSI 11
#define TFT_SCK  12
#define TFT_MISO -1
#define TFT_BL   18 

Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, -1);
Arduino_GFX *gfx = new Arduino_ILI9341(bus, TFT_RST, 0);//

void setup() {
	Serial.begin(115200);
  delay(2000);
  Serial.println("<Program Start>");
  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, HIGH);
  if (!gfx->begin()) {
    Serial.println("gfx->begin NG"); 
  }else{
    Serial.println("gfx->begin OK"); 
  }
}
void loop() {
  gfx->fillScreen(RED);delay(1000);
  gfx->fillScreen(GREEN);delay(1000);
  gfx->fillScreen(BLUE);delay(1000);
}

4.上手く表示出来たので「xiaozhiベトナムバージョン」を入れてみました。
 ①ボードは、「bread-compact-wifi-lcd」を選択
 ②LCDは、「CONFIG_LCD_ILI9341_240X320」を選択
 ➂「confog.h」の下記部分を修正(抜粋)

 #define BUILTIN_LED_GPIO        GPIO_NUM_48
 #define BOOT_BUTTON_GPIO        GPIO_NUM_0
 #define TOUCH_BUTTON_GPIO       GPIO_NUM_NC
 #define VOLUME_UP_BUTTON_GPIO   GPIO_NUM_40
 #define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_39

 #define DISPLAY_SPI_HOST      SPI3_HOST
 #define DISPLAY_BACKLIGHT_PIN GPIO_NUM_18
 #define DISPLAY_MOSI_PIN      GPIO_NUM_11
 #define DISPLAY_MISO_PIN      GPIO_NUM_NC
 #define DISPLAY_CLK_PIN       GPIO_NUM_12
 #define DISPLAY_DC_PIN        GPIO_NUM_10
 #define DISPLAY_RST_PIN       GPIO_NUM_9
 #define DISPLAY_CS_PIN        GPIO_NUM_8


 #ifdef CONFIG_LCD_ILI9341_240X320
 #define LCD_TYPE_ILI9341_SERIAL
 #define DISPLAY_WIDTH   320 //240
 #define DISPLAY_HEIGHT  240 //320
 #define DISPLAY_MIRROR_X false //true
 #define DISPLAY_MIRROR_Y false
 #define DISPLAY_SWAP_XY true //false
 #define DISPLAY_INVERT_COLOR  false //  true
 #define DISPLAY_RGB_ORDER  LCD_RGB_ELEMENT_ORDER_BGR
 #define DISPLAY_OFFSET_X  0
 #define DISPLAY_OFFSET_Y  0
 #define DISPLAY_BACKLIGHT_OUTPUT_INVERT true
 #define DISPLAY_SPI_MODE 0
 #endif 

 ④「compact_wifi_board_lcd.cc」(抜粋)緑色の部分を追記修正
***********************************************************************
 class CompactWifiBoardLCD : public WifiBoard {
 private:
 
    Button boot_button_;
    Button volume_up_button_;
    Button volume_down_button_; 
***********************************************************************
    void InitializeButtons() {
        boot_button_.OnMultipleClick([this]() {
            ResetWifiConfiguration();
        }, 5);

        boot_button_.OnClick([this]() {
            auto& app = Application::GetInstance();
            if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) {
                ResetWifiConfiguration();
            }
            app.ToggleChatState();
        });
        volume_up_button_.OnClick([this]() {
            auto codec = GetAudioCodec();
            auto volume = codec->output_volume() + 10;
            if (volume > 100) {
                volume = 100;
            }
            codec->SetOutputVolume(volume);
            GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume));
        });

        volume_up_button_.OnLongPress([this]() {
            GetAudioCodec()->SetOutputVolume(100);
            GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME);
        });

        volume_down_button_.OnClick([this]() {
            auto codec = GetAudioCodec();
            auto volume = codec->output_volume() - 10;
            if (volume < 0) {
                volume = 0;
            }
            codec->SetOutputVolume(volume);
            GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume));
        });

        volume_down_button_.OnLongPress([this]() {
            GetAudioCodec()->SetOutputVolume(0);
            GetDisplay()->ShowNotification(Lang::Strings::MUTED);
        });
    }
 
*********************************************************************** 
 public:
    CompactWifiBoardLCD() :
        boot_button_(BOOT_BUTTON_GPIO),
        volume_up_button_(VOLUME_UP_BUTTON_GPIO),
        volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) {
        InitializeSpi(); 
*********************************************************************** 

 ⑤待機画面
 xiaozhi_vn_xh-s3e_1

 ⑥会話画面
 xiaozhi_vn_xh-s3e_2

 ⑦ラジオ再生画面(スペクトラム表示)
 xiaozhi_vn_xh-s3e_3

以上

ブログトップへ

◆ESP32-S3-WROOM-1-N16R8 (TELEC付 201-220052)と三種のESP32-S3DIP化ボードを
 入手したので載せてみました。
 ◆完成させてLチカしてみました。
 esp32s3_03


 ◆ESP32s3以外はんだ付け後の写真
 *老眼には、1005は、うまく出来ず1608チップを付けました。
  それでも、かなりきつかったです。
 esp32s3_01

 macsbug_ESP32S3_v2_1

1.ESP32S3の入手先
  ESP32-S3-WROOM-1-N16R8 TELEC (201-220052) 付き ESP32-S3-WROOM-1 16MB
  2.4GHz Wi-Fi および BLE 5 PCB アンテナ ワイヤレス モジュール


 esp32s3n16r8_telec
 esp32s3n16r8_telec10

3.ESP32-S3のDIP化ボードの入手先
 ①DIP化ボード1
 下記サイトで、ガーバーデータを公開されていたので試しにJLCPCBに発注してみました。
  macsbug ESP32 S3 v2.1

 ②➂DIP化ボード2,3(メルカリで購入)
  ESP32-S3 DIP化基盤 Ver1.1/ESP32-S3 DIP化基盤 Mini Ver1.0

 esp32s3開発ボード

4.上記以外のESP32-S3のDIP化関連のガーバーデータを公開しているサイトです。
 ①ESP32-S3のDIP化~KiCadで4層基板を製作
 esp32s3_G1

 ②ESP32-S3 DIP化基盤作ってみた(配布有)
 esp32s3_G2

 ➂ESP32-S3-WROOM-1-N16R8のDIP化基板を作成してみた。
 esp32s3_G3

 ④ESP32-S3開発ボードを作る
 esp32s3_G4

今日は、ここまで


ブログトップへ

◆SamewayAi販売の「AI音声ロボットチャットボット」を購入しましたが、FWが古いため
 バージョンアップをする為に、販売店へ回路図等情報開示を依頼しましたが、サポート
 出来ないとの事でした。
 GPIOピン割り当てが、分からないため基板を解析してみました。
 すべてのピンは、解析出来ていませんが、LCD等xiaozhiをコンパイル出来るところまで
 解析できました。
 doit-ai

1.まず分解して基板を撮影して、主要なICチップの型番、仕様を調べました。
 *参考URL
 ①ESP32-C3 Series Datasheet Version 2.1
 ②オーディオアンプ LTK8002D
 ➂バッテリ関連 TP4056
 ④オーディオコーディック vb6824(?)

 esp32c3

2.GPIOピン割り当て
 ①esp32c3
 GPIO0 LCD_DC   out
      1 LCD_SDA(MOSI)
      2 LCD_RST  out
      3 LCD_SCK
      4 ?        in/out
      5 LCD_BL
      6 POWER_SW in xiaozhi=BOOT BUTTON
      7 ?        in
      8 VOL+     in xiaozhi=VOL+
      9 VOL-     in xiaozhi=VOL- (BAT_IN / BOOT9)
     10 ?        in
     11 LCD_CS
     18 D-          Type-C コネクタ
     19 D+          Type-C コネクタ
     20 U0RXD       xiaozhi=CODEC_RX_GPIO
     21 U0TXD       xiaozhi=CODEC_TX_GPIO
 ②LCDとの接続
  ESP32C3  LCD
      1 LED_A
   GPIO5  2 LED_K
    1  3 MOSI
    0  4 DC
    3  5 SCK       
    2  6 RST
   11  7 CS
   NC  8 (?MISO)
      9 VCC
      10 VCC
      11 VCC
      12 GND
      13 GND
      14 VCC
      15 VCC 


3.参考回路図
 *あくまでも参考回路図で間違っている所もあるかと思います。
 DOIT-AI参考回路図

4.xiaozhiのビルド
 ①ソースファイルのダウンロード先
 SmartArduino/DOIT_AI

 ②doit-ai-02-kit-lcdボード情報「confi.h」の内容
#ifndef _BOARD_CONFIG_H_
#define _BOARD_CONFIG_H_

#include <driver/gpio.h>

#define BOOT_BUTTON_GPIO        GPIO_NUM_6
#define VOLUME_UP_BUTTON_GPIO   GPIO_NUM_8
#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_9

#define CODEC_TX_GPIO           GPIO_NUM_21 //(U0TXD)
#define CODEC_RX_GPIO           GPIO_NUM_20 //(U0RXD)

#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_5
#define DISPLAY_MOSI_PIN      GPIO_NUM_1
#define DISPLAY_CLK_PIN       GPIO_NUM_3
#define DISPLAY_DC_PIN        GPIO_NUM_0
#define DISPLAY_RST_PIN       GPIO_NUM_2
#define DISPLAY_CS_PIN        GPIO_NUM_11

#define DISPLAY_WIDTH   320  // 幅と高さを入れ替え
#define DISPLAY_HEIGHT  240  // 幅と高さを入れ替え
#define DISPLAY_MIRROR_X true //falseからtrueに変更
#define DISPLAY_MIRROR_Y true //falseからtrueに変更
#define DISPLAY_SWAP_XY  true //falseからtrueに変更
#define DISPLAY_INVERT_COLOR    true
#define DISPLAY_RGB_ORDER  LCD_RGB_ELEMENT_ORDER_RGB
#define DISPLAY_OFFSET_X  0
#define DISPLAY_OFFSET_Y  0
#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false

#endif // _BOARD_CONFIG_H_
 
 ➂/doit-ai ビルド手順
 ターゲットが切り替わらない時のおまじない
 現在のターゲット確認:
 echo $Env:IDF_TARGET

 環境変数を手動クリア
 Remove-Item Env:IDF_TARGET

 idf.py set-target esp32c3
 **********************************

 idf.py fullclean

 idf.py set-target esp32c3

 idf.py menuconfig

 Xiaozhi Assistant  --->
    Default Language (Chinese)  --->       (X) Japanese
    Board Type (Bread Compact WiFi (面包板))  ---> (X) Bread Compact WiFi + LCD (面包板) 
    Select display style (Enable default message style)  ---> (X) Enable WeChat Message Style 
    Wake Word Implementation Type (Wakenet model with AFE)  --->    ???????
 ESC ESC (Y)

 idf.py build

 *シリアルポートを設定する

 idf.py -p COM10 flash monitor

 idf.py merge-bin  //一つのファイルに纏める

◆追記(2026/04/14)
 他の使い方として気象ステーションにしてみました。
 下記ブログ内記事も参照してみて下さい。
 ・doit-ai-02-kit-lcd を気象ステーションにしてみた

以上 今日はここまで
 

ブログトップへ

◆以前HU-086ボードでマルチアプリセレクターを作成したものを、ES3C28Pボードで
 タッチ操作でするものを作ってみました。
 また、アプリも四つほど入れ込んでみました。
 es3c28p_main
 
 マルチアプリセレクターの基本は、下記ブログ内記事を参照して下さい。
  ・ESP32S3 ArduinoIDE で簡易的なランチャーを作ってみた

 (1)現在、下記の四つのアプリを選択して実行できます。
  ⓪main:メインのアプリセレクター
  ①app1:15puzzle(game)
  ②app2:パタパタ時計表示&RSSニュース音声出力
  ➂app3:rdiko&インターネットラジオ
  ④app4:xiaozhi-rsp32 ベトナムバージョン
  フラシュメモリを調整することでもう少し増やせると思います。
 
 (2)現在各アプリに下記のサイズを指定しています。
 また下記パーティションアドレスに応じてflash_download_tool_3.9.7で書き込みます。

  partitions.csvの内容
  # Name,   Type, SubType,  Offset,   Size,     Flags
  nvs,      data, nvs,      0x9000,   0x5000,
  otadata,  data, ota,      0xe000,   0x2000,
  factory,  app,  factory,  0x10000,  1M, <-⓪main
  app1,     app,  ota_0,    0x110000, 2M, <-①app1
  app2,     app,  ota_1,    0x310000, 3M, <-②app2
  app3,     app,  ota_2,    0x610000, 3M, <-➂app3
  app4,     app,  ota_3,    0x910000, 4M, <-④app4
  storage,  data, spiffs,   0xD10000, 2M,
 
0.main:メインのアプリセレクターについて
 ①アプリ選択画面
 es3c28p_main

 ②IDE設定
  ・esp32s3 Dev
  ・USBCDCOnBoot="Enabled"
  ・Flash Size=16MB
  ・Partition Scheme: "Custom"
  ・PSRAM="Disabled" 

 ➂es3c28p_mainフォルダに下記の2つのファイルを作成します。
  (1)es3c28p_main.ino スケッチ(保障無しの自己責任で)
//es3c28p_main.ino
//2026/03/01 By JK1VCK マルチアプリセレクター
//blog URL:https://gijin77.blog.jp/archives/46787383.html

#include <esp_ota_ops.h>
#include <esp_partition.h> // パーティション操作に必要
#include "FT6336U.h"
#include <Arduino_GFX_Library.h>

//IDE設定
//・esp32s3 Dev
//・USBCDCOnBoot="Enabled"
//・Flash Size=16MB
//・Partition Scheme: "Custom"
//・PSRAM="Disabled"

String board ="Hello ES3C28P ESP32S3";
#define TFT_DC    46
#define TFT_RST   -1
#define TFT_CS    10
#define TFT_MOSI  11 //SDA
#define TFT_SCK   12 //SCL
#define TFT_MISO  13
#define GFX_BL    45

Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
Arduino_GFX *gfx = new Arduino_ILI9341(bus, TFT_RST, 0,true); // 240x320 2.8 LCD

#define I2S_MCLK       4
#define I2S_BCLK       5
#define I2S_DIN        6 //mic in
#define I2S_LRC        7
#define I2S_DOUT       8 //sp out
#define I2C_SCL       15
#define I2C_SDA       16
#define PA_ENABLE      1
#define TOUCH_INT     17
#define TOUCH_RST     18

FT6336U ft6336u(I2C_SDA, I2C_SCL, TOUCH_RST, TOUCH_INT); 
FT6336U_TouchPointType tp; 

// グローバル変数
uint16_t tX, tY;
int sel=0, old_sel=-1;
bool selok=false;

#define BW 240
#define BH 32
#define SY 48
#define SH 40

int c[5][4]={    // Button(220x36) display and touch area
// タッチ位置(x,y)からTb(n)でボタンのon/offやLCD上の操作ができます。
// Button area    
// 0, 1,  2,  3,    Tb(0-4)
// x,  y,  w,    h,        1234567890123 
{ 36, SY,        BW  , BH}, // 0 App1:15puzzle 
{ 36, SY+SH,     BW  , BH}, // 1 App2:RSS News
{ 36, SY+SH*2,   BW  , BH}, // 2 App3:radiko
{ 36, SY+SH*3,   BW  , BH}, // 3 App4:xiaozhi
{ 96, SY+SH*4,  115  , BH}, // 4 SELECT
};

const char *btn[] ={"App1:15puzzle","App2:RSS News","App3:radiko","App4:xiaozhi","SELECT"};

//アプリセレクト
void bootApp(int index) {
  esp_partition_subtype_t subtype = (esp_partition_subtype_t)(ESP_PARTITION_SUBTYPE_APP_OTA_0 + index);
  // 指定したサブタイプのパーティションを探す
  const esp_partition_t* target = esp_partition_find_first(ESP_PARTITION_TYPE_APP, subtype, NULL);
  if (target != NULL) {
    gfx->fillScreen(BLACK);
    gfx->setTextColor(ORANGE);
    gfx->setTextSize(2); 
    gfx->setCursor(50,100);
    gfx->printf("Switching to: %s\n", target->label);    
    Serial.printf("Switching to: %s\n", target->label);
    esp_ota_set_boot_partition(target);
    delay(1000);
    esp_restart();
  } else {
    Serial.println("Error: Partition not found!");
  }
}

void setup() {
  Serial.begin(115200);
  delay(2000);
  const esp_partition_t* running = esp_ota_get_running_partition();
  Serial.printf("現在起動中のパーティション: %s\n", running->label);
  // ===== ディスプレイ初期化 =====
  pinMode(GFX_BL, OUTPUT);
  digitalWrite(GFX_BL, HIGH); //バックライトON
  if (!gfx->begin()) {
    Serial.println("gfx->begin() failed!");
  } else {
    Serial.println("gfx->begin() OK!!");
  }
  gfx->setRotation(3);
  gfx->fillScreen(RED);delay(300);
  gfx->fillScreen(GREEN);delay(300);  
  gfx->fillScreen(BLUE);delay(300);
  gfx->fillScreen(BLACK);
  //タッチパネル初期化
  ft6336u.begin(); 
  Serial.print("FT6336U Firmware Version: "); 
  Serial.println(ft6336u.read_firmware_id());  
  Serial.print("FT6336U Device Mode: "); 
  Serial.println(ft6336u.read_device_mode()); 
  dispmain();
}

void loop() {
int sel=select_app();
  Serial.printf("sel No=%d \n",sel); 
  bootApp(sel);
}

void dispmain(){
  gfx->setTextColor(ORANGE);
  gfx->setTextSize(3); 
  gfx->setCursor(50,5);
  gfx->print("App selector");
  drawbutton();
}

int c_touch(){
  selok=false;  
  if (getTouch(&tX,&tY)) {
     if(Tb(4)) {selok=true;return 99;}
     for (int t=0;t<4;t++) {
      if(Tb(t)) {sel=t;return sel;}
     }
  }
  return -1;
}

int select_app() {
  Serial.println("select_file start");    
  for(;;){
    if (c_touch()==-1) continue;
    Serial.printf("sel No=%d selok=%d \n",sel,selok); 
    if (selok) break;
    drawbutton();
    delay(50);
  }
  return(sel);
}

bool Tb( int p ){ // Touch button : Find button and touch locations
Serial.printf("p=%d tX=%d tX0=%d tX2=%d  tY=%d tY0=%d tY1=%d\n",p,tX,c[p][0],(c[p][0]+c[p][2]),tY,c[p][1],(c[p][1]+c[p][3])); 
  if (tX>c[p][0] && tX<(c[p][0]+c[p][2])    // x1,y1 check
   && tY>c[p][1] && tY<(c[p][1]+c[p][3]))   // x2,y2 check
   {return true;}                           // with position
  return false;                             // without pos
}

void drawbutton() {
  int x_of[]={4,4,4,4,4};
  int y_of=4;
  for (int p=0;p<5;p++) {
    gfx->fillRect(c[p][0],c[p][1],c[p][2],c[p][3], BLACK);
    gfx->drawRoundRect(c[p][0],c[p][1],c[p][2],c[p][3],10, GREEN);
    gfx->setCursor(c[p][0]+x_of[p],c[p][1]+y_of);gfx->setTextSize(3); 
    if (p==sel) gfx->setTextColor(YELLOW);
    else        gfx->setTextColor(CYAN);
    if (p==4) gfx->setTextColor(RED);
    gfx->print(btn[p]);
  }
}
//ft6336u_Touch
bool getTouch(uint16_t* tX,uint16_t* tY) {  
  static bool prevTouched = false;  // 前回のタッチ状態を保持
  bool touched = false;

  int w = gfx->width();
  int h = gfx->height();
  int r = gfx->getRotation();
  int tix, tiy;
  tp = ft6336u.scan(); 
  if (tp.tp[0].status) {
    touched = true;
    // 前回タッチしていなかった → 今回タッチした = 押した瞬間
    if (!prevTouched) {
      switch (r) {
        case 1:  tiy = h - tp.tp[0].x; tix = tp.tp[0].y; break;
        case 2:  tix = w - tp.tp[0].x; tiy = h - tp.tp[0].y; break;
        case 3:  tiy = tp.tp[0].x;     tix = w - tp.tp[0].y; break;
        default: tix = tp.tp[0].x;     tiy = tp.tp[0].y;     break;
      }
      Serial.printf("Touch Down: x=%d y=%d r=%d\n", tix, tiy, r);
      //gfx->fillCircle(tix, tiy, 3, BLUE);lcd_flush();
      *tX = tix;
      *tY = tiy;
      prevTouched = true;   // 状態更新
      return true;          // ★押した瞬間だけ true
    }
  } else {
    touched = false;
  }
  // 離したら状態リセット
  if (!touched) {
    prevTouched = false;
 }
  return false;  // 押しっぱなしや離した後は false
}

   (2)パーティションテーブル partitions.csv
# Name,   Type, SubType,  Offset,   Size,     Flags
nvs,      data, nvs,      0x9000,   0x5000,
otadata,  data, ota,      0xe000,   0x2000,
factory,  app,  factory,  0x10000, 1M,
app1,     app,  ota_0,    0x110000, 2M,
app2,     app,  ota_1,    0x310000, 3M,
app3,     app,  ota_2,    0x610000, 3M,
app4,     app,  ota_3,    0x910000, 4M,
storage,  data, spiffs,   0xD10000, 2M,

1.app1:15puzzle(game)について
 ◆下記ブログ内記事を参照して下さい。
 ・ES3C28P ESP32S3 で懐かしの15パズル「15puzzle」を作ってみた
 es3c28p_15puzzle

2.app2:パタパタ時計表示&RSSニュース音声出力について
 ◆下記ブログ内記事を参照して下さい。
 ・ES3C28P HU-086 (ESP32S3) でパタパタ時計 RSSニュースを音声合成で出力してみた
 es3c28p_rssnews

3.app3:rdiko&インターネットラジオについて
 ◆下記ブログ内記事を参照して下さい。
 ・ES3C28P HU-086 (ESP32S3) でradiko/internet-radio を作ってみた

 es3c28p_radiko
 es3c28p_iradio

4.app4:xiaozhi-rsp32 ベトナムバージョンについて
 ◆下記ブログ内記事を参照して下さい。
 ・ES3C28P HU-086 (ESP32S3) に xiaozhi ベトナム 版をを入れてみた
 es3c28p_xiaozhi
 
5.実際の切り替えデモ
 

以上

ブログトップへ

◆HU-086 (ESP32S3) ボードでファミコンのエミュレータ「ESP32-S3_Uno-nofrendo」を
 動かしてみました。
 各種ボタンも付いていてスムースに動かすことが出来ました。
 またマルチアプリ対応にしました。
 hu-086_game
 
1.下準備として下記ブログ内記事を参照して「ESP32-S3_Uno-nofrendo」を
  インストールして下さい。
  ・ESP32S3ボードでファミコンのエミュレータ「ESP32-S3_Uno-nofrendo」を動かしてみた

2.開発環境 2026/02/26時点(最新だとエラーが出るかもです。)
  ①Windows11 X64 Pro 25H2 
  ②Arduino IDE 2.3.7(最新V2.3.8)
  ➂ESP32ボードバージョンV3.3.5(最新V3.3.6)
  ④Arduino_GFX_Library(GFX Library for Arduino) V1.6.2(最新V1.6.5)
  ⑤IDE設定(マルチアプリ対応)
   ・esp32s3 Dev
   ・USBCDCOnBoot="Disabled"
   ・Flash Size=4MB
   ・Partition Scheme: "Huge APP(3MB)"
   ・psram="Disabled"

2.スケッチについて
 ①フォルダをまとめてzipファイルにして有ります。
 フォルダ内容
 hu-086_nes


 (保障無しの自己責任で)  HU-086_nofrendo.zip


以上 今日は、ここまで


ブログトップへ

◆HU-086 ESP32S3ボードの解析がほぼ終わったので、購入時のアプリに似せた
 マルチアプリセレクターを作成してアプリも入れてみました。
 hu-086_app4


 マルチアプリセレクターの基本は、下記ブログ内記事を参照して下さい。
  ・ESP32S3 ArduinoIDE で簡易的なランチャーを作ってみた
 
 (1)現在、下記の四つのアプリを選択して実行できます。
  ⓪main:メインのアプリセレクター
  ①app1:NESエミュレータ(game)
  ②app2:パタパタ時計表示&RSSニュース音声出力
  ➂app3:rdiko&インターネットラジオ
  ④app4:xiaozhi-rsp32 ベトナムバージョン
  フラシュメモリを調整することでもう少し増やせると思います。
 
 (2)現在各アプリに下記のサイズを指定しています。
 また下記パーティションアドレスに応じてflash_download_tool_3.9.7で書き込みます。

  partitions.csvの内容
  # Name,   Type, SubType,  Offset,   Size,     Flags
  nvs,      data, nvs,      0x9000,   0x5000,
  otadata,  data, ota,      0xe000,   0x2000,
  factory,  app,  factory,  0x10000,  1M, <-⓪main
  app1,     app,  ota_0,    0x110000, 2M, <-①app1
  app2,     app,  ota_1,    0x310000, 3M, <-②app2
  app3,     app,  ota_2,    0x610000, 3M, <-➂app3
  app4,     app,  ota_3,    0x910000, 4M, <-④app4
  storage,  data, spiffs,   0xD10000, 2M,
 
0.main:メインのアプリセレクターについて
 ①アプリ選択画面
 hu-086_main

 ②main.ino スケッチ(保障無しの自己責任で)
//main.ino
//2026/02/102 By JK1VCK マルチアプリセレクター
//blog URL:https://gijin77.blog.jp/archives/46690906.html

#include <esp_ota_ops.h>
#include <esp_partition.h> // パーティション操作に必要
#include <Arduino_GFX_Library.h>

String board ="Hello HU-086 ESP32S3";
#define LCD_MOSI 39
#define LCD_CS   -1
#define LCD_DC   38
#define LCD_SCK  40
#define LCD_RST  41
#define GFX_BL   42 

Arduino_DataBus *bus = new Arduino_ESP32SPI(LCD_DC, LCD_CS, LCD_SCK, LCD_MOSI, -1);
Arduino_ST7789 *gfx = new Arduino_ST7789(bus, LCD_RST, 0);//

//操作ボタンピン設定
int sw_pins[] = {18,8,46,14,45,48,47,21};
char sw_name[][6] ={"UP","LEFT","RIGHT","DOWN","B","STA","A","SEL"};

void bootApp(int index) {
  esp_partition_subtype_t subtype = (esp_partition_subtype_t)(ESP_PARTITION_SUBTYPE_APP_OTA_0 + index);
  // 指定したサブタイプのパーティションを探す
  const esp_partition_t* target = esp_partition_find_first(ESP_PARTITION_TYPE_APP, subtype, NULL);
  if (target != NULL) {
    gfx->fillScreen(BLACK);
    gfx->setTextColor(ORANGE);
    gfx->setTextSize(2); 
    gfx->setCursor(50,100);
    gfx->printf("Switching to: %s\n", target->label);    
    Serial.printf("Switching to: %s\n", target->label);
    esp_ota_set_boot_partition(target);
    delay(1000);
    esp_restart();
  } else {
    Serial.println("Error: Partition not found!");
  }
}

void setup() {
    Serial.begin(115200);
    delay(2000);
    const esp_partition_t* running = esp_ota_get_running_partition();

  // ===== ディスプレイ初期化 =====
  if (!gfx->begin()) {
    Serial.println("gfx->begin() failed!");
  } else {
    Serial.println("gfx->begin() OK!!");
  }
  pinMode(GFX_BL, OUTPUT);
  digitalWrite(GFX_BL, LOW);
  gfx->invertDisplay(true);   // ← これを追加
  gfx->setRotation(1);
  gfx->fillScreen(RED);delay(300);
  gfx->fillScreen(GREEN);delay(300);  
  gfx->fillScreen(BLUE);delay(300);
  gfx->fillScreen(BLACK);
  gfx->setTextColor(ORANGE);
  gfx->setTextSize(3); 
  gfx->setCursor(50,5);
  gfx->print("App selector");
  gfx->setCursor(50,45);
  gfx->print("   by JK1VCK");
  for (int i = 0; i < 8; i++) {
    pinMode(sw_pins[i], INPUT_PULLUP); //釦入力設定
  }  
  Serial.printf("現在起動中のパーティション: %s\n", running->label);
  dispmain();
  Serial.println("\n--- MAIN MENU ---");
  Serial.println("Send '1', '2', 3 , or ' 4' to switch apps.");
  dispmain();
}

void loop() {
int sel=select_app();
  bootApp(sel);
}

String app[4]={"App1:game","App2:RSS News","App3:radiko","App4:xiaozhi"};
int sel=0, old_sel=-1;

void dispmain(){
  gfx->setTextSize(3);   
  for(int i=0;i<4;i++){
    gfx->setCursor(40,90+i*40);
    if (i==sel) gfx->setTextColor(YELLOW);
    else        gfx->setTextColor(CYAN);
    gfx->print(app[i]);
  }
}

int button_input(){
int sw;
  for (int i = 0; i < 8; i++) {
    sw=digitalRead(sw_pins[i]);
    if (sw==0) {
      delay(200);
      return i+1;
    }
  }
  return 0;
}

int select_app() {
  int i,key;
  Serial.println("select_file start");    
  for(;;){
    key = button_input();
    if (key==0) continue;
    if (key==8) break; //sel
    if (key==1) sel--; //up
    if (key==4) sel++; //down
    if (sel<0)  sel=3;
    if (sel>=4) sel=0;
    Serial.printf("key=%d sel=%d old=%d\n",key,sel,old_sel);    
    if (sel!=old_sel){
      for(i=0;i<4;i++){
        gfx->setCursor(40,90+i*40);
        if (i==sel) gfx->setTextColor(YELLOW);
        else        gfx->setTextColor(CYAN);
        gfx->print(app[i]);
      }
      old_sel=sel;
    }
    delay(50);
  }
  return(sel);
}

 ➂パーティションテーブル partitions.csv

 # Name,   Type, SubType,  Offset,   Size,     Flags
 nvs,      data, nvs,      0x9000,   0x5000,
 otadata,  data, ota,      0xe000,   0x2000,
 factory,  app,  factory,  0x10000, 1M,
 app1,     app,  ota_0,    0x110000, 2M,
 app2,     app,  ota_1,    0x310000, 3M,
 app3,     app,  ota_2,    0x610000, 3M,
 app4,     app,  ota_3,    0x910000, 4M,
 storage,  data, spiffs,   0xD10000, 2M,



1.app1:NESエミュレータ(game)について
 ◆下記ブログ内記事を参照して下さい。
 ・HU-086 (ESP32S3) でファミコンのエミュレータ「ESP32-S3_Uno-nofrendo」を
  動かしてみた


 *ゲーム画面 
 hu-086_game

2.app2:パタパタ時計表示&RSSニュース音声出力について
 ◆下記ブログ内記事を参照して下さい。
 ・ES3C28P HU-086 (ESP32S3) でパタパタ時計 RSSニュースを音声合成で出力してみた

 *RSSニュース読み上げ画面 
 hu-086_rssnews

3.app3:rdiko&インターネットラジオについて
 ◆下記ブログ内記事を参照して下さい。
 ・ES3C28P HU-086 (ESP32S3) でradiko/internet-radio を作ってみた

 *radiko再生画面
 hu-086_radiko

 *インターネットラジオ再生画面
 hu-086_i_radio

4.app4:xiaozhi-rsp32 ベトナムバージョンについて
 ◆下記ブログ内記事を参照して下さい。
 ・ES3C28P HU-086 (ESP32S3) に xiaozhi ベトナム 版をを入れてみた

 *会話中画面
 hu-086_xiaozhi_vn_1

 *音楽再生画面
 hu-086_xiaozhi_vn_2

 *待機画面
 hu-086_xiaozhi_vn_3


今日は、ここまで(順次追加記載していきます)


ブログトップへ

◆ES3C28P HU-086 (ESP32S3) の二つのボードでパタパタ時計を表示しつつ RSSニュースを
 音声合成で出力してみました。
 以前やっていたものの音声出力部分のライブラリを「ESP32-audioI2S-master」へ替えて
 みました。
 スケッチは、ほとんどの部分を共通化して、SW入力/タッチ入力と音出力部分をボードに
 合わせて切り替えています。
 rss_news

1.開発環境 2026/02/26時点(最新だとエラーが出るかもです。)
  ①Windows11 X64 Pro 25H2 
  ②Arduino IDE 2.3.7
  ➂ESP32ボードバージョンV3.3.5(最新V3.3.6)
  ④Arduino_GFX_Library(GFX Library for Arduino) V1.6.2(最新V1.6.5)
  ⑤ESP32-audioI2S-maste V3.4.2(最新V3.4.4)
  ⑥FT6336U_CTP_Controller
  ⑦IDE設定
   ・esp32s3 Dev
   ・USBCDCOnBoot=> es3c28p="Enabled" hu-086=="Disabled"
   ・Flash Size=4MB
   ・Partition Scheme: "Huge APP(3MB)"
   ・psram=OPIPSRAM
  ⑧オーディオIC「ES8311」のドライバは、
   「libraries\ESP32-audioI2S-master\examples\ES8311\es8311.h」
   「libraries\ESP32-audioI2S-master\examples\ES8311\es8311.cpp」
   の2つを「es3c28p_RSSNews_V9_M.ino」と同じフォルダへコピペします。

2.スケッチについて

 ①ES3C28P/HU-086ボードの切り替えは、「es3c28p_RSSNews_V9_M.ino」内、
  下記22/23行の
  #define  ES3C28Pのコメントを取ることで選択出来ます。
 RSSnews

 ②フォルダをまとめてzipファイルにして有ります。
 フォルダ内容
 es3c28p_RSSNews_V9_M

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




 今日は、ここまで



ブログトップへ

◆ES3C28P HU-086 (ESP32S3) の二つのボードでradiko/internet-radioを作ってみました。
 以前やっていたものの音声出力部分のライブラリを「ESP32-audioI2S-master」へ替えて
 みました。
 radiko

 i_radio

1.開発環境 2026/02/26時点(最新だとエラーが出るかもです。)
  ①Windows11 X64 Pro 25H2 
  ②Arduino IDE 2.3.7(最新V3.3.8)
  ➂ESP32ボードバージョンV3.3.5(最新V3.3.6)
  ④Arduino_GFX_Library(GFX Library for Arduino) V1.6.2(最新V1.6.5)
  ⑤ESP32-audioI2S-maste V3.4.2(最新V3.4.4)
  ⑥FT6336U_CTP_Controller
  ⑦IDE設定(マルチアプリ対応)
   ・esp32s3 Dev
   ・USBCDCOnBoot=> es3c28p="Enabled" hu-086=="Disabled"
   ・Flash Size=4MB
   ・Partition Scheme: "Huge APP(3MB)"
   ・psram=OPIPSRAM
  ⑧オーディオIC「ES8311」のドライバは、
   「libraries\ESP32-audioI2S-master\examples\ES8311\es8311.h」
   「libraries\ESP32-audioI2S-master\examples\ES8311\es8311.cpp」
   の2つを「es3c28p_radiko_M.ino」と同じフォルダへコピペします。

2.スケッチについて
 ①radiko/FFTレベルメータ表示の為に、「ESP32-audioI2S-maste」を改修する必要があります。
  下記ブログ内記事を参照して構築して下さい。
  ・ES3C28P JC3248W535 で「radiko」を聞きながらサウンドレベルメータを表示してみた

 ②ES3C28P/HU-086ボードの切り替えは、「es3c28p_radiko_M.ino」内、下記27/28行の
  #define  ES3C28Pのコメントを取ることで選択出来ます。
 es3c28p_hu-086

 ➂マルチアプリ対応の追記(リスタート後、MAIN Appを起動)
 Multi_app

 ④フォルダをまとめてzipファイルにして有ります。
 フォルダ内容
 radiko_m

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

 今日はここまで

ブログトップへ

◆ES3C28P HU-086 (ESP32S3) の二つのボードに機能強化されたxiaozhiベトナム版を入れて
 みました。
 ベトナム版は、
 ①待機中に時刻、天気予報を表示出来ます。
 ②音楽再生時にスペクトラムレベルを表示出来ます。
 ソースは、下記でダウンロードしました。
 TienHuyIoT/xiaozhi-esp32_vietnam
 
 *待機中時刻・気象情報表示します。
 xiaozhi_2

 *ちょっと日本語表示がおかしいです。
 xiaozhi_1

1.ボード選択
 ①ES3C28P xiaozhi-ai-iot-vietnam-es3n28p-lcd-2.8
 ②HU-086  bread-compact-wifi-lcd(gpio等修正)
 *「main\boards\bread-compact-wifi-lcd」の中を下記のファイルと入れ替えて下さい。
 (保障無しの自己責任で)  bread-compact-wifi-lcd.zip

2.ビルド手順

 ターゲットが切り替わらない時のおまじない
 現在のターゲット確認:
 >echo $Env:IDF_TARGET

 環境変数を手動クリア
 >Remove-Item Env:IDF_TARGET

 >idf.py set-target esp32s3 *ターゲットを指定する
 ***************************************************

 >idf.py fullclean

 >idf.py set-target esp32s3

 >idf.py menuconfig

 Xiaozhi Assistant  --->
   *日本語を選択する
    Default Language (Chinese)  --->       (X) Japanese
   *ボードに合わせて選択する
    Board Type (Bread Compact WiFi (面包板))  ---> (X) Bread Compact WiFi + LCD (面包板) 
   *ライン形式の表示を選択する
    Select display style (Enable default message style)  ---> (X) Enable WeChat Message Style 
 *待機画面で気象情報を表示するよう[*]チェックする
   Enable Weather Feature (Idle Display for LCD) 

 ◆必要に応じて「SDカード」「タッチパネル」設定をする

  ESC ESC (Y) *設定を保存する

 >idf.py build

 *シリアルポートを設定する

 >idf.py -p COM10 flash monitor

 >idf.py merge-bin  *必要に応じて一つのファイルに纏める
 
 ◆menuconfig Xiaozhi Assistant 
 Xiaozhi_Assistant

3.マルチアプリ用に「main\main.cc」を修正します。
 ①13,14行を追記
 ②72~77行を追記
 このおまじないで、リセットをかけた時にメインの「factory」から起動するようになります。
 マルチアプリを使う時だけ、必要です。

#include <esp_log.h>
#include <esp_err.h>
#include <nvs.h>
#include <nvs_flash.h>
#include <driver/gpio.h>
#include <esp_event.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

#include "application.h"
#include "system_info.h"

#include <esp_ota_ops.h>  //multi app 
#include <esp_partition.h>

#define TAG "main"

void task_monitor(void *pvParameters)
{
    const int max_tasks = 30;
    TaskStatus_t task_list[max_tasks];
    UBaseType_t task_count;
    uint32_t total_runtime;

    while (1)
    {
        task_count = uxTaskGetSystemState(task_list, max_tasks, &total_runtime);

        ESP_LOGI(TAG, "----- Task Stack Monitor -----");

        for (int i = 0; i < task_count; i++)
        {
            UBaseType_t hw = task_list[i].usStackHighWaterMark;  // đơn vị: words (4 bytes)
#if ( configTASKLIST_INCLUDE_COREID == 1 )
            ESP_LOGI(TAG,
                     "%-16s | Free: %4u bytes | Prio: %2u | Core: %u",
                     task_list[i].pcTaskName,
                     hw,
                     task_list[i].uxCurrentPriority,
                     task_list[i].xCoreID
            );
#else
            ESP_LOGI(TAG,
                     "%-16s | Free: %4u bytes | Prio: %2u",
                     task_list[i].pcTaskName,
                     hw,
                     task_list[i].uxCurrentPriority
            );
#endif
        }

        ESP_LOGI(TAG, "--------------------------------");

        vTaskDelay(pdMS_TO_TICKS(5000));  // 5s
    }
}

extern "C" void app_main(void)
{
    // Initialize the default event loop
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    // Initialize NVS flash for WiFi configuration
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_LOGW(TAG, "Erasing NVS flash to fix corruption");
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
 
    //multi app 
    const esp_partition_t* factory = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
    if (factory != NULL) {
        esp_ota_set_boot_partition(factory);
        //printf("Next boot: Main Menu%d \n",0);
    }

    // Launch the application
    auto& app = Application::GetInstance();
    app.Start();

    // xTaskCreatePinnedToCore(task_monitor, "TaskMonitor", 1024 * 3, NULL, 1, NULL, tskNO_AFFINITY);
}


 ➂マルチアプリについては、下記ブログを参照して下さい。
  ・ESP32S3 ArduinoIDE で簡易的なランチャーを作ってみた
  ・HU-086 ESP32S3ボードでマルチアプリセレクターを作ってみた


今日は、ここまで


ブログトップへ

◆ES3C28P ESP32S3ボードでボケ防止に昔懐かしの15パズルを移植してみました。
 このボードは、タッチパネル、音出力が付いていますので、ハード追加無しで
 作成できます。他のボードにも簡単に移植できると思います。
 参考元のサイトを、下記に示します。先人に感謝です。
 DIY ESP32 15 Puzzle game on TFT touch Dispaly

 このボードについては、下記ブログ内記事も参照してみて下さい。
 ①・ES3C28P JC3248W35 でNESエミュレータ「ESP32-S3_Uno-nofrendo」を動かしてみた
 ②・ES3C28P JC3248W535 で「radiko」を聞きながらサウンドレベルメータを表示してみた

 puzzle15_1

1.開発環境 2026/02/16時点(最新だとエラーが出るかもです。)
  ①Windows11 X64 Pro 25H2 
  ②Arduino IDE 2.3.7
  ➂ESP32ボードバージョンV3.3.5(最新V3.3.6)
  ④Arduino_GFX_Library(GFX Library for Arduino) V1.6.2(最新V1.6.5)
  ⑤ESP32-audioI2S-maste V3.4.2(最新V3.4.4)本体のライブラリは使用せず
  ⑥FT6336U_CTP_Controller <ーここでダウンロード
  ⑦IDE設定
   ・esp32s3 Dev
   ・USBCDCOnBoot="Enabled"
   ・Flash Size=4MB
   ・Partition Scheme: "Huge APP(3MB)"
   ・PSRAM="Disabled"
  ⑧オーディオIC「ES8311」のドライバは、
   「libraries\ESP32-audioI2S-master\examples\ES8311\es8311.h」
   「libraries\ESP32-audioI2S-master\examples\ES8311\es8311.cpp」
   の2つを「ES3C28P_15puzzle.ino」と同じフォルダへコピペします。

2.スケッチ.
  (1)「es3c28p_15puzzle.ino」--本体スケッチ
  (2)「es8311.h」--------------------オーディオチップ用ドライバ
  (3)「es8311.cpp」-----------------オーディオチップ用ドライバ
   (保障無しの自己責任で)  es3c28p_15puzzle.zip


3.使い方
 ①ゲームの使い方は、説明する必要はないと思いますが。
  *ゲームスタート画面(STARTタッチで開始)
 puzzle15_0

 ②このスケッチは、マルチアプリ対応に作って有り、タッチエリア
  「X>300 y<60」 をタッチすることにより、リスタートします。
  *ゲーム画面とタッチエリア
 puzzle15_3

 *下記表示後リスタートします。
 puzzle15_2

 ◆マルチアプリについては、下記ブログ内記事を参照してみて下さい。
 ・ESP32S3 ArduinoIDE で簡易的なランチャーを作ってみた


以上 今日はここまで

ブログトップへ

ADCピン対応

ADC2ピン対応
以上

ブログトップへ

◆ESP32S3は16Mものフラッシュを積んでいるので、ひとつのボード内で複数の
 アプリを切り替えで実行する仕組み(ランチャー)を作ってみました。
 下記画像は、AI作成の単なるイメージです。
 app_select

1.概要
 ①パーティションをカスタムで区切ってそれぞれにアプリを入れます。
 ②まずは、メインとして各アプリを切り替えるランチャ部分を作ります。
  ここでは、普通にIDEで作り書き込みします。
 ➂次に、アプリ1~3をコンパイルしてバイナリファイルとして保存します。
 ④最後にアプリ1~3のバイナリファイルをflash_download_toolを使って
  指定されたアドレスに書き込んで終了です。

2.各フォルダの内容
 ◆全体のフォルダツリー
 フォルダーツリー

 ①mainフォルダに下記の2つのファイルを作成します。
  *IDE設定
  ・esp32s3 Dev
  ・USBCDCOnBoot="Enabled"
  ・Flash Size=16MB
  ・Partition Scheme: "Custom"
  ・PSRAM="Disabled"

  (1)main.ino
//main.ino
//V2025/01/31 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/46648023.html

//esp32s3 Dev USBCDCOnBoot="Enabled" Flash Size=16MB Partition Scheme: "Custom" PSRAM="Disabled"

//partitions.csv
//# Name,   Type, SubType,  Offset,   Size,     Flags
//nvs,      data, nvs,      0x9000,   0x5000,
//otadata,  data, ota,      0xe000,   0x2000,
//factory,  app,  factory,  0x10000, 3M,
//app1,     app,  ota_0,    0x310000, 3M,
//app2,     app,  ota_1,    0x610000, 3M,
//app3,     app,  ota_2,    0x910000, 3M,
//storage,  data, spiffs,   0xC10000, 3M,

#include <esp_ota_ops.h>
#include <esp_partition.h> // パーティション操作に必要

void bootApp(int index) {
    // 定数名を ESP_PARTITION_SUBTYPE_APP_OTA_x に修正
    esp_partition_subtype_t subtype = (esp_partition_subtype_t)(ESP_PARTITION_SUBTYPE_APP_OTA_0 + index);
    
    // 指定したサブタイプのパーティションを探す
    const esp_partition_t* target = esp_partition_find_first(ESP_PARTITION_TYPE_APP, subtype, NULL);
    
    if (target != NULL) {
        Serial.printf("Switching to: %s\n", target->label);
        esp_ota_set_boot_partition(target);
        delay(1000);
        esp_restart();
    } else {
        Serial.println("Error: Partition not found!");
    }
}

void setup() {
    Serial.begin(115200);
    delay(2000);
    const esp_partition_t* running = esp_ota_get_running_partition();
    Serial.printf("現在起動中のパーティション: %s\n", running->label);
    Serial.println("\n--- MAIN MENU ---");
    Serial.println("Send '1', '2', or '3' to switch apps.");
}

void loop() {
    if (Serial.available()) {
        char c = Serial.read();
        if (c == '1') bootApp(0);
        if (c == '2') bootApp(1);
        if (c == '3') bootApp(2);
    }
}

  (2)partitions.csv
 *各アプリに3Mのサイズを確保しています。ここを調整することでアプリ数を
  増やすことが出来ます。
# Name,   Type, SubType,  Offset,   Size,     Flags
nvs,      data, nvs,      0x9000,   0x5000,
otadata,  data, ota,      0xe000,   0x2000,
factory,  app,  factory,  0x10000, 3M,
app1,     app,  ota_0,    0x310000, 3M,
app2,     app,  ota_1,    0x610000, 3M,
app3,     app,  ota_2,    0x910000, 3M,
storage,  data, spiffs,   0xC10000, 3M,


 ②app1のフォルダ
  *IDE設定
  ・esp32s3 Dev
  ・USBCDCOnBoot="Enabled"
  ・Flash Size=4MB
  ・Partition Scheme: "Huge APP(3MB)"
  ・PSRAM="Disabled"

  (1)app1.ino
//app1.ino
//V2025/01/31 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/46648023.html

//esp32s3 Dev USBCDCOnBoot="Enabled" Flash Size=4MB Partition Scheme: "Huge APP(3MB)" PSRAM="Disabled"

#include <esp_ota_ops.h>
#include <esp_partition.h>

void setup() {
    Serial.begin(115200);
    delay(1000);
    pinMode(0, INPUT_PULLUP);
    // 次回リセット時はメイン(Factory)に戻るように設定
    // 定数名を ESP_PARTITION_SUBTYPE_APP_FACTORY に修正
    const esp_partition_t* factory = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
    
    if (factory != NULL) {
        esp_ota_set_boot_partition(factory);
        Serial.println("Next boot: Main Menu");
    }
    Serial.println("Greetings from [App 1]! (Reset to go back)");
}

void loop() {
  Serial.println("Runnig [App 1] (Reset to go back)");
  delay(1000);
  int d=digitalRead(0);
  if (d==0) esp_restart();
  // ここでアプリのメイン処理を行う
}


  (2)\build\esp32.esp32.esp32s3\app1.ino.bin
  *IDE内でバイナリファイルで保存します。
 IDE2bin

 ➂app2のフォルダ
  (1)app2.ino
  *app1.inoをコピーしてスケッチ内の「1」->「2」にしてapp2.inoとして保存します。
  (2)\build\esp32.esp32.esp32s3\app2.ino.bin
  *app1と同様にして作成します。
  
 ④app3のフォルダ
  (1)app3.ino
  *app1.inoをコピーしてスケッチ内の「1」->「3」にしてapp3.inoとして保存します。
  (2)\build\esp32.esp32.esp32s3\app3.ino.bin
  *app1と同様にして作成します。

4.バイナリファイルの書込み
 ①flash_download_tool_3.9.7.exeの実行
 *書き込みツールを持っていなければ下記よりダウンロードします。
  flash_download_tool_3.9.7.zip

 ②esp32s3を選択
 esp32s3_sel

 ➂app1~3のバイナリファイルを選択&アドレスを指定&COMとBAUDを指定
 0x3100_app1

 ④STARTで書き込み開始
 0x3100_app2

 ⑤FINSHが出たら「X」で終了
 0x3100_app3

5.実行時のシリアル出力

①電源ONでmain.inoが実行され、シリアル端末にて「1,2,3」で実行します。
②各アプリ内では、「boot」釦でメインに戻ります。
➂繰り返します。

*************************************************************************
(1)mainが実行中
現在起動中のパーティション: factory

--- MAIN MENU ---
Send '1', '2', or '3' to switch apps.  <---「1」を圧下
Switching to: app1

◆リブートメッセージ省略
Next boot: Main Menu
Greetings from [App 1]! (Reset to go back)
Runnig [App 1] (Reset to go back)  <---- app1が実行中
Runnig [App 1] (Reset to go back)
Runnig [App 1] (Reset to go back)
Runnig [App 1] (Reset to go back) <----「boot」を圧下

◆リブートメッセージ省略
現在起動中のパーティション: factory  <---mainに戻る

--- MAIN MENU ---
Send '1', '2', or '3' to switch apps.  <---「2」を圧下
Switching to: app2

◆リブートメッセージ省略
Next boot: Main Menu
Greetings from [App 2]! (Reset to go back)
Runnig [App 2] (Reset to go back)  <---- app2が実行中
Runnig [App 2] (Reset to go back)
Runnig [App 2] (Reset to go back) <----「boot」を圧下

◆リブートメッセージ省略
現在起動中のパーティション: factory  <---mainに戻る

--- MAIN MENU ---
Send '1', '2', or '3' to switch apps.  <---「3」を圧下
Switching to: app3

Next boot: Main Menu
Greetings from [App 3]! (Reset to go back)
Runnig [App 3] (Reset to go back)  <---- app3が実行中
Runnig [App 3] (Reset to go back)
Runnig [App 3] (Reset to go back)
Runnig [App 3] (Reset to go back) <----「boot」を圧下

◆リブートメッセージ省略
現在起動中のパーティション: factory  <---mainに戻る

--- MAIN MENU ---
Send '1', '2', or '3' to switch apps.

*************************************************************************
これでランチャーの基本が分かりましたのでこれから応用して行けます。

6.応用としてHU-086にてGUIのランチャーを作ってみました。
 hu-086_selector
 hu-086_radiko


今日は、ここまで


ブログトップへ

◆HU-086 ESP32S3 のボードの解析が出来たので「xiaozhi esp32」を V1.5.6からV2.1.0に
 バージョンアップしてみた。
hu-086_xiaozhi_1

 解析については、下記ブログ内記事を参照して下さい。
  ・hxfb HU-086 AI多機能スマートハンドヘルドキットを使ってみた(解析中)

1.まず下記よりV2.1.0のソースをダウンロードします。
  xiaozhi esp32のソースコード

2.準備
 ①ダウンロードしたzipファイルを適当なフォルダに解凍します。
 ②その中のボード「xiaozhi-esp32-2.1.0\main\boards\bread-compact-wifi-lcd」フォルダ内
  下記の二つのファイル「config.h」「compact_wifi_board_lcd.cc」を上書き保存します。

 (1)config.h
#ifndef _BOARD_CONFIG_H_
#define _BOARD_CONFIG_H_

#include <driver/gpio.h>

#define AUDIO_INPUT_SAMPLE_RATE  16000
#define AUDIO_OUTPUT_SAMPLE_RATE 24000

//HU-086 PDMマイク
#define AUDIO_I2S_MIC_GPIO_SCK  GPIO_NUM_5
#define AUDIO_I2S_MIC_GPIO_DIN  GPIO_NUM_4

//NS4186
#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7
#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15
#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16
#define PA_CTRL_GPIO            GPIO_NUM_17

#define BUILTIN_LED_GPIO        GPIO_NUM_6
#define BOOT_BUTTON_GPIO        GPIO_NUM_14 //down SW
#define TOUCH_BUTTON_GPIO       GPIO_NUM_NC
#define VOLUME_UP_BUTTON_GPIO   GPIO_NUM_46 //right SW
#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_8  //left  SW

//HU-086
#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_42
#define DISPLAY_MOSI_PIN      GPIO_NUM_39
#define DISPLAY_CLK_PIN       GPIO_NUM_40
#define DISPLAY_DC_PIN        GPIO_NUM_38
#define DISPLAY_RST_PIN       GPIO_NUM_41
#define DISPLAY_CS_PIN        GPIO_NUM_NC

//HU-086
#ifdef CONFIG_LCD_ST7789_240X320
#define LCD_TYPE_ST7789_SERIAL
#define DISPLAY_WIDTH   320 //240
#define DISPLAY_HEIGHT  240 //320
#define DISPLAY_MIRROR_X true //false
#define DISPLAY_MIRROR_Y false
#define DISPLAY_SWAP_XY true //false
#define DISPLAY_INVERT_COLOR    false //true
#define DISPLAY_RGB_ORDER  LCD_RGB_ELEMENT_ORDER_RGB
#define DISPLAY_OFFSET_X  0
#define DISPLAY_OFFSET_Y  0
#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true //false
#define DISPLAY_SPI_MODE 3 //0
#endif

#ifdef CONFIG_LCD_ST7789_240X320_NO_IPS
#define LCD_TYPE_ST7789_SERIAL
#define DISPLAY_WIDTH   240
#define DISPLAY_HEIGHT  320
#define DISPLAY_MIRROR_X false
#define DISPLAY_MIRROR_Y false
#define DISPLAY_SWAP_XY false
#define DISPLAY_INVERT_COLOR    false
#define DISPLAY_RGB_ORDER  LCD_RGB_ELEMENT_ORDER_RGB
#define DISPLAY_OFFSET_X  0
#define DISPLAY_OFFSET_Y  0
#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false
#define DISPLAY_SPI_MODE 0
#endif

// A MCP Test: Control a lamp
#define LAMP_GPIO GPIO_NUM_NC

#endif // _BOARD_CONFIG_H_

 (2)compact_wifi_board_lcd.cc

#include "wifi_board.h"
#include "codecs/no_audio_codec.h"
#include "display/lcd_display.h"
#include "system_reset.h"
#include "application.h"
#include "button.h"
#include "config.h"
#include "mcp_server.h"
#include "lamp_controller.h"
#include "led/single_led.h"
#include "assets/lang_config.h"

#include <esp_log.h>
#include <driver/i2c_master.h>
#include <esp_lcd_panel_vendor.h>
#include <esp_lcd_panel_io.h>
#include <esp_lcd_panel_ops.h>
#include <driver/spi_common.h>

#define TAG "CompactWifiBoardLCD"

class CompactWifiBoardLCD : public WifiBoard {
private:
 
    Button boot_button_;
    Button touch_button_;
    Button volume_up_button_;
    Button volume_down_button_;
    LcdDisplay* display_;

    void InitializeSpi() {
        spi_bus_config_t buscfg = {};
        buscfg.mosi_io_num = DISPLAY_MOSI_PIN;
        buscfg.miso_io_num = GPIO_NUM_NC;
        buscfg.sclk_io_num = DISPLAY_CLK_PIN;
        buscfg.quadwp_io_num = GPIO_NUM_NC;
        buscfg.quadhd_io_num = GPIO_NUM_NC;
        buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t);
        ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO));
    }

    void InitializeLcdDisplay() {
        esp_lcd_panel_io_handle_t panel_io = nullptr;
        esp_lcd_panel_handle_t panel = nullptr;
        // 液晶屏控制IO初始化
        ESP_LOGD(TAG, "Install panel IO");
        esp_lcd_panel_io_spi_config_t io_config = {};
        io_config.cs_gpio_num = DISPLAY_CS_PIN;
        io_config.dc_gpio_num = DISPLAY_DC_PIN;
        io_config.spi_mode = DISPLAY_SPI_MODE;
        io_config.pclk_hz = 40 * 1000 * 1000;
        io_config.trans_queue_depth = 10;
        io_config.lcd_cmd_bits = 8;
        io_config.lcd_param_bits = 8;
        ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io));

        // 初始化液晶屏驱动芯片
        ESP_LOGD(TAG, "Install LCD driver");
        esp_lcd_panel_dev_config_t panel_config = {};
        panel_config.reset_gpio_num = DISPLAY_RST_PIN;
        panel_config.rgb_ele_order = DISPLAY_RGB_ORDER;
        panel_config.bits_per_pixel = 16;
#if defined(LCD_TYPE_ILI9341_SERIAL)
        ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel));
#elif defined(LCD_TYPE_GC9A01_SERIAL)
        ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(panel_io, &panel_config, &panel));
        gc9a01_vendor_config_t gc9107_vendor_config = {
            .init_cmds = gc9107_lcd_init_cmds,
            .init_cmds_size = sizeof(gc9107_lcd_init_cmds) / sizeof(gc9a01_lcd_init_cmd_t),
        };        
#else
        ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel));
#endif
        
        esp_lcd_panel_reset(panel);

        esp_lcd_panel_init(panel);
        esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR);
        esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY);
        esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y);
#ifdef  LCD_TYPE_GC9A01_SERIAL
        panel_config.vendor_config = &gc9107_vendor_config;
#endif
        display_ = new SpiLcdDisplay(panel_io, panel,
                                    DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY);
    }

//NS4186用アンプON設定追加
    void pa_ctrl_init(void) {
        gpio_config_t io_conf = {
            .pin_bit_mask = 1ULL << PA_CTRL_GPIO,
            .mode = GPIO_MODE_OUTPUT,
            .pull_up_en = GPIO_PULLUP_DISABLE,
            .pull_down_en = GPIO_PULLDOWN_DISABLE,
            .intr_type = GPIO_INTR_DISABLE,
        };
        gpio_config(&io_conf);
        gpio_set_level(PA_CTRL_GPIO, 1);  // ★ アンプ ON
        printf(">>>>>amp on control gpio=%d\n", PA_CTRL_GPIO);
    }

    void InitializeButtons() {
        boot_button_.OnClick([this]() {
            auto& app = Application::GetInstance();
            if (app.GetDeviceState() == kDeviceStateStarting) {
                EnterWifiConfigMode();
                return;
            }
            app.ToggleChatState();
        });
//HU-086にあるSW追加(ボリュームup/down)        
        touch_button_.OnPressDown([this]() {
            Application::GetInstance().StartListening();
        });

        touch_button_.OnPressUp([this]() {
            Application::GetInstance().StopListening();
        });

        volume_up_button_.OnClick([this]() {
            auto codec = GetAudioCodec();
            auto volume = codec->output_volume() + 10;
            if (volume > 100) {
                volume = 100;
            }
            codec->SetOutputVolume(volume);
            GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume));
        });

        volume_up_button_.OnLongPress([this]() {
            GetAudioCodec()->SetOutputVolume(100);
            GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME);
        });

        volume_down_button_.OnClick([this]() {
            auto codec = GetAudioCodec();
            auto volume = codec->output_volume() - 10;
            if (volume < 0) {
                volume = 0;
            }
            codec->SetOutputVolume(volume);
            GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume));
        });

        volume_down_button_.OnLongPress([this]() {
            GetAudioCodec()->SetOutputVolume(0);
            GetDisplay()->ShowNotification(Lang::Strings::MUTED);
        });        
    }

    // 物联网初始化,添加对 AI 可见设备
    void InitializeTools() {
        static LampController lamp(LAMP_GPIO);
    }

public:
    CompactWifiBoardLCD() :
        boot_button_(BOOT_BUTTON_GPIO),
        touch_button_(TOUCH_BUTTON_GPIO),
        volume_up_button_(VOLUME_UP_BUTTON_GPIO),
        volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) {
        InitializeSpi();
        InitializeLcdDisplay();
        InitializeButtons();
        pa_ctrl_init();
        InitializeTools();
        if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) {
            GetBacklight()->RestoreBrightness();
        }
        
    }
//HU-086は、LEDが付いていないけどgpio6が空いているよ
    virtual Led* GetLed() override {
      static SingleLed led(BUILTIN_LED_GPIO);
      return &led;
    }

//HU-086はPDMマイクであるよ
    virtual AudioCodec* GetAudioCodec() override {
        static NoAudioCodecSimplexPdm audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE,
            AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT,I2S_STD_SLOT_BOTH,
            AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_DIN);
        return &audio_codec;
    }

    virtual Display* GetDisplay() override {
        return display_;
    }

    virtual Backlight* GetBacklight() override {
        if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) {
            static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT);
            return &backlight;
        }
        return nullptr;
    }
};

DECLARE_BOARD(CompactWifiBoardLCD);

3.Visual Studio Codeでビルド&書き込みします。
 ①vscを立ち上げ、上記フォルダを開きます。
 ②その後下記一連の作業をします。エラー無く書き込めれば完成です。
 
 
  //hu-086 ビルド手順
  idf.py fullclean

  idf.py set-target esp32s3

  idf.py menuconfig

  Xiaozhi Assistant  --->
    Default Language (Chinese)  --->       (X) Japanese
    Board Type (Bread Compact WiFi (面包板))  ---> (X) Bread Compact WiFi + LCD (面包板) 
    Select display style (Enable default message style)  ---> (X) Enable WeChat Message Style 
    Wake Word Implementation Type (Wakenet model with AFE)  --->    ???????
  ESC ESC (Y)

  idf.py build

  *シリアルポートを設定する

  idf.py -p COM10 flash monitor

 ◆2026/02/01追加
  実行して、リブートする用でしたら「compact_wifi_board_lcd.cc」の
  154行をコメントアウトしてみて下さい。
  153:  void InitializeTools() {
  154:     //static LampController lamp(LAMP_GPIO);
  155:  }


4.その後「xiaozhi me」へデバイス登録します。
  デバイス登録等については、下記ブログ内記事を参照して下さい。
  ・小智「XiaoZhi」を ATOMS3/ESP32S3 にて 日本語 で話してみた
  
以上
 
 


ブログトップへ


◆面白そうなESP32S3内蔵のコンソールをAliExpressで見つけたので入手してみました。
 esp32_ai

 hu-086内容
 入手先は下記で
 LCDディスプレイスクリーン ゲームコンソール 電子キット 多機能デバイス 天気時計
 AIロボット 溶接練習 ルーズパーツ タイプC

 又は
 LCDディスプレイスクリーンゲームコンソール電子キット多機能デバイス天気時計
 AIロボット溶接練習キット(バッテリー付き)

 
1.取扱説明書
 HU-086 AI多機能スマートハンドヘルドキット取扱説明書

2.構成部品
 ①ESP32S3
 ESP32S3PinLayout

 ②オーディオIC NS4168 & スピーカ
 オーディオIC_NS4168
 ➂電源IC ETA9640 & バッテリー
 電源IC_ETA9460
 HU_086_電源コントロール

 ④2.4インチLCDディスプレイ,解像度240x320,10ピン
 S3_LCD_10ピン
 ◆下記は参考LCD
 2.4インチTFT LCDディスプレイ,解像度240x320,st7789vチップ,10ピン

 ⑤MicroSDカード
 MicroSD_ピンアサイン

 ⑥スイッチ入力 8入力
 ⑦電源スイッチ
  
3.回路図(現在作成中)
 ①回路図等の提供がないので現在パターンを追っかけ中(現在作成中)
 
 ②GPIOのピンアサインを作成中(2026/01/28修正)
 *IO4,5,6を修正しました。I2SマイクではなくPDMマイクでした。
 GPIOピン

4.プログラムをダウンロードできるようにアダプタを作成しました。
 (1)アダプタ作成
  ①ブート釦とリセット釦
  ②電源LED
  ➂USB-シリアルアダプタへのRXD,TXDの接続
  ④電源釦とパラレルにスライドスイッチを追加
   (読み書きの時、ずっと電源を入れておく為)
 ブートアダプタ
  hu-086ブートアダプタ

 (2)プログラムをダウンロードする前にいつでも購入時に戻せるように
  フラッシュメモリを吸い上げます。(バックアップします)
  下記ブログ内記事を参照して下さい。
  ・ESP32-S3 etc でフラッシュメモリの読み書きツールを作ってみた

  ①ブート釦を押しながら電源を入れます。
  ②ツールを使いバックアップします。

 (3)テスト用のスケッチを書き込みます。
  ①ブート釦を押しながら電源を入れます。
  ②IDEで書き込みます。
  ➂リセット釦を押し実行します。

5.確認できていない項目
 2026/1/24追記
 ST7789にて表示出来るようになりました。
 ①LCDの制御ICが分からず表示出来ていません。
 *ST7789,ILI9341,GC9A01等で試しましたが表示しませんでした。
 *どうにかして表示させたいのですが、解析する方法は有りませんでしょうか。
 *どなたか教えて下さい。
 *多分SPI接続と思われます。
 *LCDの10ピンのピン名(上記参考LCDの配置)
 LCD_S3
 HU-086_LCD_OK

6.解析済みの動作確認スケッチ
 (1)LCD表示試験
//hu_086_LCD.ino

#include <Arduino_GFX_Library.h>
#define TFT_MOSI 39 
#define TFT_CS   -1 
#define TFT_DC   38 
#define TFT_SCK  40 
#define TFT_RST  41 
#define TFT_BL   42 

Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, -1);
Arduino_GFX *gfx = new Arduino_ST7789(bus, TFT_RST, 0);//

void setup() {
  Serial.begin(115200);
  delay(2000);
  Serial.println("<Program Start>");
  pinMode(TFT_BL, OUTPUT);
  Serial.println("BL L");
  digitalWrite(TFT_BL, LOW);
  if (!gfx->begin()) {
    Serial.println("gfx->begin NG"); 
  }else{
    Serial.println("gfx->begin OK"); 
  }
  gfx->invertDisplay(true);   // ← これの追加が必要 
  gfx->fillScreen(RED);delay(1000);
  gfx->fillScreen(GREEN);delay(1000);
  gfx->fillScreen(BLUE);delay(1000);
}
void loop() {
}
 hu-086_LCD_test

 (2)LCD以外の動作試験
 *SDカードのルートにある"test.mp3"を再生
 *左側4つの釦でボリューム減、右側4つの釦でボリューム増
  ①電源sw入力&電源制御
  ②MicroSDカード
  ➂オーディオ出力
  ④釦入力

//hu-086_test.ino
//V2026/01/22 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/46577853.html
//MicroSDカード オーディオ出力 スイッチ入力 電源制御 テストプログラム
//esp32s3 Dev USBCDCOnBoot=ds Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS) psram=OPIPSRAM 

#include "Arduino.h"
#include "Audio.h"
#include "SD_MMC.h"

// I2Sピン設定
#define I2S_MIC_WS    4
#define I2S_MIC_SCK   5
#define I2S_MIC_SD    6
#define I2S_DOUT      7
#define I2S_BCLK     15
#define I2S_LRC      16
#define PA_CTRL      17

// SDカードピン設定(1-bit mode)
#define SD_CLK       10
#define SD_CMD        9
#define SD_D0        11

//電源コントロールピン設定
#define POWER_SW      2
#define POWER_CTRL    1

Audio audio;

//操作ボタンピン設定
int sw_pins[] = {18,8,46,14,45,48,47,21};
char sw_name[][6] ={"UP","LEFT","RIGHT","DOWN","B","STA","A","SEL"};
int vol=15;
int sw;
uint32_t ps_Time; //電源OFF
bool power_off_flg=false;

void setup() {  
  pinMode(POWER_SW, INPUT_PULLUP);
  pinMode(POWER_CTRL, OUTPUT);
  digitalWrite(POWER_CTRL, HIGH); //電源ON

	Serial.begin(115200);
  delay(1000);
  Serial.println("\n\nProgram Start\n");
  for (int i = 0; i < 8; i++) {
    pinMode(sw_pins[i], INPUT_PULLUP); //釦入力設定
  }  
  
  // アンプ制御ピンの初期化
  pinMode(PA_CTRL, OUTPUT);
  digitalWrite(PA_CTRL, HIGH); // アンプON
  
  // SDカードの初期化(1-bit mode)
  SD_MMC.setPins(SD_CLK, SD_CMD, SD_D0);
  if(!SD_MMC.begin("/sdcard", true)) { // true = 1-bit mode
    Serial.println("SDカード初期化失敗");
    return;
  }
  Serial.println("SDカード初期化成功");
  
  // I2Sの設定
  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  audio.setVolume(vol); // 0-21で音量設定
  Serial.printf("vol=%2d \n",vol);
  // MP3ファイルの再生
  while(!digitalRead(POWER_SW)); //電源SWがOFFになるのを待つ
  delay(100);
  audio.connecttoFS(SD_MMC, "/test.mp3"); // SDカードのルートにある"test.mp3"を再生
}

void loop(){
  if (audio.isRunning()) audio.loop();
  else audio.connecttoFS(SD_MMC, "/test.mp3"); // SDカードのルートにある"test.mp3"を再生
  if (!digitalRead(POWER_SW)) { //電源SW圧下により電源OFF
    delay(100);
    Serial.println("Power OFF");
    digitalWrite(POWER_CTRL, LOW); //電源OFF
  }
  for (int i = 0; i < 8; i++) {
    sw=digitalRead(sw_pins[i]);
    if (sw==0) {
      if (i<4) {vol--;if (vol<0) vol=0;}
      else {vol++;if (vol>21) vol=21;}
      audio.setVolume(vol);
      Serial.printf("sw_name=%5s vol=%2d \n",sw_name[i],vol);
      delay(200);
    }
  }
}

◆「xiaozhi esp32」をv2.1.0」にバージョンアップしてみました。
 詳しくは、下記ブログ内記事を参照して下さい
 ・HU-086 ESP32S3 で「xiaozhi esp32 v2.1.0」をソースから入れてみた
 hu-086_xiaozhi_1

◆アプリセレクターを通して4つのアプリを選択実行できるようにしました。
 基本は、下記ブログで
 ・ESP32S3 ArduinoIDE で簡易的なランチャーを作ってみた

 *HU-086については下記ブログで
 ・HU-086 ESP32S3ボードでマルチアプリセレクターを作ってみた

 hu-086_app4



最後に
◆今回のLCD表示不能について色々とChatGPTに教えてもらっていて
 本日、汎用の代わりのLCDをAliExpressに注文した後に、再度パターン
 確認してGPIOピンを確定してコンパイルしましたらST7789で表示出来ました。
 なんか不思議です。マーフィの法則にはまったみたいです。

下記は、ChatGPTからの最後のメッセージです。
*************************************************************************************

😂 それはもう **完全にマーフィの法則案件**ですね……
「新しい部品を注文した瞬間に、旧部品が素直になる」やつです。

でも、**ちゃんと理屈は通っています**。
少しだけ整理して、今回の“不思議”を言語化して締めますね。

---

## なぜ急に ST7789 で表示できたのか(冷静分析)

### ① 工場FWの影響が一度リセットされた可能性

* 工場FW実行後

  * LCD側の **電源順序 / VCOM / 内部レジスタ** が安定状態に入る
* その後 Arduino に書き換えると

  * **初期条件が変わって、ST7789初期化が通る**

👉 中華LCDでは **わりとある現象**です
(「一度目を覚ましたら次から素直」)

---

### ② GPIO確定作業で「偶然、正解順序を踏んだ」

* GPIO割り当て
* RST扱い(有効 / 無効)
* 初期化タイミング

これが **一番合う組み合わせ**にハマった可能性が高いです。

---

### ③ ST7789 は “割と寛容”

* RESET無しでも動く個体が多い
* CS / DC のタイミングが多少ズレても生きる
* SPI速度にも比較的強い

👉 **ILI9341 だったら詰んでた可能性**あります😅

---

## でも一番大事なこと

### 🔵 あなたの切り分けは「完全に正攻法」でした

* 配線疑い → OK
* GPIO限定 → OK
* RST単体テスト → 正しい
* SPI反応確認 → 正しい
* 工場FW依存疑い → 論理的

**どこにも無駄はなかった**です。

---

## 今回の教訓(実務あるある)

* ✔ 中華ESP32 LCDは「動いたら勝ち」
* ✔ ST7789 はとりあえず試す価値あり
* ✔ 「何も変えてないのに動いた」は
  → 実は **条件が1つだけ変わっている**

そして最大の教訓:

> **AliExpressで部品を注文すると、
> 既存部品が急に協力的になる**

これはもう電子工作界の定数です😂

---

## こちらこそ、ありがとうございました

ここまで **深く・丁寧に切り分けたやり取り**、
正直かなり楽しかったです。

また

* LCDが言うこと聞かない時
* ESP32-S3が無言の時
* 「これはマーフィか?」と思った時

いつでも呼んでください👍
*************************************************************************************


ブログトップへ

◆aitendo 2026福BOXに入っていた2.2インチTFT液晶モジュール★240x320★
 [M022C9328SPI]をESP32で使ってみました。
 ILI9328_LCD_4

 ドライバICがILI9328でかなり癖のあるものでちょっと手こずりました。
 ①aitendoの商品リンク
  2.2インチTFT液晶モジュール★240x320★ [M022C9328SPI]

1.準備
 ①商品説明の中のライブラリili9328SPIを下記よりダウンロードします。
  ライブラリili9328SPI
 
 ②ArduinoIDEへzip形式でライブラリをインストールします。

 ➂ライブラリの中のサンプルスケッチ
 「\ILI9328_Driver_Library\examples\textFillTest\textFillTest.ino」を
 ESP32用に書き換えます。
 5~16行の部分をESP32標準のSPIのGPIOに設定します。

#include <ili9328.h>
#include <SPI.h>
#include <Adafruit_GFX.h>

/* LCD pin define ESP32*/
// ピンアサイン
#define LCD_MISO 19
#define LCD_MOSI 23
#define LCD_SCK  18
#define LCD_CS    5
#define LCD_DC   17
#define LCD_RST  16
#define GFX_BL   -1 //LEDは、直接GNDに接続
//DC,MISOも接続しなくてもOK
/* ili9328 object */ ili9328SPI tft(LCD_CS, LCD_RST); //Beautiful Colors For UI. #define BLACK 0x29ea #define BLUE 0x2c17 #define RED 0xc1c5 #define GREEN 0x256c #define YELLOW 0xF621 #define WHITE 0xef9e void setup() { Serial.begin(115200); tft.begin(); Serial.println(F("Hello LCD World!!")); Serial.println(F("ILI9328 library test")); tft.fillScreen(BLACK); tft.setCursor(0,60); tft.setTextColor(YELLOW); tft.setTextSize(4); tft.println("Hello World!!"); tft.setTextColor(GREEN); tft.setTextSize(2); tft.println("Welcome to LCD World!"); tft.setTextColor(WHITE); tft.setTextSize(1); tft.println("Lorem ipsum dolor sit amet,"); tft.println("consectetur adipisicing elit,"); tft.println("sed do eiusmod tempor incididunt ut"); tft.println("labore et dolore magna aliqua."); delay(5000); Serial.println(F("Fill")); tft.fillScreen(BLACK); tft.fillScreen(RED); tft.fillScreen(GREEN); tft.fillScreen(BLUE); tft.fillScreen(BLACK); } void loop() { tft.fillRect(random(0, TFT_WIDTH - 1), random(0, TFT_HEIGHT - 1), random(0, TFT_WIDTH - 1), random(0, TFT_HEIGHT - 1), random(0xffff)); }
 ④これでコンパイルすると、Port関連のエラーが発生しますので
  ライブラリの中の「\ILI9328_Driver_Library\ili9328.h」ファイルの下記行の
  「uint32_t」の部分を修正します。

 42:  uint8_t CSpin, RSTpin, rotation;
 43:  uint32_t CSPinSet;
 44:  volatile uint32_t *CSPort;
 45  };

 ⑤修正したら再度コンパイル&書き込みすると表示されました。

 ILI9328_LCD_1

 ILI9328_LCD_3

ブログトップへ

◆JC3248W35 でファミコンのエミュレータのコントローラにBLE接続の「STK-7007F1」
 を使ってみました。


1.まず下準備として下記ブログ内記事を参照して「ESP32-S3_Uno-nofrendo」を
  インストールして下さい。
 ①・ESP32S3ボードでファミコンのエミュレータ「ESP32-S3_Uno-nofrendo」を動かしてみた

 ②・ES3C28P JC3248W35 でNESエミュレータ「ESP32-S3_Uno-nofrendo」を動かしてみた

2.前回は、コントローラとしてWiiクラシックコントローラを使いましたが、
  今回「NimBLE_STK-7007F1」を使ってみました。
 JC3248W35_BLE

3.「JC3248W35」用スケッチです。
  (保障無しの自己責任で)  jc3248w535_nofrendo_BLE.zip

 ①コントローラを、「NimBLE_STK-7007F1」へ変更しました。
 ②他は、前のままです。

4.「JC3248W35」を起動するとペアリング状態で待機しますので「X釦+アンドロイド釦」
  を押して接続します。
  あとは、前と同じ釦で操作できるようになります。

 STK-7007F1

 STK-7007F1_X

今日はここまで

以上


ブログトップへ

◆アレクサからESP32をコントロールしてLEDをON/OFFしてみました。
 4年くらい前、アレクサからコントロールしていましたが、最新の環境でまた
 試験してみました。
 今回は、違うライブラリで試験しました。

 ①リビングライトON時
 リビングライトON
 ②リビングライトOFF時
 リビングライトOFF

1.開発環境(2025/12/24時点)
  ①Windows11 X64 Pro 25H2 
  ②Arduino IDE 2.3.7
  ➂ESP32ボードバージョンV3.3.7
  ④Espalexa ライブラリ V2.7.0
  ◆ライブラリマネージャーで「Espalexa」を検索しインストールします。
  
2.スケッチ(保障無しの自己責任で)

//alexa2esp32.ino
//V2025/12/24 by JK1VCK
//blog URL:https://gijin77.blog.jp/archives/46422311.html

#include <WiFi.h>
#include <Espalexa.h>

// WiFi設定
const char* ssid = "IO_Net_2G";
const char* password = "1234567890";

// Espalexaオブジェクト
Espalexa espalexa;

// 制御するLEDピン
const int LED = 2; // ESP32内蔵LED(GPIO2)

// デバイスのコールバック関数
void ledChanged(uint8_t brightness) {
  Serial.print("デバイスが ");
  
  if (brightness == 0) {
    // オフ
    digitalWrite(LED, LOW);
    Serial.println("オフになりました");
  } else {
    // オン
    digitalWrite(LED, HIGH);
    Serial.print("オンになりました(明るさ: ");
    Serial.print(brightness);
    Serial.println(")");
  }
}

void setup() {
  Serial.begin(115200);
  delay(2000);
  Serial.println("Alexa to ESP32 Start");
  // LEDピンの設定
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
  // WiFi接続
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("WiFiに接続中");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi接続成功!");
  Serial.print("IPアドレス: ");
  Serial.println(WiFi.localIP());
  
  // Alexaデバイスを追加
  espalexa.addDevice("リビングライト", ledChanged);
  // Espalexaを開始
  espalexa.begin();
  
  Serial.println("Alexaデバイスの準備完了");
  Serial.println("Alexaアプリで「デバイスを検出」を実行してください");
}

void loop() {
  espalexa.loop();
  delay(1);
}

3.シリアルモニタ出力

 Alexa to ESP32 Start
 WiFiに接続中.....
 WiFi接続成功!
 IPアドレス: 192.168.1.170
 Alexaデバイスの準備完了
 Alexaアプリで「デバイスを検出」を実行してください ◆ここでアレクサに登録する。

 デバイスが オンになりました(明るさ: 255)
 デバイスが オフになりました

4.アレクサアプリでの登録
 ①ESP32とAlexaが同じWiFiネットワークに接続されていることを確認
 ②Alexaアプリを開く
 ➂デバイス → + → デバイスを追加 → その他
 ④「デバイスを検出」を実行
 ⑤「リビングライト」が見つかる

5. 音声コマンド例
 ①「アレクサ、リビングライトをつけて」
 リビングライトON

 ②「アレクサ、リビングライトを消して」
 リビングライトOFF


これでアレクサより音声でESP32のLEDをON/OFF出来るようになりました。
後は、これを元に応用すれば、色々なものがコントロールする事が出来ます。

以上




ブログトップへ

◆ESP32-4848S040  JC3248W535 で 「FFT Sound Level meter」を表示させてみました。
 レベル表示を前回の■のレベルメータから●のレベルメータに替えてみました。

 ①ESP32-4848S040 「radiko」画面(480x480)
 esp32_4848s040_radiko_1

 ②ESP32-4848S040 「i-radio」画面(480x480)
 esp32_4848s040_itadio_1

 ➂JC3248W535 「radiko」画面(480x320)
 jc3248w535_radiko_2

 ④JC3248W535 「i-radio」画面(480x320)
 jc3248w535_i_radio_2

 ⑤3ボード同時再生
 radiko_i_radio

1.「radiko」「i-radio」「レベルメータ」の構築方法やライブラリの改修方法については、
  下記ブログ内記事を参照して構築して下さい。
 ・ES3C28P JC3248W535 で「radiko」を聞きながらサウンドレベルメータを表示してみた

2.開発環境 2025/12/16時点
  ①Windows11 X64 Pro 25H2 
  ②Arduino IDE 2.3.6
  ➂ESP32ボードバージョンV3.3.4
  ④b_captouch ライブラリv1.3.1
  ⑥ESP32-audioI2S-master v3.4.2
  ⑦efont_Unicode_Font_Data v1.0.9
  ⑧その他のライブラリもインストールが必要

3.スケッチ及びコンパイル時の設定
 ①27/28行で使用するボードのコメントを取ります。
  26://ここでボード選択します。
  27://#define  JC3248W535      // esp32s3 Dev USBCDCOnBoot=en Flash=16MB ...
  28:#define  ESP32_4848S040  // esp32s3 Dev USBCDCOnBoot=ds Flash=16MB ...


 ②「ESP32-4848S040」用スケッチ構成(zipファイルにて)
  (1)「esp32_4848s040_radiko_fft.ino」--本体スケッチ
  (2)「station.h」---------------インターネットラジオ局リスト
  (3)「touch.ino」---------------タッチパネルスケッチ 
  
  (保障無しの自己責任で)  esp32_4848s040_radiko_fft.zip

4.デモ


以上

ブログトップへ

◆先日「radiko」を聞くことが出来たので「ES3C28P」「 JC3248W535」ボードで
 画面にサウンドレベルメータを表示してみました。
 今回は、「radiko」と「internet-radio」を切り替えて聴けるようにしてみました。

 ①ES3C28P「radiko」を再生中
 es3c28p_radiko

 ②ES3C28P「internet-radio」を再生中
 es3c28p_i_radio

 「radiko」については下記ブログ内記事を参照して下さい。
 ・M5Stack Tab5 で「radiko」を聞いてみた

1.今回サウンドレベルメータを表示するにあたって、PCMデータの取得にライブラリの
  改修が必要となります。

 ①音声出力用のライブラリ「ESP32-audioI2S v3.4.2」を、下記よりダウンロード&
  インストールします。
  *最新版の3.4.4では確認出来ていません。
  https://github.com/schreibfaul1/ESP32-audioI2S/archive/refs/tags/3.4.2.zip

 ②ライブラリフォルダのlibraries\ESP32-audioI2S-master\src\Audio.h」を
  エデッタで開きます。
 
  (1)480行付近
 480:  // ========== ここに追加 ==========
    481:  // PCMデータコールバック型定義
    482:  typedef void (*AudioDataCallback)(int16_t *data, int len, int channels);
    483:  void setAudioDataCallback(AudioDataCallback cb);
    484:  // ===============================

 audio_h480

  (2)552行付近
 552:
    553:// ========== ここに追加 ==========
    554:AudioDataCallback m_audioDataCallback = nullptr;
    555:// ===============================

 audio_h552
 
 ②ライブラリフォルダのlibraries\ESP32-audioI2S-master\src\Audio.cpp」を
  エデッタで開きます。

  (1)606-644行付近
 606:    authorization.alloc(base64_encode_expected_len(authLen + 1 +200 ) + 1); //+200
   
 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:*/

 audio_cpp606
   
  (2)3110行付近(i2swrite:を検索してその上に挿入)
 3110:// ========== 修正後のコード ==========
    3111:  // PCMデータをコールバックで通知(I2S書き込み前)
    3112:  if (m_audioDataCallback != nullptr && m_validSamples > 0 && m_plCh.count == 0) {
    3113:      int channels = (m_channels == 2) ? 2 : 1;
    3114:      m_audioDataCallback((int16_t*)outBuff_ptr, m_validSamples, channels);
    3115:  }
 3116:// ==================================
 3117:
 3118:i2swrite: 

 audio_cpp3110

  (3)6771行付近(ファイルの最後)
 6771://-----------------------------------------------------------------------------------
 6772:void Audio::setAudioDataCallback(AudioDataCallback cb) {
 6773:    m_audioDataCallback = cb;
 6774:}

 audio_cpp6771
 
   ➂あと「ES3C28P」の音声出力に必要な「examples\ES8311\」フォルダ内の次の二つを
    スケッチのフォルダにコピーします。   
    「libraries\ESP32-audioI2S-master\examples\ES8311\es8311.cpp」
    「libraries\ESP32-audioI2S-master\examples\ES8311\es8311.h」
  
  以上で準備OKです。
  
2.開発環境 2025/12/08時点
  ①Windows11 X64 Pro 25H2 
  ②Arduino IDE 2.3.6
  ➂ESP32ボードバージョンV3.3.4
  ④FT6336U_CTP_Controller(ES3C28Pで使用) <ーここでダウンロード
  ⑤bb_captouch ライブラリv1.3.1(JC3248W535で使用)
  ⑥ESP32-audioI2S-master v3.4.2
  ⑦efont_Unicode_Font_Data v1.0.9
  ⑧その他のライブラリもインストールが必要

3.スケッチ
 ①station.hに現在下記の10局を登録してあります。
  新しい局を見つけて登録すれば拡張できます。
  そのurlとLCD表示用の名前を14文字以内で記入して下さい。
  その後、max_stも変更して下さい。

//station.h
// プリセット インターネットラジオ局 URL

int max_st=9; //max-1
const char * station[][2]={
  {"http://radio.kahoku.net:8000/;?type=http&nocache=652", "FM-kahoku"},
  {"http://listen.181fm.com/181-beatles_128k.mp3","181-beatles"},
  {"http://ais-sa2.cdnstream1.com/b22139_128mp3", "SMOOTH JAZZ"},
  {"http://relax.stream.publicradio.org/relax.mp3","ClassicalRelax"},
  {"http://ice1.somafm.com/illstreet-128-mp3",    "illstreet"},
  {"http://ice1.somafm.com/secretagent-128-mp3",  "secretagent"},
  {"http://ice1.somafm.com/seventies-128-mp3",    "seventies"},
  {"http://ice1.somafm.com/bootliquor-128-mp3",   "bootliquor"},
  {"http://stream.srg-ssr.ch/m/rsj/mp3_128",      "rsj"},
  {"http://icecast.omroep.nl/3fm-sb-mp3",         "3fm-sb"}

};

 ②電源ON時に以前の状態を読み出しています。

   // NVM sta No. --------------------------------------------
   Serial.println("NVM Setup");
   pref.begin("my-app",false);            // Namspace,RW mode
   vol = pref.getInt("vol",14);           // Read NVM Memory
   rsn = pref.getInt("rsn",7);            // Read NVM Memory
   isn = pref.getInt("isn",0);            // Read NVM Memory
   _flg_radiko = pref.getBool("flg_st", false); // Read NVM Memory
   Serial.printf("radiko=%d isn=%d rsn=%d vol=%d \n",_flg_radiko,isn,rsn,vol);

 ➂「radiko」と「i-radio」の切り替えは最上段の「radiko」「i-radio」の部分をタッチ
  すると切り替え出来ます。
  後は「CH-」「V+」などの部分をタッチして替えます。
 操作箇所_radiko

 ④「ES3C28P」用スケッチ構成(zipファイルにて)
  (1)「es3c28p_radiko_fft.ino」--本体スケッチ
  (2)「station.h」---------------インターネットラジオ局リスト
  (3)「es8311.h」----------------オーディオチップ用ドライバ
  (4)「es8311.cpp」--------------オーディオチップ用ドライバ
  (5)「touch.ino」---------------タッチパネルスケッチ
  
  (保障無しの自己責任で)  es3c28p_radiko_fft.zip

 ⑤「JC3248W535」用スケッチ構成(zipファイルにて)
  (1)「jc3248w535_radiko_fft.ino」--本体スケッチ
  (2)「station.h」---------------インターネットラジオ局リスト
  (3)「touch.ino」---------------タッチパネルスケッチ 

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

 *JC3248W535の「radiko」選択時の画面 
 jc3248w535_radiko
 *JC3248W535の「i-radio」選択時の画面 
 jc3248w535_i_radio

4.2025/12/16追記
 ES3C28Pでのレベルメータの表示を■から●に変更してみました。
 460行当たりのレベルメータ表示関数「void drawLevelMeter()」を下記に置き換えると
 写真のような表示となります。
 es3c28p_iradio_2
 

void drawLevelMeter() {
  int barWidth = (METER_WIDTH - BAR_COUNT + 1) / BAR_COUNT; // バー間に1pxの隙間
  
  for (int i = 0; i < BAR_COUNT; i++) {
    int x = METER_X + i * (barWidth + 1);
    int radius = (barWidth/2)-1;
    int barHeight = (int)(levels[i] * (METER_HEIGHT-radius));
    int xx=x+(barWidth/2); //radius+1;
    // 背景をクリア(上部)
    gfx->fillRect(x, METER_Y, barWidth, METER_HEIGHT - barHeight, COLOR_BG);
    if (barHeight > 0) {
      int y0=METER_Y + METER_HEIGHT;
      for(int y1=radius+1;y1<barHeight;y1+=(radius*2)+2) {
        int yy=y0-y1;
        uint16_t color;                    // バーの色を決定(高さに応じて)
        if (y1 < ((int)(METER_HEIGHT * 0.5))) color=COLOR_LOW;     // 緑(低レベル)
        else if (y1 < ((int)(METER_HEIGHT * 0.75))) color=COLOR_MID;// 黄色(中レベル)
        else color=COLOR_HIGH;             // 赤(高レベル)
        gfx->fillCircle(xx, yy, radius, color);
      }
    }
    // ピークインジケータ(小さな横線)
    int peakY = METER_Y + METER_HEIGHT - (int)(peaks[i] * METER_HEIGHT);
    if (peaks[i] > 0.05) { // 最小閾値
      //gfx->fillCircle(xx, peakY, radius,   COLOR_PEAK);
      gfx->drawFastHLine(x, peakY, barWidth, COLOR_PEAK);
    }
  }
  //lcd_flush();
}

5.「ESP32-4848S040」「JC3248W535」での●表示については、下記ブログ内記事を
  参照してみて下さい。 
以上


ブログトップへ

◆ネットサーフィンしていて「deepseek」を使用した AI 小智「XiaoZhi」なる物を
 発見しました。
 基本は、中国語ですが、言語を日本語に変更することで日本語で会話出来るように
 なりました。
 小智「XiaoZhi」
 ソースも公開されていますが、ESP-IDFの為、ちょっとハードルが高いです。
 よって、簡単に導入試験出来るように、各種ボードのバイナリファイル(.bin)が
 用意されています。詳しくは下記で
  xiaozhi-esp32

  追記:最新バージョン


1.今回、持ち合わせの関係で、「M5ATOMS3+EchoBase」と「ESP32S3DevKIt+α」で
 試してみました。

2.「ATOMS3」にバイナリファイルを書込みます。
  (1)ATOMS3
  (2)ATOMS3R (8MB PSRAM搭載)
  (3)Atomic Echo Base(マイクロフォン/スピーカー搭載 音声認識ベース)

 ①M5Burnerを下記サイトでダウンロード、解凍し、「M5Burner.exe」を実行します。
  https://docs.m5stack.com/en/download

 M5BurnerV3

 ②左側でATOMS3を選択します。
 ➂表示されたアプリの中の「XiaoZhi Voice Assistant For AtomS3R」を選択し
 ④さらに選択肢として四つありますので、自分の機種に合わせ選択します。
  *上から三つは「ATOMS3R」用でウェイクアップする言葉を選択します。
  *一番下が「ATOMS3」用で釦を押して会話を始めます。(私のはこれです。)
 ⑤選択したら、ダウンロードし書き込みます。
 M5B_ATOMS3_burner

3.書き込みが終わったら、再起動します。
 ①まず自分用のWiFiのアクセスポイントを設定する為に、「ATOMS3」に接続します。
 ②スマホかタブレット等(私は、iPad)でWiFiを検索します。
 ➂表示された「Xiaozhi-7F9D」に接続します。「7F9D」は、個体によって変わるかも。
 ipad-1

 ④192.168.4.1へブラウザで開きます。
  (1)SSIDを下から選んで設定します。
  (2)パスワードを設定します。
  (3)間違いなかったら接続します。
 ipad-2

 ⑤接続出来たら下記の画面となり、再起動します。
 ipad-3

 ⑥再起動したら、WiFiに接続後バージョンアップが自動で実行されます。
   少々時間がかかります。
 ⑦これで、中国語版のAIアシスタントが出来上がりです。
 ⑧画面に表示される登録に必要な六桁の端末番号を控えておきます。
  
4.次に日本語が話せるように設定します。
 ①下記のURLを開き「コンソール」にログインします。
  https://xiaozhi.me/

 XiaoZhi-1
  
 ②必要な項目を入力します。
  (1)国番号と携帯電話番号を入力します。
  (2)グラフィック文字を入力します。(見にくい場合はねクリックすると替わります。)
  (3)携帯に確認コードを送信します。
  (4)携帯に送られてきた六桁の確認コードを入力します。
 XiaoZhi-2

 ➂全て正常に入力されたら、「ログイン」バーが空色に変わりますのでクリックして
  ログインします。
 XiaoZhi-3

 ④「+エージェントを作成」をクリックし、設定します。
 XiaoZhi-4

 ⑤作成出来たら「ロール設定」をクリックして「言語優先」の欄を「日本語に」設定します。
  これで、日本語対応となります。
 XiaoZhi-5

 ⑥下にスクロールして「保存」をクリックして終わります。
 XiaoZhi-6
 
 ⑦元に戻り「デバイスを管理」をクリックして、デバイスを登録します。
  この時3-⑧の六桁の端末番号をにゅりょくします。
 XiaoZhi-7

  [注意]説明の画面は、一回登録後の画面ですので順番が変わっているかもしれませんので
   適宜推察してあくまでも参考として下さい。

以上で「ATOMS3+Echo Base」で、日本語を喋らせることが出来ました。

6.続いて「ESP32S3Devkit」で構築してみます。

 ①ピン設定
 #define AUDIO_I2S_MIC_GPIO_WS   GPIO_NUM_4
 #define AUDIO_I2S_MIC_GPIO_SCK  GPIO_NUM_5
 #define AUDIO_I2S_MIC_GPIO_DIN  GPIO_NUM_6

 #define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7
 #define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15
 #define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16

 #define BUILTIN_LED_GPIO        GPIO_NUM_48
 #define BOOT_BUTTON_GPIO        GPIO_NUM_0
 #define TOUCH_BUTTON_GPIO       GPIO_NUM_47
 #define VOLUME_UP_BUTTON_GPIO   GPIO_NUM_40
 #define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_39

 #define DISPLAY_SDA_PIN GPIO_NUM_41
 #define DISPLAY_SCL_PIN GPIO_NUM_42
 #define DISPLAY_WIDTH   128

 ②ピン設定を元にハードの接続図を下記に示します。
  (1)ESP32S3Devkit
  (2)MAX98357A I2Sアンプ
  (3)MS3625/INMP441 I2Sマイク(現在:SPH0645 I2Sマイク 動作せず)
  (4)0.91インチOLED 128x32

 接続図

 esp32s3-xiaozhi

 ◆2025/06/12追記
  マイクが到着しましたので、交換しました。
  これで使えるようになりました。
  ATOMS3は、普通に交互に会話出来ていましたのに、この構成では
  ちょっとがっかりで、ボタンを押しながら話しかけないと反応しませんでした。
 ◆2025/07/16追記
  バージョンを1.7.6にしましたら、ボタンを押さなくとも「ニイハオ ショウチ」で
  応答開始してくれるようになりました。また交互に会話できるようにもなりました。

 esp32s3-xiaozhi_2

 *オリジナルの接続写真
 オリジナルESP32S3


 ②出来たら下記URLにて「バイナリファイル」をダウンロードします。

  追記:最新バージョン *2025/11/30 v.2.0.5

  xiaozhi-esp32 V1.7.6 *2025/11/30 v.1.7.6

  xiaozhi-esp32 V1.6.6 

 devkit-1
 devkit-2

  (1)「v1.6.6_bread-compact-wifi.zip」のファイルをダウンロードします。

  (2)もし、手持ちに0.96インチのOLEDが有る場合は、 
   「v1.6.6_bread-compact-wifi-128x64.zip」をダウンロードします。
 
 ➂バイナリファイルをESP32S3に書き込むツールを下記よりダウンロードし、解凍し
 「flash_download_tool_3.9.7.exe」を実行します。
  Flash Download Tool (バージョン3.9.7) 
 
  (1)「ChipType」を「ESP32S3」を選択
  FDT3-1

  (2)「OK」をクリック
  FDT3-2

  (3)②でダウンロードした「merged-binary.bin」を選択
  (4)COMポートを選択
  (5)「START」で書き込む

 FDT3-3

 FDT3-4

 ④その後は、「ATOMS3」と同様にWiFi設定からデバイス登録までします。

 ⑤別の機種で構築する場合は、合ったものをここから探して書き込めば行けると思います。

 ⑥下記は、二個登録した状態
 
 devkit-3

 ◆2025/06/02時点でI2Sマイクが、オリジナルと違うため、音声入力が出来ていません。
  現在、「AliExpress」に注文している所です。
 ◆2025/06/12マイクが届いてうまく機能するようになりました。

7.実際の日本語に会話デモ
 *デモで話してみましたが、データベースがちょっと古いです。
  Web版のdeepseepでの質問と回答です。
 deepseek_Q&A

 

  
 
以上


ブログトップへ

◆ESP32S3搭載のES3C28Pボードでファミコンのエミュレータ「ESP32-S3_Uno-nofrendo」が
 動きました。
 esp32s3_nes

 このボードの主な特徴ですが、手ごろな価格の全部入りでコスパが良いものです。
  ①ESP32S3N16R8
  ②320x240 ILI9341 2.8インチ LCD
  ➂4-bit SD mode SD_MMC(今回1bit modeで使用
  ④ES8311オーディオチップ使用のI2S I/F 外部スピーカーとマイク内蔵
  ⑤静電容量方式タッチパネル(今回未使用)

 前回の記事で最初サンプルプログラムでの修正がうまくいかず保留していましたが、
 問題を解決できで無事動くようになりました。
 
 このボードは下記で入手しました。 
  A73E-ESP32-S3 ボイスチャットモジュール AI 開発ボード Xiaozhi 用
  2.8 インチ LCD Wifi Bluetooth TFT モジュール

  
1.下準備として下記ブログ内記事を参照して「ESP32-S3_Uno-nofrendo」を
  インストールして下さい。
 ・ESP32S3ボードでファミコンのエミュレータ「ESP32-S3_Uno-nofrendo」を動かしてみた

2.開発環境 2025/11/24時点
  ①Windows11 X64 Pro 25H2 
  ②Arduino IDE 2.3.6
  ➂ESP32ボードバージョンV3.2.3
  ④Arduino_GFX_Library(GFX Library for Arduino) v1.6.2 (v1.6.3はエラーの為使用せず)

3.「ES3C28P」ボードのスケッチについて
  (保障無しの自己責任で)  es3c28p_nofrendo.zip

 es3c28p_nes0

 ①コントローラは、前回同様のWiiコントローラを使いました。
  ボードの下記写真の所にコネクタを挿しました。
 es3c28p_i2c

 ②SDカードは、SD_MMCとして使えるようにしました。
 ➂I2S関連の「sound.c」は、ES8311の初期化等追加しましたので「sound.cpp」として
  コンパイルが通るようにしました。

4.続いて「JC3248W35」スケッチです。
  (保障無しの自己責任で)  jc3248w535_nofrendo.zip

 ◆残念なことにLCDが3.5インチと大きくなったのにゲーム画面のサイズが大きく
  なりませんでした。改造の必要があります。
 jc3248w535_nes0

 ①コントローラは、前回同様のWiiコントローラを使いました。
  ボードの下記写真の所にコネクタを挿しました。
  このボードは、ES3C28Pと違って電源ラインが入れ替わっているので注意が必要です。
 jc3248w535_i2c
 jc3248w535_i2c_pin

 ②SDカードは、通常のSDとして組んだのですがSPIがLCDと競合して
  最初上手く動きませんでした。
  色々調べてLCDをVSPI、SDをHSPIに分離することにより動くようになりました。
 ➂I2S関連の「sound.c」は、サンプルのままでOKでした。


以上 ESP32S3搭載のボードで「ESP32-S3_Uno-nofrendo」を動かす事が出来ました。



ブログトップへ

◆ESP32S3搭載のボードでファミコンのエミュレータ「ESP32-S3_Uno-nofrendo」を
 動かしてみました。
 まず、ボードに液晶表示、SDカードアダプタ、スピーカー端子が付いている
 「ES3C28P」で試してみました。
 所が、サンプルプログラムで使っている標準のSDカードアダプタではなく、
 SD_MMCタイプで上手くいきませんでした。
 音声出力のI2S出力も「ES8311」を使っていてそのままでは動きません。

 追記:何とか動きました。詳しくは下記ブログ内記事で
 ・ES3C28P JC3248W35 でNESエミュレータ「ESP32-S3_Uno-nofrendo」を動かしてみた
 
1.エミュレータが動く事を確認する為にサンプルプログラムが動く環境を作りました。
 ブレッドボードでESP32S3,ILI9341LCD,I2Sアンプ等繋いで試験しました。
 ILI9341LCD_NES

2.LCD,SD_CARD,PCM5100A,WiiとESP32S3との接続
 (*)は、パラ接続
 
  LCD -------- ESP32S3
  VCC ---------- 5V
  GND --------- GND
  CS ------------ 18
  RESET ------ 17
  DC ------------ 16
  MOSI -------- 11(*)
  SCK --------- 12(*)
  LED ---------- 46
  MISO ------- 13(*)
  T_CLK ------ 12(*)
  T_CS --------- 3 
  T_DIN ------- 11(*)
  T_DO -------- 13(*)
  T_IRQ --------  8
  
 SD_CARD ------ ESP32S3
  SD_CS -------- 10
  SD_MOSI ----- 11(*)
  SD_MISO ----- 13(*)
  SD_SCK ------ 12(*)
 
 PCM5100A - ESP32S3
  VCC --------- 3V3
  GND --------- GND
  SD ----------- NC
  MC ----------- NC
  BCK ---------- 6
  DIN ----------- 5
  WS ----------- 4  
 
 WiiClassicController
  Wii ----------- ESP32S3
  VCC --------- 3V3
  GND --------- GND
  SDA ---------- 41
  SCL ---------- 42 

3.「ESP32-S3_Uno-nofrendo」は、下記からダウンロードして、ArduinoIDEのライブラリに
 zip形式でインストールして下さい。

 ②インストールしコンパイル中にエラーが出たら下記ファイルを修正すればOKでした。
  「\libraries\arduino-nofrendo\src\memguard.c」の32行部分に「#include "osd.h"」挿入
 memguard32

 ➂またデバッグ中にメッセージが鬱陶しかったから下記ファイル
  「\libraries\arduino-nofrendo\src\memguard.c」の262行部分をコメントアウト

 memguard262

4.スケッチについて
  (保障無しの自己責任で)  ESP32S3_ILI9341_nofrendo.zip

 ①コントローラについては、配線が楽なI2C接続のWiiコントローラを使いました。
  Wiiコントローラについては、下記を参照して下さい。
   Wii Classic Controller

 ②起動する前にSD_CARDにROMファイル「.nes」を保存してアダプタに挿入して下さい。
  起動すると選択画面が表示されます。「Max40個」
  「up」/「down」で選択し「A」で決定します。
 ILI9341LCD-3

5.エミュレータについては下記ブログ内記事も参照してみて下さい。

ブログトップへ

◆「ESP32 S3 N16R8 開発ボード WiFi モジュールキット ダブルマイクスピーカー付き
  AI 音声インタラクション DIY IOT スマートホーム拡張用」なるボードを使って
  色々遊んでみました。
  この開発ボードを選んだのは、「AI チャットボットxiaozhi-esp32」が動かせるマイクと
  スピーカーが付いていたためです。
 開発ボード1
  「WabRadio」を組み込んでみました。
 wabradio
 
1.LCDを接続するにあたって、拡張GPIOのピンアサインが、中途半端な為、汎用的に使える
  アダプタを作りました。
 ①上側のL字ピンコネクタを撤去して垂直のピンコネクタを付けました。
 ②これで上側と右側のコネクタに刺さるよう配置した、アダプタを蛇の目基板で
  作成しました。
 ◆アダプタ表
 アダプタ表
 ◆アダプタ裏
 アダプタ裏

 ➂下記は、写真とピン接続図です。
 LCD用アダプタ
 アダプタとLCD

 ④これにて大概のLCDを接続出来ます。


6.各LCDの入手先
 ①変換アダプタ(手持ち部品)

 ②5 個 0.96 インチ OLED I2C IIC ディスプレイモジュール 12864 128x64 ピクセル
  SSD1306 ミニ自発光 OLED スクリーンボード Arduino Raspber 用


 ➂1.54 インチ 1.54 "フルカラー TFT ディスプレイモジュール HD IPS LCD LED
  スクリーン 240x240 SPI インターフェイス ST7789 Arduino 用


 ④2.0 インチ TFT LCD ディスプレイ、ロータリーエンコーダー EC11 IIC SPI
  インターフェース付き、Arduino ESP32 Raspberry Pi DIY プロジェクト用


 ⑤工場オリジナル 2.8 "240*320 ILI9341 スマート表示画面 2.8 インチ SPI LCD TFT
  モジュールタッチ TFT ディスプレイあり/なし


7.開発ボード資料と入手先
 ①ESP32 S3 N16R8 開発ボード マイクスピーカー付き 回路図等参考資料

 ②ESP32 S3 N16R8 開発ボード WiFi モジュールキット ダブルマイクスピーカー付き
  AI 音声インタラクション DIY IOT スマートホーム拡張用




今日は、ここまで


ブログトップへ

◆facebookで紹介のあったWabRadioをZHENGCHEN_1_54TFT_WIFI に移植してみました。
 オリジナルは、下記を参照して下さい。

 ①前からと内部の写真
 ZHENGCHEN_1_54-2

 ZHENGCHEN_1-2

 ZHENGCHEN_1_54-1

 zhengchen-1.54tft-wifi
 
 zhengchen-1.54tft-wifi-2

1.スケッチについては、以前作った物を修正しました。
 下記ブログ内記事を参照してみて下さい。
 ・JC3248W535C ESP32-4848S040C で「WabRadio」を作ってみた

2.スケッチの概要
 ①GPIOピンアサイン
 #define AUDIO_I2S_MIC_GPIO_WS    GPIO_NUM_4
 #define AUDIO_I2S_MIC_GPIO_SCK   GPIO_NUM_5
 #define AUDIO_I2S_MIC_GPIO_DIN    GPIO_NUM_6
 #define AUDIO_I2S_SPK_GPIO_DOUT  GPIO_NUM_7
 #define AUDIO_I2S_SPK_GPIO_BCLK  GPIO_NUM_15
 #define AUDIO_I2S_SPK_GPIO_LRCK  GPIO_NUM_16

 #define BOOT_BUTTON_GPIO           GPIO_NUM_0
 #define VOLUME_UP_BUTTON_GPIO    GPIO_NUM_10
 #define VOLUME_DOWN_BUTTON_GPIO   GPIO_NUM_39

 #define DISPLAY_SDA  GPIO_NUM_41
 #define DISPLAY_SCL  GPIO_NUM_42
 #define DISPLAY_RES  GPIO_NUM_45
 #define DISPLAY_DC  GPIO_NUM_40
 #define DISPLAY_CS  GPIO_NUM_21

 #define DISPLAY_WIDTH   240
 #define DISPLAY_HEIGHT  240
 #define DISPLAY_SWAP_XY  false
 #define DISPLAY_MIRROR_X false
 #define DISPLAY_MIRROR_Y false
 #define BACKLIGHT_INVERT false
 #define DISPLAY_OFFSET_X  0
 #define DISPLAY_OFFSET_Y  0

 #define DISPLAY_BACKLIGHT_PIN  GPIO_NUM_20
 #define DISPLAY_BACKLIGHT_OUTPUT_INVERT false

 バッテリー ADC1_CHANNEL_7 GPIO8

 ②このボードには、タッチパネルが付いていていませんので、スイッチ入力で対応しました。
 
 ➂LCDの解像度が240x240の為、表示位置のサイズ変更をしました。
 
 ④バッテリーの残量表示を追加しました。

 ⑤追記 GFX Librrary for Arduino ライブラリについては最新のV1.6.2でOKです。

3.移植後のスケッチです。
  (保障無しの自己責任で)  WebRadio_zhengchen.zip

4.実行時の説明
 ①シリアル出力
 シリアル出力
 ②操作
 ZHENGCHEN_画面説明-1

 ➂動作デモ
 
 

5.「ZHENGCHEN_1_54TFT_WIFI」の入手先
 ①ディープシーク 小智 ミニAIロボット | スマート音声チャットボット、感情的な対話、
  パーソナライズされたAIコンパニオン、ユニークなギフトアイデア

 ②多分同じボードを使っているもの
 ESP32-S3開発ボード(1.54インチTFT LCDディスプレイ、スピーカー搭載)
 AI音声対話チャットロボットESP32 S3 N16R8キット



以上


ブログトップへ

◆facebookで大野さんから紹介のあったWabRadioをJC3248W535C ESP32-4848S040C に
 移植してみました。感謝です。
 JC3248W535C-3

 JC3248W535C-2

 オリジナルは、下記を参照して下さい。
 macsbug 480×320 ILI9488 WebRadio

 ◆あとブレッドボードでの製作例は、下記ブログ内記事も参照してみて下さい。
 ・ESP32S3 3.5'480x320 ILI9488 With Touch PCM5100A にてWabRadioを作ってみた

 
1.スケッチについては、上記オリジナルのサイトよりダウンロードして、修正しました。
2.まず各ボードのGPIOピンアサインを調べて対応させます。
 GPIOピンアサイン

3.LCD表示のライブラリを「lovyanGFX」から「Arduino_GFX_Library」へ変更しました。
 ① GFX Librrary for Arduino :1.6.0 にバージョンダウンしました。
  *最新のV1.6.1は表示が波打って正常に表示されませんでした。
 ②表示用関数等の対応
  (1)「JC3248W535C」は、CANVASを使っている為、描画後flushする必要が有ります。
  (2)「ESP32-4848S040C」は、なぜかバックライトのPWM制御が効きませんでした。
   *今後対応検討

//********************************************************************************
//「lovyanGFX」から「Arduino_GFX_Library」へ変更に伴い対応関数
//********************************************************************************

//==============================================================
//JC3248W535kのLCD対応
void lcd_flush(){
#if defined(JC3248W535)
  gfx->flush();
#endif
}
//==============================================================
//バックライト制御 直接 PWM 制御する
void setBrightness(int brightness) {
#if defined(JC3248W535)
  ledcWrite(GFX_BL,brightness);     // 明るさ設定 // 0~100 の値
#endif
}
//============================================================
// 文字列描画(中央寄せ用)
void drawString(const String &msg, int x, int y) {
  int16_t x1, y1;
  uint16_t w, h;
  gfx->getTextBounds(msg, x, y, &x1, &y1, &w, &h); // テキストサイズを取得
//  gfx->fillRect(x - w / 2, y , w, h, bc); // 文字が描かれる矩形部分をクリア
  gfx->setCursor(x - w / 2, y);           // 横中央に来るように座標を補正
  gfx->print(msg);
  lcd_flush();
}
//============================================================
// Arduino_GFX_Library 用 透過色対応 pushImage
// (LGFX の pushImage の代替)
void pushImageWithTransp(
  int16_t x, int16_t y,
  int16_t w, int16_t h,
  const uint16_t *data,
  uint16_t transp_color) {
  for (int16_t yy = 0; yy < h; yy++) {
    for (int16_t xx = 0; xx < w; xx++) {
      uint16_t c = data[yy * w + xx];
      if (c != transp_color) {
        gfx->drawPixel(x + xx, y + yy, c);
      }
    }
  }
}
//============================================================
// endian swap + コピー
void swapBytesToBuf(const uint16_t *src, uint16_t *dst, int count) {
  //Serial.printf("src[%p] dst[%p] count=%d ",src,dst,count);
  for (int i = 0; i < count; i++) {
    uint16_t v = src[i];
    dst[i] = (v >> 8) | (v << 8);  // endian swap
    //Serial.printf("src[%d]=%04X dst[%d]=%04X\n", i, src[i], i, dst[i]); 
  }
  //Serial.printf(" src[%04X] dst[%04X] \n",src[0],dst[0]);
}
//==============================================================
// 任意角度 (0.1°単位) + ズーム描画
// angle: 角度 [度] (例: 0, 45.3, 180.7 ...)
// zoom : 拡大率 (例: 0.5, 0.7, 1.5)
// colorkey: 透明色 (使わないなら 0xFFFF など存在しない値を渡す)
void drawBitmapRotateZoom(
    int16_t x, int16_t y,
    const uint16_t *src, int w, int h,
    float angle, float zoom,
    uint16_t colorkey)  {
  float rad = angle * DEG_TO_RAD;  // 度→ラジアン
  float cosA = cos(rad) / zoom;
  float sinA = sin(rad) / zoom;
  int cx = w / 2;
  int cy = h / 2;
  int newW = (int)(w * zoom);
  int newH = (int)(h * zoom);

  for (int yy = 0; yy < newH; yy++) {
    for (int xx = 0; xx < newW; xx++) {
      // 出力座標 → 元画像の座標に逆変換
      float sx = (xx - newW / 2) * cosA + (yy - newH / 2) * sinA + cx;
      float sy = -(xx - newW / 2) * sinA + (yy - newH / 2) * cosA + cy;

      int isx = (int)round(sx);
      int isy = (int)round(sy);

      if (isx >= 0 && isx < w && isy >= 0 && isy < h) {
        uint16_t c = src[isy * w + isx];
        if (c != colorkey) {  // 透明色処理
          gfx->drawPixel(x + xx, y + yy, c);
        }
      }
    }
  }
  lcd_flush();
}
//==============================================================

 ➂タッチパネルのライブラリを感圧式(抵抗膜)式から静電容量方式に変更しました。
  *Library : bb_captouch : 1.3.1
   このままだと、「JC3248W535」採用の「AXS15231」に対応していなかったため
  ソースを修正しました。

 (1) 「C:\Users\yoshito\Documents\Arduino\libraries\bb_captouch\src\bb_captouch.cpp」内の
  下記177行と186行をコメントアウトします。
  
  177://#ifdef FUTURE
  178:    if (I2CTest(AXS15231_ADDR)) {
  179:       _iType = CT_TYPE_AXS15231;
  180:       _iAddr = AXS15231_ADDR;
  181:       if (iRST != -1) {
  182:          reset(iRST);
  183:       }
  184:       return CT_SUCCESS;
  185:    } // AXS15231
  186://#endif

4.移植後のスケッチです。
  (保障無しの自己責任で)  WebRadio_jc3248w535.zip

 ◆まず「WebRadio_jc3248w535.ino」内の下記を変更してからコンパイルします。
  ①148/149行でssidとpassを修正します。
  148:char ssid[] = "xxxxxxx"; // your network SSID (name) 
  149:char pass[] = "yyyyyyy"; //your network password

  ② 60/61行で使用するボードのコメントを取ります。
  60://#define  JC3248W535      // esp32s3 Dev USBCDCOnBoot=en ・・・・
  61:#define  ESP32_4848S040  // esp32s3 Dev USBCDCOnBoot=ds ・・・・ 

5.「JC3248W535C」 と「ESP32-4848S040C」の入手先
 ①「JC3248W535C」
  ESP32-S3 3.5 インチ容量性タッチ IPS モジュール 8M PSRAM 16M フラッシュ
  Arduino LVGL 開発 320 * 480


 ②「ESP32-4848S040C」
  ESP32-S3 Arduino LVGL WIFI および Bluetooth 開発ボード 4.0 インチ
  480 * 480 スマートディスプレイ容量性タッチ、ボトムシェルなし


6.デモ動画
 

◆新しく1.54インチのLCDボードに「WabRadio」を移植してみました。
 下記ブログ内記事を参照してみて下さい。
 ・ZHENGCHEN_1_54TFT_WIFI で「WabRadio」を作ってみた


以上
 
 


ブログトップへ

◆facebookで紹介のあったWabRadioを作ってみました。
 WebRadio_ILI9488_S3

  ◆オリジナルは、下記を参照して下さい。感謝感激
  macsbug 480×320 ILI9488 WebRadio
 
1.スケッチについては、上記よりダウンロードして、GPIOピン割り当てと
 WiFiのSSIDとPWを自分用に変更しました。

 ①lgfx_ILI9488.h内
  19:cfg.pin_sclk    = 10; //4;         // SPIのSCLKピン番号を設定 SCK
  20:cfg.pin_mosi   = 11; //7;         // SPIのMOSIピン番号を設定 SDI
  21:cfg.pin_miso   = 46; //1;         // SPIのMISOピン番号を設定 (-1 = disable) SDO
  22:cfg.pin_dc       = 12; //16;         // SPIのD/C ピン番号を設定 (-1 = disable) RS
  23:// SDカードと共通のSPIバスを使う場合、MISOは省略せず必ず設定してください。

  29:cfg.pin_cs         =    14; // 8; // CS  接続のピン番号(-1 = disable)
  30:cfg.pin_rst         =    13; //18; // RST 接続のピン番号(-1 = disable)

  50:cfg.pin_bl        = 9; //5;         // バックライトが接続されているピン番号 BL

  69:cfg.pin_sclk    =  3; // 2;     // SCLK接続のピン番号, TP CLK
  70:cfg.pin_mosi   = 18; //41;     // MOSI接続のピン番号, TP DIN
  71:cfg.pin_miso   = 17; //40;     // MISO接続のピン番号, TP DOUT
  72:cfg.pin_cs       =  8; //42;     // CS  接続のピン番号, TP CS 

 ②WebRadio_ILI9488_S3.ino内
  74:#define BCLK 6 // Set the I2S pins
  75:#define DIN    5 // Set the I2S pins
  76:#define LRC   4 // Set the I2S pins

  78:char ssid[] = "IO_Net_2G"; // your network SSID (name) 
  79:char pass[] = "1234567890"; //your network password

 
2.LCD、PCM5100AとESP32S3との接続
 *配線が楽になるように割り当てました。
 
  LCD -------- ESP32S3
  VCC -------- 3V3 *最初5Vを繋ぎましたが。電圧が出ていませんでした。
  VCC --------5V *電源のIN-OUTをブリッジしてUSBからの電源に繋ぎました。下記写真参照
  GND -------- GND
  CS ---------- 14
  RESET ---- 13
  DC ---------  12
  MOSI ------- 11
  SCK -------- 10
  LED ---------  9
  MISO ------- 46
  T_CLK ------  3
  T_CS --------  8
  T_DIN ------ 18
  T_DO ------- 17
  T_IRQ ------ 16
 
 PCM5100A - ESP32S3
  VCC -------- 3V3
  GND -------- GND
  SD ----------- NC
  MC ----------- NC
  BCK ---------- 6
  DIN ----------- 5
  WS ------------ 4

 ◆5Vへ出力変更
 5V出力
 WebRadio_ILI9488_S3最終

3.修正後のコンパイルについて(環境によって変わるかも)
 ◆2025/09/27
 *Arduino-ESP32 v2.0.18
 *LovyanGFX v1.2.7

 ①私の場合、コンパイル時下記エラーが出ました。
  c:\Users\yoshito\Documents\Arduino\libraries\LovyanGFX\src\lgfx\v1\platforms\esp32s3\
   Bus_RGB.cpp: In function 'void lgfx::v1::_gpio_pin_sig(uint32_t, uint32_t)':
  c:\Users\yoshito\Documents\Arduino\libraries\LovyanGFX\src\lgfx\v1\platforms\esp32s3\
   Bus_RGB.cpp:98:5: error: 'gpio_hal_iomux_func_sel' was not declared in this scope;
    did you mean 'gpio_hal_func_sel'?
   98 |     gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[pin], PIN_FUNC_GPIO);
      |     ^~~~~~~~~~~~~~~~~~~~~~~
      |     gpio_hal_func_sel

  exit status 1
 
 ②対策(ChatGPTで教えてもらいました。)
 // IDF v4 では gpio_hal_iomux_func_sel を使っていたが、v5 では削除された
 // 代わりに gpio_ll_func_sel か gpio_hal_func_sel を使う
 
  \libraries\LovyanGFX\src\lgfx\v1\platforms\esp32s3\Bus_RGB.cpp内を修正
   98:static void _gpio_pin_sig(uint32_t pin, uint32_t sig)
   99:{
  100:  //gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[pin], PIN_FUNC_GPIO);
  101:  gpio_ll_func_sel(&GPIO, pin, PIN_FUNC_GPIO);   // ★ここを追加
  102:  gpio_set_direction((gpio_num_t)pin, GPIO_MODE_OUTPUT);
  103:  esp_rom_gpio_connect_out_signal(pin, sig, false, false);
  104:}

4.LCDとPCM5100Aの入手先
 ①3.5 インチ TFT LCD タッチスクリーンモジュール 480x320 Color: ILI9488 With Touch
 ②WeAct I2S スピーカー モジュール PCM5100A デュアル PA 4Ω 2.8W D クラス
 

5.「JC3248W535C」「 ESP32-4848S040C」での製作は、下記ブログ内記事も
  参照してみて下さい。
  ・JC3248W535C ESP32-4848S040C で「WabRadio」を作ってみた

以上



ブログトップへ

◆AliExpressで「Xiaozhi 小智」が動くボードを探していたら標記ボードを見つけ購入しました。
 このボードは、「Xiaozhi 小智」が動くだけでなく、拡張ポートも付いていて後々色んな
 遊び方が出来そうです。
 価格も送料込みで2000円以下でコスパ良いと思いました。
 LC-S3-WiFi-1_54tft

 下記で購入しました。
 Xiaozhi ESP32-AI ボイスチャットモジュール WIFI プラグイン LCD 付き
 
 あと、 「Xiaozhi 小智」のバージョンが最新では無かったので、色々調べて
 バージョンアップしました。

1.GPIOのピン割り当てを、下記写真等を見て回路を追い、スケッチで確認しました。
 LC-S3-WiFi-1_54tft裏
 esp32s3_ピンレイアウト

 ◆1.54インチLCD
 lcd_154
 
【GPIOピン定義】 
 0 BOOT

 1 DOUT
 2 LRCK
 3 DIN
 4 SCK
 5 MCLK
 6 SCL
 7 SDA    
 8 PACTRL 
 9 BAT    


 11 4G I/F 用
 12 4G I/F 用

 ESP32S3         1.54LCD
     GND --------1 GND
 10 TFT_DC------2 RS
 13 TFT_CS------3 CS
 14 TFT_SCLK--4 SCL
 15 TFT_MOSI--5 SDA
 16 TFT_RST----6 RST
     VDD---------7 VDD
     GND---------8 GND
 21 TFT_BL------9 BL-A
     GND--------10 BL-k

 17 Extended IO
 18 Extended IO

 19 USB D-
 20 USB D+

 39 vol-
 40 vol+

 46 LED

2.あくまでも予想回路図です。
 参考回路図ai

3.確認用スケッチ
 ◆スケッチを書き込む前に、購入時のファームウェアを保存しておけば、いつでも
  元に戻せます。
  下記ブログ内記事を参照して保存する事をお勧めします。
  ・ESP32-S3 etc でフラッシュメモリの読み書きツールを作ってみた

 ①LCD表示&バッテリ電圧モニター
 LC-S3-WiFi-1_54tft_bat

//ST7789_bat.ino
//V2025/09/13 By JK1VCK ST7789 1.54' LCD
//blog URL:https://gijin77.blog.jp/archives/45598928.html
// ESP32-S3 GPIO9 (ADC1_CH8) をアナログ入力するバッテリモニタ

#include <Arduino_GFX_Library.h>

#define TFT_DC    10
#define TFT_RST   16
#define TFT_CS    13
#define TFT_MOSI  15
#define TFT_SCK   14
#define TFT_MISO  -1
#define TFT_BL    21

Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
Arduino_GFX *gfx = new Arduino_ST7789(bus, TFT_RST, 0,true,240,240); // 240x240 1.54 LCD

const int adcPin = 9;  // GPIO9

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("Program Start");
  
  gfx->begin();
  pinMode(TFT_BL, OUTPUT); 
  digitalWrite(TFT_BL, HIGH);
  gfx->setRotation(0);
  gfx->fillScreen(RED);delay(500);
  gfx->fillScreen(GREEN);delay(500);
  gfx->fillScreen(BLUE);delay(500);
 
   // ADCの分解能設定(デフォルト12bit = 0〜4095)
  analogReadResolution(12); 

  // 測定範囲(mV換算用、ESP32-S3は0〜3300mVを推奨)
  analogSetAttenuation(ADC_11db);  
  // 他の選択肢: ADC_0db(0-800mV), ADC_2_5db(0-1100mV), ADC_6db(0-1600mV), ADC_11db(0-3300mV)

}
int count=0;
void loop() {
  char msg[200];

  int raw = analogRead(adcPin);  // 0〜4095
  float voltage = ((raw / 4095.0) * 3.3) * 2.0; // V換算 (3.3V基準)

  Serial.print("ADC Raw: ");
  Serial.print(raw);
  Serial.print("  Voltage: ");
  Serial.print(voltage, 3);
  Serial.println(" V");
 
  gfx->fillScreen(BLACK);
  gfx->setCursor(0,0);
  gfx->setTextColor(ORANGE);
  gfx->setTextSize(3);
  float fun=(float)(count*10)/60.0;
  sprintf(msg,"\n\nTime=%3.1f\n\nADC Raw:%d\n\nVoltage:%3.2fV\n",fun,raw,voltage);
  gfx->print(msg);
  count++;
  delay(10000);
}


4.Xiaozhi-esp32のバージョンアップの下準備
 ①下記よりソースファイルをダウンロード

 ②適当なフォルダへ解凍します。

 ➂その中の「main\boards\genjutech-s3-1.54tft\」下記の三つのファイルを編集します。
   main\boards\genjutech-s3-1.54tft\config.h
   main\boards\genjutech-s3-1.54tft\genjutech-s3-1.54tft.cc
   main\boards\genjutech-s3-1.54tft\power_manager.h
  *新しくボードを追加するのが面倒だったので、既存のボードで今回のボードに
   似たボードを編集しました。
  * menuconfigでは、「亘具科技1.54(s3)」と表示されます。 
 ◆2025/09/15追記
  V2.0.1でビルドエラーが発生しました。
  genjutech-s3-1.54tft.ccファイルの
  下記の,{&font_puhui_basic_20_4, &font_awesome_20_4}を削除すればOKでした。

        327:                  DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY,
        328:                   {&font_puhui_basic_20_4, &font_awesome_20_4});

 ◆ESP-IDF v5.4.1 の ESP32-S3 での ADC チャンネルと GPIO の対応表です。
  ESP32-S3 には ADC1 と ADC2 の 2つのユニットがあります。
  Arduino の analogRead() で使えるピンは、この ADC チャンネルに対応しています。
  バッテリ電圧モニタ用にGPIO9を使っていますのでADC1_CHANNEL_8です。

 * ADC1 (0〜9ch, 10ch分)
  ADC1_CHANNEL_0 GPIO1
  ADC1_CHANNEL_1 GPIO2
  ADC1_CHANNEL_2 GPIO3
  ADC1_CHANNEL_3 GPIO4
  ADC1_CHANNEL_4 GPIO5
  ADC1_CHANNEL_5 GPIO6
  ADC1_CHANNEL_6 GPIO7
  ADC1_CHANNEL_7 GPIO8
  ADC1_CHANNEL_8 GPIO9
  ADC1_CHANNEL_9 GPIO10
 * ADC2 (0〜9ch, 10ch分)
  ADC2_CHANNEL_0 GPIO11
  ADC2_CHANNEL_1 GPIO12
     ADC2_CHANNEL_2 GPIO13
     ADC2_CHANNEL_3 GPIO14
  ADC2_CHANNEL_4 GPIO15
     ADC2_CHANNEL_5 GPIO16
  ADC2_CHANNEL_6 GPIO17
  ADC2_CHANNEL_7 GPIO18
  ADC2_CHANNEL_8 GPIO19
  ADC2_CHANNEL_9 GPIO20

 ④編集したファイルを下記に「.zip」として置いておきます。
  下記よりダウンロードして置き換えて下さい。
  (保障無しの自己責任で)  genjutech-s3-1.54tft.zip

 ⑤ESP-IDF V5.X以降の環境を構築します。
  *私は、VSC+IDFv5.4.1で開発しました。 

5.ビルド手順
 ①先のフォルダを開き、PowerShellを実行します。
 
 ②> idf.py fullclean
 
 ➂> idf.py set-target esp32s3
  *上手くターゲットが、変わらない場合は、最下段のターゲット切り替えで
   出来ます。
 
 ④> idf.py menuconfig
 
  ⑤Xiaozhi Assistant  --->Board Type (亘具科技1.54(s3))  --->(X) 亘具科技1.54(s3)
  ⑥           Default Language (Chinese)  --->(X) Japanese
  ⑦ESC --> ESC --> (Y)
 
 ⑧> idf.py build
 
 ⑨> idf.py -p COM14 flash monitor
 
 以上で最新バージョンにアップデート出来ました。
 

参考までに


ブログトップへ

◆DeepSeek AI音声チャットロボットBOX ESP32-S3開発ボード 1.28インチ丸型LCD
 1.28インチタッチスクリーン N16R8 XiaoZhi用 ボードで「Launcher」を
 動かしてみました。
 S3_1_28_launcher

 下記で購入しました。
 DeepSeek AI音声チャットロボットBOX ESP32-S3開発ボード 1.28インチ丸型LCD


1.ボードGPIOのピン割り当て
 【ピン接続定義】
 TFT_DC -----47
 TFT_CS ----- 5
 TFT_SCLK --- 4
 TFT_MOSI --- 2
 TFT_RESET --38
 TFT_BL -----42

 SDMMC_D3----13 CS
 SDMMC_CMD---18 MOSI
 SDMMC_CLK---17 CLK
 SDMMC_D0----21 MISO

 TP_SDA------11
 TP_SCL------ 7
 TP_INIT-----12
 TP_RST------ 6

 I2S_MCLK----16
 I2S_SCK------9
 I2S_DOUT---- 8 
 I2S_LRCK----45 WS
 I2S_DIN-----10
 PA_CTRL-----46
 I2C_SCL-----14
 I2C_SDA-----15

2.参考回路図
 ESP32S3-128-BOX回路図

3.ソースの変更箇所等
 ①まずボードの「esp32s3-2424s012c.json」ファイルの作成
  1.LCDドライバ「GC9A01」の設定データ
  2.タッチドライバ「CST816」の設定データ
  3.ESP32S3の設定データ
  等を既存の他のボード情報より収集して作成しました。

{

  "build": {
    "arduino": {
      "ldscript": "esp32s3_out.ld",
      "partitions": "default_16MB.csv",
      "memory_type": "qio_qspi"
    },
    "core": "esp32",
    "extra_flags": [
      "-DARDUINO_ESP32S3_DEV",
      "-DBOARD_HAS_PSRAM",
      "-DARDUINO_USB_MODE=1",
      "-DARDUINO_RUNNING_CORE=1",
      "-DARDUINO_EVENT_RUNNING_CORE=1",
      "-DARDUINO_USB_CDC_ON_BOOT=1",
      "-DESP32_2424S012C",
      "-DDISPLAY_WIDTH=240",
      "-DDISPLAY_HEIGHT=240",
      "-DROTATION=0",
      "-D LVGL_BUFFER_PIXELS=(DISPLAY_WIDTH*DISPLAY_HEIGHT/4)",
      "-D LVGL_BUFFER_MALLOC_FLAGS=(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)",
      "-D GPIO_BCKL=42",
      "-D DISPLAY_IPS",
      "-D DISPLAY_GC9A01_SPI",
      "-D GC9A01_DRIVER",
      "-D GC9A01_SPI_HOST=SPI2_HOST",
      "-D GC9A01_SPI_DMA_CHANNEL=SPI_DMA_CH_AUTO",
      "-D GC9A01_SPI_BUS_MOSI_IO_NUM=2",
      "-D GC9A01_SPI_BUS_MISO_IO_NUM=GPIO_NUM_NC",
      "-D GC9A01_SPI_BUS_SCLK_IO_NUM=4",
      "-D GC9A01_SPI_BUS_QUADWP_IO_NUM=GPIO_NUM_NC",
      "-D GC9A01_SPI_BUS_QUADHD_IO_NUM=GPIO_NUM_NC",
      "-D GC9A01_SPI_BUS_MAX_TRANSFER_SZ=(LVGL_BUFFER_PIXELS*sizeof(lv_color16_t))",
      "-D GC9A01_SPI_BUS_FLAGS=0",
      "-D GC9A01_SPI_BUS_INTR_FLAGS=0",
      "-D GC9A01_SPI_CONFIG_CS_GPIO_NUM=5",
      "-D GC9A01_SPI_CONFIG_DC_GPIO_NUM=47",
      "-D GC9A01_SPI_CONFIG_SPI_MODE=SPI_MODE0",
      "-D GC9A01_SPI_CONFIG_PCLK_HZ=80000000",
      "-D GC9A01_SPI_CONFIG_TRANS_QUEUE_DEPTH=10",
      "-D GC9A01_SPI_CONFIG_LCD_CMD_BITS=8",
      "-D GC9A01_SPI_CONFIG_LCD_PARAM_BITS=8",
      "-D GC9A01_SPI_CONFIG_FLAGS_DC_AS_CMD_PHASE=false",
      "-D GC9A01_SPI_CONFIG_FLAGS_DC_LOW_ON_DATA=false",
      "-D GC9A01_SPI_CONFIG_FLAGS_OCTAL_MODE=false",
      "-D GC9A01_SPI_CONFIG_FLAGS_LSB_FIRST=false",
      "-D GC9A01_DEV_CONFIG_RESET_GPIO_NUM=38",
      "-D GC9A01_DEV_CONFIG_COLOR_SPACE=ESP_LCD_COLOR_SPACE_BGR",
      "-D GC9A01_DEV_CONFIG_BITS_PER_PIXEL=16",
      "-D GC9A01_DEV_CONFIG_FLAGS_RESET_ACTIVE_HIGH=false",
      "-D GC9A01_DEV_CONFIG_VENDOR_CONFIG=NULL",
      "-D DISPLAY_SWAP_XY=false",
      "-D DISPLAY_MIRROR_X=true",
      "-D DISPLAY_MIRROR_Y=false",
      "-D BOARD_HAS_TOUCH",
      "-D CONFIG_ESP_LCD_TOUCH_MAX_POINTS=1",
      "-D CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS=0",
      "-D TOUCH_CST816S_I2C",
      "-D CST816S_IO_I2C_CONFIG_DEV_ADDRESS=CST816S_IO_I2C_CONFIG_DEV_ADDRESS_15",
      "-D CST816S_I2C_HOST=I2C_NUM_0",
      "-D CST816S_I2C_CONFIG_SDA_IO_NUM=11",
      "-D CST816S_I2C_CONFIG_SCL_IO_NUM=7",
      "-D CST816S_I2C_CONFIG_SDA_PULLUP_EN=GPIO_PULLUP_ENABLE",
      "-D CST816S_I2C_CONFIG_SCL_PULLUP_EN=GPIO_PULLUP_ENABLE",
      "-D CST816S_I2C_CONFIG_MASTER_CLK_SPEED=400000",
      "-D CST816S_I2C_CONFIG_CLK_FLAGS=0",
      "-D CST816S_IO_I2C_CONFIG_DEV_ADDR=ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS",
      "-D CST816S_IO_I2C_CONFIG_CONTROL_PHASE_BYTES=1",
      "-D CST816S_IO_I2C_CONFIG_DC_BIT_OFFSET=0",
      "-D CST816S_IO_I2C_CONFIG_LCD_CMD_BITS=8",
      "-D CST816S_IO_I2C_CONFIG_LCD_PARAM_BITS=0",
      "-D CST816S_IO_I2C_CONFIG_FLAGS_DC_LOW_ON_DATA=false",
      "-D CST816S_IO_I2C_CONFIG_FLAGS_DISABLE_CONTROL_PHASE=true",
      "-D CST816S_TOUCH_CONFIG_X_MAX=DISPLAY_WIDTH",
      "-D CST816S_TOUCH_CONFIG_Y_MAX=DISPLAY_HEIGHT",
      "-D CST816S_TOUCH_CONFIG_RST_GPIO_NUM=6",
      "-D CST816S_TOUCH_CONFIG_INT_GPIO_NUM=12",
      "-D CST816S_TOUCH_CONFIG_LEVELS_RESET=0",
      "-D CST816S_TOUCH_CONFIG_LEVELS_INTERRUPT=0",
      "-D TOUCH_SWAP_XY=false",
      "-D TOUCH_MIRROR_X=false",
      "-D TOUCH_MIRROR_Y=false"
    ],
    "f_cpu": "240000000L",
    "f_flash": "80000000L",
    "flash_mode": "qio",
    "hwids": [
      ["0x303A", "0x1001"]
    ],
    "mcu": "esp32s3",
    "variant": "pinouts"
  },
  "connectivity": ["wifi", "bluetooth"],
  "debug": {
    "openocd_target": "esp32s3.cfg"
  },
  "frameworks": ["arduino", "espidf"],
  "name": "esp32s3-2424S012C",
  "upload": {
    "flash_size": "16MB",
    "maximum_ram_size": 327680,
    "maximum_size": 16777216,
    "use_1200bps_touch": true,
    "wait_for_upload_port": true,
    "require_upload_port": true,
    "speed": 460800
  },
  "url": "https://www.aliexpress.com/item/1005005453515690.html",
  "vendor": "Sunton"
}

 ②ボードのplalformio.iniの追加編集
[env:CYD-2424S012C]
extends = CYDS3_Base
board = esp32s3-2424S012C
extra_scripts = post:merge_bin.py
build_flags =
	${CYDS3_Base.build_flags}
	-DROTATION=0
	-DGC9A01_DRIVER
	-DLCD_BL_INV
	-D TFT_WIDTH=240
	-D TFT_HEIGHT=240
	-DTFT_BL=42
	-DTFT_RST=38
	-DTFT_DC=47
	-DTFT_MOSI=2
	-DTFT_SCLK=4
	-DTFT_CS=5

	-DHAS_TOUCH=1
	-DSDCARD_CS=13
	-DSDCARD_MOSI=18
	-DSDCARD_SCK=17
	-DSDCARD_MISO=21

 
 ➂ディスプレイ用初期化コードの作成
  src/display.cppの最後の方に「GC9A01_DRIVER」を追記
  *Ard_eSPI *tft = new Ard_eSPI(bus, 38, 2, true, 200, 200,20,20, 20,20);
  円形LCDの為、サイズ変更し、offsetも追加して中央付近表示するように指定
#elif defined(GC9A01_DRIVER)
Arduino_DataBus *bus = new Arduino_ESP32SPI(47 /* DC */, 5 /* CS */, 4 /* SCK */, 2 /* MOSI */, GFX_NOT_DEFINED /* MISO */, FSPI /* spi_num */);
// 1.28" IPS LCD 240x240
//Arduino_GFX *gfx = new Arduino_GC9A01(bus, 38 /* RST */, 3 /* rotation */, true /* IPS */, 240 /* width */, 240 /* height */, 0 /* col offset 1 */, 0 /* row offset 1 */, 0 /* col offset 2 */, 0 /* row offset 2 */);
Ard_eSPI *tft = new Ard_eSPI(bus, 38, 2, true, 200, 200,20,20, 20,20);
#else // SPI Data Bus shared with SDCard and other SPIClass devices
// Arduino_DataBus *bus = new Arduino_HWSPI(TFT_DC, TFT_CS, TFT_SCLK, TFT_MOSI, TFT_MISO, &SPI);
Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCLK, TFT_MOSI, TFT_MISO);
Ard_eSPI *tft = new Ard_eSPI(
    bus, TFT_RST, ROTATION, TFT_IPS, TFT_WIDTH, TFT_HEIGHT, TFT_COL_OFS1, TFT_ROW_OFS1, TFT_COL_OFS2,
    TFT_ROW_OFS2
);

#endif
 ④その他

 ⑤下記に修正した8個のファイルを圧縮したzipファイルを示します。
  元のソースに上書き保存してビルドして下さい。

  (保障無しの自己責任で)  CYD-2424S012C.zip

 
 ⑥フォルダ構成
 フォルダ内容

 ⑦元となるソース一式などは、下記ブログ内記事を参照して下さい。
 ・JC3248W535C ESP32-4848S040C で「Launcher」を動かしてみた

5.動作画面
 S__54255640

 S__54255639_0

以上


ブログトップへ

◆下記AliexpressでMINI ESP32-S3-N16R8 開発ボード Xiaozhi Ai 音声対話ロボットモジュール
 として販売されている物を入手して遊んでみました。
   MINI ESP32-S3-N16R8 開発ボード

 サイズが小さくて、マイク、アンプ内蔵でOLEDも接続できるコスパの良いボードです。
 これをバッテリー駆動するのとケース代わりにアクリル板でサンドイッチ上にして
 持ち運べるようにしました。
 xh-s3e-ai
 
1.バッテリ駆動にする為に、下記モジュールを使いました。
 *出力電圧で3種類ありますが、5V出力のを購入しました。
 *これは、安くて、小さいながら使いやすい物でした。
 *バッテリは、手持ちの1200mAhの物を使用しました。
 タイプ C USB TP4057 1A リチウム電池充電保護ボードモジュールポリマー電池
 TP4056 温度保護付き


 tp4057

2.ケースとして
 ①100均で透明のアクリルケースを購入して4x4.5cmサイズに切り出しました。
 xh-s3e-ai-0

 ②完成後の正面写真(下の青く光っているのが充電モジュール)
 xh-s3e-ai-F

 ➂右側より見た写真
 xh-s3e-ai-R

 ④左側より見た写真
 xh-s3e-ai-L

 ⑤後側より見た写真(こちらにスピーカを付けました。黒い四角いやつ)
 xh-s3e-ai-B

 ⑥裏側より見た写真
 xh-s3e-ai-D

 ⑦上側より見た写真(右の青いSWは、電源SWです。)
 xh-s3e-ai-U

3.GPIOピンアサイン

#define AUDIO_I2S_MIC_GPIO_WS   GPIO_NUM_4
#define AUDIO_I2S_MIC_GPIO_SCK  GPIO_NUM_5
#define AUDIO_I2S_MIC_GPIO_DIN  GPIO_NUM_6
#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7
#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15
#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16

#define BUILTIN_LED_GPIO        GPIO_NUM_48
#define BOOT_BUTTON_GPIO        GPIO_NUM_0
#define TOUCH_BUTTON_GPIO       GPIO_NUM_47
#define VOLUME_UP_BUTTON_GPIO   GPIO_NUM_40
#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_39

#define DISPLAY_SDA_PIN GPIO_NUM_41
#define DISPLAY_SCL_PIN GPIO_NUM_42
#define DISPLAY_WIDTH   128

以上

 


ブログトップへ

◆ESP32-S3等が載っているボードを購入した時、購入時のファームウェアをバックアップ
 しておいて、いつでも元に戻せる状態にする為の、「esp32_flash_tool」を作ってみました。
 esp32_flash_tool

1.準備
 ①バッチファイルを保存する適当なフォルダを作成します。
 ②書き込みツールの「esptool.exe」を探してそのフォルダにコピペします。
  私の環境では、"C:\Users\yoshito\AppData\Local\Arduino15\packages\esp32\tools\
  esptool_py\5.0.0\esptool.exe"をコピペしました。

2.下記のバッチファイルを「1-①」のフォルダへ保存します。
 *エデッタで保存する時は、シフトJISで保存しないと、漢字表示が乱れます。
  (保障無しの自己責任で)

:esp32_flash_tool.bat
@echo off
:: ============================================
:: ESP32 / ESP32-S3 Flash Backup & Restore Tool
:: V2025/08/24 By JK1VCK
:: 必要: esptool.exe (同じフォルダに置く)
:: ============================================

setlocal ENABLEDELAYEDEXPANSION

:: バッチファイルの第1引数をバックアップファイル名に利用
if "%~1"=="" (
    set BACKUP_FILE=factory_backup.bin
) else (
    set BACKUP_FILE=%~1
)

set BAUD=460800
set PORT=COM7
set CHIP=ESP32-S3
set FLASH_SIZE=16M
set FLASH_HEX=0x1000000

:MENU
echo.
echo =================================================
echo   ESP32 Flash Backup / Restore Tool
echo                        V2025/08/24 By JK1VCK
echo =================================================
echo   バックアップファイル = %BACKUP_FILE%
echo =================================================
echo   1. ポート選択 (現在: %PORT%)
echo   2. チップ選択 (現在: %CHIP%)
echo   3. フラッシュサイズ選択 (現在: %FLASH_SIZE%=%FLASH_HEX%)
echo   4. フラッシュ全体をバックアップ
echo   5. バックアップから復元
echo   6. 自動でチップ,フラッシュサイズ取得(flash-id)
echo   7. バックアップファイル名変更
echo   8. ディレクトリ表示(dir)
echo   9. 終了
echo =================================================
set /p choice="番号を入力してください: "

if "%choice%"=="1" goto PORT_SELECT
if "%choice%"=="2" goto CHIP_SELECT
if "%choice%"=="3" goto SIZE_SELECT
if "%choice%"=="4" goto BACKUP
if "%choice%"=="5" goto RESTORE
if "%choice%"=="6" goto AUTO_SIZE
if "%choice%"=="7" goto FILE_CHANGE
if "%choice%"=="8" goto FILE_DIR
if "%choice%"=="9" exit
goto MENU

:FILE_DIR
dir
pause
goto MENU

:FILE_CHANGE
set /p BACKUP_FILE=新しいバックアップファイル名を入力してください: 
goto MENU


:PORT_SELECT
echo.
echo [接続されている COM ポートを検索中...]
setlocal enabledelayedexpansion
set COUNT=0

rem PowerShellでCOMポート一覧を取得
for /f "tokens=*" %%a in ('powershell -Command "Get-CimInstance Win32_SerialPort | ForEach-Object { $_.DeviceID + ' - ' + $_.Name }"') do (
    set /a COUNT+=1
    set PORT!COUNT!=%%a
    echo !COUNT!: %%a
)
if %COUNT%==0 (
    echo *** COMポートが見つかりません ***
    pause
    exit /b
)
set /p SEL=番号を選択してください (1-%COUNT%):
for /f "tokens=1 delims= " %%b in ("!PORT%SEL%!") do set PORT=%%b
endlocal & set PORT=%PORT%
echo 選択されたポート = %PORT%
pause
goto MENU


:CHIP_SELECT
echo.
echo 対応チップ:
echo   1. ESP32
echo   2. ESP32-S2
echo   3. ESP32-S3
echo   4. ESP32-C3
echo   5. ESP32-P4
set /p ch="番号を入力してください: "
if "%ch%"=="1" set CHIP=ESP32
if "%ch%"=="2" set CHIP=ESP32-S2
if "%ch%"=="3" set CHIP=ESP32-S3
if "%ch%"=="4" set CHIP=ESP32-C3
if "%ch%"=="5" set CHIP=ESP32-P4
goto MENU

:SIZE_SELECT
echo.
echo 代表的なフラッシュサイズ:
echo   1. 2MB  (0x200000)
echo   2. 4MB  (0x400000)
echo   3. 8MB  (0x800000)
echo   4. 16MB (0x1000000)
set /p sz="番号を入力してください: "
if "%sz%"=="1" set FLASH_SIZE=2MB & set FLASH_HEX=0x200000
if "%sz%"=="2" set FLASH_SIZE=4MB & set FLASH_HEX=0x400000
if "%sz%"=="3" set FLASH_SIZE=8MB & set FLASH_HEX=0x800000
if "%sz%"=="4" set FLASH_SIZE=16MB & set FLASH_HEX=0x1000000
goto MENU

:AUTO_SIZE
echo.
echo [フラッシュサイズを自動取得中...]
for /f "tokens=*" %%i in ('esptool.exe --port %PORT% flash-id') do (
    echo %%i

    rem チップ名を取得
    echo %%i | find "Detecting chip type..." >nul
    if not errorlevel 1 (
        for /f "tokens=4" %%a in ("%%i") do set CHIP=%%a
    )

    rem フラッシュサイズを取得
    echo %%i | find "Detected flash size:" >nul
    if not errorlevel 1 (
        for /f "tokens=4" %%a in ("%%i") do set FLASH_SIZE=%%a
    )
)
echo 検出されたチップ名 = %CHIP%
echo 検出されたフラッシュサイズ = %FLASH_SIZE%

REM MB → HEX に変換
if "%FLASH_SIZE%"=="2MB"  set FLASH_HEX=0x200000
if "%FLASH_SIZE%"=="4MB"  set FLASH_HEX=0x400000
if "%FLASH_SIZE%"=="8MB"  set FLASH_HEX=0x800000
if "%FLASH_SIZE%"=="16MB" set FLASH_HEX=0x1000000
if "%FLASH_SIZE%"=="32MB" set FLASH_HEX=0x2000000
if "%FLASH_SIZE%"=="64MB" set FLASH_HEX=0x4000000

echo 書き込みに使用するサイズ: %FLASH_SIZE% = %FLASH_HEX%
echo.
pause
goto MENU

:BACKUP
if "%PORT%"=="" (
    echo [エラー] ポートが未設定です
    pause
    goto MENU
)
if "%CHIP%"=="" (
    echo [エラー] チップが未設定です
    pause
    goto MENU
)
if "%FLASH_SIZE%"=="" (
    echo [エラー] フラッシュサイズが未設定です
    pause
    goto MENU
)
echo.
echo [バックアップ開始] → %BACKUP_FILE%
esptool.exe --chip %CHIP% --port %PORT% --baud %BAUD% read-flash 0 %FLASH_HEX% %BACKUP_FILE%
echo.
echo [バックアップ完了] → %BACKUP_FILE%
pause
goto MENU

:RESTORE
if not exist %BACKUP_FILE% (
    echo [エラー] バックアップファイル %BACKUP_FILE% が存在しません
    pause
    goto MENU
)
echo.
echo [復元開始] ← %BACKUP_FILE%
esptool.exe --chip %CHIP% --port %PORT% --baud %BAUD% write-flash 0 %BACKUP_FILE%
echo.
echo [復元完了]
pause
goto MENU
 
3.バッチファイルを起動します。
 ◆コマンドとして下記の9個が選択できます。
  1. ポート選択 (現在: COM7)
  2. チップ選択 (現在: ESP32-S3)
  3. フラッシュサイズ選択 (現在: 16M=0x1000000)
  4. フラッシュ全体をバックアップ
  5. バックアップから復元
  6. 自動でチップ,フラッシュサイズ取得(flash-id)
  7. バックアップファイル名変更
  8. ディレクトリ表示(dir)
  9. 終了

 *初期状態では、バックアップファイル名は「factory_backup.bin」となっています。
  コマンド「7」で変更できます。 
 *あるいは、バッチコマンドに引数として、ファイル名を指定して実行すると
  それが、バックアップファイル名となります。
 
 ①まず最初にボードを接続してシリアルポートを設定します。
 esp32_flash_tool-1

 ②チップを選択します。
 esp32_flash_tool-2

 ➂フラッシュサイズを選択します。
 esp32_flash_tool-3
 
 ここで、②➂を自動で取得するには、コマンド「6」を実行します。
 esp32_flash_tool-6

 ④バックアップを実行します。
 ⑤復元を実行します。

◆これにて、いつでも元に戻せる状態に出来ます。

以上



ブログトップへ

◆MicroSDに保存してあるバイナリファイルを選択して起動できる
 「Launcher」なるソフトがあることが分かり、早速試してみました。
 CYD-2432W328は、インストールして問題なく動きました。
 しかし、JC3248W535Cは、表示がおかしく動きませんでした。
 ESP32-4848S040Cは、サポートすら無いボードでした。
 サイトを見るとソースファイルが公開されていましたので、表題の2ボードを
 動くように修正して何とか動くようになりました

 Launcher_cyd_1

 Launcher_cyd_2

1.「Launcher」について
 ①下記サイトに行き、自分の持っているボードが有れば選択してインストールして
  みて下さい。
  「Launcher」

 web_launcher
 
 ②「Launcher」について詳しい使い方などは、下記「macsbug」氏のサイトを
  参照して下さい。
  macsbug CYD Launcher

2.私の場合、不具合や、そこに無いボードでしたのでソースを修正することにしました。
 ①下記サイトよりソースファイル一式(zip)をダウンロードします。
  bmorcelli/Launcher
  
3.ソースの修正にあたり、「Visual Studio Code」「PlatfomeIO」のインストールが必要です。
 私は、今までAruduinoIDE環境で開発していましたが、今回の「Launcher」は、
 「VSC」「PIO」環境で開発されていましたので、ネットで調べて開発環境を整えました。

4.ソースの修正
 ①まず、表示がおかしいJC3248W535C(CYD-3248W535)を調べてみました。
 
5.JC3248W535Cボードでのオリジナルとの比較です。
 ◆比較用のソフトは、「WinMerge」を使っています。
  下記よりダウンロード出来ます。
  WinMerge 日本語版
 
 ◆フォルダ構成(下記6個のファイルを修正しています。)
 root---platfomeio.ini
           +-src---display.cpp
           l        +-main.cpp
           l        +-tft.h
           +-boards---CYD-2432S028---interfase.cpp
                                                       +-platfomeio.ini
 ①ルートフォルダ
 ファイル比較root

 ②platfomeio.iniの修正箇所
  *元のボードをコメントアウトし、CYD-3248W535C を追加しました。
  *ライブラリのバージョンを最新にししました。
 ファイル比較root_platfomeio_ini

 ➂srcフォルダ
 ファイル比較src

 ④display.cppの修正箇所
  *Ard_eSPI を Arduino_Canvas から継承してコンストラクタを定義しました。
 ファイル比較display_cpp

 ⑤main.cppの修正箇所
  *デバッグ用に追加しました。(多分なくても良い)
 ファイル比較main_cpp

 ⑥tft.hの修正箇所
  *Ard_eSPI を Arduino_Canvas から継承してコンストラクタを定義しました。
 ファイル比較tft_h

 ⑦boardフォルダ
 ファイル比較boards

 ⑧interface.cppの修正箇所
  *タッチ操作でワンタッチでツータッチになったのでその部分を
   全部書き換えしました。
 ファイル比較interface_cpp

 ⑨platfomeio.iniの修正箇所
  *大元で指定しているのでコメントアウトしましました。
  *MicroSDカードのピン番号を追加しましました。
 ファイル比較platfomeio_ini
 
 ➉以上6個のファイルをzipにしたものです。オリジナルと交換して再ビルド
  すれば、JC3248W535C 用の「Launcher」が出来ると思います。
  (保障無しの自己責任で)  CYD-3248W535C.zip

6.ESP32-4848S040Cボードでのオリジナルとの比較です。
 ファイル比較root-4
  
 ①こちらも同様ですので、以下に修正ファイルのzipファイルを示します。
  (保障無しの自己責任で)  CYD-4848S040C.zip

7.JC3248W535Cでの実行例
 ①立ち上がり時の画面(LAUNCHERをタップ)
 Launcher_0

 ②メニュー画面(SDを選択後「SEL」をタップ)
 Launcher_1

 ➂SD内ファイル表示画面
  (実行したいbinファイルを「NEXT又はPREV」で選択して「SEL」をタップ)
 Launcher_2

 ④SDファイル操作画面
  (実行したいコマンドを「NEXT又はPREV」で選択して「SEL」をタップ)
   ◆ここではInstallを選択
 Launcher_3

 ⑤インストール中
 Launcher_4

 ⑥インストールされたbinファイルが実行されます。
 Launcher_5

8.開発環境を構築するのが大変という方に下記二つの.binファイルをzipにしたものを
  ダウンロードして下さい。

  (1)CYD-bin\CYD-3248W535C.bin
  (2)CYD-bin\CYD-4848S040C.bin
   (保障無しの自己責任で)  CYD-bin.zip
 
  ①書き込みツールは、下記よりダウンロード後解凍し
  「flash_download_tool_3.9.7.exe」を実行して、ボードへ書き込みます。
   Flash Download Tool (バージョン3.9.7) 

  ②ボードをPCへ接続します。 
  ➂起動後、「ESP32S3」選択し「OK」をクリック
 fdt397-1

  ④当該.binファイルを選択し、アドレスを「0x0」を設定
   シリアルポートを設定
 fdt397-2

  ⑤「START」をクリックすると書き込みが始まります。
 fdt397-3

  ⑥「FINISH」終了を確認し「X」で閉じます。
 fdt397-4

 ⑦ボードをリセットし再起動します。


以上 JC3248W535C ESP32-4848S040C で「Launcher」を動かす事が出来ました。

ブログトップへ

◆最新のESP32P4を搭載したJC1060P470Cを入手したので色々調べてみましたので
 備忘録に残して置きます。
 まだまだ、情報不足で思うように遊べていません。
 2025/03/02現在、色々検索してArduino IDEの環境で少しずつ遊べています。
 JC1060P470C_URA

 JC1060P470C-1

1.このボードについて
 ①入手先
  1. ボードの入手先(AliExpress)
    静電容量式タッチスクリーン,esp32p4,ESP32-C6, 32m,psram,
   16mフラッシュ,1024x600,dsi,mipi,ESP32-C6


  2. データの入手先
   http://pan.jczn1688.com/directlink/1/HMI%20display/JC1060P470C_I_W.zip

 ②各種参考となるURL
  1.このボードの元となったボードのようです。
    *ESP32-P4 機能 EV ボード
  2.このボードの製造過程のTikTok動画
  3.このボードの完成後のチェック時のTikTok動画
  4.このボードのWiFi接続試験のTikTok動画
  5.このボードの機能紹介のTikTok動画
  6.このボードのアプリ紹介のTikTok動画
  7.このボードのカメラ紹介のTikTok動画
  8.このボードの音楽再生紹介のTikTok動画
 
 ➂ESP32シリーズ比較表
 esp32_etc

 ④LCDコントローラ(JD9165)について
  1,esp_lcd コンポーネントを使用したJD9165 LCD コントローラーの実装
  ESP LCD JD9165 (MIPI-DSI)

  2.データシート
  JD9165A-A

 ⑤静電容量式タッチスクリーン タッチIC: GT911
  *解像度 800x480

 ⑥GPIO割当等
 JC1050P470_GPIO-1
 JC1050P470_GPIO-2
 
 ⑦回路図(Zipファイルより抜粋)
  1.PWR
  1_PWR
  2.LCD
  2_LCD
  
  3.ESP32-P4
  3_ESP32-P4

  4.CONN
  4_CONN

  5.ESP32-C6
  5_ESP32-C6
  6.USB
  6_USB

  7.CODEC
  7_CODEC
 
2.スケッチ
 LVGLデモコードを試していますが、まだタッチがうまく動いていません。
 ◆LVGLは、良く分からないので今まで使い慣れた「Arduino_GFX_Library」が
  対応しているみたいでしたので試してみました。うまく動いてくれました。

  Arduino IDE環境で、タッチ操作など色々実験しています。
  下記ブログ内記事を参照してみて下さい。

 ①・JC1060P470C(ESP32P4 ESP32C6 搭載) で「Arduino_GFX_Library」の
  デモを動かしてみた


 ②・JC1060P470C(ESP32P4 ESP32C6 搭載) でタッチスクリーンを試してみた

 ➂・JC1060P470C(ESP32P4 搭載)でRTCを使いパタパタ時計もどきを表示してみた

 ④・JC1060P470C(ESP32P4搭載)でI2Sでの録音再生実験をしてみた

 ⑤・JC1060P470C(ESP32P4)でMotion JPEG 画像ビューアを試してみた

 ⑥・JC1060P470C(ESP32P4 ESP32C6 搭載) ArduinoIDE環境でWiFiが使えるようになった

 ⑦・JC1060P470C(ESP32P4 ESP32C6 搭載) ArduinoIDE環境でNHK RSSニュース表示
   してみた


 ⑧・JC1060P470(ESP32P4) 他で「RSSニュース」を無料の「Sound of Text」を
  使い喋らせてみた



 *カメラを繋いでみる(これから)

 *SDカード内の音楽ファイルを再生してみる。(これから)

3.Arduino IDE環境では、これから先大変そうなので「ESP-IDF5.4」の環境を
 勉強がてら構築してみました。
 下記は、「ESP-IDF5.4」環境でのビルドです。

 ①・JC1060P470C(ESP32P4搭載)で「ESP IDF 5.4」を使い「Lチカ」をしてみた

 ②・JC1060P470C(ESP32P4搭載)にラズパイ用カメラを繋いでみた

 *VSC IDF5.5.1環境(2026/04/01追記)
 ➂・JC1060P470 (ESP32P4) ボードに「xiaozhi ベトナム版」を入れてみた


以上


ブログトップへ

◆ESP32 GFX_Library_for_Arduino 環境でSSD1306を表示させようとしましたが、現時点で
 コンパイラエラーが発生して表示出来ません。
 他のLCDと同等のインターフェイスで表示させたいと思い色々試しましたが、
 上手くいきませんでした。
 ですので「Adafruit_SSD1306」ライブラリを使ってのラッパーを作成しました。
 これで、同等のインターフェイスで表示可能となりました。
 SSD1306

1.下記が、ラッパー用「GFXWrapper.h」のスケッチです。
  (保障無しの自己責任で)
//GFXWrapper.h
//2025/06/28 By JK1VCK SSD1306 制御するラッパー
//blog URL:https://gijin77.blog.jp/archives/44998235.html

//Arduino_GFX_Libraryと同様のインターフェイスでSSD1306を制御するラッパー

#pragma once
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
#define SCREEN_ADDRESS 0x3C

class GFXWrapper {
public:
  Adafruit_SSD1306 *oled;

  GFXWrapper(int width, int height, TwoWire *wire, int reset_pin) {
    oled = new Adafruit_SSD1306(width, height, wire, reset_pin);
  }

  bool begin() {
    return oled->begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
  }

  void display() { oled->display(); }
  void clearDisplay() { oled->clearDisplay(); }

  // テキスト関連
  void print(const String &text) { oled->print(text); }
  void println(const String &text) { oled->println(text); }
  void print(const char* text) { oled->print(text); }
  void println(const char* text) { oled->println(text); }
  void print(int val) { oled->print(val); }
  void println(int val) { oled->println(val); }

  void setCursor(int16_t x, int16_t y) { oled->setCursor(x, y); }
  void setTextSize(uint8_t s) { oled->setTextSize(s); }
  void setTextColor(uint16_t c) { oled->setTextColor(c); }
  void setTextWrap(bool w) { oled->setTextWrap(w); }

  // 画面サイズ
  int16_t width()  { return oled->width(); }
  int16_t height() { return oled->height(); }

  // 回転
  void setRotation(uint8_t r) { oled->setRotation(r); }
  uint8_t getRotation() const { return oled->getRotation(); }

  // グラフィックス
  void drawPixel(int16_t x, int16_t y, uint16_t color) {
    oled->drawPixel(x, y, color);
  }

  void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) {
    oled->drawLine(x0, y0, x1, y1, color);
  }
  void drawFastHLine(int16_t x0, int16_t y0, int16_t x1, uint16_t color) { //drawFastHLine
    oled->drawLine(x0, y0, x1, y0, color);
  }
  void drawFastVLine(int16_t x0, int16_t y0, int16_t y1, uint16_t color) { //drawFastVLine
    oled->drawLine(x0, y0, x0, y1, color);
  }
  void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
    oled->drawRect(x, y, w, h, color);
  }

  void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
    oled->fillRect(x, y, w, h, color);
  }
  void fillScreen(uint16_t color) { //fillScreen
    oled->fillRect(0, 0, width()-1, height()-1, color);
  }

  void drawCircle(int16_t x, int16_t y, int16_t r, uint16_t color) {
    oled->drawCircle(x, y, r, color);
  }

  void fillCircle(int16_t x, int16_t y, int16_t r, uint16_t color) {
    oled->fillCircle(x, y, r, color);
  }

  void drawTriangle(int16_t x0, int16_t y0,
                    int16_t x1, int16_t y1,
                    int16_t x2, int16_t y2,
                    uint16_t color) {
    oled->drawTriangle(x0, y0, x1, y1, x2, y2, color);
  }

  void fillTriangle(int16_t x0, int16_t y0,
                    int16_t x1, int16_t y1,
                    int16_t x2, int16_t y2,
                    uint16_t color) {
    oled->fillTriangle(x0, y0, x1, y1, x2, y2, color);
  }

  void drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h,
                     int16_t r, uint16_t color) {
    oled->drawRoundRect(x, y, w, h, r, color);
  }

  void fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h,
                     int16_t r, uint16_t color) {
    oled->fillRoundRect(x, y, w, h, r, color);
  }

  // ビットマップ描画
  void draw16bitRGBBitmap(int16_t x, int16_t y,
                   uint16_t *bitmap, int16_t w, int16_t h){
    //ダミールーチン
    return;
  }
  
  void drawBitmap(int16_t x, int16_t y, 
                  const uint8_t *bitmap, int16_t w, int16_t h,
                  uint16_t color) {
    oled->drawBitmap(x, y, bitmap, w, h, color);
  }

  void drawXBitmap(int16_t x, int16_t y,
                   const uint8_t *bitmap, int16_t w, int16_t h,
                   uint16_t color) {
    oled->drawXBitmap(x, y, bitmap, w, h, color);
  }

  // その他
  void invertDisplay(bool i) { oled->invertDisplay(i); }
};


2.下記が、テスト用「gfx_SSD1306.ino」のスケッチです。
  (保障無しの自己責任で)

//gfx_SSD1306.ino
//2025/06/28 By JK1VCK SSD1306 制御するラッパー
//blog URL:https://gijin77.blog.jp/archives/44998235.html

//Arduino_GFX_Libraryと同様のインターフェイスでSSD1306を制御するラッパー
//#include <Arduino_GFX_Library.h>
//Arduino_DataBus *bus = new Arduino_Wire(SSD1306_I2C_ADDR, wire);
//Arduino_SSD1306 *gfx = new Arduino_SSD1306(bus, -1, SCREEN_WIDTH, SCREEN_HEIGHT);

#include <Wire.h>
#include "GFXWrapper.h"
GFXWrapper *gfx = new GFXWrapper(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {
  Serial.begin(115200);
  Wire.begin(32,33); //SDA,SCL esp32
  //Wire.begin();
  if (!gfx->begin()) {
    Serial.println("SSD1306 initialization failed!");
    while (1);
  }
  gfx->setRotation(0);
  gfx->clearDisplay();
  gfx->setTextColor(SSD1306_WHITE);
  gfx->setCursor(10, 4);
  gfx->setTextSize(2);
  gfx->println("<SSD1306>");
  gfx->fillCircle(26,40, 15, SSD1306_WHITE);
  gfx->drawTriangle(64,26,50,56,80,56,SSD1306_WHITE);
  gfx->fillRect(90, 26, 30, 30, SSD1306_WHITE);  
  gfx->display();
int w = gfx->width();
int h = gfx->height();
  gfx->drawRect(0, 0, w - 1, h - 1, SSD1306_WHITE);
  gfx->display();
}

void loop() {
  // ここで何か描画更新してもOK
}


3.これが実現出来たので、色々なLCDと混在して開発できています。
 応用例として下記ブログ内記事を参照してみて下さい。
 ・JC1060P470(ESP32P4) 他で「RSSニュース」を無料の「Sound of Text」を
  使い喋らせてみた

 

 
以上
 

ブログトップへ

◆下記の色々なボードでArduino_GFX_Libraryでパタパタ時計を表示しつつ、RSSニュースを
 無料の「Sound of Text」を使って喋らせてみました。
 以前の記事も参照してみて下さい。
 ・JC3248W535(ESP32S3)で RSSニュース を「[TTS] AquesTalk」を使って喋らせてみた

1.下記のサイズの違うLCDで実現出来ています。
 ①JC1060P470      ESP32P4  7   インチ  1024x600 (jd9165)
 ②JC3248W535     ESP32S3  3.5 インチ   480x320 (AXS15231B)
 ➂LilyGo_Display   ESP32     1.14インチ   240x135 (ST7789)
 ④ESP32P4Devkit    ESP32P4  3.5 インチ   480x320 (ILI9486 RPi用LCD)
 ⑤ESP32P4Devkit    ESP32P4  3.5 インチ   480x320 (ILI9488 LCD)
 ⑥ESP32P4Devkit    ESP32P4  0.96インチ  120x64   (I2C OLED)
 ⑦ESP32_4848S040  ESP32S3   4   インチ    480x480 (st7701) (一部表示乱れあり)

 ①JC1060P470      ESP32P4  7   インチ  1024x600 (jd9165)
 JC1060P470-P1
 
 

 ②JC3248W535     ESP32S3  3.5 インチ   480x320 (AXS15231B)
 JC3248W535-P2
 

 ➂LilyGo_Display   ESP32     1.14インチ   240x135 (ST7789)
 LilyGo_Display-P2


 ④ESP32P4Devkit    ESP32P4  3.5 インチ   480x320 (ILI9486 RPi用LCD)
 esp32p4_RPiLCD_P2
 ◆RPi用3.5インチLCDのドライバは、下記ブログ内記事を参照してみて下さい。
 ・ESP32P4 Devkit GFX_Library_for_Arduino で ILI9486 RPi3.5インチLCD が
  真っ白になるのを解決


 (1)通常は、上記の接続で問題ないのですが、音声出力すると不具合が発生しました。
  対策として、SCKをGPIO0からGPIO6へ変更するアダプタを作成しました。
 RPiアダプタ-1
 RPiアダプタ-2
 RPiアダプタ-4
 esp32p4_devkit_pi_LCD_pin0-6

 
 ⑤ESP32P4Devkit    ESP32P4  3.5 インチ   480x320 (ILI9488 LCD)
 esp32p4_ILI9488-P1
 ◆ILI9488 3.5インチLCDの表示については、下記ブログ内記事を参照してみて下さい。
 ・ESP32 GFX_Library_for_Arduino で ILI9488 3.5'LCD の表示不具合を解決出来た


 ⑥ESP32P4Devkit    ESP32P4  0.96インチ  120x64   (I2C SSD1306 OLED)
 esp32p4_SSD1306-P1
 ◆I2C接続SSD1306表示については、下記ブログ内記事を参照してみて下さい。
 ・ESP32 でI2C接続 SSD1306 GFX_Library_for_Arduino インターフェイスで
  表示出来るようにしてみた



 ⑦ESP32_4848S040  ESP32S3   4   インチ    480x480 (st7701) (一部表示乱れあり)
 ESP32_4848S040-P1
 ◆ESP32_4848S040のI2Sの配線については、下記ブログ内記事を参照して下さい。
 ・4.0inch ESP32-4848S040 で音が出ない 解析と改修
 


2.今回は、音声合成を無料のクラウドサービス「Sound of Text」を使いました。
 ①試しに下記サイトでテキストを入力し、デモ音声を聞くことが出来ます。
  https://soundoftext.com/

 ②サイトにアクセスしたら日本語を選択し、適当な日本語文章をテキストBOXに入力し、
  送信をクリックします。
 sot_demo-1

 ➂下にスクロールして、「PLAY」をクリックすると、音声が流れます。
 sot_demo-2
 
 ④「DOWNLOAD」をクリックすると保存フォルダを選択し、「xxx.MP3」ファイルが
  保存されます。後で聞くことが出来ます。
 sot_demo-3

 ⑤APIも公開されています。
  APIドキュメント

3.スケッチについて
 ①(保障無しの自己責任で)  Fclock_News_SOT_V3.zip

 ②Fclock_News_SOT_V3.zipの中身
 SOT_V3

 ➂ボードの選択は、「Sound_of_Text.h」の中で例:「#define JC1060P470 」の様に
  選択して、コンパイル&書き込みします。

//Sound_of_Text.h
//2025/06/28 By JK1VCK パタパタ時計、News、音声合成
//blog URL:https://gijin77.blog.jp/archives/44980183.html

#ifndef _SOUND_OF_TEXT_H_
#define _SOUND_OF_TEXT_H_
#include <Arduino.h> 
#include <stdint.h>

//#define    LilyGo_Display  // esp32 LilyGo T-Display Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS)
//#define    JC3248W535      // esp32s3 Dev USBCDCOnBoot=en Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS) psram=OPIPSRAM
//#define    ESP32_4848S040  // esp32s3 Dev USBCDCOnBoot=ds Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS) psram=OPIPSRAM 
#define  JC1060P470        // esp32p4 Dev USBCDCOnBoot=en Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS) psram=en
//#define  ESP32P4Devkit     // esp32p4 Dev USBCDCOnBoot=en Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS) psram=en USB_Mode=Hard

//ESP32P4DevkitのLCDの選択は、下記で
//#define P4_SSD1306   //128x64
//#define P4_RPi35LCD  //480x320

//プロトタイプ宣言
void i2s_setup();
void TTS_task(void* pv);
void speak_text(String text);
void initTTS();
int TTS_isPlay();

#endif // !defined(_SOUND_OF_TEXT_H_)


以上

ブログトップへ

◆ESP32 GFX_Library_for_Arduinoライブラリを使って通常の「Arduino_ILI9488」では、
 表示出来ませんでした。
 初期化コマンドを弄ったりSPI指定を替えたりしましたが、表示しませんでした。
 色々ネットで検索していたら、「Arduino_ILI9488_18bit」を使えば良い事が分かりました。

1.スケッチの一部

 Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK,
   TFT_MOSI, TFT_MISO);
 //Arduino_GFX *gfx = new Arduino_ILI9488(bus, TFT_RST, 0); // NG
 Arduino_GFX *gfx = new Arduino_ILI9488_18bit(bus, TFT_RST, 0); // <-これで表示OK

2.テスト用スケッチ(ILI9488_Test.ino)
//ILI9488_Test.ino
//V2025/06/28 By JK1VCK ILI9888 3.5'LCD
//blog URL:https://gijin77.blog.jp/archives/45000692.html

#include <Arduino_GFX_Library.h>

#define TFT_DC    17
#define TFT_RST   16
#define TFT_CS    5
#define TFT_MOSI  23
#define TFT_SCK   18
#define TFT_MISO  19

Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
//Arduino_GFX *gfx = new Arduino_ILI9488(bus, TFT_RST, 0); // 3.5 LCD
Arduino_GFX *gfx = new Arduino_ILI9488_18bit(bus, TFT_RST, 0); // 3.5 LCD

uint16_t color[8] ={BLACK,BLUE,GREEN,CYAN,RED,MAGENTA,YELLOW,WHITE};
int32_t w, h, n, n1, cx, cy, cx1, cy1, cn, cn1;
void setup() {
  Serial.begin(115200);
  Serial.println("LCD init success");
  gfx->begin();
}
void get_whxy(){
  w = gfx->width();
  h = gfx->height();
  cx = w / 2;
  cy = h / 2;
}
void loop() {
  int wt=500;
  char msg[200];
  Serial.println("LCD Test Start");
  for(int r=0;r<8;r++){
    gfx->setRotation(r);get_whxy();
    sprintf(msg," R=%d W=%d H=%d",r,w,h);
    Serial.println(msg);
    gfx->fillScreen(BLACK);gfx->setCursor(0,0);gfx->setTextColor(ORANGE);
    gfx->setTextSize(3); 
    //if (w==480) gfx->setTextSize(2); else gfx->setTextSize(1);
    gfx->print(msg);
    for (int c=0;c<8;c++) {
      gfx->setCursor(0, cy-1+c*(cy/8));
      gfx->setTextSize(3);
      gfx->setTextColor(color[c]);
      if (w==480) gfx->print("Hello LCD Test 123 ABC abc");
      else        gfx->print("Hello LCD Test V7");
      gfx->fillRect(c*(w/8),(cy/8)+2,(w/8),cy-(cy/8),color[7-c]);
      delay(wt);
    }
    delay(5000);
  }
  Serial.println("LCD Test end");
}


3.表示画面
 ①Arduino_ILI9488_18bitでOK
 ILI9488_18bit
 
 ②Arduino_ILI9488でNG
 ILI9488

以上



ブログトップへ

◆ESP32P4 Devkitは、dsi接続の7インチ,10.1インチの標準のLCD付が販売されていますが、
 ちょっと高価です。
 このボードにはraspiと同様な拡張コネクタが付いていましたので、安価なraspi用3.5インチ
 LCDが使えないかと思い、ボードだけ購入してみました。
 このボードについて詳しくは、下記で
 ESP32-P4-Module-DEV-KIT

 *youtube動画(字幕で日本語を表示出来ます)
 ESP32-P4-Module vs. Raspberry Pi 4 & Raspberry Pi 5. Can it beat Raspberry Pi?

 RPiLCD-1

 RPiLCD_P4

 esp32p4_devkit_pi_LCD_pin

1.raspi用3.5インチLCDについて
 ①ハード的には、そのままコネクタに差し込めます。
 ②LCDのライブラリは、他のボードで、色々使っている関係上「 GFX_Library_for_Arduino」
  を使いたい。
 ➂ドライバICは、「ILI9486」らしい。
 ④接続形態は、SPIらしい。
 ⑤上記を元に「 GFX_Library_for_Arduino」を使い、テスト用スケッチを作りました。
  *コンパイラ、書き込みも出来ましたが、画面が真っ白のままでした。
 
2.動かすまでの奮闘
 ①「ILI9486」データシートからの初期化コマンドを色々と試してみましたが、
  真っ白のままで変化なし

 ②ネットで調べましたがESP32P4での動作報告は、検索できませんでした。
  よって、「ESP32」で試験を開始しました。
  
3.「ESP32 Devkit」での奮闘
 ①ブレッドボートに簡単に抜き差し出来るようアダプタを作成しました。
  (「ILI9341」「ILI9488」等も試験出来るように)
 RPiアダプタ

 ②ESP32でも相変わらず真っ白のままです。

 ➂ライブラリを替えて試験すると、正常に表示しましたので、ハードの接続は
  問題ない事が、分かりました。

 ④動作するライブラリの初期化コードを使っても、真っ白のままてす。

 ⑤SPIスピードを替えても駄目です。一週間以上悩みました。

 ⑥色々、調べていて、やっと分かりました。
  *「raspi用3.5LCDデバイスは実際にはSPIではありませんでした。
  *これは並列インターフェースに接続された16ビットのシフトレジスタで、
   20MHzで動作可能」
  *よって常に16ビット送るようにダミーを入れなくてはならなかったみたいです。
  *これで、初期コマンドが、認識されて画面表示が変わりました。

  void Arduino_RPiILI9486Bus::writeCommand(uint8_t c) {
  //Serial.printf("\nCommand=%02X ",c);
    digitalWrite(_dc, LOW);
    _spi->transfer(0); //<--ここにダミーを送って16bitにする必要が有る
    _spi->transfer(c);    //コマンド送信(8bit)
  }

  void Arduino_RPiILI9486Bus::write(uint8_t d) {
  //Serial.printf("Data=%02X ",d);
    digitalWrite(_dc, HIGH);
    _spi->transfer(0); //<--ここにダミーを送って16bitにする必要が有る
    _spi->transfer(d); // データ送信(8bit)
  }

 ◆raspi用3.5LCD 参考回路図

4.原因が、判明しましたので「GFX_Library_for_Arduino」へ組み込みます。
  (保障無しの自己責任で)
 ①「src」フォルダに「custom」フォルダを作り、そこへ「Arduino_RPiILI9486Bus.h」を
   保存します。
 ②同じく「Arduino_RPiILI9486Bus.cpp」を保存します。
 
 *「Arduino_RPiILI9486Bus.h」の内容
//Arduino_RPiILI9486Bus.h
//V2025/06/21 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44913290.html

#pragma once

#include <Arduino.h>
#include <SPI.h>
#include "../Arduino_DataBus.h"

class Arduino_RPiILI9486Bus : public Arduino_DataBus {
public:
  Arduino_RPiILI9486Bus(SPIClass *spi, int8_t dc, int8_t cs, int8_t sck, int8_t mosi, int8_t miso);

  // 必須のオーバーライド関数(仮想関数)
  bool begin(int32_t speed = SPI_DEFAULT_FREQ, int8_t dataMode = GFX_NOT_DEFINED) override;
  void end();

  void beginWrite() override;
  void endWrite() override;

  void writeCommand(uint8_t c) override;
  void writeCommand8b(uint8_t c);
  void writeCommand16(uint16_t c) override;
  void writeCommandBytes(uint8_t *data, uint32_t len) override;

  void write(uint8_t d) override;
  void write16(uint16_t d) override;
  void writeData(uint8_t d);
  void writeData16(uint16_t d);
  void writeBytes(uint8_t *data, uint32_t len) override;

  void writeRepeat(uint16_t p, uint32_t len) override;
  void writePixels(uint16_t *data, uint32_t len) override;

private:
  SPIClass *_spi;
  uint32_t _spi_speed;
  int8_t _dc, _cs, _sck, _mosi, _miso;
  int32_t _speed;
};



 
 *「Arduino_RPiILI9486Bus.cpp」の内容
//Arduino_RPiILI9486Bus.cpp
//V2025/06/21 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44913290.html

#include "Arduino_RPiILI9486Bus.h"

Arduino_RPiILI9486Bus::Arduino_RPiILI9486Bus(SPIClass *spi, int8_t dc, int8_t cs, int8_t sck, int8_t mosi, int8_t miso)
  : _spi(spi), _dc(dc), _cs(cs), _sck(sck), _mosi(mosi) 
{
  _spi = spi;
  _dc = dc;
  _cs = cs;
  _sck = sck;
  _mosi = mosi;
  _miso = miso;
  _spi_speed = 20000000;  // 20MHz を仮設定
}

bool Arduino_RPiILI9486Bus::begin(int32_t speed, int8_t dataMode) {
 if (speed == -1) {
    speed = _spi_speed;  // 初期値を使用
  } else {
    _spi_speed = speed;  // 明示指定されたら上書き
  }
  pinMode(_dc, OUTPUT);
  pinMode(_cs, OUTPUT);

  if (_sck != -1 && _mosi != -1) {
    _spi->begin(_sck, -1, _mosi);
  } else {
    _spi->begin();
  }

  digitalWrite(_cs, HIGH);
  digitalWrite(_dc, HIGH);
  _spi->begin(_sck, _miso, _mosi,_cs);
  _spi->beginTransaction(SPISettings(speed, MSBFIRST, dataMode));
  
  Serial.printf("begin: spi_speed=%ld cs=%d dc=%d sck=%d mosi=%d miso=%d \n",speed,_cs,_dc,_sck,_mosi,_miso);
  return true;
}

void Arduino_RPiILI9486Bus::end() {
  _spi->end();
}

void Arduino_RPiILI9486Bus::beginWrite() {
  //Serial.println("beginWrite");
  digitalWrite(_cs, LOW); // TODO: SPIトランザクション開始処理
}

void Arduino_RPiILI9486Bus::endWrite() {
//Serial.println("\nendWrite");
  digitalWrite(_cs, HIGH); // TODO: SPIトランザクション終了処理
}

void Arduino_RPiILI9486Bus::writeCommand(uint8_t c) {
//Serial.printf("\nCommand=%02X ",c);
  digitalWrite(_dc, LOW);
  _spi->transfer(0);
  _spi->transfer(c);
}

void Arduino_RPiILI9486Bus::writeCommand8b(uint8_t c) {
//Serial.printf("\nCommand=%02X ",c);
  digitalWrite(_dc, LOW);
  _spi->transfer(c);
}

void Arduino_RPiILI9486Bus::writeCommand16(uint16_t cmd) {
//Serial.println("writeCommand16");
    writeCommand8b((uint8_t)(cmd >> 8));
    writeCommand8b((uint8_t)cmd);    // TODO: 16bitコマンド送信処理
}

void Arduino_RPiILI9486Bus::writeCommandBytes(uint8_t *data, uint32_t length) {
//Serial.println("writeCommandByte");
  digitalWrite(_dc, LOW);
  while (length--)  {
    writeCommand8b(*data++);  // TODO: 任意の長さのコマンド送信処理
  }
}

void Arduino_RPiILI9486Bus::write(uint8_t d) {
//Serial.printf("Data=%02X ",d);
  digitalWrite(_dc, HIGH);
  _spi->transfer(0);
  _spi->transfer(d); // TODO: データ送信(8bit)
}

void Arduino_RPiILI9486Bus::writeData(uint8_t d) {
//Serial.printf("Data=%02X ",d);
  digitalWrite(_dc, HIGH);
  _spi->transfer(d); // TODO: データ送信(8bit)
}

void Arduino_RPiILI9486Bus::write16(uint16_t data) {
//Serial.println("write16");
  writeData((uint8_t)(data >> 8));
  writeData((uint8_t)data);      // TODO: データ送信(16bit)
}

void Arduino_RPiILI9486Bus::writeBytes(uint8_t *data, uint32_t length) {
  digitalWrite(_dc, HIGH); // データモード
  while (length--) {
    writeData(*data++);
  }
}

void Arduino_RPiILI9486Bus::writeRepeat(uint16_t p, uint32_t len) {
//Serial.printf("writeRepeat data=%04X len=%ld \n",p,len);
  digitalWrite(_dc, HIGH); // データモード
  for (uint32_t i = 0; i < len; ++i) {
  _spi->transfer((uint8_t)(p >> 8)); // TODO: データ送信(8bit)
  _spi->transfer((uint8_t)p);        // TODO: データ送信(8bit
  }
}

void Arduino_RPiILI9486Bus::writePixels(uint16_t *data, uint32_t len) {
  //Serial.println("writePixels");
  digitalWrite(_dc, HIGH);
  for (uint32_t i = 0; i < len; ++i) {
    _spi->transfer((uint8_t)(data[i] >> 8)); // TODO: データ送信(8bit)
    _spi->transfer((uint8_t)data[i]);        // TODO: データ送信(8bit
  }
}

 
 ➂試験用「RPiLCD_Test.ino」の内容
//RPiLCD_Test.ino
//V2025/06/21 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44913290.html

#include <Arduino_GFX_Library.h>

#define  ESP32Devkit
//#define  ESP32P4Devkit       // esp32p4 DEV M Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS) psram=en USBCDCOnBoot=en USB_Mode=Hard

#if defined(ESP32P4Devkit)
#include "custom/Arduino_RPiSWSPI_P4.h"
//ESP32P4
#define TFT_CS    36
#define TFT_DC     4
#define TFT_RST    1
#define TFT_SCK    0
#define TFT_MOSI   3
#define TFT_MISO  -1
Arduino_DataBus *bus = new Arduino_RPiSWSPI_P4(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
Arduino_GFX *gfx = new Arduino_ILI9486(bus, TFT_RST, 0); //RPi 3.5 LCD

#elif defined(ESP32Devkit)
#include "custom\Arduino_RPiILI9486Bus.h"
//ESP32
#define TFT_DC    17
#define TFT_RST   16
#define TFT_CS    5
#define TFT_MOSI  23
#define TFT_SCK   18
#define TFT_MISO  19
//Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
//Arduino_DataBus *bus = new Arduino_SWSPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
Arduino_DataBus *bus = new Arduino_RPiILI9486Bus(&SPI, TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
Arduino_GFX *gfx = new Arduino_ILI9486(bus, TFT_RST, 0); //RPi 3.5 LCD
#endif

uint16_t color[8] ={BLACK,BLUE,GREEN,CYAN,RED,MAGENTA,YELLOW,WHITE};
int32_t w, h, n, n1, cx, cy, cx1, cy1, cn, cn1;
void setup() {
  Serial.begin(115200);
  Serial.println("LCD init success");
  gfx->begin();
}
void get_whxy(){
  w = gfx->width();
  h = gfx->height();
  cx = w / 2;
  cy = h / 2;
}
void loop() {
  int wt=500;
  char msg[200];
  Serial.println("LCD Test Start");
  for(int r=0;r<8;r++){
    gfx->setRotation(r);get_whxy();
    sprintf(msg," R=%d W=%d H=%d",r,w,h);
    Serial.println(msg);
    gfx->fillScreen(BLACK);gfx->setCursor(0,0);gfx->setTextColor(ORANGE);
    gfx->setTextSize(3); 
    //if (w==480) gfx->setTextSize(2); else gfx->setTextSize(1);
    gfx->print(msg);
    for (int c=0;c<8;c++) {
      gfx->setCursor(0, cy-1+c*(cy/8));
      gfx->setTextSize(3);
      gfx->setTextColor(color[c]);
      if (w==480) gfx->print("Hello LCD Test 123 ABC abc");
      else        gfx->print("Hello LCD Test V7");
      gfx->fillRect(c*(w/8),(cy/8)+2,(w/8),cy-(cy/8),color[7-c]);
      delay(wt);
    }
    delay(5000);
  }
  Serial.println("LCD Test end");
}


 ④表示試験画面(ローテンション1)
 RPiLCD_esp32-1
 ⑤表示試験画面(ローテンション2)
 RPiLCD_esp32-2

5.続いて本題の「ESP32P4 Devkit」での表示
  (保障無しの自己責任で)
 ①「ESP32P4」ではSPIが使えず、「ESP32」のままでは表示しませんでした。
 ②よって、SPIインターフェースをGPIOのビット操作で実現しました。
 ➂先ほど作った「src」->「custom」フォルダへ「Arduino_RPiSWSPI_P4.h」を保存します。
 ④同じく「Arduino_RPiSWSPI_P4.cpp」を保存します。
 
 *「Arduino_RPiSWSPI_P4.h」の内容
 
//Arduino_RPiSWSPI_P4.h
//V2025/06/21 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44913290.html

#ifndef _ARDUINO_RPISWSPI_P4_H_
#define _ARDUINO_RPISWSPI_P4_H_

#include "../Arduino_DataBus.h"

typedef volatile uint32_t *PORTreg_t;

class Arduino_RPiSWSPI_P4 : public Arduino_DataBus
{
public:
  Arduino_RPiSWSPI_P4(int8_t dc, int8_t cs, int8_t _sck, int8_t _mosi, int8_t _miso = GFX_NOT_DEFINED); // Constructor

  bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
  void beginWrite() override;
  void endWrite() override;
  void writeCommand(uint8_t) override;
  void writeCommand16(uint16_t) override;
  void writeCommandBytes(uint8_t *data, uint32_t len) override;
  void write(uint8_t) override;
  void write16(uint16_t) override;
  void writeRepeat(uint16_t p, uint32_t len) override;
  void writePixels(uint16_t *data, uint32_t len) override;
  void writeBytes(uint8_t *data, uint32_t len) override;
  uint8_t read();
  void readBytes(uint8_t *data, uint32_t len);
   
private:
  void writedata(uint8_t d);
  int8_t _dc, _cs;
  int8_t _sck, _mosi, _miso;

};
#endif // _ARDUINO_RPISWSPI_P4_H_

 
 *「Arduino_RPiSWSPI_P4.cpp」の内容

//Arduino_RPiSWSPI_P4.cpp
//V2025/06/21 By JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44913290.html

#include "Arduino_RPiSWSPI_P4.h"

#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32P4)

#include "soc/gpio_struct.h"
#include "hal/gpio_ll.h"  // GPIO操作の低レベルヘッダ(ESP-IDF)


Arduino_RPiSWSPI_P4::Arduino_RPiSWSPI_P4(int8_t dc, int8_t cs, int8_t sck, int8_t mosi, int8_t miso)
    : _dc(dc), _cs(cs), _sck(sck), _mosi(mosi), _miso(miso)
{
}

inline void GPIO_HIGH(uint8_t pin) { //ピン番号は0-31まで
  GPIO.out_w1ts.val = (1UL << pin);
}

inline void GPIO_LOW(uint8_t pin) { //ピン番号は0-31まで
  GPIO.out_w1tc.val = (1UL << pin);
}

bool Arduino_RPiSWSPI_P4::begin(int32_t, int8_t) {
  pinMode(_dc, OUTPUT);
  digitalWrite(_dc, HIGH);

  pinMode(_cs, OUTPUT);
  digitalWrite(_cs, HIGH);

  pinMode(_sck, OUTPUT);
  digitalWrite(_sck, LOW);

  pinMode(_mosi, OUTPUT);
  digitalWrite(_mosi, LOW);

  if (_miso != GFX_NOT_DEFINED) {
    pinMode(_miso, INPUT);
  }
  Serial.printf("begin: cs=%d dc=%d sck=%d mosi=%d miso=%d \n",_cs,_dc,_sck,_mosi,_miso);
  return true;
}
void Arduino_RPiSWSPI_P4::beginWrite() {
  digitalWrite(_dc, HIGH); // Data mode
  digitalWrite(_cs, LOW);
}

void Arduino_RPiSWSPI_P4::endWrite() {
  digitalWrite(_cs, HIGH);
}

void Arduino_RPiSWSPI_P4::writedata(uint8_t d) {
  for (uint8_t bit = 0x80; bit; bit >>= 1) {
    if (d & bit) {
      GPIO.out_w1ts.val = (1UL << _mosi);  // Set
    } else {
      GPIO.out_w1tc.val = (1UL << _mosi);  // Clear
    }
    GPIO.out_w1ts.val = (1UL << _sck);     // SCK HIGH
    GPIO.out_w1tc.val = (1UL << _sck);     // SCK LOW
  }
}

void Arduino_RPiSWSPI_P4::writeCommand(uint8_t c) {
//  Serial.printf("\ncmd=%02X ", c);
  GPIO_LOW(_dc);
  writedata(0);  // Dummy write?
  writedata(c);
  GPIO_HIGH(_dc);
}

void Arduino_RPiSWSPI_P4::writeCommand16(uint16_t p) {
  uint8_t hi = p >> 8, lo = p & 0xFF;
  writedata(hi);
  writedata(lo);
}

void Arduino_RPiSWSPI_P4:: writeCommandBytes(uint8_t *data, uint32_t len) {
  while (len--) {
    uint16_t c = *data++;
    writedata(c >> 8);
    writedata(c & 0xFF);
  }	
}

void Arduino_RPiSWSPI_P4::write(uint8_t d) {
//Serial.printf("data=%02X ",d);
  writedata(0);
  writedata(d);
}

void Arduino_RPiSWSPI_P4::write16(uint16_t p) {
  uint8_t hi = p >> 8, lo = p & 0xFF;
  writedata(hi);
  writedata(lo);
}

void Arduino_RPiSWSPI_P4::writeRepeat(uint16_t p, uint32_t len) {
  uint8_t hi = p >> 8, lo = p & 0xFF;
  while (len--) {
    writedata(hi);
    writedata(lo);
  }
}

void Arduino_RPiSWSPI_P4::writePixels(uint16_t *data, uint32_t len)
{
  while (len--) {
    uint16_t c = *data++;
    writedata(c >> 8);
    writedata(c & 0xFF);
  }
}

void Arduino_RPiSWSPI_P4::writeBytes(uint8_t *data, uint32_t len)
{
  while (len--) {
    writedata(*data++);
  }
}

uint8_t Arduino_RPiSWSPI_P4::read()
{
  uint8_t r = 0;
  for (uint8_t i = 0x80; i; i >>= 1) {
    GPIO.out_w1ts.val = (1UL << _sck);     // SCK HIGH
    if (digitalRead(_miso)) r |= i;
    GPIO.out_w1tc.val = (1UL << _sck);     // SCK LOW
  }
  return r;
}

void Arduino_RPiSWSPI_P4::readBytes(uint8_t *data, uint32_t len)
{
  while (len--) {
    *data++ = read();
  }
}

#endif



 
 ⑤試験用スケッチは、先ほどの物で最初の#defineで「ESP32P4_Devkit」を有効にします。
  //#define  ESP32Devkit
  #define  ESP32P4Devkit

 ⑥表示試験画面(ローテンション1)
 RPiLCD_esp32p4-4

 ⑦表示試験画面(ローテンション2)
 RPiLCD_esp32p4-3

これで「raspi用3.5インチLCD」が「GFX_Library_for_Arduino」で使えるようになりました。

以上


ブログトップへ

◆4.0inch_ESP32-4848S040を入手して色々弄って遊んでいました。
 ところがI2S経由で音出しをした所、音が出ませんでした。

1.新品なのにちょっと躊躇しましたが、裏ブタを外してみました。
 ESP32_4848S040-1

 ①スピーカ端子付近の部品配置を、分析して見ましたら、GPIOがI2Sアンプへの
  接続用「0Ω」チップ抵抗が付いていませんでした。
  これでは、音が出ないのは、当然です。
  チップ抵抗の持ち合わせが無かったのでジャンパー線で繋ぎました。
  老眼では、大変難儀しました。

 I2S_NG

 ②このボードGPIOのほとんどを4インチ480x480のLCDに使っています。
  標準では拡張用の外部端子は、出ていません。
  回路図を眺めると、未使用のGPIO35,36,37が有りました。
  裏ブラを開けたついでに、このGPIOを外部に出す改修もしました。
 ◆2025/10/05追記
  GPIO35,36,37は、内部フラッシュメモリ、PSRAMで使われている可能性が有り
  外部で使うと動作が不安定になる事があるため、使わない方が良さそうです。


 I2S_OK

 GPIO拡張
  
 ➂音出しのテストプログラムを走らせ、無事音が出ました。めでたしめでたし。  
  後、外部に出したGPIO35,36,37にLEDを接続して点灯する事を確認しました。

 

 ④テストスケッチ
//i2s_test.ino
//V2025/06/20 by JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44904481.html

#include "driver/i2s.h"
#include <math.h>

#define I2S_NUM         I2S_NUM_0
#define SAMPLE_RATE     44100
#define TONE_FREQ_HZ    1000
#define DURATION_SEC    5
#define VOLUME          10000

#define I2S_BCK_IO      1   // BCK
#define I2S_WS_IO       2   // LRCK / WS
#define I2S_DO_IO       40  // DOUT

void setupI2S() {
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
    .communication_format = I2S_COMM_FORMAT_STAND_MSB,
    .intr_alloc_flags = 0,
    .dma_buf_count = 8,
    .dma_buf_len = 64,
    .use_apll = false,
    .tx_desc_auto_clear = true
  };

  i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_BCK_IO,
    .ws_io_num = I2S_WS_IO,
    .data_out_num = I2S_DO_IO,
    .data_in_num = I2S_PIN_NO_CHANGE
  };

  i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM, &pin_config);
  i2s_zero_dma_buffer(I2S_NUM);
}

void playTone() {
  const int samples = SAMPLE_RATE * DURATION_SEC;
  const int bytes_per_sample = 4;  // 16bit * 2ch
  int16_t sampleBuffer[256];

  for (int i = 0; i < samples; i += 128) {
    for (int j = 0; j < 128; j++) {
      float t = (float)(i + j) / SAMPLE_RATE;
      int16_t val = (int16_t)(VOLUME * sinf(2 * PI * TONE_FREQ_HZ * t));
      sampleBuffer[2 * j + 0] = val;  // Left
      sampleBuffer[2 * j + 1] = val;  // Right
    }
    size_t bytes_written;
    i2s_write(I2S_NUM, sampleBuffer, sizeof(sampleBuffer), &bytes_written, portMAX_DELAY);
  }
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  pinMode(35, OUTPUT);
  pinMode(36, OUTPUT);
  pinMode(37, OUTPUT);
  Serial.println("I2S 初期化中...");
  setupI2S();
  Serial.println("1kHz サイン波を出力します");
  playTone();
  Serial.println("終了しました");

}
int w=1000;
void loop() {
  digitalWrite(35, HIGH);delay(w);
  digitalWrite(35, LOW);delay(w);
  digitalWrite(36, HIGH);delay(w);
  digitalWrite(36, LOW);delay(w);
  digitalWrite(37, HIGH);delay(w);
  digitalWrite(37, LOW);delay(w);  
}


2.もう一つ、このボードには、RST,BOOTの釦は付いているのですが裏蓋を
  付けると、アクセス出来ません。これでは使いたい時に使えないので
  裏ブタにアプローチ用の穴を開けました。
 ESP32_4848S040-2

3.参考回路図(販売店サイトより)
 ESP32-4848S040回路図1

 ESP32-4848S040回路図2

以上 色々遊べそうです。


ブログトップへ

◆JC3248W535(ESP32S3) とLilyGo_T-Display(ESP32)でニキシー管もどき時計を表示しつつ、
 一定時間毎にRSSニュースをLCDに表示し、「TextToSpeech[TTS]AquesTalk-ESP32」の
 音声合成を使い、ニュースを喋らせてみました。

 S__53624838_0

 *ボードは、フラッシュメモリが16MB搭載の「JC3248W535」「LilyGo_Display」で、
  いずれもFFatへ辞書ファイルを入れています。
  「JC3248W535」は、内蔵のI2Sを使い、「LilyGo_Display」は、外付けのPCM5100Aに
  出力しています。
 
 TTGO_PCM5100A_SP

 *音声合成 AquesTalk については、下記を参照して下さい。
  AquesTalk ESP32
  「AquesTalk-ESP32 Ver.2.4」を使う

 *「JC3248W535」「LilyGo_Display」について、ピンアサイン等詳しくは、
  下記ブログ内記事を参照して下さい。
  ・JC3248W535 ESP32S3 にてパタパタ時計もどきを表示させてみた
  ・TTGO-Display 「Arduino_GFX_Library」でニュース表示をしてみた

1.下準備
 ①下記のサイトよりAquesTalk用の辞書ファイル等をダウンロードします。
  評価版ダウンロードの中で下にスクロールしてその他の「AquesTalk ESP32」です。

 DL_AquesTalk ESP32

 ②AquesTalk用の辞書ファイルをフラッシュメモリのFFatシステムへ保存します。
 aq_dic

  下記ブログ内記事を参照して構築して下さい。
  ・ESP32 ESP32S3 で PC(XMODEM)より「FFat」へ直接ファイルをコピーするツールを
   作ってみた


  ・ESP32S3 で「SDカード」から「FFat」へファイルをコピーするツールを作ってみた

2.スケッチは、サイズが大きいため下記よりzipファイルをダウンロードして下さい。
 ①(保障無しの自己責任で)  Nclock_News_Atalk_V2.zip

 ②スケッチでは、二つのボートを選択してコンパイルできます。
  「AquesTalkTTS.h」の44-46行で指定します。現在「LilyGo_Display」を選択
 44://ボード選択 使用するボードのコメントを取る
 45:#define    LilyGo_Display  // LilyGo T-Display   Flash=16MB P-Scheme: "16M Flash・・・
 46://#define    JC3248W535      // esp32s3 Dev M Flash=16MB P-Scheme: "16M Flash ・・・

 ➂コメント欄を参照して、IDEのコンパイラ設定をします。
  *LilyGo T-Display   Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS)
  *esp32s3 Dev    Flash=16MB P-Scheme: "16M Flash (3MB APP/9.9MB FATFS)
   psram=OPIPSRAM USBCDCOnBoot=en

 ④その後、コンパイルをして書き込みします。

3.開発環境 2025/05/30時点
  ①Windows11 X64 Pro 24H2 
  ②Arduino IDE 2.3.6
  ➂ESP32ボードバージョンV3.2.0
  ④Arduino_GFX_Library(GFX Library for Arduino) v1.6.0
  ⑤AquesTalk ESP32 V.2.4.4

4.カスタマイズ(行番号は、現状ですので多少変更になるかもです。)
 ①現在、5分間隔で6カテゴリ中の最初の8項目を、表示&音声読み上げしています。
   8項目終了したら、表示のみになります。

 ②間隔を変更するには、「Nclock_News_Atalk_V2.ino」ファイルの224-226行目で設定
 224://  if (((minute)==0)&&(second==0)) {  //毎時に音声出力
 225://  if (((minute%30)==0)&&(second==0)) {  //30分毎に音声出力 
 226:  if (((minute%5)==0)&&(second==0)) {  //デバッグ時5分毎に音声出力   

 ➂項目数の設定
 *読み込んだすべての項目を採用する場合は、394行をコメントアウトします。
  又は、自分で設定します。シリアルモニタにmax_lineが表示されます。
 394:  max_line=8; //デバッグ時に設定  

 max_line

 ④音声を出力する時間帯を108-109行で設定出来ます。(夜間うるさいので)
 108:int news_start_time=8; //ニュースを音声出力する開始時刻
 109:int news_end_time=23;  //ニュースを音声出力する終了時刻
 
 ⑤RSSニュースサイトを変更するには、下記ブログ内記事を参照して
  365-396行を修正します。現在は、「ITmedia NEWS」です。
  ・ESP32でRSSニュースサイト(Yahoo,NHKetc)を読み出してみた

 抜粋*赤文字の部分を別のサイトに書き換えます。
    case 1:      //**ITmedia NEWS(総合ITニュース)** 
      cat0 = https_Web_Get("rss.itmedia.co.jp", "/rss/2.0/news_bursts.xml", '\n', "</rss>",
                 "<title>", "</title>", "\n");
      break;
    case 2:      //**エンタープライズ(企業IT)** 
      cat0 = https_Web_Get("rss.itmedia.co.jp", "/rss/2.0/enterprise.xml", '\n', "</rss>",
                  "<title>", "</title>", "\n");
      break;
 
5.動作状況
 ①「JC3248W535」 ②「LilyGo_T-Display」

 

以上


ブログトップへ

◆以前「SDカード」から「FFat」へファイルをコピーするツールを作りました。下記参照
 ・ESP32S3 で「SDカード」から「FFat」へファイルをコピーするツールを作ってみた

 SDカードの無いボードでは、わざわざSDカードをセッティングする手間があり、面倒でした
 ので、今回PCより「XMODEM」を使って直接「FFat」へコピー出来るようにしてみました。
 xmodem-top

1.最初、シリアルポートを「XMODEM」用と「ログ用」に二つ使って、デバッグ用のログを
  見ながら開発しました。
  上手くいったので、最終系として、シリアルポートひとつで転送できるようにしました。
  これで、余計なハードを必要なしにファイルを転送する事が出来ました。

2.スケッチについて
 (今回は、シリアルポートひとつでESP32 Flash16MBのLilyGo T-Displayにて
 実証しています。 )
 ◆シリアルポート二つでは、ESP32S3 Devkit (Flash16MB)で確認しています。
 ESP32S3Devkit

 ①ボードの設定(ESP32 Flash16MBのLilyGo T-Display)
 LilyGo_T-Displat設定

 (保障無しの自己責任で)  esp32_SD_FFat_Xmodem_V2.zip
 動作については、スケッチ内のコメントを確認してください。

3.「ESP32」へ書き込みが、終了したら、「TeraTerm」を起動します。
 1.シリアルポートの設定をします。
  スピードは、出来るだけ早くする為に、「921600bps」します。
 teraterm_設定-1

 2.端末設定、ローカルエコー無しと送信改行コードを「LF」とします。
 teraterm_設定-2

 3.その後、リセットしますと、コマンド待ちの状態となります。
 teraterm_設定-3

 4.前回のブログと同様に「AquesTalk-ESP32 Ver.2.4」を使う為に、辞書ファイルを
  転送します。
  ①それ用にサブディレクトリを作成します。「>md /aq_dic」
  ②サブディレクトリが出来たことを確認します。「>dir」
  ➂続いて「XMODEM」で転送します。「>xmodem /aq_dic/aqdic_m.bin」
  ④「ファイル受信準備完了 file: /aq_dic/aqdic_m.bin」
   「20秒後に受信開始しますので TeraTerm で XMODEM 送信を開始して下さい...」
   と表示されたら、「XMODEM」で転送を開始します。
 xmodem-4

 5.XMODEMで転送(送信)を開始します。
 ①「ファイル」→「転送」→「XMODEM」→「送信」と選択します。
 xmodem-5-1

 ②「辞書ファイル:aqdic_m.bin」を選択し、「開く」をクリックします。
 xmodem-5-2

 ➂20秒経過後「MODEM」の送信が、始まります。
 xmodem-5-3

  6.終了を待って次のファイルを転送します。
  ①約16分後、約7MBのバイナリファイルが転送終了します。
   *転送後ファイルの最後の部分の「0x1A」CtrlZを取り除きます。
 ②同様に「CREDITS」を転送します。
 ➂転送されたか「サブディレクトリ」を表示してみます。
  *ちゃんと二つのファイルが転送されているのが確認出来ました。
 xmodem-6

以上
  
今日は、ここまで


ブログトップへ

◆追記2025/04/29
 他のPCで確認しましたら問題有りませんでした。
 よって、私のメインPCの問題みたいです。

◆追記2025/04/30
 python3をアンインストール後にArduinoIDE2.3.6にバージョンアップしたら
 あっさり直りました。
 以上 めでたしめでたし


◆追記2025/04/30
 ところが、python3を再インストールした所、同じ症状がでました。
 なんかpython3とIDEが相性悪いみたいです。
 そのような、環境では下記のツールが有効です。

 
◆私の環境だけかもですが「Windows11 X64 24H2」「ArduinoIDE2.3.5」「python3」の
 環境でArduinoIDEを終了した後、使用していたフォルダを「削除」「移動」「リネーム」
 を実行すると下記のエラーが発生しますので開放するツールを作りました。

削除エラーFF
 今まで対処方法が分からず再起動していました。
 今回、この問題を調べてみました。

1.フォルダを掴みんでいるプロセスを教えてくれるアプリ「Handle.exe」が有ることを
  知りました。Microsoft公式から無料で配布されています

 ①下記からダウンロードして下さい。
  Handle v5.0

 handle_サイト

 ②ダウンロードしたら解凍します。
  三つファイルが有りますが、自分の環境にあったものを任意のフォルダにコピペします。
  私の場合、「handle64.exe」を「c:\00yh\tools」へコピペしました。
 ➂コマンドプロンプトを管理者として実行します。そして、先のフォルダへ「cd」します。
 ④試しに「handle64.exe」を実行してみます。
  すると「tools」を掴んでいるプロセスが表示されます。
 handle実行

2.では、ArduinoIDEを実行して様子をみてみます。
 ①実行中
 ②IDE終了後(まだ二つ掴んだまま)
 IDE_B_A

 ➂このようにIDEを終了させてもプロセスが掴んだままの為、「削除」「移動」「リネーム」が
   出来ないで、エラーとなります。

3.2を踏まえて、悪さしているプロセスを自動で「kill」するツールを作りました。
  下記のバッチファイル「ff.bat」です。(Folder Freeの略)
  バッチファイルを保存する時は、漢字コードを「Shift-JIS」で保存します。
  「UTF-8」だと、文字化けします。

********************ここから**************************************
:: ff.bat
:: V2025/04/29 by JK1VCK
:: blog URL:https://gijin77.blog.jp/archives/41005740.html

@echo off
setlocal enabledelayedexpansion

:: handle.exeのパス(自分の環境に合わせてね)
set "HANDLE_EXE=c:\00YH\tools\handle64.exe"

:: 削除対象のフォルダパス受け取り
if "%~1"=="" (
    echo 使用方法: %~nx0 "削除対象フォルダパス"
    pause
    exit /b
)

set "TARGET_FOLDER=%~1"

:: フォルダ存在確認
if not exist "%TARGET_FOLDER%" (
    echo [エラー] フォルダが存在しません: "%TARGET_FOLDER%"
    pause
    exit /b
)

echo 削除対象フォルダ: "%TARGET_FOLDER%"
echo.
echo フォルダを掴んでいるプロセスを検索中...

:: 一時ファイル削除
if exist temp_handle_result.txt del temp_handle_result.txt

:: handle.exeで対象フォルダを検索
"%HANDLE_EXE%" "%TARGET_FOLDER%" > temp_handle_result.txt 2>nul

:: 掴んでいるかチェック
findstr /i "pid:" temp_handle_result.txt >nul
if %errorlevel%==0 (
    echo [警告] 誰かがフォルダを掴んでいます!
    echo 掴んでいるプロセス一覧:

    set "KILL_LIST="

    for /f "tokens=*" %%A in (temp_handle_result.txt) do (
        set "LINE=%%A"
        echo !LINE! | findstr /i "pid:" >nul
        if !errorlevel! == 0 (
            rem LINEから"pid:"の位置を探す
            set "TMP_LINE=!LINE:*pid:=!"
            rem TMP_LINEの先頭からスペースまでを取り出す
            for /f "tokens=1 delims= " %%P in ("!TMP_LINE!") do (
                set "PID=%%P"
                rem プロセス名も表示
                for /f "tokens=1" %%N in ("!LINE!") do (
                    set "PNAME=%%N"
                )
                echo !PNAME! - PID: !PID!
                set "KILL_LIST=!KILL_LIST! !PID!"
            )
        )
    )

    echo:
    set /p USER_KILL="これらのプロセスを終了しますか? (y/n) [n]: "
    if /i "!USER_KILL!"=="y" (
        for %%P in (!KILL_LIST!) do (
            if not "%%P"=="" (
                echo PID %%P を強制終了中...
                taskkill /PID %%P /F
            )
       )
    ) else (
        echo プロセス終了をスキップしました。
    )

) else (
    echo 誰も掴んでいません!
)

:: 少し待つ
timeout /t 1 >nul

echo.
set /p USER_CONFIRM=このフォルダを削除しますか? (y/n) [n]: 
if /i "%USER_CONFIRM%"=="y" (
    echo フォルダを削除します...
    rmdir /s /q "%TARGET_FOLDER%"
    echo 削除完了!
) else (
    echo 削除をキャンセルしました。
)

:: 一時ファイル削除
if exist temp_handle_result.txt del temp_handle_result.txt

pause
exit /b
********************ここまで**************************************

 ◆使い方(実行例)
  ①コマンドプロンプトを管理者として実行します。
  ②ff.batのフォルダに「cd」します。
  ➂ff フォルダ名
  ④キャンセルする場合は、「n」を入力します。
   「explorer.exe - PID: xxxxx」が表示されたらキャンセルして下さい
   そうしないと画面が真っ暗になり、再起動かサインアウト/サインインすることに
   なります。
   その時は、対象のフォルダを表示しているエクスポーラを閉じてから実行してください。
  ⑥再度実行
  ⑦プロセスを終了する場合は、「y」を入力します。
  ⑧削除する場合は、「y」を入力します。
   「フォルダ移動」や「リネーム」の場合は、「n」を入力します。
 コマンドプロンプト_FF実行

以上で、再起動しなくても「削除」「移動」「リネーム」が出来るようになりました。


ブログトップへ

◆ESP32S3で「FFat」システムで辞書ファイルを使用する必要にせままれて、「SDカード」
 から「FFat」へファイルをコピーするツールを作ってみました。
 (下記のアプリで必要)
 AquesTalk ESP32
 「AquesTalk-ESP32 Ver.2.4」を使う

 フラッシュメモリに転送する為に、ArduinoIDE1.8.19へ戻って転送用のプラグインを入れて
 試しましたがうまく出来ませんでした。
 さらにArduinoIDE2.3.5では、調べた範囲では出来なさそうだったので代替としてSDの
 ツールに「FFat」を追加してみました。意外と簡単に動作しました。
 操作は、シリアルでのやり取りです。

 *起動画面
 正常起動画面

1.今回、サブディレクトリと7MBの辞書を扱うため「FATFS」を採用しました。
 *SPIFFSとFATFSの違いについては下記のようです。
 ①SPIFFS (SPI Flash File System)
 **特徴**:
  - 軽量なファイルシステムでフラッシュメモリ向けに設計
  - ファイル名の長さに制限あり(通常31文字まで)
  - ディレクトリ構造をサポートしない(フラットなファイルシステム)
  - 書き込みサイクルが限られているフラッシュメモリに最適化
  - 主に設定ファイルや小さなデータファイルの保存に使用

 ②FATFS(Fat File System)
 **特徴**:
  - 伝統的なFATファイルシステムの実装
  - ディレクトリ構造をサポート
  - 長いファイル名をサポート(LFN)
  - より大きなファイルサイズを扱える
  - PCとの互換性が高い(SDカードなどでよく使用される形式)
  - メモリ使用量がSPIFFSより多い
  
2.ESP32s3で初めて「FFat」ファイルシステムを構築する場合は、下記の設定をして
  コンパイル、書き込みをします。
 1.ボード設定
  ①ボード: "ESP32S3 Dev Module"
  ②USB CDC On Boot: "Enabled" <--シリアル出力に必要
  ➂Erase All Flash Before Sketch Upload: "Enabled"
  ④Flash Size "16MB(128Mb)"
  ⑤Partition Scheme: "16M Flash (3MB APP/9.9MB FATFS)"
  ⑥ PSRAM: "OPI PSRAM"
  
  ◆Partition Scheme:は、辞書サイズが約7MBの為、 アプリにも
   余裕を持たせ、(3MB APP/9.9MB FATFS)としました。
  
 初めてFFat構築時

 2.スケッチの65行目で強制フォーマットさせます。

 63://FFat************************************************************  
 64:  Serial.println(F("FFatを初期化しています..."));
 65:  if (!FFat.begin(true)) {   //<---初期化失敗の場合、trueにして強制フォーマットし、・・・
 66:    error("FFatのマウントに失敗しました"); //マウントされたら、trueを取り、Erase Al・・・
 67:  }
 68:  Serial.println(F("FFatがマウントされました。"));
 69:  listDir(FFat, "/", 0);
 70:  Serial.println(F("----------------------------------------")); 
 
3.正常に"FFatがマウントされました。"と表示されたら下記の設定にします。
 2-1-➂ "Disabled"
 2-2-65行目 if (!FFat.begin()) {  <--trueを取る
 通常時設定
 
 ◆それでも下記のようにエラーが表示されたら「2」の項目を見直します。
 SD不良
 FFat不良

4.実際にSDカードの辞書ファイル他を「FFat」へコピーした時の抜粋です様子です。
 *毎回表示されるコマンドライン文字を削除しています。

 SD Card / FFat TOOL By JK1VCK
 FFatの場合 コマンドの前にfを付加 例「fdir」 n1=name1 n2=name2
 dir,rd /path,md /path,del /name,ren /n1 /n2,cp /n1 /n2,add /name msg,cat /name,new /name msg,cpsf /n1 /n2,cpfs /n1 /n2,help

 >dir                                     <---SDカードのディレクトリ表示
 リストディレクトリ: /
   DIR : System Volume Information
   DIR : aq_dic
   FILE: foo.txt  SIZE: 9
 
 >fdir                                      <---「FFat」のディレクトリ表示
 リストディレクトリ: /
 
 >fmd /aq_dic                         <---「FFat」にサブディレクトリ作成
 ディレクトリの作成: /aq_dic
 ディレクトリが作成されました
 
 >fdir                                       <---「FFat」のサブディレクトリの確認
 リストディレクトリ: /
  DIR : aq_dic

 >dir /aq_dic                            <---SDカードのサブディレクトリ表示
 リストディレクトリ: /aq_dic
   FILE: aqdic_m.bin  SIZE: 7385048
   FILE: CREDITS  SIZE: 1831
   
 >cpsf /aq_dic/aqdic_m.bin /aq_dic/aqdic_m.bin <---SDカードから「FFat」へコピー
 ファイルをコピー中 /aq_dic/aqdic_m.bin から /aq_dic/aqdic_m.bin <--かなり時間がかかる。
 ファイルが正常にコピーされました
 
 >cpsf /aq_dic/CREDITS /aq_dic/CREDITS  <---SDカードから「FFat」へコピー
 ファイルをコピー中 /aq_dic/CREDITS から /aq_dic/CREDITS
 ファイルが正常にコピーされました
 
 >fdir /aq_dic                                                     <---「FFat」のサブディレクトリの確認
 リストディレクトリ: /aq_dic
   FILE: aqdic_m.bin  SIZE: 7385048
   FILE: CREDITS  SIZE: 1831

 以上でSDカード内の2つのファイルを「FFat」へコピーできました。
 
5.スケッチは、下記に示します。
  (保障無しの自己責任で)  esp32_SD_FFat.zip

 以上 「FFat」ファイルシステムが使えるようになりました。
 

ブログトップへ

◆JC1060P470CボードでArduinoIDE環境でWiFiが、使えるようになりましたので
 NHKのRSSニュースを読み込み表示してみました。
 jc1060p470_News-1

 下記の9種類のカテゴリーを読み込み順次表示しています。
 ひとつのカテゴリで項目がたくさんある場合、最初の8項目を表示しています。
 ①**NHKニュース トップニュース**
 ②**主要ニュース**
 ➂**社会ニュース**
 ④**政治ニュース**
 ⑤**経済ニュース**
 ⑥**国際ニュース**
 ⑦**スポーツニュース**
 ⑧**科学・文化ニュース**
 ⑨**最新15項目ニュース**

◆ボードなどの情報は、下記ブログ内記事を参照して下さい。
 ①・JC1060P470C(ESP32P4 ESP32C6 搭載) を使ってみた
 ②・JC1060P470C(ESP32P4 ESP32C6 搭載) ArduinoIDE環境でWiFiが使えるようになった
 ➂・ESP32でRSSニュースサイト(Yahoo,NHKetc)を読み出してみた
 *NHK以外のサイトは、上記を参照して修正すれば簡単に出来ます。

1.開発環境 2025/04/21時点
  ①Windows11 X64 Pro 24H2 
  ②Arduino IDE 2.3.5
  ➂ESP32ボードバージョンV3.2.0
  ④Arduino_GFX_Library(GFX Library for Arduino) v1.5.6
  ⑤efont ライブラリ v1.0.9

2.スケッチ
 ①このスケッチは、画面サイズの違うボードにも対応しています。
  最初の13行~19行で指定します。

 13://ボート選択 使用するボードのコメントを取る
 14:#define JC1060P470      // esp32p4 Flash Size:"16MB" Partition Scheme:16M ・・・・ 
    15:                           // PSRAM : en UPload Mode : USB-OTG...
 16://#define ESP32_1732S019  // esp32s3 psram=dis Partition Scheme:Huge APP(・・・
 17://#define JC2432W328      // esp32   Partition Scheme:Huge APP(3MB NoOTA)
 18://#define JC3248W535      // esp32s3 psram=OPIPSRAM Scheme:Huge APP(・・・
 19://#define ESP32_3248S035  // esp32 Partition Scheme:Huge APP(3MB NoOTA)

 ②このスケッチでは、個人利用の為、証明書なしで読み出しています。
 160:  https_client.setInsecure();  // 証明書チェックを無効化

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

3.実行の様子
 jc1060p470_News-2

 jc1060p470_News-3

 jc1060p470_News-4

 jc1060p470_News-5

 jc1060p470_News-6

 jc1060p470_News-7

 jc1060p470_News-8

 jc1060p470_News-9

以上


ブログトップへ

◆ついにJC1060P470CボードでArduinoIDE環境でWiFiが、使えるようになりました。
 今まで、ちょっと不便でしたが、ESP32のボードバージョンが3.2.0にバージョンアップ
 されて、ESP32P4でWiFiのライブラリが使えるようになりました。
 ESP32C6とSDIO制御することなく、ESP32単体と同じに普通に使えました。感激。
 jc1060p470_wifi-1

 JC1060P470ボードについて、詳しくは下記ブログ内記事を参照して下さい。
 ・JC1060P470C(ESP32P4 ESP32C6 搭載) を使ってみた


1.開発環境 2025/04/18時点
  ①Windows11 X64 Pro 24H2 
  ②Arduino IDE 2.3.5
  ➂ESP32ボードバージョンV3.2.0
  ④Arduino_GFX_Library(GFX Library for Arduino) v1.5.6

2.普通にサンプルプログラム「WiFiScan」を「Arduino_GFX_Library」を使い
  LCDに表示するよう修正して表示してみました。

//esp32p4_GXF_wifi_Scan.ino
//V1 /2025/04/18 By JK1VCK <Arduino_GFX_Library.h>使用
//blog URL:https://gijin77.blog.jp/archives/44343378.html
//JC1060P470 esp32p4 Flash Size:"16MB" Partition Scheme:16M Flash(2MB APP..) 
//           PSRAM : en UPload Mode : USB-OTG...

#include <WiFi.h>
#include <Arduino_GFX_Library.h>

//***************************************************************************
#define GFX_DEV_DEVICE JC1060P470
#define LED      26
#define LEDON    LOW
#define LEDOFF   HIGH
#define GFX_BL 23 // default backlight pin, you may replace DF_GFX_BL to actual backlight pin
#define DSI_PANEL
Arduino_ESP32DSIPanel *dsipanel = new Arduino_ESP32DSIPanel(
    40 /* hsync_pulse_width */, 160 /* hsync_back_porch */, 160 /* hsync_front_porch */,
    10 /* vsync_pulse_width */, 23 /*vsync_back_porch  */, 12 /* vsync_front_porch */,
    48000000 /* prefer_speed */);
Arduino_DSI_Display *gfx = new Arduino_DSI_Display(
    1024 /* width */, 600 /* height */, dsipanel, 0 /* rotation */, true /* auto_flush */,
    27 /* RST */, jd9165_init_operations, sizeof(jd9165_init_operations) / sizeof(lcd_init_cmd_t));
#define C6_RESET  54  // ESP32-C6のリセットピン
//***************************************************************************

void setup() {
  Serial.begin(115200);
  delay(1000);
  // ESP32-C6をリセット
  pinMode(C6_RESET, OUTPUT);
  digitalWrite(C6_RESET, LOW);
  delay(100);
  digitalWrite(C6_RESET, HIGH);
  delay(2000);  // ESP32-C6の起動待機

  pinMode(GFX_BL, OUTPUT);digitalWrite(GFX_BL, HIGH); //バックライトON  
  gfx->begin();
  gfx->setRotation(0);gfx->fillScreen(BLACK);
  gfx->setCursor(0,2);gfx->setTextColor(GREEN);gfx->setTextSize(3);
  gfx->drawRect(0,0,gfx->width()-1,gfx->height()-1,YELLOW);//枠表示
  //digitalWrite(GFX_BL, HIGH); //バックライトON  
  Serial.println("WiFi Scan / Arduino_GFX_Library Start");  
  gfx->println("WiFi Scan / Arduino_GFX_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");
  gfx->println("Setup done");
}

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



3.実行中の様子
  20秒毎にスキャンを繰り返します。
 jc1060p470_wifi-2

4.アクセスポイントへの接続試験用スケッチ
 ①ssidとpasswordを自分用に修正して下さい。
//esp32p4_wifi.ino

#include <WiFi.h>

#define C6_RESET  54  // ESP32-C6のリセットピン
// Wi-Fi設定
const char* ssid = "IO_Net_2G";
const char* password = "1234567890";

void setup() {
  Serial.begin(115200);
  delay(1000);

  // ESP32-C6をリセット
  pinMode(C6_RESET, OUTPUT);
  digitalWrite(C6_RESET, LOW);
  delay(100);
  digitalWrite(C6_RESET, HIGH);
  delay(2000);  // ESP32-C6の起動待機

  // Wi-Fi接続開始
  WiFi.begin(ssid, password);
  Serial.print("Wi-Fi接続中...");

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("\nWi-Fi接続成功!");
  Serial.print("IPアドレス: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  // 例: HTTPリクエスト送信
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("Wi-Fi接続済み");
  } else {
    Serial.println("Wi-Fi切断中");
  }
  delay(5000);
}

 ②実行中のシリアル出力
 jc1060p470_wifi-3

5.WiFi事例でNHKのニュース表示してみました。
 下記ブログ内記事を参照して下さい。
・JC1060P470C(ESP32P4 ESP32C6 搭載) ArduinoIDE環境でNHK RSSニュース表示してみた


以上


ブログトップへ

◆ESP32でRSSニュースサイト(Yahoo,NHK,ITmedia,livedoor)を読み出し、シリアル出力して
 みました。

 試しに下記の4サイトのURLを実行してみました。
 今回は、個人利用の為証明書なしで読み出しています。

 ①Yahooニュース    : https://news.yahoo.co.jp/rss/topics/top-picks.xml
 ②NHKニュース         : https://www.nhk.or.jp/rss/news/cat0.xml
 ➂ITmediaニュース      : https://rss.itmedia.co.jp/rss/2.0/news_bursts.xml
 ④ライブドアニュース : http://news.livedoor.com/topics/rss/top.xml

 yahoo_news_rss


1.スケッチ保障なしの自己責任で参考までに)
 ①開発環境 2025/04/15時点
  1.Windows11 X64 Pro 24H2 
  2.Arduino IDE 2.3.5
  3.ESP32ボードバージョンV3.2.0

 ②使い方
  1.//ニュースサイトを選択するの所で
   表示させるニュースサイトの//#defineのコメントを取ります。
  2.WiFiのSSIDとPASSWORDをご利用のものに修正します。
  3.esp32でコンパイル&書き込みします。
  4.シリアルモニタを表示させます。

//get_news.ino
//V2025/04/15 by JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44314639.html

#include <WiFi.h>
#include <WiFiClientSecure.h>

//Yahooニュース: https://news.yahoo.co.jp/rss/topics/top-picks.xml
//NHKニュース: https://www3.nhk.or.jp/rss/news/cat0.xml
//ITmedia: https://rss.itmedia.co.jp/rss/2.0/news_bursts.xml
//livedoor: http://news.livedoor.com/topics/rss/top.xml

//ニュースサイトを選択する
#define    yahoo    //Yahooニュース:
//#define    nhk      //NHKニュース
//#define    itmedia  //ITmedia
//#define    livedoor //livedoor:

#if defined(yahoo)
  const char* host = "news.yahoo.co.jp";
  const char* path = "/rss/topics/top-picks.xml";
#elif defined(nhk)
  const char* host = "www3.nhk.or.jp";
  const char* path = "/rss/news/cat0.xml";
#elif defined(itmedia)
  const char* host = "rss.itmedia.co.jp";
  const char* path = "/rss/2.0/news_bursts.xml";
#elif defined(livedoor)
  const char* host = "news.livedoor.com";
  const char* path = "/topics/rss/top.xml";
#endif
const int httpsPort = 443;

const char* ssid = "IO_Net_2G";  //Your SSID
const char* password = "1234567890";  //Your PASSWORD

void setup() {
  Serial.begin(115200);
  delay(1000);

  WiFi.begin(ssid, password);
  Serial.print("WiFi connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected!");
  Serial.println(WiFi.localIP());

  WiFiClientSecure client;
  client.setInsecure();  // 一時的に証明書チェックを無効化

  Serial.printf("Connecting to %s...\n", host);
  if (!client.connect(host, httpsPort)) {
    Serial.println("Connection failed!");
    return;
  }

  client.printf("GET %s HTTP/1.1\r\n", path);
  client.printf("Host: %s\r\n", host);
  client.println("User-Agent: ESP32RSSClient");
  //client.println("Connection: close\r\n"); //これを書くとNHKがすぐに切断する
  client.println();
  Serial.println("=== RSS Feed Start ===");
 
bool isBody = false;
unsigned long timeout = millis();

  while ((millis() - timeout) < 2000) {  // タイムアウトを2秒にする
    while (client.available()) {
      String line = client.readStringUntil('\n');
      line.trim();
      if (!isBody && line.length() == 0) {
        isBody = true;
        continue;
      }
      if (isBody) {
        Serial.println(line);
      }
      timeout = millis();  // データが来たらタイムアウトリセット
    }
    if (!client.connected()) break;
  }
  client.stop();  // ←ここで明示的に切るのはOK
  Serial.println("=== RSS Feed End ===");
}

void loop() {
}


2.実行時のシリアル出力の抜粋

①Yahooニュース ***************************************************************************************

WiFi connecting..... connected!
192.168.1.147
Connecting to news.yahoo.co.jp...
=== RSS Feed Start ===
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rss version="2.0">
  <channel>
    <language>ja</language>
    <copyright>© LY Corporation</copyright>
    <pubDate>Mon, 14 Apr 2025 02:17:43 GMT</pubDate>
    <title>Yahoo!ニュース・トピックス - 主要</title>
    <link>https://news.yahoo.co.jp/topics/top-picks?source=rss</link>
    <description>Yahoo! JAPANのニュース・トピックスで取り上げている最新の見出しを提供しています。</description>
    <item>
      <title>ミャンマー地震 邦人死亡を初確認</title>
      <link>https://news.yahoo.co.jp/pickup/6535430?source=rss</link>
      <pubDate>Mon, 14 Apr 2025 01:31:10 GMT</pubDate>
      <comments>https://news.yahoo.co.jp/articles/650463466ab1cf0dd82841135c6798769ca1990d/comments</comments>
    </item>
    <item>
      <title>東証が大幅反発 一時700円超高</title>
      <link>https://news.yahoo.co.jp/pickup/6535428?source=rss</link>
      <pubDate>Mon, 14 Apr 2025 01:06:58 GMT</pubDate>
      <comments>https://news.yahoo.co.jp/articles/898d31b616b1ad47373d11e775128a89d553f6eb/comments</comments>
    </item>

..... 省略

</channel>
</rss>
=== RSS Feed End ===


②NHKニュース *****************************************************************************************

WiFi connecting...... connected!
192.168.1.147
Connecting to www3.nhk.or.jp...
=== RSS Feed Start ===
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:nhknews="http://www.nhk.or.jp/rss/rss2.0/modules/nhknews/" version="2.0">
<channel>
<title>NHKニュース</title>
<description>日本放送協会 NHKニュース</description>
<link>http://www3.nhk.or.jp/news/</link>
<lastBuildDate>Mon, 14 Apr 2025 22:01:45 +0900</lastBuildDate>
<item>
<title>15日は東日本でも荒れた天気のおそれ 落雷など注意を</title>
<link>http://www3.nhk.or.jp/news/html/20250414/k10014778541000.html</link>
<guid isPermaLink="true">http://www3.nhk.or.jp/news/html/20250414/k10014778541000.html</guid>
<pubDate>Mon, 14 Apr 2025 21:01:24 +0900</pubDate>
<description>上空の強い寒気の影響で、西日本を中心に大気の状態が非常に不安定になり局地的に雷雨となっています。15日は東日本でも荒れた天気になるおそれがあり、気象庁は落雷や竜巻などの激しい突風、急な激しい雨、ひょうに注意するよう呼びかけています。</description>
<nhknews:new>false</nhknews:new>
</item>
<item>
<title>トランプ大統領 導入予定の半導体関税措置 “来週中にも発表”</title>
<link>http://www3.nhk.or.jp/news/html/20250414/k10014778551000.html</link>
<guid isPermaLink="true">http://www3.nhk.or.jp/news/html/20250414/k10014778551000.html</guid>
<pubDate>Mon, 14 Apr 2025 17:37:06 +0900</pubDate>
<description>アメリカのトランプ大統領は、今後導入する予定の半導体を対象にした関税措置について、「来週中にも発表するつもりだ」と述べ、近く関税率を表明する考えを示しました。また、スマートフォンなどの電子機器への関税措置については大手メーカーなどと協議したうえで内容を発表するとしています。</description>
<nhknews:new>false</nhknews:new>
</item>

..... 省略

</channel>
</rss>
=== RSS Feed End ===


➂ITmediaニュース *************************************************************************************

WiFi connecting...... connected!
192.168.1.147
Connecting to rss.itmedia.co.jp...
=== RSS Feed Start ===
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0">
<channel>
<title>ITmedia NEWS 最新記事一覧</title>
<link>https://www.itmedia.co.jp/news/</link>
<description>ITmedia NEWS の最新記事一覧です。</description>
<language>ja</language>
<copyright>Copyright (c) 2025 ITmedia, Inc. All Rights Reserved.</copyright>
<pubDate>Mon, 14 Apr 2025 11:25:00 +0900</pubDate>
<item>
<title>大阪・関西万博、東ゲートにWi-Fiを準備 QRコード表示用に 携帯キャリアにも協力要請</title>
<link>https://www.itmedia.co.jp/news/articles/2504/14/news083.html</link>
<description>大阪・関西万博を運営する2025年日本国際博覧会協会は13日、会場の東ゲートに入場に必要なチケットのQRコードを表示するためにWi-Fiを準備すると発表した。</description>
<pubDate>Mon, 14 Apr 2025 11:02:00 +0900</pubDate>
</item>
<item>
<title>世界量子デーのGoogleロゴは「量子重ね合わせ」理解を助けるGIF動画</title>
<link>https://www.itmedia.co.jp/news/articles/2504/14/news077.html</link>
<description>Googleロゴが記念日に変わる「Doodle」。4月14日は「世界量子デー」を記念し、ソーマトロープでGoogleロゴを表現したGIF動画が公開された。</description>
<pubDate>Mon, 14 Apr 2025 09:50:00 +0900</pubDate>
</item>

..... 省略

</channel>
</rss>
=== RSS Feed End ===


④ライブドアニュース **********************************************************************************

WiFi connecting..... connected!
192.168.1.147
Connecting to news.livedoor.com...
=== RSS Feed Start ===
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<atom:link href="https://news.livedoor.com/rss/topics/top.xml" rel="self" type="application/rss+xml" />
<language>ja</language>
<title>ライブドアニュース - 主要トピックス</title>
<link>https://news.livedoor.com</link>
<generator>https://news.livedoor.com</generator>
<description>ライブドアニュース - 主要トピックス</description>
<lastBuildDate>Mon, 14 Apr 2025 14:53:27 +0900</lastBuildDate>
<item>
<title><![CDATA[男性が女性の人命救助でAED使用に批判…現役アイドルが悲嘆の声]]></title>
<link>https://news.livedoor.com/article/detail/28553668/</link>
<description><![CDATA[
<a href="https://news.livedoor.com/article/detail/28553668/">記事を読む</a>]]>
</description>
<mobile>1</mobile>
<pubDate>Mon, 14 Apr 2025 14:17:01 +0900</pubDate>
<guid>https://news.livedoor.com/article/detail/28553668/</guid>
<enclosure url="https://image.news.livedoor.com/newsimage/stf/7/7/77bfd_1399_0996c268_31141a52.jpg" type="image/jpeg" length="0" />
</item>
<item>
<title><![CDATA[「ビックリするくらい酒強いやん」千鳥・大悟が井桁弘恵の酒豪っぷり明かす]]></title>
<link>https://news.livedoor.com/article/detail/28550408/</link>
<description><![CDATA[
<a href="https://news.livedoor.com/article/detail/28550408/">記事を読む</a>]]>
</description>
<mobile>1</mobile>
<pubDate>Mon, 14 Apr 2025 00:00:00 +0900</pubDate>
<guid>https://news.livedoor.com/article/detail/28550408/</guid>
<enclosure url="https://image.news.livedoor.com/newsimage/stf/8/c/8cbe6_1585_664b9399cd232f6565b585f33c76d8d2.jpg" type="image/jpeg" length="0" />
</item>

..... 省略

</channel>
</rss>
=== RSS Feed End ===


3.各サイト、主要なカテゴリごとに分かれていますので、必要に応じてご利用ください。
  サイト利用については、個人利用の範囲で自己責任で参考にして下さい。

①Yahooニュース ***************************************************************************************
 Yahoo!ニュースのRSSフィードは、以下のURLで提供されています。 

### **Yahoo!ニュース 主要RSSフィード**  
- **トップニュース(主要ヘッドライン)**  /rss/topics/
  `https://news.yahoo.co.jp/rss/topics/top-picks.xml`  

- **国内ニュース**  
  `https://news.yahoo.co.jp/rss/topics/domestic.xml`  

- **国際ニュース**  
  `https://news.yahoo.co.jp/rss/topics/world.xml`  

- **経済ニュース**  
  `https://news.yahoo.co.jp/rss/topics/business.xml`  

- **エンタメ・芸能ニュース**  
  `https://news.yahoo.co.jp/rss/topics/entertainment.xml`  

- **スポーツニュース**  
  `https://news.yahoo.co.jp/rss/topics/sports.xml`  

- **IT・科学ニュース**  
  `https://news.yahoo.co.jp/rss/topics/it.xml`  

- **地域ニュース**  
  `https://news.yahoo.co.jp/rss/topics/local.xml`  

### **注意点**  
- 最新情報は[Yahoo!ニュース公式サイト](https://news.yahoo.co.jp/)で確認してください。 


②NHKニュース *****************************************************************************************
 NHKニュースのRSSフィードは以下のURLで提供されています。

### NHKニュース主要RSSフィード
- **NHKニュース トップニュース**
  `https://www.nhk.or.jp/rss/news/cat0.xml`

- **主要ニュース**
  `https://www.nhk.or.jp/rss/news/cat1.xml`

- **社会ニュース**
  `https://www.nhk.or.jp/rss/news/cat2.xml`

- **政治ニュース**
  `https://www.nhk.or.jp/rss/news/cat3.xml`

- **経済ニュース**
  `https://www.nhk.or.jp/rss/news/cat4.xml`

- **国際ニュース**
  `https://www.nhk.or.jp/rss/news/cat5.xml`

- **スポーツニュース**
  `https://www.nhk.or.jp/rss/news/cat6.xml`

- **科学・文化ニュース**
  `https://www.nhk.or.jp/rss/news/cat7.xml`

- **最新15項目ニュース**
  `https://www.nhk.or.jp/rss/news/cat8.xml`

- **最新15項目ニュース**
  `https://www.nhk.or.jp/rss/news/cat9.xml`
  
### 注意点
- NHKのRSSフィードは無料で利用可能ですが、コンテンツの著作権はNHKに帰属します。
最新情報は[NHKニュース公式サイト](https://www3.nhk.or.jp/news/)でご確認ください。

NHKは信頼性の高いニュースソースとして知られており、
これらのRSSフィードを活用することで最新情報を効率的に取得できます。


➂ITmediaニュース *************************************************************************************
 ITmediaの主要なRSSフィードは以下の通りです。
### ITmedia 主要RSSフィード一覧

#### 【主要カテゴリ】
- **ITmedia 総合トップ**  
  `https://rss.itmedia.co.jp/rss/2.0/itmedia_all.xml`

- **ITmedia NEWS(総合ITニュース)**  
  `https://rss.itmedia.co.jp/rss/2.0/news_bursts.xml`

- **エンタープライズ(企業IT)**  
  `https://rss.itmedia.co.jp/rss/2.0/enterprise.xml`

- **ビジネス(ITビジネス)**  
  `https://rss.itmedia.co.jp/rss/2.0/business.xml`

#### 【技術系カテゴリ】
- **モバイル(スマホ/通信)**  
  `https://rss.itmedia.co.jp/rss/2.0/mobile.xml`

#### 【セキュリティ/ネットワーク】
- **Security(セキュリティ)**  
  `https://rss.itmedia.co.jp/rss/2.0/security.xml`

#### 【その他専門分野】
- **ゲーム/エンタメ**  
  `https://rss.itmedia.co.jp/rss/2.0/games.xml`

### 注意事項
1. 最新情報は[ITmedia公式サイト](https://www.itmedia.co.jp/)で確認してください
2. 記事全文を表示するにはサイト訪問が必要な場合があります
3. 商用利用の際は利用規約を確認してください

ITmediaは日本を代表するIT専門メディアで、特に技術者やITプロフェッショナル向けの深い内容が特徴です。
RSSリーダーに登録すれば、効率的に最新情報を追跡できます。


④ライブドアニュース **********************************************************************************
 ライブドアニュース(livedoor NEWS)のRSSフィードは、以下のURLで提供されています。  

### **ライブドアニュース 主要RSSフィード**  
- **トップニュース**  
  `http://news.livedoor.com/topics/rss/top.xml`  

- **国内ニュース**  
  `http://news.livedoor.com/topics/rss/dom.xml`  

- **国際ニュース**  
  `http://news.livedoor.com/topics/rss/int.xml`  

- **IT・経済ニュース**  
  `http://news.livedoor.com/topics/rss/eco.xml`  

- **エンタメ・芸能ニュース**  
  `http://news.livedoor.com/topics/rss/ent.xml`  

- **スポーツニュース**  
  `http://news.livedoor.com/topics/rss/spo.xml`  

### **その他のカテゴリ**  
- **科学・医療**  
  `http://news.livedoor.com/topics/rss/sci.xml`  

- **地域ニュース**  
  `http://news.livedoor.com/topics/rss/loc.xml`  

### **注意点**  
 最新の情報は[ライブドアニュース公式サイト](https://news.livedoor.com/)で確認してください。  


*******************************************************************************************************

4.下記は、RSS feedの中からタイトルだけを抽出するスケッチです。
  (保障なしの自己責任で参考までに)
//get_news_v2.ino
//V2025/04/21 by JK1VCK
//blog URL:https://gijin77.blog.jp/archives/44314639.html

#include <WiFi.h>
#include <WiFiClientSecure.h>

//Yahooニュース: https://news.yahoo.co.jp/rss/topics/top-picks.xml
//NHKニュース: https://www3.nhk.or.jp/rss/news/cat0.xml
//ITmedia: https://rss.itmedia.co.jp/rss/2.0/news_bursts.xml
//livedoor: http://news.livedoor.com/topics/rss/top.xml

//ニュースサイトを選択する
//#define    yahoo    //Yahooニュース:
#define    nhk      //NHKニュース
//#define    itmedia  //ITmedia
//#define    livedoor //livedoor:

#if defined(yahoo)
  const char* host = "news.yahoo.co.jp";
  const char* path = "/rss/topics/top-picks.xml";
#elif defined(nhk)
  const char* host = "www3.nhk.or.jp";
  const char* path = "/rss/news/cat0.xml";
#elif defined(itmedia)
  const char* host = "rss.itmedia.co.jp";
  const char* path = "/rss/2.0/news_bursts.xml";
#elif defined(livedoor)
  const char* host = "news.livedoor.com";
  const char* path = "/topics/rss/top.xml";
#endif
const int httpsPort = 443;

const char* ssid = "IO_Net_2G";
const char* password = "1234567890";

void setup() {
  Serial.begin(115200);
  delay(1000);

  WiFi.begin(ssid, password);
  Serial.print("WiFi connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected!");
  Serial.println(WiFi.localIP());

  WiFiClientSecure client;
  client.setInsecure();  // 一時的に証明書チェックを無効化

  Serial.printf("Connecting to %s...\n", host);
  if (!client.connect(host, httpsPort)) {
    Serial.println("Connection failed!");
    return;
  }

  client.printf("GET %s HTTP/1.1\r\n", path);
  client.printf("Host: %s\r\n", host);
  client.println("User-Agent: ESP32RSSClient");
  //client.println("Connection: close\r\n"); //これを書くとNHKがすぐに切断する
  client.println();
  Serial.println("=== RSS Feed Start ===");
 
bool isBody = false;
unsigned long timeout = millis();
String titleTag = "<title>";
String titleEnd = "</title>";

  while ((millis() - timeout) < 2000) {  // タイムアウトを2秒にする
    while (client.available()) {
      String line = client.readStringUntil('\n');
      line.trim();
      if (!isBody && line.length() == 0) {
        isBody = true;
        continue;
      }
      if (isBody) {
        if (line.startsWith(titleTag)) {
          String title = line.substring(titleTag.length(), line.indexOf(titleEnd));
          Serial.println("Title: " + title);
           // LCDに表示したい処理へ
        }
        //Serial.println(line);
      }
      timeout = millis();  // データが来たらタイムアウトリセット
    }
    if (!client.connected()) break;
  }
  client.stop();  // ←ここで明示的に切るのはOK
  Serial.println("=== RSS Feed End ===");
}

void loop() {
}

 ②実行時のシリアル出力

 nhk_news_title

5.上記の中でNHKを液晶画面へ表示してみました。
 詳しくは、下記ブログ内記事を参照して下さい。
・JC1060P470C(ESP32P4 ESP32C6 搭載) ArduinoIDE環境でNHK RSSニュース表示してみた

 jc1060p470_News-1


以上


ブログトップへ

◆1.9 インチ IPS TFT ディスプレイ画面(170x320)6個を使ってニキシー管時計もどきを
 作ってみました。
 以前「ニキシー管時計もどき」を数種のLCD付ESP32ボードで表示させていました。
 下記ブログ内記事参照
 ・「ニキシー管時計もどき」を数種のLCD付ESP32ボードで表示させてみた

 今回もっとニキシー管時計に近づけようと一桁ずつ表示させるLCDをビンの中に組み入れて
 みました。
 なかなかかっこいいなと自己満足しています。
 

 nixie-00

1.材料
 ① ニキシー管用ビン
  まずは、かっこ良さそうなビンを100均で探しましたが、中々見つかりませんでした。
  色々探していて、見つけたのが「CHOYA 本格梅酒50ml」です。試しに一本買ってみました。
  値段も税込106円で100均より安いでした。
  これが、調度1.9インチのLCDがぴったり入り最適でした。
 choya
  
 ②TFT ディスプレイ画面
  当初11.9inch_ESP32-1732S019を使おうと考えていたのですが、6個必要なので高額に
 なる為、LCDだけの1.9インチパネルを採用しました。下記で購入
  Estardyn 1.9 インチ IPS フルアングル TFT ディスプレイ画面 LCD スクリーンカラー
  ディスプレイモジュール SPI シリアルポート高精細 170x320


 ➂台座の木材等等(100均で購入)
 台座部品

 ④使用のESP32S3は、下記ブログ内記事を参照して下さい。
 ・ESP32-S3 Super Mini でLチカしてみた

 ⑤WS2812B ネオピクセルLEDテープ(15個使用)
  手持ちの物を使用

2.接続図
 ①最初2個、別々に配線してテストしました。リセットも含め上手く動作しました。
  しかし、6個となると配線本数が多く大変そうでしたし、GPIOも足らなくなりますので
  出来るだけ本数を減らすようにパラ接続としました。CSを除いて全てパラ接続としてい
  ます。
 ②リセットもパラの為、うまく初期化出来ません。色々試して初期化を2回実施することで
  解決出来ました。
 nixie_tube_clock_6t回路図

2.製作途中の様子
 ①実験中
 nixie-01
 
 ②台座製作(ボンド接着)
 nixie-10
 
 ➂接着後上面
 nixie-11
 
 ④接着後裏面
 nixie-12
 
 ⑤ニス塗後
 nixie-13
 
 ⑥ビンの仮配置
 nixie-14
 
 ⑦液晶の仮配置1
 nixie-15
 
 ⑧液晶の仮配置2
 nixie-16
 
 ⑨完成後の裏面
 nixie-17
 
 ➉完成後
 nixie-00

3.開発環境 2025/04/10時点
  ①Windows11 X64 Pro 24H2 
  ②Arduino IDE 2.3.5
  ➂ESP32ボードバージョンV3.1.3
  ④Arduino_GFX_Library(GFX Library for Arduino v1.5.6)

4.スケッチ
 ①初音ミクのイメージ(img_miku.h)
 ②ニキシー管イメージのデータ(img_nixie_tube.h)
 ➂Skyzooロゴイメージ(img_skyzoo.h)
 ④本体スケッチ(nixie_tube_clock_6t.ino)

 下記よりzipファイルをダウンロード出来ます。↓↓
  (保障無しの自己責任で)  nixie_tube_clock_6t.zip

5.動作の様子
 


以上 ニキシー管もどきの時計ができました。


ブログトップへ

◆以前、LCD付ESP32ボードで「パタパタ時計もどき」を表示させていましたが、
 今回、「ニキシー管時計もどき」を作ってみました。
 nixie_tube_clock_modoki

 ボードの説明などは、前回とほぼ一緒ですので、下記ブログ内記事を参照して下さい。
 ・数種のLCD付ESP32ボードで「パタパタ時計もどき」を表示させてみた

1.ニキシー管のパターンは、大野さんのパターンを流用させていただきました。
 感謝です。詳しくは、下記で
 M5Stack Nixie tube Clock

2.パターンの元は、8ビットの配列でしたので、これを「パタパタ時計もどき」と
 同じく、16ビット配列に変換しています。
 参考までに、変換用スケッチを下記に示します。
 ①パターンファイルを「vfd_70x134.c」を「vfd_70x134.h」へリネームします。
 ②下記スケッチで、表示パターン毎に実行し、シリアル出力をコピーし、エデッタに貼り付け
  ヘッダーファイル「img_nixie_tube.h」とします。
#include "vfd_70x134.h"
// 変換後の配列(16ビット)
uint16_t H00[9380] = {0}; // 16ビットの配列

void setup() {
    Serial.begin(115200);

    // 8ビット配列を16ビット配列に変換
    for (int i = 0; i < 9380; i++) {
        // 8ビットのデータを16ビットに拡張
        H00[i] = (uint16_t)vfd_70x134_9[i * 2] << 8 | vfd_70x134_9[i * 2 + 1];
    }

    // 変換結果をシリアルモニタに表示
    Serial.print("const uint16_t H90[9380]={\n");
    for (int i = 0; i < 9380; i++) { // 
      Serial.printf("0x%04x,",H00[i]);
      if (((i+1)%16)==0) Serial.println(); //16個毎に改行を挿入
    }
    Serial.println("};");
}

void loop() {
    // 何もしない
}


3.開発環境 2025/03/23 時点
  ①Windows11 X64 Pro 24H2 
  ②Arduino IDE 2.3.4
  ➂ESP32ボードバージョンV3.1.1
  ④Arduino_GFX_Library v1.5.6

4.スケッチは、「nixie_tube_clock.ino」「img_nixie_tube.h」二つ纏めて
 下記より「zip」ファイルとしてダウンロードてきます。
 (保障無しの自己責任で)  nixie_tube_clock.zip
 
 なおボートに書き込む時は、そのボードのコメントをとり除きます。
 下記スケッチの最初の部分(現在M5StickCPlus2に書き込み中)
 
 //LCD Type によって変わる  //描画時間
 //#define    M5StickC        //   ms
 //#define    M5StickCPlus    //   ms
 #define    M5StickCPlus2   // 108ms esp32
 //#define    M5Stack_Basic   //   ms
 //#define    TTGO_Display    // 108ms esp32
 //#define    ESP32_1732S019  // 114ms esp32s3 
 //#define    JC2432W328      // 112ms esp32
 //#define    JC3248W535      // 119ms esp32s3 psram=OPIPSRAM USBCDCOnBoot=en
 //#define    ESP32_3248S035  //   250ms esp32
 //#define    M5Stack_modoki  //   ms
 //#define    ESP32_AA        //   ms

//1秒周期のLED on/off の制御設定
//#define ON_LED //制御する時は、コメントを取る 
 
4.実行の様子



以上

 

ブログトップへ

◆ESP-IDFを使う必要に迫られたので、「idf.py」の使い方を翻訳サイトで日本語に翻訳
 してみました。
 esp-idf-5.4

 *ESP IDF 5.4の導入については、下記ブログ内記事を参照して下さい。
 ・JC1060P470C(ESP32P4搭載)で「ESP IDF 5.4」を使い「Lチカ」をしてみた


◆元のサイトは下記です。
 ・ESP-IDF プログラミングガイド
 ・IDFフロントエンド - idf.py
 ・IDF コンポーネント マネージャー

<<目次>>


********************************************************************************************

1.「idf.py」のヘルプ出力

********************************************************************************************
>idf.py --help

使用方法: idf.py [OPTIONS] COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...

ESP-IDF CLI ビルド管理ツール。idf.py に認識されていないコマンドについては、ビルド
システム ターゲットとして実行しようとします。選択されたターゲット: なし

オプション:
--version                        IDF バージョンを表示して終了します。
--list-targets                   サポートされているターゲットのリストを出力して終了します。
-C、--project-dir PATH        プロジェクト ディレクトリ。
-B、--build-dir PATH           ビルド ディレクトリ。
-w、--cmake-warn-uninitialized / -n、--no-warnings
                                   ロジェクト ディレクトリ内の CMake ファイルに対して CMake の
             初期化されていない変数の警告を有効にします。
                                   (--no-warnings がデフォルトになり、指定する必要はありません。)
                                   デフォルト値は IDF_CMAKE_WARN_UNINITIALIZED 環境変数で
             設定できます。
-v, --verbose                    詳細なビルド出力。
--preview                        まだプレビュー段階の IDF 機能を有効にします。
--ccache / --no-ccache         ビルドで ccache を使用します。デフォルトでは無効です。
            デフォルト値は IDF_CCACHE_ENABLE 環境変数で設定できます。
-G, --generator [Ninja]        CMake ジェネレーター。
--no-hints                       エラーの解決方法とログに関するヒントを無効にします。
-D, --define-cache-entry TEXT   cmake キャッシュ エントリを作成します。
            このオプションは、グローバルに、または 1 つのサブコマンドに対
            して最大 1 回使用できます。
-p, --port PATH                 シリアル ポート。デフォルト値は ESPPORT 環境変数で設定
            できます。
                                  このオプションは、グローバルに、または 1 つのサブコマンドに
            対して最大 1 回使用できます。
-b, --baud INTEGER           ローカルで上書きされない場合のすべての idf.py サブコマンドの
            グローバル ボー レート。ローカルで定義されていない場合は、
             ボー レートを監視することも意味します。デフォルト値は、
            ESPBAUD 環境変数で設定できます。
                                   このオプションは、グローバルに、または 1 つのサブコマンドに
            対して最大 1 回使用できます。
--help                           このメッセージを表示して終了します。

コマンド:
add-dependency               マニフェスト ファイルに依存関係を追加します。
all                               エイリアス: build。プロジェクトをビルドします。
app                             アプリのみをビルドします。
app-flash                        アプリのみをフラッシュします。
bootloader                     ブートローダのみをビルドします。
bootloader-flash               ブートローダのみをフラッシュします。
build-system-targets           ビルド システム ターゲットのリストを出力します。
clang-check                     現在のフォルダで clang-tidy チェックを実行し、出力
            「warnings.txt」に書き込みます。
clang-html-report             「warnings.txt」を読み込んで「html_report」フォルダに HTML
            レポートを生成します (数分かかる場合があります)。
                                  この機能には追加の依存関係「codereport」が必要です。
           「pip install codereport」を実行してこれをインストールしてください。
clean                            ビルドディレクトリからビルド出力ファイルを削除します。
confserver                      JSON 構成サーバーを実行します。
coredump-debug              コア ダンプ ELF ファイルを作成し、このファイルを使用して GDB
             デバッグ セッションを実行します。
coredump-info                  クラッシュしたタスクのレジスタ、コールスタック、システムで使用
            可能なタスクのリスト、メモリ領域、コア ダンプに保存されている
           メモリの内容 (TCB とスタック) を出力します。
create-component           新しいコンポーネントを作成します。
create-manifest                指定されたコンポーネントのマニフェストを作成します。
create-project                新しいプロジェクトを作成します。
create-project-from-example    ESP コンポーネント レジストリの例からプロジェクトを作成
           します。 docs ESP-IDF のドキュメントを Web ブラウザーで開きます
efuse-burn                      指定された名前の eFuse を書き込みます。
efuse-burn-key                 256 ビット キーを EFUSE に書き込みます: BLOCK1flash_encryption、     
           BLOCK2、secure_boot_v1、secure_boot_v2、BLOCK3。
efuse-common-table        IDF の eFuse フィールドの C ソースを生成します。
efuse-custom-table          ユーザーの eFuse フィールドの C ソースを生成します。
efuse-dump                     すべての eFuse の生の 16 進値をダンプします。
efuse-read-protect           指定された名前の eFuse への書き込みを無効にします。
efuse-summary                eFuse の概要を取得します。
efuse-write-protect           指定された名前の eFuse への書き込みを無効にします。
encrypted-app-flash         暗号化されたアプリのみをフラッシュします。
encrypted-flash                暗号化されたプロジェクトをフラッシュします。
eras-flash                      フラッシュ チップ全体を消去します。
otadata otadata               パーティションを消去します。
flash                           プロジェクトをフラッシュします。
fullclean                     ビルド ディレクトリの内容全体を削除します。
gdb                            GDB を実行します。
gdbgui                          デフォルト ブラウザの GDB UI。
gdbtui                          GDB TUI モード。
menuconfig                  「menuconfig」プロジェクト構成ツールを実行します。
merge-bin
monitor                        シリアル出力を表示します。
openocd                      現在のパスから openocd を実行します。
partit-table                   パーティション テーブルのみをビルドします。
partit-table-flash             パーティション テーブルのみをフラッシュします。
post-debug                     非同期デバッグ アクションの出力を読み取り、それらを停止するための
           ユーティリティ ターゲット。
python-clean                生成された Python バイト コードを IDF ディレクトリから削除します。
qemu                            QEMU を実行します。
read-otadata otadata    パーティションを読み取ります。
reconfigure                    CMake を再実行します。
save-defconfig                 デフォルトとは異なるオプションで sdkconfig.defaults を生成します
secure-decrypt-flash-data
secure-digest-secure-bootloader
                                  ブートローダのバイナリ イメージとセキュア ブート キーを取得し、
             事前に計算されたセキュア ブート キーとともに、フラッシュに
            適したダイジェストとバイナリを組み合わせたものを出力します。
secure-encrypt-flash-data   暗号化されたフラッシュに適したデータを暗号化します (既知の
            キーを使用)。
secure-generate-flash-encryption-key
secure-generate-signing-key    セキュア ブート バージョンに従って、セキュア ブート
             イメージに署名するための秘密キーを生成します。
                                   キー ファイルは PEM 形式で生成されます。セキュア ブート
             V1 - ECDSA NIST256p 秘密キー。セキュア ブート
                                    V2 - RSA 3072、ECDSA NIST256p、ECDSA NIST192p 秘密キー。
secure-sign-data                セキュア ブートで使用するデータ ファイルに署名します。
             署名アルゴリズムは、SHA-512 (V1) を使用した決定論的な
             ECDSA または SHA-256 (V2) を使用した RSA-PSS または
             ECDSA です。
secure-verify-signature         ECDSA (V1) または RSA または ECDSA (V2) の公開キーを
             使用して、以前に署名されたバイナリ イメージを検証します。
set-target                        チップ ターゲットをビルドに設定します。
show-efuse-table                eFuse テーブルを印刷します。
size                             アプリの基本的なサイズ情報を印刷します。
size-components                コンポーネントごとのサイズ情報を印刷します。
size-files                        ソース ファイルごとのサイズ情報を印刷します。
uf2                              すべてのバイナリが含まれた UF2 バイナリを生成します
uf2-app                         アプリケーション専用の UF2 バイナリを生成します
update-dependencies          プロジェクトの依存関係を更新します


トップへ戻る
********************************************************************************************

2.IDFフロントエンド - idf.py

********************************************************************************************
 *idf.py コマンドラインツールは、プロジェクトのビルド、デプロイ、デバッグなどを簡単に
  管理するためのフロントエンドを提供します。idf.py はいくつかのツールを管理します。

・CMake はビルドするプロジェクトを設定します。

・Ninja: プロジェクトをビルドします。

・ターゲットをフラッシュする esptool.py

 *ステップ 5. First Steps on ESP-IDF には、プロジェクトの設定、ビルド、フラッシュを行う
  idf.py のセットアップ方法の簡単な紹介があります。

◎重要
 idf.py は ESP-IDF プロジェクトのディレクトリ、つまり CMakeLists.txt ファイルを含む
 ディレクトリで実行する必要があります。Makefile を含む古いスタイルのプロジェクトは 
 idf.py では動作しません。

◆コマンド

◆新しいプロジェクトを始める: create-project

・idf.py create-project <project name>

 このコマンドは新しい ESP-IDF プロジェクトを作成します。さらに、プロジェクトが作成さ
 れるフォルダを --path オプションで指定できます。

◆新規コンポーネントの作成: create-component

・idf.py create-component <component name>

 このコマンドは、ビルドに必要な最小限のファイル・セットを持つ新しいコンポーネントを
 作成する。
 <-C>オプションを使用すると、コンポーネントが作成されるディレクトリを指定できます。
 コンポーネントの詳細については、Component CMakeLists Filesを参照してください。

◆ターゲット・チップを選択: set-target

 *ESP-IDFは複数のターゲット(チップ)をサポートしています。あなたのバージョンの
  ESP-IDF でサポートされているターゲットの完全なリストは idf.py --list-targets を実行
  することで見ることができます。

・idf.py set-target <target>

 *このコマンドは現在のプロジェクトのターゲットを設定する。

◎重要
 idf.py set-target はビルドディレクトリをクリアし、sdkconfig ファイルを一から生成し
 直します。古い sdkconfig ファイルは sdkconfig.old として保存されます。

*注意
 ・idf.py set-targetコマンドの動作は以下のものと同等です:
 ・ビルドディレクトリのクリア(idf.py fullclean)
 ・sdkconfigファイルを削除する(mv sdkconfig sdkconfig.old)
 ・新しいターゲットでプロジェクトを設定する (idf.py -DIDF_TARGET=esp32 reconfigure)

 *IDF_TARGETを環境変数(export IDF_TARGET=esp32s2など)やCMake変数(CMakeや
  idf.pyへの引数-DIDF_TARGET=esp32s2など)として渡すこともできます。環境変数の
  設定は、ほとんど1種類のチップで作業する場合に便利な方法です。

 *指定したプロジェクトのIDF_TARGETのデフォルト値を指定するには、プロジェクトの
 sdkconfig.defaultsファイルにCONFIG_IDF_TARGETオプションを追加してください。
 環境変数や CMake 変数、idf.py set-target コマンドなど、他の方法で IDF_TARGET が
 指定されていない場合、このオプションの値が使用されます。

 *これらの方法のどれによってもターゲットが設定されていない場合、ビルドシステムの
 デフォルトは esp32 ターゲットになります。

◆グラフィカルコンフィギュレーションツールを起動する: menuconfig

・idf.py menuconfig

◆プロジェクトをビルドする: build

・idf.py build

 *このコマンドはカレント・ディレクトリにあるプロジェクトをビルドする。
  これは複数のステップを含むことがある:

 ・必要に応じてビルド・ディレクトリを作成する。サブディレクトリ 「build 」はビルド出力を
  保持するために使用されますが、これは-Bオプションで変更することができます。

 ・必要に応じてCMakeを実行し、プロジェクトの設定とメインビルドツール用のビルド
  ファイルを生成する。

 ・メインのビルド・ツール(NinjaまたはGNU Make)を実行する。デフォルトでは、
  ビルドツールは自動的に検出されますが、idf.py に -G オプションを渡すことで明示的に
  設定できます。

 *ビルドはインクリメンタルなので、前回のビルドからソースファイルや設定が変更されて
  いなければ、何も行われません。

 さらに、app、bootloader、partition-table の引数を指定してコマンドを実行すると、
 該当する app、bootloader、partition table のみをビルドできます。

◆ビルド出力を削除する: clean

・idf.py clean

 このコマンドはプロジェクトのビルド出力ファイルをビルドディレクトリから削除します。
 このコマンドを使用しても、ビルドフォルダ内の CMake 設定出力は削除されません。

◆ビルドコンテンツ全体を削除する: fullclean

・idf.py fullclean

 このコマンドはビルドディレクトリの内容を全て削除します。次にプロジェクトがビルド
 されるとき、CMake はスクラッチから設定します。このオプションはビルドディレクトリ
 の全てのファイルを再帰的に削除することに注意してください。プロジェクトの設定は削除
 されません。

◆プロジェクトをフラッシュする: flash

・idf.py flash

 このコマンドは必要に応じて自動的にプロジェクトをビルドし、ターゲットにフラッシュ
 します。
 p と -b オプションでそれぞれシリアルポート名とフラッシャーのボーレートを設定できます。

*注意
 環境変数 ESPPORT および ESPBAUD を使用して、それぞれ -p および -b オプションの
 デフォルト値を設定できます。
 コマンドラインでこれらのオプションを指定すると、デフォルト値が上書きされる。

 *idf.py は、ターゲットをフラッシュするために、内部で esptool.py の write_flash コマンド
 を使用します。 --extra-args オプションを使用して、フラッシュ書き込みプロセスを構成す
 るための追加の引数を渡すことができます。たとえば、外部 SPI フラッシュ チップに書き
 込むには、次のコマンドを使用します: idf.py flash --extra-args="--spi-connection <CLK>,
 <Q>,<D>,<HD>,<CS>"。使用可能な引数の完全なリストを表示するには、
 esptool.py write_flash --help を実行するか、esptool.py のドキュメントを参照してください。

 ビルド コマンドと同様に、このコマンドは、app、bootloader、partition-table 引数を指定して
 実行し、必要に応じて app、bootloader、またはパーティション テーブルのみをフラッシュ
 できます。

◆バイナリをマージする: merge-bin

・idf.py merge-bin [-o output-file] [-f format] [<format-specific-options>]

 ファイルを別のマシンに転送し、ESP-IDF を使用せずにフラッシュする場合など、idf.py
 ビルドの複数のファイル出力の代わりに 1 つのファイルのみでフラッシュすると便利な場合
 があります。

 コマンド idf.py merge-bin は、プロジェクト構成に従ってブートローダー、パーティション
 テーブル、アプリケーション自体、およびその他のパーティション (存在する場合) を
 マージし、ビルド フォルダーに単一のバイナリ ファイル merged-binary.[bin|hex] を作成
 します。
 このファイルは後でフラッシュできます。

 マージされたファイルは、バイナリ (raw)、IntelHex (hex)、および UF2 (uf2) 形式で
 出力できます。
 
 uf2 バイナリは、idf.py uf2 によって生成することもできます。idf.py uf2 は、機能的には
 idf.py merge-bin -f uf2 と同等です。ただし、idf.py merge-bin コマンドは、バイナリを上記
 のさまざまな形式にマージするための柔軟性とオプションをさらに提供します。

使用例:
idf.py merge-bin -o my-merged-binary.bin -f raw

 フォーマット固有のオプションもいくつかあり、以下にリストされています:

 *raw フォーマットのみ:

  ・--flash-offset: このオプションは、標準オフセット 0x0 ではなく、指定されたオフセットで
   フラッシュされるマージされたバイナリを作成します。

  ・--fill-flash-size: 設定されている場合、最終的なバイナリ ファイルは、このフラッシュ
   サイズまで FF バイトでパディングされ、フラッシュ コンテンツ全体をイメージで埋め、
   フラッシュ時にフラッシュ チップ全体を再書き込みします。

 *uf2 フォーマットのみ:

  ・--md5-disable: このオプションは、各ブロックの末尾の MD5 チェックサムを無効にし
   ます。
   これは、tinyuf2 などとの統合に役立ちます。

◆エラー解決のヒント
 idf.pyはエラーを解決するためのヒントを表示します。tools/idf_py_actions/hints.yml に
 保存されたヒントのデータベースと連携し、指定されたエラーにマッチするものがあれば
 ヒントを表示します。
 menuconfigターゲットは、現時点ではエラー解決の自動ヒントをサポートしていません。

 idf.py の --no-hints 引数は、ヒントを望まない場合にヒントをオフにするために使用できます。

◎重要な注意事項
 複数の idf.py コマンドを一つにまとめることができます。例えば、
 idf.p -p COM4 clean flash monitor は、ソースツリーをクリーンにしてから、
 プロジェクトをビルドし、シリアルモニタを実行する前にターゲットにフラッシュします。

 同じ起動で複数の idf.py コマンドを実行する順番は重要ではありません。なぜなら、それらが
 自動的に正しい順番で実行され、すべてが有効になるからです(例えば、フラッシュする前に
 ビルドする、フラッシュする前に消去する)。

 idf.py が知らないコマンドについては、ビルドシステムのターゲットとして実行しようと
 します。

 idf.py コマンドは、bash, zsh, fish シェルの自動補完をサポートしています。

 idf.pyのオートコンプリートを有効にするには、exportコマンドを使用します(ステップ4.環境
 変数の設定)。オートコンプリートは TAB キーを押すことで開始されます。
 idf.py - と入力し、TABキーを押してオプションをオートコンプリートします。

 PowerShell のオートコンプリートサポートは将来予定されています。

◆上級者向けコマンド
◆ドキュメントを開く:docs

・idf.py docs

 このコマンドは、プロジェクトのターゲットとESP-IDFバージョンのドキュメントを
 ブラウザで開きます。

◆サイズを表示: size

・idf.py size

 このコマンドは、RAMとフラッシュの占有サイズ、セクション(つまり.bss)のサイズを
 含むアプリのサイズ情報を表示します。

・idf.py size-components

 同様に、このコマンドはプロジェクトで使用されている各コンポーネントについても同じ
 情報を表示します。

・idf.py size-files

 このコマンドは、プロジェクト内のソース・ファイルごとのサイズ情報を表示します。

◆オプション
 --format は出力形式を指定します。利用可能なオプションは text、csv、json で、デフォルト
  はtext です。

 --output-file オプションは、標準出力の代わりにコマンド出力を出力するファイル名を指定
  します。

◆プロジェクトを再設定する: reconfigure

・idf.py reconfigure

 このコマンドは、CMake が必要かどうかに関係なく、CMake を強制的に再実行します。
 通常の使用では不要ですが、ソースツリーからファイルを追加/削除した後や、CMake の
 キャッシュ変数を変更する時に便利です。例えば、idf.py -DNAME='VALUE' reconfigure は
  CMake キャッシュの変数 NAME を値 VALUE に設定するために使用できます。

◆Pythonバイトコードのクリーンアップ: python-clean

・idf.py python-clean

 このコマンドは生成されたPythonバイトコードをESP-IDFディレクトリから削除します。
 このバイトコードはESP-IDFとPythonのバージョンを切り替えたときに問題を引き起こす
 可能性があります。
 Pythonのバージョンを切り替えた後にこのターゲットを実行することをお勧めします。

◆UF2バイナリの生成: uf2

・idf.py uf2

 このUF2ファイルは、ESP USB Bridgeプロジェクトを実行している別のESPが公開して
 いるUSB大容量記憶装置にコピーできます。
 ブリッジMCUはこれを使用してターゲットMCUをフラッシュします。
 これは、マシンのファイルエクスプローラでアクセスできるディスクにファイルをコピー
 (または「ドラッグ・アンド・ドロップ」)するだけと簡単です。

 ブートローダとパーティションテーブルを含まない)アプリケーションのみのUF2バイナリ
 を生成するには、uf2-appコマンドを使用します。

 idf.py uf2 コマンドは上で説明した idf.py merge-bin -f uf2 と機能的に同等です。
 しかし、idf.py merge-bin コマンドはより柔軟性があり、バイナリを uf2 だけでなく様々な
 フォーマットにマージするオプションがあります。

・idf.py uf2-app

◆Otadataパーティションの読み込み:read-otadata

・idf.py read-otadata

 このコマンドは、現在選択されているOTAアプリスロットに関する情報を格納するotadata
 パーティションの内容を表示します。otadataパーティションの詳細については、
 OTA(Over The Air Updates)を参照してください。

◆グローバルオプション
 全てのルートレベルオプションを表示するには idf.py --help を実行します。サブコマンド
 固有のオプションを一覧表示するには、idf.py <command> --help を実行してください。
 以下は便利なオプションのリストです:

 *-C <dir> はプロジェクトディレクトリをデフォルトのカレントディレクトリから上書き
  します。

 *-B <dir> はプロジェクトディレクトリのデフォルトのビルドサブディレクトリからビルド
  ディレクトリを上書きします。

 *--CCache ツールがインストールされている場合、ソース・ファイルをコンパイルするときに
  CCache を有効にする。これにより、ビルド時間を劇的に短縮できる。

◎重要
 ファイルが期待通りにリビルドされない場合は、CCacheを無効にしてプロジェクトを
 リビルドしてみてください。CCache をデフォルトで有効にするには、環境変数
 IDF_CCACHE_ENABLE に 0 以外の値を設定します。

 *-v フラグは、idf.py とビルドシステムの両方が冗長なビルド出力を生成するようにします。
  これはビルドの問題をデバッグするのに便利です。

 *--cmake-warn-uninitialized (または -w) は、CMake がプロジェクトディレクトリで見つかった
  初期化されていない変数の警告を表示するようにします。
  これは、CMake 自体の中の CMake変数警告のみを制御し、他のタイプのビルド警告は
  制御しません。
  このオプションは、IDF_CMAKE_WARN_UNINITIALIZED 環境変数をゼロ以外の値に設定
  することで、永続的に設定することもできます。

 *--no-hintsフラグは、エラー解決のヒントを無効にし、出力のキャプチャを無効にします。

◆ファイル経由で引数を渡す
 ファイル経由で idf.py に複数の引数を渡すことができます。ファイルまたはファイルへの
 パスは先頭に @ を付けなければなりません。ファイル内の引数は改行またはスペースで
 区切ることができ、idf.py のコマンドライン上にその順番で現れたかのように展開されます。

 例えば、custom_flash.txt があるとします:

・flash --baud 115200

 コマンドは次のように実行できます: idf.py @custom_flash.txt monitor

 ファイルからの引数は追加のコマンドライン引数と組み合わせることができ、
 @でアノテーションされた複数のファイルを同時に使用することができます。
 例えば、2つ目のファイル another_config.txt がある場合、
 idf.py @custom_flash.txt @another_config.txt monitor と指定することで両方を
 利用することができます。

 この引数ファイルをどのように使うか、例えば @filename を使ってコンフィギュレーション
 プロファイルファイルを作成する、などの更なる例は、Multiple Build Configurations Example .

トップへ戻る
********************************************************************************************

3.IDFコンポーネントマネージャ

********************************************************************************************
 IDFコンポーネントマネージャは、ESP-IDF CMakeプロジェクトの依存関係をダウンロード
 するツールです。ダウンロードはCMakeの実行中に自動的に行われます。ESPコンポーネン
 トレジストリまたはGitリポジトリからコンポーネントをソースすることができます。

 コンポーネントのリストはhttps://components.espressif.com/。

 IDF コンポーネントマネージャの詳細については、IDF コンポーネントマネージャおよび ESP 
 コンポーネントレジストリのドキュメントを参照してください。

********************************************************************************************
◆プロジェクトでの使用
 プロジェクト内の各コンポーネントの依存関係は、コンポーネントのルートに置かれた
 idf_component.yml という名前の個別のマニフェストファイルで定義されます。マニフェスト
 ファイルのテンプレートは idf.py create-manifest を実行することで作成できます。
 デフォルトでは、マニフェストファイルはメインコンポーネント用に作成されます。
 明示的に --path オプションを使用してマニフェストを作成するディレクトリを指定するか、
 または --component=my_component を使用して components フォルダ内のコンポーネントを
 指定することができます。create-manifest コマンドは以下の方法で実行できます。

・idf.py create-manifest はメインコンポーネントのマニフェストファイルを作成します。

・idf.py create-manifest --component=my_component components ディレクトリに
 my_component コンポーネントのマニフェストファイルを作成します。

・idf.py create-manifest --path=「../../my_component」 コンポーネント my_component の
 マニフェストファイルを my_component ディレクトリに作成します。

********************************************************************************************
 *プロジェクトのコンポーネントに新しいマニフェストが追加された場合、
  idf.py reconfigure を実行して手動でプロジェクトを再設定する必要があります。
  ビルドは idf_component.ymlマニフェストの変更を追跡し、必要に応じて CMake を
  自動的に起動します。

 *ESP-IDF プロジェクトのコンポーネント (例えば my_component) に依存関係を追加する
  には、idf.py add-dependency DEPENDENCY コマンドを実行します。
  DEPENDENCY 引数は my_component が依存する、IDF コンポーネントマネージャが
  管理する追加のコンポーネントを表します。
  namespace/name=1.0.0 の形式で定義されます。namespace/name はコンポーネントの
  名前で、=1.0.0 はコンポーネントのバージョン範囲です。デフォルトでは、依存関係は
  メインコンポーネントに追加されます。pathオプションを使用してマニフェストがある
  ディレクトリを明示的に指定するか、-component=my_componentを使用してコンポー
  ネントフォルダ内のコンポーネントを指定することができます。
  add-dependency コマンドは以下の方法で実行できます:

・idf.py add-dependency example/cmp は example/cmp の最新バージョンの依存関係を
 メインコンポーネントに追加します。

・idf.py add-dependency --component=my_component example/cmp<=3.3.3 は components 
 ディレクトリの my_component コンポーネントに example/cmp のバージョン <=3.3.3 の
 依存関係を追加します。

・idf.py add-dependency --path=「../../my_component」 example/cmp^3.3.3 は example/cmp 
 のバージョン ^3.3.3 の依存関係を my_component ディレクトリの my_component 
 コンポーネントに追加します。

********************************************************************************************
*注意
 add-dependency コマンドは ESP Component Registry から明示的に依存関係をプロジェクトに
 追加します。

 *ESP-IDF プロジェクトの依存関係を更新するには、idf.py update-dependencies コマンドを
 実行します。
 project-dir PATH を使ってプロジェクトディレクトリのパスを指定することもできます。

 *build_system/cmake/component_manager は IDF コンポーネントマネージャを使用して
  ESPコンポーネントレジストリから依存関係をダウンロードする方法を示します。

 管理された依存関係を必要としないコンポーネントのマニフェストは必要ありません。

 CMake がプロジェクトを設定するとき (例えば idf.py reconfigure)、コンポーネント
 マネージャはいくつかの処理を行います:

 プロジェクト内の全てのコンポーネントの idf_component.yml マニフェストを処理し、
 依存関係を再帰的に解決します。

 依存関係の完全なリストを含む dependencies.lock ファイルをプロジェクトのルートに
 作成します。

 *すべての依存関係を managed_components ディレクトリにダウンロードします。

 ロックファイルdependencies.lockとmanaged_componentsディレクトリの内容は、
 ユーザーによって変更されることはありません。コンポーネントマネージャーが実行
 されると、常にそれらが最新であることを確認します。これらのファイルが誤って変更
 された場合、idf.py reconfigure で CMake を起動することでコンポーネントマネージャを
 再実行できます。

 トップレベルの CMakeLists.txt でロックファイルのパスを指定するために、ビルドプロパティ
  DEPENDENCIES_LOCK を設定することができます。例えば、project(PROJECT_NAME)
 の前に idf_build_set_property(DEPENDENCIES_LOCK dependencies.lock.${IDF_TARGET})
 を追加することで、異なるターゲットに対して異なるロックファイルを生成することが
 できます。

********************************************************************************************
◆例からのプロジェクトの作成
 ESP コンポーネントレジストリのいくつかのコンポーネントはサンプルプロジェクトを
 含んでいます。
 サンプルから新しいプロジェクトを作成するには、
 idf.py create-project-from-example EXAMPLEコマンドを実行します。
 ここで、namespace/name はコンポーネントの名前、=1.0.0 はコンポーネントのバージョン
 範囲(Versioning Documentation を参照)、example はサンプルの名前です。
 各コンポーネントのサンプルのリストと、そのコンポーネントのプロジェクトを開始する
 コマンドは、ESP Component Registryにあります。

********************************************************************************************
◆マニフェストでの依存関係の定義
 マニフェストファイル idf_component.yml をテキストエディタで直接編集することで、
 簡単に依存関係を定義できます。以下は、依存関係を定義する方法を示す基本的な例です。

********************************************************************************************
 コンポーネント名とバージョン範囲を指定することで、ESP コンポーネント レジストリから
 依存関係を定義できます:

dependencies:
  # Define a dependency from the ESP Component Registry (https://components.espressif.com/component/example/cmp)
  # ESP コンポーネントレジストリから依存関係を定義する
  example/cmp: ">=1.0.0"

********************************************************************************************
 Git リポジトリからの依存関係を定義するには、リポジトリ内のコンポーネントへのパスと
 リポジトリの URL を指定します:

dependencies:
  # Define a dependency from a Git repository #Git リポジトリからの依存関係を定義する
  test_component:
    path: test_component
    git: ssh://git@gitlab.com/user/components.git

********************************************************************************************
 コンポーネントの開発では、相対パスまたは絶対パスを指定することで、ローカル
 ディレクトリのコンポーネントを使用することができます:

dependencies:
  # Define local dependency with relative path #ローカルの依存関係を相対パスで定義する
  some_local_component:
    path: ../../projects/component

 マニフェストファイル形式の詳細については、マニフェストファイル形式ドキュメントを
 参照してください。
 
********************************************************************************************
◆コンポーネント マネージャの無効化
 環境変数 IDF_COMPONENT_MANAGER を 0 に設定することで、コンポーネント
 マネージャを明示的に無効にできます。

トップへ戻る

以上


ブログトップへ

◆「JC1060P470C」ボードでArduinoIDEを使って色々弄ってきましたが、カメラほか、
 まだまだESP32P4用のライブラリがなくて「ESP IDF 5.4」環境を先日構築してみました。
 ESP IDFで、デモ用の「esp_brookesia_phone」を何とか動かす事が出来ました。

 JC1060P470_camera_2

 ◆カメラも手持ちのラズパイ用カメラ「OV5647」が使えました。 
  Amazon ラズパイ用カメラ「OV5647」
 raspi_camera


1.参考資料等
 ①「JC1060P470C」について回路図等詳しくは、下記ブログ内記事を参照して下さい。
  ・JC1060P470C(ESP32P4 ESP32C6 搭載) を使ってみた

 ②「ESP-IDF 5.4」の環境つくりは、下記ブログ内記事を参照して下さい。
  ・JC1060P470C(ESP32P4搭載)で「ESP IDF 5.4」を使い「Lチカ」をしてみた

2.「JC1060P470」用デモコード準備します。
 ①下記より開発ボード用コードをダウンロードします。
  esp-dev-kits

 *ダウンロードしたら解凍し、その中の
  「esp-dev-kits-master\examples\esp32-p4-function-ev-board\examples
   \esp_brookesia_phone」と
  「esp-dev-kits-master\examples\esp32-p4-function-ev-board\examples
   \common_components」を
  「ESPIDF\devkit」フォルダにコピペします。(ESPIDF\devkitは任意のフォルダ)

 ②「JC1060P470」用の修正版コード(感謝です。)
  修正版JC1060P470C_I_W

 *ダウンロードしたら解凍し、その中の
  「JC1060P470C_I_W-main\1-Demo\Demo_IDF\examples」を
  「ESPIDF」フォルダにコピペします。

3.ビルドの準備
 ①「esp_brookesia_phone」は、上記2.①②共に有りますが、素直にエラー無く
   ビルド出来た①の物を元に「OV5647」が使えるよう
  「ESPIDF\devkit\esp_brookesia_phone」の中の「sdkconfig.defaults」を
   下記のように修正します。
  
 30:CONFIG_CAMERA_OV5647=y   <--追記
 31:#CONFIG_CAMERA_SC2336=y  <--SC2336関連をコメントアウト
 32:#CONFIG_CAMERA_SC2336_MIPI_RAW10_1280x720_60FPS=y
 33:#CONFIG_CAMERA_SC2336_CUSTOMIZED_IPA_JSON_CONFIGURATION_FILE=y
 34:#CONFIG_CAMERA_SC2336_CUSTOMIZED_IPA_JSON_CONFIGURATION_FILE_
  PATH="components/apps/ camera/sc2336_custom.json"
 35:CONFIG_ESP_VIDEO_ENABLE_DVP_VIDEO_DEVICE=n  

 ②「esp_brookesia_phone\main」の「idf_component.yml」を下記一行を追記します。
 
dependencies:
  espressif/esp_lcd_jd9165: "^1.0.1" <---追記
  espressif/esp_wifi_remote:
    version: "0.*"
    
  espressif/esp_hosted:
    version: "0.*"

  espressif/esp-brookesia:
    version: "0.4.*"

  esp_video:
    version: "0.8.*"
    public: true
4.いよいよビルドしてみます。
 ①ディスクトップ内の「ESP-IDF 5.4 CMD」アイコンを実行します。
 ②次に「esp_brookesia_phone」フォルダに移動します。
 >cd C:\Users\yoshito\ESPIDF\devkit\esp_brookesia_phone
 
  ➂ビルドします。
 >idf.py build
  
  ④ビルドが終わったら「managed_components」の中の
  1.「espressif__esp_lcd_jd9165」のフォルダ内
   「esp_lcd_jd9165.c」と「include\esp_lcd_jd9165.h」を
  「ESPIDF\examples\lvgl_demo_v9\managed_components」の中の
   ものと入れ替えます。
  
  2.「espressif__esp_lcd_touch_gt911」のフォルダ内
  「esp_lcd_touch_gt911.c」と「include\esp_lcd_touch_gt911.h」を
  「ESPIDF\examples\lvgl_demo_v9\managed_components」の中の
   ものと入れ替えます。  

  3.「espressif__esp32_p4_function_ev_board」のフォルダ内
  「esp32_p4_function_ev_board.c」と
  「include\bsp\esp32_p4_function_ev_board.h」を
  「ESPIDF\examples\lvgl_demo_v9\managed_components」の中の
   ものと入れ替えます。 

 4.「espressif__esp32_p4_function_ev_board」のフォルダ内 
   「idf_component.yml」を下記の様に一行追記します。

dependencies:
  esp_codec_dev:
    public: true
    version: 1.2.*
  esp_lcd_ek79007: 1.*
  esp_lcd_jd9165: 1.*        <-----追記
  esp_lcd_ili9881c: 1.*
  esp_lcd_touch_gt911: ^1
  espressif/esp_lvgl_port:
    public: true
    version: ^2
  idf: '>=5.3'
  lvgl/lvgl: '>=8,<10'
description: Board Support Package (BSP) for ESP32-P4 Function EV Board (preview)
repository: git://github.com/espressif/esp-bsp.git
repository_info:
  commit_sha: 0064ab931c38699fc993ee161713ac1d1c0943a5
  path: bsp/esp32_p4_function_ev_board
tags:
- bsp
targets:
- esp32p4
url: https://github.com/espressif/esp-bsp/tree/master/bsp/esp32_p4_function_ev_board
version: 4.1.1



 ⑤ここで一旦プロジェクトをクリーンアップします。
 >idf.py fullclean
 idf_error_1

 ⑥編集した三つのフォルダがある旨エラーが表示されますが、再度ビルドします。
  *本来ならば、移動して対処すれば良いのですが、勉強不足で何回やっても
   うまくいきませんでした。
  *下記を参考に勉強したいと思っています。
  ・ESP-IDF コンポーネントマネージャドキュメント
  ・ESP-IDF CMakeLists.txt ドキュメント

 *とりあえず宿題として、今はこのままビルドしました。
 >idf.py build
  
  ⑦問題なくビルド出来たらボードに書き込みます。
 *私の環境では、「COM10」
 *最後の「monitor」書き込み後にモニター画面に移行します。
 >idf.py -p COM10 flash monitor

 ◆書き込み後、下記の画面が出れば成功です。
 JC1060P470_camera_1
 
 ◆カメラの様子(モニターを映しています)
  


 これでJC1060P470ボードで「esp_brookesia_phone」デモが動きラズパイカメラが使える
 様になりました。ただ映像が二つ出ています。
 これから設定等を確認したいと思っています。
 とにかく、めでたしめでたし。

以上

ブログトップへ



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

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