. Freenove ESP32-WROVER CAMボード【FNK0060 & FNK0060B】を試してみました【Arduino使用】 | あろしーど
Freenove ESP32-WROVER CAMボード【FNK0060 & FNK0060B】を試してみました【Arduino使用】 | あろしーど
Freenove ESP32-WROVER CAMボード【FNK0060 & FNK0060B】を試してみました【Arduino使用】 | あろしーど

Freenove ESP32-WROVER CAMボード【FNK0060 & FNK0060B】を試してみました【Arduino使用】

Apply to FNK0060. Contribute to Freenove/Freenove_ESP32_WROVER_Board development by creating an account on GitHub.

Freenove ESP32-S3-WROOM CAMボード【FNK0085】を試してみました【Arduino使用】 aloseed.com
  1. 特徴
  2. 画像ギャラリー
    1. Freenove ESP32-WROVER Board FNK0060(v1.6)
    2. Freenove ESP32-WROVER Board FNK0060B(v3.0)
    3. サイズ
    4. カメラモジュール(OV2640)例
    1. v1.6 (FNK0060)
    2. v3.0 (FNK0060B)
    3. 使用できるGPIOについて
      1. カメラ使用時
      2. v3.0の場合 (SDカードスロット使用時)
      1. CameraWebServer (Arduino IDEスケッチ例を使用する場合)
      2. 映像を液晶ディスプレイに表示する(HSPI使用例)
        1. スケッチ1 (Adafruit GFXライブラリ使用)
        2. スケッチ2 (LovyanGFXライブラリ使用)
        3. プリズムを使ってみました
        1. 表示できる画像ファイルについて

        特徴

        項目仕様詳細ESP32モジュールESP32-WROVER-E(技適マーク付き)工事設計認証番号:211-200403CPUスピード 240MHzフラッシュメモリ 4MBPSRAM 8MB※1ワイヤレス通信規格 802.11n(周波数帯は 2.4GHzのみ )カメラオンボードカメラ(コネクタ)付属カメラモジュールFNK0060(v1.6)OV2640 66°

        ※1 Arduinoで使用可能な容量は4MBまでです。※2 シリアルドライバをインストールしていない場合は別途インストールが必要です。

        画像ギャラリー

        Freenove ESP32-WROVER Board FNK0060(v1.6) 外箱 ボード本体の他、USBケーブルとリーフレットが付属しています。 袋からボードを取り出したところ Freenove ESP32-WROVER Board FNK0060B(v3.0) 外箱 FNK0060B FNK0060の内容に加えSDカード(1GB)とSDカードリーダーが付属しています カメラはOV3660です SDカードスロットが確認できます サイズ カメラモジュール(OV2640)例

        左から 66° 21mm(付属カメラ) 120°21mm 160°21mm68°75mm 160°75mm

        120° 21mmを取り付けたところ 160° 21mmを取り付けたところ

        ピン配列

        v1.6 (FNK0060) v3.0 (FNK0060B) 使用できるGPIOについて カメラ使用時 v3.0の場合 (SDカードスロット使用時) カメラ未使用時について

        I2Cのピンとして、SCL 22、SDA 21を使用

        GitHub - aloseed/esp32_oled_clock Contribute to aloseed/esp32_oled_clock development by creating an account on GitHub. ESP32-WROVER-DEV v1.6 CAM基板を使ってみた WROVER カメラ付きモジュールを入手しました。基本機能はじめ、技適付きでBluetooth、Wifiなど機能豊富です。 tamanegi.digick.jp

        Arduinoボード設定

        Arduinoの追加ボード(サードパーティボード)&ライブラリまとめ

        ArduinoでURLの追加が必要なボード(サードパーティボード)とよく使うライブラリをまとめてみました。ボードを追加する方法Arduino IDEArduino IDEから > の画面を開きます。後述のサードパーティボードに記載してある追.

        aloseed.com
        • ボードインストール

        [ツール] > [ボード] > [ボードマネージャ]からESP32ボードをインストールします。

        [ツール] > [ボード] > [ESP32 Arduino※] > [ESP32 Wrover Module]を選択します。※Arduinoの表記はArduino IDEバージョン1系のみ

        環境ポート名Mac/dev/cu.wchusbserial*WindowsCOM* *(アスタリスク)は任意の文字列を表しています。

        書き込みモード(Download Boot)

        BOOTボタン 」を押しながら、「 リセットボタン 」を押すと書き込みモードになります。

        v3.0の場合

        サンプルプログラム (Arduinoスケッチ)

        Arduino IDE バージョン1.8.19 (※1系)2系(2.x.x)は最新版でOKESP32 Arduinoボード基本的に最新版でOK Freenove_ESP32_WROVER_Board/C at main ?? Freenove/Freenove_ESP32_WROVER_Board

        Apply to FNK0060. Contribute to Freenove/Freenove_ESP32_WROVER_Board development by creating an account on GitHub.

        CameraWebServer (Arduino IDEスケッチ例を使用する場合)

        CameraWebServerスケッチを書き込む場合、スケッチサイズの関係上[ツール] > [Partition Scheme] > [Huge APP (3MB No OTA/1MB SPIFFS)]を選択してください。

        GitHubのサンプルスケッチに Sketch_06.1_CameraWebServer がありますが、Arduino IDEのスケッチ例([スケッチ例] > [ESP32] > [Camera] > [CameraWebServer])を使用する場合、次のように修正します。

        映像を液晶ディスプレイに表示する(HSPI使用例)

        素材はこちら

        液晶ディスプレイ

        左: 1.54インチ 右: 1.3インチ

        製作例

        • 液晶ディスプレイST7789のものを使っています。

        スケッチ1 (Adafruit GFXライブラリ使用) スケッチで使用しているライブラリについて
        • Adafruit ST7735 and ST7789 Library
        • Adafruit GFX Library
        • TJpg_Decoder
        #include "esp_camera.h" #include #include // Core graphics library #include // Hardware-specific library for ST7789 #include // Pin definition for CAMERA_MODEL_WROVER_KIT #define PWDN_GPIO_NUM -1 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 21 #define SIOD_GPIO_NUM 26 #define SIOC_GPIO_NUM 27 #define Y9_GPIO_NUM 35 #define Y8_GPIO_NUM 34 #define Y7_GPIO_NUM 39 #define Y6_GPIO_NUM 36 #define Y5_GPIO_NUM 19 #define Y4_GPIO_NUM 18 #define Y3_GPIO_NUM 5 #define Y2_GPIO_NUM 4 #define VSYNC_GPIO_NUM 25 #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22 // Pin definition for TFT HSPI #define TFT_SCLK 14 #define TFT_MISO -1 #define TFT_MOSI 13 #define TFT_CS 15 // Chip select control pin #define TFT_DC 32 // Data Command control pin #define TFT_RST 33 // Pin button #define PIN_BTN 12 Adafruit_ST7789 tft = Adafruit_ST7789(&SPI, TFT_CS, TFT_DC, TFT_RST); bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap) < // Stop further decoding as image is running off bottom of screen if (y >= tft.height()) return 0; tft.drawRGBBitmap(x, y, bitmap, w, h); // Return 1 to decode next block return 1; > void init_camera() < camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = Y2_GPIO_NUM; config.pin_d1 = Y3_GPIO_NUM; config.pin_d2 = Y4_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM; config.pin_d4 = Y6_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; config.pin_d6 = Y8_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM; config.pin_xclk = XCLK_GPIO_NUM; config.pin_pclk = PCLK_GPIO_NUM; config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; config.pin_sscb_sda = SIOD_GPIO_NUM; config.pin_sscb_scl = SIOC_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.frame_size = FRAMESIZE_UXGA; config.pixel_format = PIXFORMAT_JPEG; // for streaming config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; config.fb_location = CAMERA_FB_IN_PSRAM; config.jpeg_quality = 12; config.fb_count = 1; // if PSRAM IC present, init with UXGA resolution and higher JPEG quality // for larger pre-allocated frame buffer. if (config.pixel_format == PIXFORMAT_JPEG) < if (psramFound()) < config.jpeg_quality = 10; config.fb_count = 2; config.grab_mode = CAMERA_GRAB_LATEST; >else < // Limit the frame size when PSRAM is not available config.frame_size = FRAMESIZE_SVGA; config.fb_location = CAMERA_FB_IN_DRAM; >> else < // Best option for face detection/recognition config.frame_size = FRAMESIZE_QVGA; #if CONFIG_IDF_TARGET_ESP32S3 config.fb_count = 2; #endif >// camera init esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) < Serial.printf("Camera init failed with error 0x%x", err); for (;;) ; >sensor_t *s = esp_camera_sensor_get(); // initial sensors are flipped vertically and colors are a bit saturated if (s->id.PID == OV3660_PID) < s->set_vflip(s, 1); // flip it back s->set_brightness(s, 1); // up the brightness just a bit s->set_saturation(s, -2); // lower the saturation > // drop down frame size for higher initial frame rate if (config.pixel_format == PIXFORMAT_JPEG) < s->set_framesize(s, FRAMESIZE_QVGA); > > void setup() < Serial.begin(115200); Serial.println("ESP32-WROVER-CAM Picture"); init_camera(); // Use HSPI SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI); // if the display has CS pin try with SPI_MODE0 tft.init(240, 240); // Init ST7789 display 240x240 pixel tft.fillScreen(ST77XX_BLACK); TJpgDec.setJpgScale(1); // The decoder must be given the exact name of the rendering function above TJpgDec.setCallback(tft_output); pinMode(PIN_BTN, INPUT); >void take_picture() < Serial.println("Taking picture.."); camera_fb_t *fb = NULL; fb = esp_camera_fb_get(); if (!fb) < Serial.println("Camera capture failed"); return; >static uint16_t w = 0, h = 0; TJpgDec.getJpgSize(&w, &h, fb->buf, fb->len); Serial.print("- Width = "); Serial.print(fb->width); Serial.print(", height = "); Serial.println(fb->height); // Draw the image, top left at 0,0 TJpgDec.drawJpg(0, 0, fb->buf, fb->len); // Free buffer esp_camera_fb_return(fb); > void loop() < static int state = LOW; if (digitalRead(PIN_BTN) == HIGH) < Serial.println("Button pressed"); take_picture(); state = HIGH; >else if (digitalRead(PIN_BTN) == LOW && state == HIGH) < tft.fillScreen(ST77XX_BLACK); state = LOW; >delay(500); > パーツボードGPIO備考TFT SCL14HSPI SCLKTFT SDA13HSPI MOSITFT CS15HSPI CS 1.3インチLCDでは配線不要 TFT DC32 TFT RST33 BUTTON(スイッチ)12ボタン(トグルスイッチ)INPUT ※TFTは液晶ディスプレイ(LCD)を表しています

        スケッチの修正について

        tft.init(240, 240, SPI_MODE2); // Init ST7789 display 240x240 pixel pinMode(PIN_BTN, INPUT_PULLDOWN); スケッチ2 (LovyanGFXライブラリ使用) スケッチで使用しているライブラリ
        • LovyanGFX
        #include "esp_camera.h" #include // Pin definition for CAMERA_MODEL_WROVER_KIT #define PWDN_GPIO_NUM -1 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 21 #define SIOD_GPIO_NUM 26 #define SIOC_GPIO_NUM 27 #define Y9_GPIO_NUM 35 #define Y8_GPIO_NUM 34 #define Y7_GPIO_NUM 39 #define Y6_GPIO_NUM 36 #define Y5_GPIO_NUM 19 #define Y4_GPIO_NUM 18 #define Y3_GPIO_NUM 5 #define Y2_GPIO_NUM 4 #define VSYNC_GPIO_NUM 25 #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22 // Pin definition for TFT HSPI #define TFT_SCLK 14 #define TFT_MISO -1 #define TFT_MOSI 13 #define TFT_CS 15 // Chip select control pin #define TFT_DC 32 // Data Command control pin #define TFT_RST 33 // Pin button #define PIN_BTN 12 int32_t lcd_width; int32_t lcd_height; int32_t y; // LCD表示画像の倍率 float zoom; // カメラ画像フレームバッファ camera_fb_t *fb; // ST7789 1.3インチ CSなし class LGFX : public lgfx::LGFX_Device < lgfx::Panel_ST7789 _panel_instance; lgfx::Bus_SPI _bus_instance; // SPIバスのインスタンス public: LGFX(void) < < // バス制御の設定を行います。 auto cfg = _bus_instance.config(); // バス設定用の構造体を取得します。 // SPIバスの設定 cfg.spi_host = SPI3_HOST; cfg.spi_mode = 0; // SPI通信モードを設定 (0 ~ 3) cfg.freq_write = 40000000; // 送信時のSPIクロック (最大80MHz, 80MHzを整数で割った値に丸められます) cfg.freq_read = 20000000; // 受信時のSPIクロック // cfg.spi_3wire = true; // 受信をMOSIピンで行う場合はtrueを設定 // cfg.use_lock = true; // トランザクションロックを使用する場合はtrueを設定 cfg.dma_channel = SPI_DMA_CH_AUTO; // 使用するDMAチャンネルを設定 (0=DMA不使用 / 1=1ch / 2=ch / SPI_DMA_CH_AUTO=自動設定) cfg.pin_sclk = TFT_SCLK; // SPIのSCLKピン番号を設定 cfg.pin_mosi = TFT_MOSI; // SPIのMOSIピン番号を設定 cfg.pin_miso = TFT_MISO; // SPIのMISOピン番号を設定 (-1 = disable) cfg.pin_dc = TFT_DC; // SPIのD/Cピン番号を設定 (-1 = disable) _bus_instance.config(cfg); // 設定値をバスに反映します。 _panel_instance.setBus(&_bus_instance); // バスをパネルにセットします。 > < // 表示パネル制御の設定を行います。 auto cfg = _panel_instance.config(); // 表示パネル設定用の構造体を取得します。 cfg.pin_cs = -1; // CSが接続されているピン番号 (-1 = disable) cfg.pin_rst = -1; // RSTが接続されているピン番号 (-1 = disable) cfg.pin_busy = -1; // BUSYが接続されているピン番号 (-1 = disable) cfg.panel_width = 240; // 実際に表示可能な幅 cfg.panel_height = 240; // 実際に表示可能な高さ cfg.invert = true; // パネルの明暗が反転してしまう場合 trueに設定 // cfg.rgb_order = true; // パネルの赤と青が入れ替わってしまう場合 trueに設定 _panel_instance.config(cfg); >setPanel(&_panel_instance); // 使用するパネルをセットします。 lgfx::pinMode(TFT_RST, lgfx::pin_mode_t::output); lgfx::pinMode(TFT_SCLK, lgfx::pin_mode_t::output); lgfx::gpio_lo(TFT_RST); lgfx::gpio_hi(TFT_SCLK); lgfx::gpio_hi(TFT_RST); > >; static LGFX tft; void init_camera() < camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = Y2_GPIO_NUM; config.pin_d1 = Y3_GPIO_NUM; config.pin_d2 = Y4_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM; config.pin_d4 = Y6_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; config.pin_d6 = Y8_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM; config.pin_xclk = XCLK_GPIO_NUM; config.pin_pclk = PCLK_GPIO_NUM; config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; config.pin_sscb_sda = SIOD_GPIO_NUM; config.pin_sscb_scl = SIOC_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.frame_size = FRAMESIZE_UXGA; config.pixel_format = PIXFORMAT_JPEG; // for streaming config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; config.fb_location = CAMERA_FB_IN_PSRAM; config.jpeg_quality = 12; config.fb_count = 1; // if PSRAM IC present, init with UXGA resolution and higher JPEG quality // for larger pre-allocated frame buffer. if (config.pixel_format == PIXFORMAT_JPEG) < if (psramFound()) < config.jpeg_quality = 10; config.fb_count = 2; config.grab_mode = CAMERA_GRAB_LATEST; >else < // Limit the frame size when PSRAM is not available config.frame_size = FRAMESIZE_SVGA; config.fb_location = CAMERA_FB_IN_DRAM; >> else < // Best option for face detection/recognition config.frame_size = FRAMESIZE_QVGA; #if CONFIG_IDF_TARGET_ESP32S3 config.fb_count = 2; #endif >// camera init esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) < Serial.printf("Camera init failed with error 0x%x", err); for (;;) ; >sensor_t *s = esp_camera_sensor_get(); // initial sensors are flipped vertically and colors are a bit saturated if (s->id.PID == OV3660_PID) < s->set_vflip(s, 1); // flip it back s->set_brightness(s, 1); // up the brightness just a bit s->set_saturation(s, -2); // lower the saturation > // drop down frame size for higher initial frame rate if (config.pixel_format == PIXFORMAT_JPEG) < s->set_framesize(s, FRAMESIZE_QVGA); > > void setup() < Serial.begin(115200); Serial.println("ESP32-WROVER-CAM Picture"); // スイッチの入力設定 pinMode(PIN_BTN, INPUT_PULLDOWN); tft.init(); // 画面回転はLCDに合わせて設定してください // tft.setRotation(1); lcd_width = tft.width(); lcd_height = tft.height(); // カメラ初期化 init_camera(); // カメラ画像の横幅を取得 fb = esp_camera_fb_get(); if (!fb) < Serial.println("Camera capture failed"); // カメラ画像が取得できない場合は停止 for (;;) yield(); >// LCD画像の倍率をセット zoom = lcd_width / (float)fb->width; y = (lcd_height - fb->height * zoom) / 2; > void loop() < static int state = LOW; if (digitalRead(PIN_BTN) == HIGH) < // Serial.println("Button pressed"); // フレームバッファ解放 esp_camera_fb_return(fb); // カメラのフレームを取得 fb = esp_camera_fb_get(); if (!fb) < Serial.println("Camera capture failed"); // カメラ画像が取得できない場合は停止 for (;;) yield(); >// Serial.println("Taking picture.."); tft.drawJpg(fb->buf, fb->len, 0, y, lcd_width, lcd_height, 0, 0, zoom); state = HIGH; > else if (digitalRead(PIN_BTN) == LOW && state == HIGH) < tft.clear(); state = LOW; >delay(100); > LovyanGFX LCDクラス定義例【Arduino使用】 aloseed.com プリズムを使ってみました created by Rinker ピクチャーフレーム (v3.0向け) スケッチで使用しているライブラリ
        • LovyanGFX
        #include "SD_MMC.h" #include #define SD_MMC_CMD 15 //Please do not modify it. #define SD_MMC_CLK 14 //Please do not modify it. #define SD_MMC_D0 2 //Please do not modify it. // ESP32 for ST7789 1.3LCD #define TFT_MISO -1 #define TFT_MOSI 13 #define TFT_SCLK 12 #define TFT_DC 32 #define TFT_RST 33 class LGFX : public lgfx::LGFX_Device < lgfx::Panel_ST7789 _panel_instance; lgfx::Bus_SPI _bus_instance; // SPIバスのインスタンス public: LGFX(void) < < // バス制御の設定を行います。 auto cfg = _bus_instance.config(); // バス設定用の構造体を取得します。 // SPIバスの設定 cfg.spi_host = SPI3_HOST; cfg.spi_mode = 0; // SPI通信モードを設定 (0 ~ 3) cfg.freq_write = 40000000; // 送信時のSPIクロック (最大80MHz, 80MHzを整数で割った値に丸められます) // cfg.freq_read = 20000000; // 受信時のSPIクロック cfg.spi_3wire = true; // 受信をMOSIピンで行う場合はtrueを設定 cfg.use_lock = true; // トランザクションロックを使用する場合はtrueを設定 cfg.dma_channel = SPI_DMA_CH_AUTO; // 使用するDMAチャンネルを設定 (0=DMA不使用 / 1=1ch / 2=ch / SPI_DMA_CH_AUTO=自動設定) cfg.pin_sclk = TFT_SCLK; // SPIのSCLKピン番号を設定 cfg.pin_mosi = TFT_MOSI; // SPIのMOSIピン番号を設定 cfg.pin_miso = TFT_MISO; // SPIのMISOピン番号を設定 (-1 = disable) cfg.pin_dc = TFT_DC; // SPIのD/Cピン番号を設定 (-1 = disable) _bus_instance.config(cfg); // 設定値をバスに反映します。 _panel_instance.setBus(&_bus_instance); // バスをパネルにセットします。 > < // 表示パネル制御の設定を行います。 auto cfg = _panel_instance.config(); // 表示パネル設定用の構造体を取得します。 cfg.pin_cs = -1; // CSが接続されているピン番号 (-1 = disable) cfg.pin_rst = -1; // RSTが接続されているピン番号 (-1 = disable) cfg.pin_busy = -1; // BUSYが接続されているピン番号 (-1 = disable) cfg.panel_width = 240; // 実際に表示可能な幅 cfg.panel_height = 240; // 実際に表示可能な高さ cfg.readable = false; // データ読出しが可能な場合 trueに設定 cfg.invert = true; // パネルの明暗が反転してしまう場合 trueに設定 // cfg.rgb_order = true; // パネルの赤と青が入れ替わってしまう場合 trueに設定 // cfg.bus_shared = true; _panel_instance.config(cfg); >setPanel(&_panel_instance); // 使用するパネルをセットします。 lgfx::pinMode(TFT_RST, lgfx::pin_mode_t::output); lgfx::pinMode(TFT_SCLK, lgfx::pin_mode_t::output); lgfx::gpio_lo(TFT_RST); lgfx::gpio_hi(TFT_SCLK); lgfx::gpio_hi(TFT_RST); > >; const unsigned long displayDuration = 2000; // Display time (2 seconds) LGFX lcd; // LGFX instance std::vector fileList; int currentIndex = 0; int32_t screenWidth; int32_t screenHeight; void initFileSystem() < // SDカードスロット初期化 SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0); if (!SD_MMC.begin("/sdcard", true)) < Serial.println("Card Mount Failed"); for (;;) yield(); >> void createFileList() < File root = SD_MMC.open("/"); File file = root.openNextFile(); while (file) < String filePath = file.path(); if (!filePath.startsWith("/.") && (filePath.endsWith(".jpg") || filePath.endsWith(".png"))) < fileList.push_back(filePath); >file = root.openNextFile(); > root.close(); if (fileList.empty()) < Serial.println("No image files found in SD."); for (;;) yield(); >> // Get JPEG image size bool getJpgSize(File &file, int &width, int &height) < uint8_t data[5]; file.read(data, 2); if (data[0] == 0xFF && data[1] == 0xD8) < while (file.read(data, 4) == 4) < if (data[0] == 0xFF && (data[1] >= 0xC0 && data[1] else < uint16_t size = data[2] > > return false; > // Get PNG image size bool getPngSize(File &file, int &width, int &height) < uint8_t data[24]; if (file.read(data, 24) == 24) < if (data[0] == 0x89 && data[1] == 0x50 && data[2] == 0x4E && data[3] == 0x47) < width = data[16] > return false; > void drawImage(const String &fileName) < File file = SD_MMC.open(fileName, FILE_READ); if (!file) < Serial.println("Failed to open file: " + fileName); return; >// Serial.printf("%s\n", fileName.c_str()); int imgWidth = 0, imgHeight = 0; bool validImage = false; bool isJpg = false; // サイズ取得 if (fileName.endsWith(".jpg")) < validImage = getJpgSize(file, imgWidth, imgHeight); isJpg = true; >else if (fileName.endsWith(".png")) < validImage = getPngSize(file, imgWidth, imgHeight); >if (!validImage) < file.close(); Serial.println("Invalid or unsupported image format."); return; >// ファイル開始位置を戻す file.seek(0); // スケーリング float scaleX = static_cast(screenWidth) / imgWidth; float scaleY = static_cast(screenHeight) / imgHeight; float scale = min(scaleX, scaleY); // x座標 センタリング int32_t x = (screenWidth - imgWidth * scale) / 2; lcd.startWrite(); lcd.clear(); if (isJpg) < lcd.drawJpg(&file, x, 0, screenWidth, screenHeight, 0, 0, scale); >else < lcd.drawPng(&file, x, 0, screenWidth, screenHeight, 0, 0, scale); >lcd.endWrite(); file.close(); > void setup() < Serial.begin(115200); // LCD初期化 lcd.init(); screenWidth = lcd.width(); screenHeight = lcd.height(); // SDカードスロット初期化 initFileSystem(); // 画像ファイルリスト取得 createFileList(); >void loop() < // 画像を描画 drawImage(fileList[currentIndex]); // 次の画像(インデックス) currentIndex = (currentIndex + 1) % fileList.size(); delay(displayDuration); >

        対応LCD 1.3インチ ST7789 CSなし

        LCDピン/GPIOGNDGNDVCC3.3VSCL12SDA13RES33DC32BLK未接続 表示できる画像ファイルについて 映像を液晶ディスプレイに表示する シャッター機能付き (v3.0向け) #include "esp_camera.h" #include "SD_MMC.h" #include // Pin definition for CAMERA_MODEL_WROVER_KIT #define PWDN_GPIO_NUM -1 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 21 #define SIOD_GPIO_NUM 26 #define SIOC_GPIO_NUM 27 #define Y9_GPIO_NUM 35 #define Y8_GPIO_NUM 34 #define Y7_GPIO_NUM 39 #define Y6_GPIO_NUM 36 #define Y5_GPIO_NUM 19 #define Y4_GPIO_NUM 18 #define Y3_GPIO_NUM 5 #define Y2_GPIO_NUM 4 #define VSYNC_GPIO_NUM 25 #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22 // Pin definition for SD MMC #define SD_MMC_CMD 15 //Please do not modify it. #define SD_MMC_CLK 14 //Please do not modify it. #define SD_MMC_D0 2 //Please do not modify it. // Pin definition for TFT HSPI // #define TFT_SCLK 14 #define TFT_MISO -1 #define TFT_MOSI 13 #define TFT_SCLK 12 // #define TFT_CS 15 // Chip select control pin #define TFT_DC 32 // Data Command control pin #define TFT_RST 33 // カメラ画像の更新間隔 (ミリ秒で指定) 500ミリ秒間隔 #define UPDATE_INTERVAL (500u) // Shutter button #define SHUTTER_BUTTON 0 int32_t lcd_width; int32_t lcd_height; int32_t y; // LCD表示画像の倍率 float zoom; // カメラ画像フレームバッファ camera_fb_t* fb; // シャッター volatile bool shutter = false; // ST7789 1.3インチ CSなし class LGFX : public lgfx::LGFX_Device < lgfx::Panel_ST7789 _panel_instance; lgfx::Bus_SPI _bus_instance; // SPIバスのインスタンス public: LGFX(void) < < // バス制御の設定を行います。 auto cfg = _bus_instance.config(); // バス設定用の構造体を取得します。 // SPIバスの設定 cfg.spi_host = SPI3_HOST; cfg.spi_mode = 0; // SPI通信モードを設定 (0 ~ 3) cfg.freq_write = 40000000; // 送信時のSPIクロック (最大80MHz, 80MHzを整数で割った値に丸められます) // cfg.freq_read = 20000000; // 受信時のSPIクロック cfg.spi_3wire = true; // 受信をMOSIピンで行う場合はtrueを設定 cfg.use_lock = true; // トランザクションロックを使用する場合はtrueを設定 cfg.dma_channel = SPI_DMA_CH_AUTO; // 使用するDMAチャンネルを設定 (0=DMA不使用 / 1=1ch / 2=ch / SPI_DMA_CH_AUTO=自動設定) cfg.pin_sclk = TFT_SCLK; // SPIのSCLKピン番号を設定 cfg.pin_mosi = TFT_MOSI; // SPIのMOSIピン番号を設定 cfg.pin_miso = TFT_MISO; // SPIのMISOピン番号を設定 (-1 = disable) cfg.pin_dc = TFT_DC; // SPIのD/Cピン番号を設定 (-1 = disable) _bus_instance.config(cfg); // 設定値をバスに反映します。 _panel_instance.setBus(&_bus_instance); // バスをパネルにセットします。 > < // 表示パネル制御の設定を行います。 auto cfg = _panel_instance.config(); // 表示パネル設定用の構造体を取得します。 cfg.pin_cs = -1; // CSが接続されているピン番号 (-1 = disable) cfg.pin_rst = -1; // RSTが接続されているピン番号 (-1 = disable) cfg.pin_busy = -1; // BUSYが接続されているピン番号 (-1 = disable) cfg.panel_width = 240; // 実際に表示可能な幅 cfg.panel_height = 240; // 実際に表示可能な高さ cfg.readable = false; // データ読出しが可能な場合 trueに設定 cfg.invert = true; // パネルの明暗が反転してしまう場合 trueに設定 // cfg.rgb_order = true; // パネルの赤と青が入れ替わってしまう場合 trueに設定 // cfg.bus_shared = true; _panel_instance.config(cfg); >setPanel(&_panel_instance); // 使用するパネルをセットします。 lgfx::pinMode(TFT_RST, lgfx::pin_mode_t::output); lgfx::pinMode(TFT_SCLK, lgfx::pin_mode_t::output); lgfx::gpio_lo(TFT_RST); lgfx::gpio_hi(TFT_SCLK); lgfx::gpio_hi(TFT_RST); > >; static LGFX lcd; void init_camera() < camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = Y2_GPIO_NUM; config.pin_d1 = Y3_GPIO_NUM; config.pin_d2 = Y4_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM; config.pin_d4 = Y6_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; config.pin_d6 = Y8_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM; config.pin_xclk = XCLK_GPIO_NUM; config.pin_pclk = PCLK_GPIO_NUM; config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; config.pin_sscb_sda = SIOD_GPIO_NUM; config.pin_sscb_scl = SIOC_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.frame_size = FRAMESIZE_UXGA; config.pixel_format = PIXFORMAT_JPEG; // for streaming config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; config.fb_location = CAMERA_FB_IN_PSRAM; config.jpeg_quality = 12; config.fb_count = 1; // if PSRAM IC present, init with UXGA resolution and higher JPEG quality // for larger pre-allocated frame buffer. if (config.pixel_format == PIXFORMAT_JPEG) < if (psramFound()) < config.jpeg_quality = 10; config.fb_count = 2; config.grab_mode = CAMERA_GRAB_LATEST; >else < // Limit the frame size when PSRAM is not available config.frame_size = FRAMESIZE_SVGA; config.fb_location = CAMERA_FB_IN_DRAM; >> else < // Best option for face detection/recognition config.frame_size = FRAMESIZE_QVGA; #if CONFIG_IDF_TARGET_ESP32S3 config.fb_count = 2; #endif >// camera init esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) < Serial.printf("Camera init failed with error 0x%x", err); for (;;) yield(); >sensor_t* s = esp_camera_sensor_get(); // initial sensors are flipped vertically and colors are a bit saturated if (s->id.PID == OV3660_PID) < s->set_vflip(s, 1); // flip it back s->set_brightness(s, 1); // up the brightness just a bit s->set_saturation(s, -2); // lower the saturation > // drop down frame size for higher initial frame rate if (config.pixel_format == PIXFORMAT_JPEG) < s->set_framesize(s, FRAMESIZE_VGA); > > void sdmmcInit(void) < SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0); if (!SD_MMC.begin("/sdcard", true)) < Serial.println("Card Mount Failed"); for (;;) yield(); >uint8_t cardType = SD_MMC.cardType(); if (cardType == CARD_NONE) < Serial.println("No SD_MMC card attached"); for (;;) yield(); >Serial.print("SD_MMC Card Type: "); if (cardType == CARD_MMC) < Serial.println("MMC"); >else if (cardType == CARD_SD) < Serial.println("SDSC"); >else if (cardType == CARD_SDHC) < Serial.println("SDHC"); >else < Serial.println("UNKNOWN"); >uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024); Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize); Serial.printf("Total space: %lluMB\r\n", SD_MMC.totalBytes() / (1024 * 1024)); Serial.printf("Used space: %lluMB\r\n", SD_MMC.usedBytes() / (1024 * 1024)); > void createDir(fs::FS& fs, const char* path) < Serial.printf("Creating Dir: %s\n", path); if (fs.mkdir(path)) < Serial.println("Dir created"); >else < Serial.println("mkdir failed"); >> int readFileNum(fs::FS& fs, const char* dirname) < File root = fs.open(dirname); if (!root) < Serial.println("Failed to open directory"); return -1; >if (!root.isDirectory()) < Serial.println("Not a directory"); return -1; >File file = root.openNextFile(); int num = 0; while (file) < file = root.openNextFile(); num++; >return num; > void writejpg(fs::FS& fs, const char* path, const uint8_t* buf, size_t size) < File file = fs.open(path, FILE_WRITE); if (!file) < Serial.println("Failed to open file for writing"); return; >file.write(buf, size); file.close(); Serial.printf("Saved file to path: %s\r\n", path); > void shutterTask(void* arg) < for (;;) < if (!shutter && digitalRead(SHUTTER_BUTTON) == LOW) < shutter = true; >yield(); > > void setup() < Serial.begin(115200); Serial.println("ESP32-WROVER-CAM Picture"); // シャッターボタン pinMode(SHUTTER_BUTTON, INPUT_PULLUP); // LCD初期化 lcd.init(); // 画面回転はLCDに合わせて設定してください lcd.setRotation(1); lcd_width = lcd.width(); lcd_height = lcd.height(); // カメラ初期化 init_camera(); // カメラ画像の横幅を取得 fb = esp_camera_fb_get(); if (!fb) < Serial.println("Camera capture failed"); // カメラ画像が取得できない場合は停止 for (;;) yield(); >// LCD画像の倍率をセット zoom = lcd_width / (float)fb->width; y = (lcd_height - fb->height * zoom) / 2; // SDカード初期化 sdmmcInit(); createDir(SD_MMC, "/camera"); //Start Shutter tasks xTaskCreateUniversal(shutterTask, "shutterTask", 8192, NULL, 1, NULL, CONFIG_ARDUINO_RUNNING_CORE); > void loop() < static auto last = millis(); if (millis() - last >UPDATE_INTERVAL) < // フレームバッファ解放 esp_camera_fb_return(fb); // カメラのフレームを取得 fb = esp_camera_fb_get(); if (!fb) < Serial.println("Camera capture failed"); // カメラ画像が取得できない場合は停止 for (;;) yield(); >Serial.println("Taking picture.."); lcd.drawJpg(fb->buf, fb->len, 0, y, lcd_width, lcd_height, 0, 0, zoom); last = millis(); > if (shutter) < while (digitalRead(SHUTTER_BUTTON) == LOW) yield(); if (fb != NULL) < int photo_index = readFileNum(SD_MMC, "/camera"); if (photo_index != -1) < String path = "/camera/" + String(photo_index) + ".jpg"; // グレイに塗りつぶし シャッターを表現 lcd.clear(TFT_DARKGREY); Serial.println("camera shutter"); // 画像保存 writejpg(SD_MMC, path.c_str(), fb->buf, fb->len); // LCDをクリア lcd.clear(TFT_BLACK); shutter = false; > > > >

        対応LCD 1.3インチ ST7789 CSなし

        LCDピン/GPIOGNDGNDVCC3.3VSCL12SDA13RES33DC32BLK未接続

        関連記事

        【簡単!】Raspberry Pi Picoでデバッグプローブを作る方法【Arduino】

        RP2040ボード(例: Raspberry Pi Pico)をデバッグするのにRaspberry Pi Debug Probeは便利ですが、価格はちょっと高めです。Raspberry Pi Picoを使えば、デバッグプローブを低コストで実.

        aloseed.com Seeed Studio XIAO RP2350を試してみました

        Seeed Studio XIAO RP2350を入手したので試してみました。本記事ではArduino(C/C++)とMicroPythonで試してみます。開発環境としてVSCodeを使うこともできます。参考URL:スペック (XIAO R.

        aloseed.com 【コラム】ソフトウェアが主役になる時代【RP2040とRP2350の比較】

        2024年に入り、マイコン市場はハードウェアの進化からソフトウェアの活用にシフトしています。特にRP2040は、引き続き人気ですが、Raspberry Pi Pico 2に搭載された新しいマイクロコントローラ、RP2350も注目を集めていま.

        aloseed.com Raspberry Pi Pico 2を試してみました【Picoとのスペック比較など】

        Raspberry Pi Pico 2が登場しました。Raspberry Pi Pico 2についてまとめてみたいと思います。参考URL:RP2350 A2の不具合情報RP2350マイクロコントローラに関するErrata 9(E9)では、以.

        aloseed.com 【KiCad】プリント基板(PCB)に挑戦【PCBGOGO】 aloseed.com Raspberry Pi Pico W / Pico 2 Wを試してみました【Arduino、MicroPython】

        Raspberry Pi Pico WとRaspberry Pi Pico 2 Wを入手したのでArduinoとMicroPythonで試してみたいと思います。本記事に掲載のプログラムはRaspberry Pico 2 Wでも動作することを.

        aloseed.com Freenove ESP32-S3-WROOM CAMボード【FNK0085】を試してみました【Arduino使用】 aloseed.com WizFi360-EVB-Pico【WIZnet】を試してみました【Arduino使用】

        Raspberry Pi Pico Wの登場でRP2040(Raspberry Pi Pico)にいよいよWi-Fiが搭載されるようになりましたが、これ以前にWIZnetからWizFi360-EVB-PicoというWi-Fiモジュールが搭載.

        aloseed.com Raspberry Pi Zero 2 W 体験記

        国内向け(技適マーク付き)のRaspberry Pi Zero 2 Wを入手したので試していきたいと思います。パッケージに技適マーク(シール)が確認できます準備ケースAliExpressでお安めのケースを見つけたので、ものは試しということで.

        aloseed.com Freenove ESP32-WROVER CAMボード【FNK0060 & FNK0060B】を試してみました【Arduino使用】

        ESP32-WROVER CAMボード(Freenove FNK0060 または FNK0060B)はESP32-WROVER-E(技適マーク付き)とカメラが搭載されたボードです。こちらを入手したので情報をまとめてみました。FNK0060B.

        aloseed.com RP2040-0.42LCD【01Space】を試してみました【Arduino使用】

        RP2040-0.42LCDを入手したので試してみました。特徴RP2040 0.42インチLCDディスプレイ搭載小型MCUボードフラッシュメモリ 2MBUSB Type-CQwiic互換コネクタ搭載リセットボタンブートボタンソフトウェアは、.

        aloseed.com M5Stamp C3U Mateを試してみました【Arduino使用】

        M5Stamp C3U Mateを入手したのでArduinoで試してみました。参考URL:M5Stamp C3とM5Stamp C3Uの主な違いについてM5Stamp C3との違いは、主にシリアル変換IC(CH9102F)搭載の有無です。M.

        aloseed.com RP2040-Zero【Waveshare】を試してみました【Arduino使用】

        Waveshare RP2040-Zeroを入手したので試してみました。特徴RP2040搭載小型MCUボードUSB Type-C端面スルーホール(キャリアボードに直接はんだづけが可能)RGB LED(WS2812)リセットボタンブートボタン.

        aloseed.com RP2040-Plus【Waveshare】を購入してみました

        当ブログでは、過去にArduino Nano RP2040 Connectを購入した体験記事を執筆しましたが、今回はRP2040-PlusというWaveshareのRP2040を搭載したボードを購入したのでご紹介したいと思います。Waves.

        aloseed.com Seeed Studio XIAO RP2040を試してみました【Arduino使用】

        Seeed Studio XIAO RP2040を入手したので試してみました。Seeed Studio XIAO RP2040は、MCUにRP2040を搭載したXIAOで、Seeeduino XIAOとピン配置/形状に互換性があるのが特徴で.

        aloseed.com M5Stamp C3 Mateを試してみました【Arduino使用】

        M5Stamp C3 Mateを入手したので試してみました。参考URL:M5Stamp C3U Mateも記事にしました。スケッチは本記事に掲載したもので試しています。本記事では、プログラムにArduino(C/C++)を使っています。ピン.

        aloseed.com Adafruit QT Py RP2040を試してみました【Arduino使用】

        Adafruit QT Py RP2040を入手したので試してみました。特徴Seeeduino XIAO、Adafruit QT Py(SAMDベースモデル)互換のピン配置/形状USB Type-CRGB NeoPixel LED内蔵STE.

        aloseed.com Arduino Nano RP2040 Connectを購入してみました

        今回は、Arduino Nano RP2040 Connectを公式ストアで購入してみました、という体験記事になります。もの好きなのは間違いないですね。購入までの流れ公式ストア購入したものは、ピンヘッダーが装着されていないバージョン(ABX.

        aloseed.com あろっちをフォローする あろっちをフォローする

        関連記事

        Raspberry Pi 4 体験記【初!ラズパイ】

        今回は、Raspberry Pi 4の購入に至った経緯から、動作させる(使用できる)ところまで僕が体験した過程を紹介したいと思います。※Raspberry Pi 400 日本語キーボード版(キーボード一体型Raspberry Pi)も入手し.

        Raspberry Pi OS Tips

        Raspberry Pi OSは、Debian(GNU/Linux)ベースのRaspberry Pi用のOSです。この記事では、Raspberry Pi OSでできるカスタマイズなどのTipsを書いていきます。Raspberry Pi OS.

        M5Stack スクロールユニット & ジョイスティック2ユニットをRaspberry Pi Pico/RP2040ボード(Arduino-Pico)、MicroPythonで使おう

        M5Stack用 スクロールユニットとM5Stack用 ジョイスティック2ユニットをRaspberry Pi Pico/RP2040ボード(Arduino-Pico)、MicroPythonで使うためのプログラムを紹介します。

        【Vesonn】Raspberry Pi 5 16GB スターターキット レビュー【キットの内容とセットアップ手順】 Raspberry Pi 5 スターターキット(Raspberry Pi 5 Starter Kit)に含まれる内容やセットアップ手順を紹介します。

        コメント

        参考になる記事を書いていただきありがとうございます。 モジュールについてですが、本物のFreenove FNK0060はESP32-WROVER-Eの正しい証明番号(211-200403)ですが、ジェネリックというか偽物の方はESP-WROOM32の証明番号(211-161007)を適当に書いてるだけなのでモジュールの相違というより単に違反品のようです。

        ご覧いただきましてありがとうございます。 ご指摘の点についてこちらでも確認できましたので記事の内容を一部修正いたしました。 今後もより正確で役に立ちそうな情報を発信していきたいと思っていますのでよろしくお願いします。

        コメント失礼します。 ピン配列の説明について、 「カメラ使用時は以下が外部ピンとして使用できるかと思います。 GPIO12〜GPIO15(HSPI対応) GPIO32、GPIO33」 これはピン配置画像の「CAM_〇〇」以外のGPIOピンが全て外部ピンとして使用できるということでしょうか。また、FLASHピンもカメラと連動して外部ピンとしては使えなくなってしまうのでしょうか。

        ご覧いただきましてありがとうございます。 カメラ使用時は、 CAM_〇〇が使用できないということでOKです。 それで、これ以外のGPIOピンが使えるかというところですが、 カメラ非使用時においても、 FLASHピンは内部フラッシュメモリの接続に使用されている関係で常時使用不可かと思います。 また、LEDに接続されているピン(LED_〇〇)も使用できないと考えます。 GPIO0に関してはBOOTボタンに接続されており起動時書き込みモードにするために使われるため、使わない方が良いかと考えます。 従いまして、カメラ使用時に使用できるGPIOは本文にも記載してある通り以下のGPIOピンになるかと思います。 GPIO12〜GPIO15(HSPI対応) GPIO32、GPIO33

        コメントをどうぞ コメントをキャンセル サイト内を検索 人気記事 Raspberry Pi Pico W / Pico 2 Wを試してみました【Arduino、MicroPython】 2023.03.30 2026.02.12 Freenove ESP32-S3-WROOM CAMボード【FNK0085】を試してみました【Arduino使用】 2022.12.26 2025.09.10 Raspberry Pi Pico 2を試してみました【Picoとのスペック比較など】 2024.08.26 2025.09.04 RP2040-Zero【Waveshare】を試してみました【Arduino使用】 2022.03.16 2025.04.03 Freenove ESP32-WROVER CAMボード【FNK0060 & FNK0060B】を試してみました【Arduino使用】 2022.08.19 2025.09.10 新着記事 【Vesonn】Raspberry Pi 5 16GB スターターキット レビュー【キットの内容とセットアップ手順】 MacBook Airとーとー買っちゃいました【13インチ M4モデル】デスクトップ環境 2026.01.16 2026.03.14 ドットマトリクス(MAX7219)に日本語を表示してみよう【Arduino使用】 2025.04.15 2026.01.25 【Vesiri】Raspberry Pi 5 スターターキット 体験記【レビュー】 2025.02.25 2026.03.16 M5Stack スクロールユニット & ジョイスティック2ユニットをRaspberry Pi Pico/RP2040ボード(Arduino-Pico)、MicroPythonで使おう 2025.02.17 2025.09.30 目次
        1. 特徴
        2. 画像ギャラリー
          1. Freenove ESP32-WROVER Board FNK0060(v1.6)
          2. Freenove ESP32-WROVER Board FNK0060B(v3.0)
          3. サイズ
          4. カメラモジュール(OV2640)例
          1. v1.6 (FNK0060)
          2. v3.0 (FNK0060B)
          3. 使用できるGPIOについて
            1. カメラ使用時
            2. v3.0の場合 (SDカードスロット使用時)
            1. CameraWebServer (Arduino IDEスケッチ例を使用する場合)
            2. 映像を液晶ディスプレイに表示する(HSPI使用例)
              1. スケッチ1 (Adafruit GFXライブラリ使用)
              2. スケッチ2 (LovyanGFXライブラリ使用)
              3. プリズムを使ってみました
              1. 表示できる画像ファイルについて