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

Raspberry Pi/電子工作
スポンサーリンク

こんにちは、あろっちです。

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

Freenove FNK0060は現在SDカードスロット搭載モデル(with Memory Card Slot and Card)があるようです。
旧ロットはSDカードスロットがありませんでした。

本記事は旧ロットを元に書いております。ご了承ください。

ESP32-WROVER CAMボードには、Freenoveのオリジナル品(FNK0060)とジェネリック品があります。

Freenove FNK0060は基板にFREENOVEの文字がシルク印刷されています。

左: Freenove FNK0060 右: ジェネリック品

参考サイト:

https://lang-ship.com/blog/work/esp32-cam-fnk0060/(Lang-ship)

上記にたなかさんの情報がありますので参考にしてください。
こちらによるとジェネリック品のESP32-WROVER-Eモジュールはクローン品(いわゆる偽物)とのことで筆者の方でも挙動の違いを確認しました。

本記事ではオリジナル品であるFreenove FNK0060の情報をお届けしたいと思います。
※掲載している画像の一部にジェネリック品の画像がありますがご了承ください。2023年2月6日

本記事は以下を参考にしています。

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

本記事ではArduino(C/C++)で試してみます。

ESP32-S3-WROOM-1を搭載したモデルが入手できましたので記事を書きました。ぜひご覧ください。

スポンサーリンク

特徴

Freenove ESP32-WROVER Board FNK0060

外箱
ボード本体の他、USBケーブルとリーフレットが付属しています。
袋からボードを取り出したところ
モジュールESP32-WROVER-E
(技適マーク付き)
工事設計認証番号: 211-200403
フラッシュメモリ 4MB
PSRAM 8MB※1
カメラオンボードカメラ
(コネクタ)
付属カメラモジュール
OV2640 66°
USBシリアルMicro USBシリアル変換IC
CH340※2
※1 Arduinoで使用可能な容量は4MBまでです。
※2 シリアルドライバをインストールしていない場合は別途インストールが必要です。

ESP32-S3-WROOM-1を搭載したモデルの記事を書きました。ぜひご覧ください。

ギャラリー

※画像はジェネリック品ですがFreenove FNK0060と同サイズです。ご了承ください。2023年2月6日

普通のブレッドボード(400穴)だと片側1ピン分の穴が確保できます。

ブレッドボード2枚を連結して設置すると左右どちらもピン穴が確保できました。

サンハヤトのニューブレッドボードでは、3ピン分(片側1ピン、他方2ピン)ピン穴が確保できました。
このボードを使うのにオススメのブレッドボードです。
※このボードの使用例を後述のサンプルプログラムに掲載しています。

カメラモジュール(OV2640)例

カメラモジュール(OV2640)には様々なバリエーションがあります。
こちらは別途購入したもの。

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

カメラはコネクタ接続なので換装して使えます。

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

ピン配列

※画像のバー付きのピン(GPIO)はカメラ(コネクタ)に接続されています。

カメラ使用時は以下が外部ピンとして使用できるかと思います。

GPIO12〜GPIO15(HSPI対応)
GPIO32、GPIO33

※HSPIを使用したスケッチ例を後述のサンプルプログラムに掲載しました。※2022年10月22日

本ボードは普通にESP32開発ボードとして使用することもでき、スターターキットが販売されています。

参考サイト:

ESP32-S3-WROOM-1を搭載したモデルの記事を書きました。ぜひご覧ください。

Arduinoボード設定

Arduino IDEにESP32ボードを追加しておきます。

追加方法については、以下の記事をご参照ください。

  • ボードインストール

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

  • ボードの選択

[ツール] > [ボード] > [ESP32 Arduino] > [ESP32 Wrover Module]を選択します。

  • シリアルポートの選択

ボードが接続されているポートを選択します。

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

※シリアルポートが認識されない場合はCH340用シリアルドライバを以下からダウンロードしてインストールしてください。

GitHub
https://github.com/Freenove/Freenove_ESP32_WROVER_Board/tree/main/CH340

PlatformIO IDEを使用する場合

動作確認した内容を記載します。

PlatformIO IDE

バージョン Core 6.1.4/Home 3.4.3

開発環境

PlatformEspressif 32バージョン 5.1.1
ボードEspressif ESP-WROVER-KITフレームワーク
Arduino

CameraWebServerの修正済みArduinoスケッチをインポートしてプロジェクトを作成
※スケッチ例の修正方法は後述のサンプルプログラムに掲載しています。

以下の設定で動作確認しました。

platformio.ini (例)

[env:esp-wrover-kit]
platform = espressif32
board = esp-wrover-kit
framework = arduino
;upload_port = /dev/cu.wchusbserial14110
upload_speed = 921600
monitor_speed = 115200

upload_port

上記パラメーターはボードが接続されているシリアルポートを明示するパラメーターです。
コメントアウトしていますが、必要であれば設定してください。

こちらがPlatformIO IDEで書き込んだCameraWebServerの動作例です。

動作例

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

開発環境

Arduino IDE バージョン1.8.19 (※1系)
2系(2.x.x)は最新版でOK
ESP32 Arduinoボード基本的に最新版でOK

以下にpdfやサンプルスケッチがあります。

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_05.1_CameraWebServerがありますが、Arduino IDEのスケッチ例([スケッチ例] > [ESP32] > [Camera] > [CameraWebServer])を使用する場合、次のように修正します。

  1. カメラモデルの指定
    CAMERA_MODEL_WROVER_KITのコメントをはずし、CAMERA_MODEL_AI_THINKERをコメントアウトします。
  2. Wi-Fi設定
    ssidとpasswordを接続先Wi-Fiのssidとpasswordに書き換えます。

スケッチを書き込んだのち、シリアルモニターを開きリセットボタンを押すとCameraWebServerのURL(画像赤枠参照)が確認できます。

ブラウザからシリアルモニターに表示されたURLにアクセスすると以下のような画面が表示されます。

動作例

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

ボタンを押すと映像が液晶ディスプレイに表示されるというスケッチ例です。

素材はこちら

液晶ディスプレイ

今回のスケッチ例ではST7789の液晶ディスプレイを使用します。

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

いずれも解像度は240×240です。

ちなみに1.3インチの方はCSピンがありません。そのためスケッチを動かす場合は修正が必要です。

製作例

1.54インチディスプレイの例

1.54インチディスプレイ使用
右の箱は今回の被写体に使っている素材で製作には無関係です。

1.3インチディスプレイの例

1.3インチディスプレイ使用
パーツについて
  • 液晶ディスプレイ
    ST7789のものを使っています。

  • ボタン
    1.54インチディスプレイの例で使用しているボタンはタッチでON/OFFができるトグルスイッチ式のものです。
    1.3インチディスプレイの例ではスライドスイッチを使用してみました。

  • ブレッドボード
    ニューブレッドボード(サンハヤト)を使っています。
スケッチで使用しているライブラリについて
  • Adafruit ST7735 and ST7789 Library
  • Adafruit GFX Library
  • TJpg_Decoder

いずれのライブラリもArduino IDEのライブラリマネージャーから検索してインストールできます。

スケッチ

#include "esp_camera.h"
#include <SPI.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <TJpg_Decoder.h>

// 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 SCLK
TFT SDA13HSPI MOSI
TFT CS15HSPI CS
1.3インチLCDでは配線不要
TFT DC32
TFT RST33
BUTTON(スイッチ)12ボタン(トグルスイッチ)
INPUT
※TFTは液晶ディスプレイ(LCD)を表しています

液晶ディスプレイはHSPIで接続するようにしています。

スイッチに割り当てるGPIOが不足したため、GPIO12(HSPI MISO)を入力ピンに割り当てています。

スケッチの修正について

1.3インチディスプレイを使用する場合、CSピンがないためSPIをMODE 2に設定します。

tft.initの箇所を以下のように修正します。

  tft.init(240, 240, SPI_MODE2); // Init ST7789 display 240x240 pixel

スライドスイッチを使用する場合

以下のようにON側に3.3V(赤ワイヤー)、OFF側にGND(黒ワイヤー)、入力(青ワイヤー)をGPIO12に接続すればON/OFFを実現できます。

今回の製作例のようにON側の3.3V(赤ワイヤー)のみ配線する場合、以下のようにOFF側にスイッチを入れているとき入力ピン(青ワイヤー)の状態が不安定になります。

そこで、setup関数内のボタン入力ピンの設定を以下のようにINPUT_PULLDOWNにするとスイッチがOFF側(入力ピン(青ワイヤー)が開放された状態)の時に内部プルダウンされるようになるのでGNDの配線をしなくても動作するようになるかと思います。

  pinMode(PIN_BTN, INPUT_PULLDOWN);

1.3インチディスプレイ動作例

プリズムを使ってみました

見た目は透明なブロックみたいな感じです。1辺25.4mmの正方形です。

このプリズムを液晶ディスプレイに乗せるとプリズムに映像が投影されます。

投影している様子がこちら

関連記事

当ブログのマイコン記事です。ぜひご覧ください。

コメント

  1. 匿名 より:

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

    • あろっち あろっち より:

      ご覧いただきましてありがとうございます。

      ご指摘の点についてこちらでも確認できましたので記事の内容を一部修正いたしました。

      今後もより正確で役に立ちそうな情報を発信していきたいと思っていますのでよろしくお願いします。

  2. 匿名 より:

    コメント失礼します。

    ピン配列の説明について、
    「カメラ使用時は以下が外部ピンとして使用できるかと思います。

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

    • あろっち あろっち より:

      ご覧いただきましてありがとうございます。

      カメラ使用時は、
      CAM_〇〇が使用できないということでOKです。

      それで、これ以外のGPIOピンが使えるかというところですが、
      カメラ非使用時においても、
      FLASHピンは内部フラッシュメモリの接続に使用されている関係で常時使用不可かと思います。
      また、LEDに接続されているピン(LED_〇〇)も使用できないと考えます。
      GPIO0に関してはBOOTボタンに接続されており起動時書き込みモードにするために使われるため、使わない方が良いかと考えます。

      従いまして、カメラ使用時に使用できるGPIOは本文にも記載してある通り以下のGPIOピンになるかと思います。
      GPIO12〜GPIO15(HSPI対応)
      GPIO32、GPIO33

タイトルとURLをコピーしました