Spresense + HDR カメラで写真を 10 枚撮って microSD カードに保存するスケッチ
前書き
Spresense 公式サイトのチュートリアルはうまく動かせなかったので ChatGPT の力を借りてコードを書いた。
このコードで Spresense の HDR カメラで連続 10 枚の写真を撮って、それを microSD カードに保存することができたので記録しておく。
豆知識
Arduino IDE で書くプログラムのことをスケッチと呼ぶらしい。
Arduino IDE で書くプログラムは C++ に近いらしい。
機器の組み合わせ (開発風景)
コードを動かした時の機器の組み合わせと開発風景です。都内某所のカフェでこんなふうに開発しています。
青いプチプチはたぶん静電効果のあるプチプチ (Spresense を買っていたときについていたものと記憶している) なので、これに包んで小さなポーチに入れて持ち運びしています。
青いプチプチの下に白い紙 (ノートを破ったもの) を敷いているのは、この開発風景の写真映りを良くするためのもので機能的な意味はありません。
パソコンの USB ポートにデータ転送ができる USB ケーブル を接続し、この USB ケーブルを Spresense メインボードに接続しています。
Spresense メインボードに、HDR カメラ が接続されています。写真の中で LED が 1 個青く光っているのは Spresense メインボードの LED です。
Spresense メインボードは、拡張ボードとドッキングする形で接続されています。
拡張ボードには 128 GB の Micro SD カード が挿入されています。水色に写っている箇所です。この Micro SD カードにカメラで撮った写真が保存されます。
拡張ボードの動作電圧設定は 5V にしています。買ったときから 5V の設定だったと思います。この電圧設定はジャンパと呼ばれる小さなパーツの差込口を変えることで変更できます。公式サイトのこのドキュメント を見ていただくとわかりやすいかな、と。
どうやって Spresense の電源オン・オフする?
USB ケーブルを接続したら電源オンになり、USB ケーブルを外すと電源オフになる、っていうそれだけだと思います。
電源をオン・オフする物理的なスイッチはないと思う。(もしあったらいつかここの記載を修正する)
コード
#include <Camera.h> #include <SDHCI.h> #include <stdio.h> #define BAUDRATE (115200) #define TOTAL_PICTURE_COUNT (10) #define STREAMING_PRINT_INTERVAL (100) SDClass theSD; int take_picture_count = 0; int streaming_frame_count = 0; void printError(enum CamErr err) { Serial.print("Error: "); switch(err){ case CAM_ERR_NO_DEVICE: Serial.println("No Device"); break; case CAM_ERR_ILLEGAL_DEVERR: Serial.println("Illegal device error"); break; case CAM_ERR_ALREADY_INITIALIZED: Serial.println("Already initialized"); break; case CAM_ERR_NOT_INITIALIZED: Serial.println("Not initialized"); break; case CAM_ERR_NOT_STILL_INITIALIZED: Serial.println("Still picture not initialized"); break; case CAM_ERR_CANT_CREATE_THREAD: Serial.println("Failed to create thread"); break; case CAM_ERR_INVALID_PARAM: Serial.println("Invalid parameter"); break; case CAM_ERR_NO_MEMORY: Serial.println("No memory"); break; case CAM_ERR_USR_INUSED: Serial.println("Buffer already in use"); break; case CAM_ERR_NOT_PERMITTED: Serial.println("Operation not permitted"); break; default: Serial.println("Unknown error"); break; } } void CamCB(CamImage img) { if(img.isAvailable()){ img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565); streaming_frame_count++; }else{ Serial.println("Failed to get video stream image"); } } void setup() { CamErr err; Serial.begin(BAUDRATE); while(!Serial){ ; // wait for serial port to connect. Needed for native USB port only } Serial.println("Established a serial connection."); while(!theSD.begin()){ Serial.println("Please insert microSD card."); delay(1000); } Serial.println("microSD card has been initialized."); Serial.println("Preparing a camera"); err = theCamera.begin(); if(err != CAM_ERR_SUCCESS){ printError(err); return; } Serial.println("Camera has been initialized."); Serial.println("Start streaming"); err = theCamera.startStreaming(true, CamCB); if(err != CAM_ERR_SUCCESS){ printError(err); return; } Serial.println("Streaming started."); Serial.println("Setting Auto white balance parameter"); err = theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT); if(err != CAM_ERR_SUCCESS){ printError(err); return; } Serial.println("Auto white balance has been set."); Serial.println("Setting a still picture format"); err = theCamera.setStillPictureImageFormat(CAM_IMGSIZE_QUADVGA_H, CAM_IMGSIZE_QUADVGA_V, CAM_IMAGE_PIX_FMT_JPG); if(err != CAM_ERR_SUCCESS){ printError(err); return; } Serial.println("Still picture format set."); } void loop() { while(take_picture_count < TOTAL_PICTURE_COUNT){ sleep(1); Serial.println("Calling takePicture() method..."); CamImage img = theCamera.takePicture(); if(img.isAvailable()){ char filename[16] = {0}; sprintf(filename, "PICT%03d.JPG", take_picture_count); Serial.print("Saving taken picture as "); Serial.print(filename); Serial.println(""); theSD.remove(filename); File myFile = theSD.open(filename, FILE_WRITE); myFile.write(img.getImgBuff(), img.getImgSize()); myFile.close(); } else { Serial.println("Failed to take picture"); } take_picture_count++; } if(take_picture_count == TOTAL_PICTURE_COUNT){ Serial.println("End."); theCamera.end(); while(true){ delay(1000); // デバイスをフリーズさせないために少し待つ } } }
コードを動かした時のコンソール表示
以下が Arduino IDE です。
上記 赤枠 のところが Upload ボタンで、これをクリックすると 青枠内 のスケッチが Spresense にアップロード (転送) されます。
スケッチの転送が終わると Spresense が再起動して (たぶん) そのあとスケッチが自動実行されます。
このとき、ピンク の Serial Monitor のところにメッセージやログが表示されてプログラム動作状況の確認ができます。
Serial Monitor のところに表示される情報もテキストでぺたっと貼っておきます。
Established a serial connection. microSD card has been initialized. Preparing a camera Camera has been initialized. Start streaming Streaming started. Setting Auto white balance parameter Auto white balance has been set. Setting a still picture format Still picture format set. Calling takePicture() method... Saving taken picture as PICT000.JPG Calling takePicture() method... Saving taken picture as PICT001.JPG Calling takePicture() method... Saving taken picture as PICT002.JPG Calling takePicture() method... Saving taken picture as PICT003.JPG Calling takePicture() method... Saving taken picture as PICT004.JPG Calling takePicture() method... Saving taken picture as PICT005.JPG Calling takePicture() method... Saving taken picture as PICT006.JPG Calling takePicture() method... Saving taken picture as PICT007.JPG Calling takePicture() method... Saving taken picture as PICT008.JPG Calling takePicture() method... Saving taken picture as PICT009.JPG End.
PICT000.jpg から PICT009.jpg まで合計 10 枚の画像が保存されている状況がわかります。