AtomS3R CAMで写真を保存 ~ ATOMIC TFカードリーダーを使う

今までにAtomS3R CAMのカメラ映像をPCやスマートフォンで映してみましたが、今回はSDカードに画像として保存する仕組みを作ってみました。これは、トイカメラを作成するプロトタイプとなります。
1.ATOMIC TFカードリーダーを使う
ATOMシリーズでSDカードを使う周辺機器として「ATOMIC TFカードリーダー」があります。これは、ATOMシリーズを本体に格納して使うことができるため、配線の手間が省けて便利な機器です。しかしながら、ATOMシリーズにある本体下部のGPIOを占有してしまうため、空いたGPIOが使えなくなる欠点もあります。
今回はシャッターボタンが必要ですが、GROVEのGPIOを使用することで対応しました。
なお、AtomS3R CAMはATOMIC TFカードリーダーの適応機種とはなっていません。あくまでも自己責任の上、利用することとなります。ご注意ください。
2.ハードウェア構成

AtomS3R CAMとATOMIC TFカードリーダー、バッテリーであるTAILBAT、シャッターボタンのためのプッシュボタン、各種配線を用意しました。
SDカードはSPI接続になり、以下のGPIOを使用します。
SCK -> GP07
MISO -> GP08
MOSI -> GP06
使わないGPIOもありますが、ATOMIC TFカードリーダーに端子がないために使えなくなります。そのため、シャッターボタンはGROVE端子にあるGP01を使います。唯一、GP02が空いていますが、これだけでは背面液晶を用意することができません。
3.プログラム
既にJPEG画像の取得までプログラムを作っているので、画像をSDカードへ保存するロジックを追加すれば良いです。また、シャッターボタンを処理するロジックを追加します。
プログラムは、公式で提供しているAtomS3R CAMとATOMIC TFカードリーダーのサンプルを参考にさせて頂いています。
以下、今回のプログラムです。
#include "camera_pins.h"
#include "esp_camera.h"
#include <SPI.h>
#include "FS.h"
#include "SD.h"
#define SCK 7
#define MISO 8
#define MOSI 6
#define SHUTTER 1 // GROVE GPIO 1番
camera_fb_t* fb = NULL;
uint8_t* out_jpg = NULL;
size_t out_jpg_len = 0;
static camera_config_t camera_config = {
.pin_pwdn = PWDN_GPIO_NUM,
.pin_reset = RESET_GPIO_NUM,
.pin_xclk = XCLK_GPIO_NUM,
.pin_sscb_sda = SIOD_GPIO_NUM,
.pin_sscb_scl = SIOC_GPIO_NUM,
.pin_d7 = Y9_GPIO_NUM,
.pin_d6 = Y8_GPIO_NUM,
.pin_d5 = Y7_GPIO_NUM,
.pin_d4 = Y6_GPIO_NUM,
.pin_d3 = Y5_GPIO_NUM,
.pin_d2 = Y4_GPIO_NUM,
.pin_d1 = Y3_GPIO_NUM,
.pin_d0 = Y2_GPIO_NUM,
.pin_vsync = VSYNC_GPIO_NUM,
.pin_href = HREF_GPIO_NUM,
.pin_pclk = PCLK_GPIO_NUM,
.xclk_freq_hz = 20000000,
.ledc_timer = LEDC_TIMER_0,
.ledc_channel = LEDC_CHANNEL_0,
.pixel_format = PIXFORMAT_RGB565,
.frame_size = FRAMESIZE_QVGA,
.jpeg_quality = 0,
.fb_count = 2,
.fb_location = CAMERA_FB_IN_PSRAM,
.grab_mode = CAMERA_GRAB_LATEST,
.sccb_i2c_port = 0,
};
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(POWER_GPIO_NUM, OUTPUT);
digitalWrite(POWER_GPIO_NUM, LOW);
delay(500);
esp_err_t err = esp_camera_init(&camera_config);
if (err != ESP_OK) {
Serial.println("カメラの初期化に失敗しました");
delay(1000);
esp_restart();
} else {
Serial.println("カメラの初期化に成功しました");
}
// 画像反転
// sensor_t *s = esp_camera_sensor_get();
// s->set_vflip(s, 0);
delay(100);
pinMode(SHUTTER, INPUT_PULLUP); // シャッター プルアップ
SPI.begin(SCK, MISO, MOSI, -1);
if(!SD.begin()){
Serial.println("カードが入っていません");
return;
}
}
void saveImageToSD(camera_fb_t *fb) {
if (!fb) {
Serial.println("画像の取得に失敗しました");
return;
}
String path = "/image_" + String(millis()) + ".jpg";
Serial.println(path);
File file = SD.open(path, FILE_WRITE);
if(!file){
Serial.println("画像ファイルのオープンに失敗しました");
return;
}
file.write(out_jpg, out_jpg_len);
file.close();
Serial.println("画像を保存しました: " + path);
}
void loop() {
// put your main code here, to run repeatedly:
int btn = digitalRead(SHUTTER);
if (btn == LOW) {
// シャッターが押された
//
fb = esp_camera_fb_get();
if (fb) {
frame2jpg(fb, 255, &out_jpg, &out_jpg_len);
Serial.printf("pic size: %d\n", out_jpg_len);
saveImageToSD(fb);
esp_camera_fb_return(fb);
}
}
// 終了処理がないので、追加してください
delay(250); // 0.25秒ごとに更新
}
4.トイカメラにするには

今回、筐体に組み込んでみようと思ったのですが、丁度良い筐体がなくて断念しています。やっぱり、3Dプリンタが必要ですね。欲しいけれど運用する資金が厳しいので、購入していません。
また、背面モニタが欲しいですが、空きのGPIOが足りないため難しいです。解決するには、ATOMIC TFカードリーダーにAtomS3R CAMを直接接続しないで、空きのGPIOを有効活用するようにすればできると思います。I2CのSD1306ドライバを使うOLEDであれば、白黒ですが実現できそうです。
5.自作カメラを作ってみよう

今回は30万画素のAtomS3R CAMを使いましたが、AtomS3R M12カメラキットなら300万画素ですから、そこそこきれいな写真が撮れると思います。でも、オートフォーカスは欲しいかな。のっぺりした写真は好みではないので。
それと、やっぱり3Dプリンターが欲しいです。AtomS3R CAMを使ったトイカメラを公開している方もいらっしゃるので、それを使うとちょっとしたトイカメラになります。何とか3Dプリンターの資金集めをしなければなりませんね。
みなさんも、自作のトイカメラを作ってみてはいかがでしょうか。