こんにちは、あろっちです。
ESP32-WROVER CAMボード(Freenove FNK0060)はESP32-WROVER-E(技適マーク付き)とカメラが搭載されたボードです。
こちらを入手したので情報をまとめてみました。
ESP32-WROVER CAMボードには、Freenoveのオリジナル品(FNK0060)とジェネリック品があります。
Freenove FNK0060は基板にFREENOVEの文字がシルク印刷されています。
参考サイト:
https://lang-ship.com/blog/work/esp32-cam-fnk0060/(Lang-ship)
上記にたなかさんの情報がありますので参考にしてください。
こちらによるとジェネリック品のESP32-WROVER-Eモジュールはクローン品(いわゆる偽物)とのことで筆者の方でも挙動の違いを確認しました。
本記事ではオリジナル品であるFreenove FNK0060の情報をお届けしたいと思います。
※掲載している画像の一部にジェネリック品の画像がありますがご了承ください。2023年2月6日
本記事は以下を参考にしています。
本記事ではArduino(C/C++)で試してみます。
ESP32-S3-WROOM-1を搭載したモデルが入手できましたので記事を書きました。ぜひご覧ください。
特徴
Freenove ESP32-WROVER Board FNK0060
モジュール | ESP32-WROVER-E (技適マーク付き) 工事設計認証番号: 211-200403 | フラッシュメモリ 4MB PSRAM 8MB※1 |
カメラ | オンボードカメラ (コネクタ) | 付属カメラモジュール OV2640 66° |
USBシリアル | Micro USB | シリアル変換IC CH340※2 |
※2 シリアルドライバをインストールしていない場合は別途インストールが必要です。
ESP32-S3-WROOM-1を搭載したモデルの記事を書きました。ぜひご覧ください。
ギャラリー
※画像はジェネリック品ですがFreenove FNK0060と同サイズです。ご了承ください。2023年2月6日
普通のブレッドボード(400穴)だと片側1ピン分の穴が確保できます。
ブレッドボード2枚を連結して設置すると左右どちらもピン穴が確保できました。
サンハヤトのニューブレッドボードでは、3ピン分(片側1ピン、他方2ピン)ピン穴が確保できました。
このボードを使うのにオススメのブレッドボードです。
※このボードの使用例を後述のサンプルプログラムに掲載しています。
カメラモジュール(OV2640)例
カメラモジュール(OV2640)には様々なバリエーションがあります。
こちらは別途購入したもの。
カメラはコネクタ接続なので換装して使えます。
ピン配列
※画像のバー付きのピン(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* |
Windows | COM* |
※シリアルポートが認識されない場合はCH340用シリアルドライバを以下からダウンロードしてインストールしてください。
GitHub
https://github.com/Freenove/Freenove_ESP32_WROVER_Board/tree/main/CH340
PlatformIO IDEを使用する場合
動作確認した内容を記載します。
PlatformIO IDE
開発環境
Platform | Espressif 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やサンプルスケッチがあります。
CameraWebServer (Arduino IDEスケッチ例を使用する場合)
GitHubのサンプルスケッチにSketch_05.1_CameraWebServerがありますが、Arduino IDEのスケッチ例([スケッチ例] > [ESP32] > [Camera] > [CameraWebServer])を使用する場合、次のように修正します。
- カメラモデルの指定
CAMERA_MODEL_WROVER_KITのコメントをはずし、CAMERA_MODEL_AI_THINKERをコメントアウトします。 - 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.3インチディスプレイの例
いずれのライブラリも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 SCL | 14 | HSPI SCLK |
TFT SDA | 13 | HSPI MOSI |
TFT CS | 15 | HSPI CS 1.3インチLCDでは配線不要 |
TFT DC | 32 | |
TFT RST | 33 | |
BUTTON(スイッチ) | 12 | ボタン(トグルスイッチ) INPUT |
液晶ディスプレイは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の正方形です。
このプリズムを液晶ディスプレイに乗せるとプリズムに映像が投影されます。
投影している様子がこちら
関連記事
当ブログのマイコン記事です。ぜひご覧ください。
コメント
参考になる記事を書いていただきありがとうございます。
モジュールについてですが、本物の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