画像をマイクロ SD カードに保存する監視カメラの作成 2/2

画像をマイクロ SD カードに保存する監視カメラの作成 1/2」では、 JPEG TTL カメラ、SD カードモジュール、そして Arduino Uno との接続方法について説明しました。

おさらいすると、SD カードモジュールは SPI インターフェイスで、Arduino Uno では SS、MOSI、MISO、SCLK の順に、 10, 11, 12, 13 です。

ここに接続しているので、次のコードでは SPI インターフェイスに関するピン番号の指定が出てきません。

Arduino IDE の準備等については「Arduino Software (IDE) のインストールと設定」をみてください。

プログラミング

先にコードの全体を記載すると次の通りです。

/*
 * Arduino UNO + TTL Camera + SD Storage w/SPI Interface 
 */
#include <Adafruit_VC0706.h>
#include <SoftwareSerial.h>
#include <SD.h>

const int PIN_LED = 4;
// CAMERA TX => 2
// CAMERA RX => 3
SoftwareSerial cameraconnection = SoftwareSerial(2,3);
Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);
boolean camera_found = false;
int file_count = 1;
char fname[16];

void setup() {

  SD.begin();
  
  if( cam.begin() ){
    camera_found = true;
  }
  else{
    return;
  }

  pinMode(PIN_LED, OUTPUT);
  digitalWrite(PIN_LED, LOW);
}

void loop() {
  
  if( !camera_found) {
    return;
  }

  digitalWrite(PIN_LED, HIGH);
  
  cam.setImageSize(VC0706_640x480);
  
  if( cam.takePicture() ){

    set_filename();
    
    File file = SD.open( 
      fname, 
      FILE_WRITE | O_TRUNC );
    
    if( file ){

      uint16_t len = cam.frameLength();
    
      while (len > 0) {
        uint8_t *buf;
        uint8_t bytesToRead = min(64, len);
        buf = cam.readPicture(bytesToRead);      
        file.write( buf, bytesToRead );
        len -= bytesToRead;
      }

      file.close();
    }
    
  }

  cam.reset();

  digitalWrite(PIN_LED, LOW);

  delay(5000);
}


void set_filename(){
  sprintf(fname, "IMG%04d.JPG", file_count++);
  
  if( file_count > 9999 ){
    file_count = 1; // Overwrite
  }
}

setup 関数

setup 関数ではまず、SD.begin で SD ライブラリの初期化をします。

SS (CS) ピンを既定値以外にする場合は、SD.begin メソッドにピン番号を渡します。 今回は Arduino Uno で SS を既定値の D10 にしているので、引数なしで呼び出しています。

カメラの操作については Adafruit の Adafruit_VC0706 ライブラリを利用しています。 こちらも同じ名前の begin メソッドで初期化します。

さらに LED は D4 で使うので pinMode 関数で OUTPUT にモードをセットして、 LOW にしておきます。

loop 関数

写真の撮影

loop 関数では、Adafruit_VC0706 の setImageSize でサイズ指定した後、 takePicture で写真を撮影します。

ファイル名

set_filename 関数は、このプログラム内で定義しましたが、fname というファイル名を保持するバッファにファイル名を書き込んでいます。 "IMG" という文字に続いて、数字4桁で左側ゼロ埋めで連番をとして、拡張子の ".JPG" を続けています。

ファイル名は 8.3 ルールに従うことになってます。ライブラリが大文字のファイル名を作るので、初めから大文字のファイル名にしておくと良いでしょう。

ファイル名は 8 文字までいけるなら、連番でも 9999 で制限をかける必要もないのですが、一つのディレクトリにあまりに多くのファイルを置くのも好ましくないので切ってます。 ファイル数が多くなるならディレクトリで分けるべきでしょうね。

今回は 9999 を過ぎたらまた 1に戻り、元のファイルを上書きしてしまいます。

O_TRUNC フラグを指定してファイルを開く

次に SD.open メソッドでファイルを開きます。同名のファイルがある場合は、上書きします。

SD.open メソッドはデフォルトの動作で、アペンドモードでファイルを開きます。すなわち、 既存のファイルが存在する場合は、そのファイルの最後につなげる形でデータを書き込みます。

画像ファイルを単純にデータをつなげてもデータが壊れるだけなので、 FILE_WRITE フラグに O_TRUNC フラグを明示的に追加し SD.open を呼び出しています。 O_TRUNC フラグはファイルサイズゼロに切り詰めてから書き込みます。

撮影間隔

loop 関数は 5 秒の delay をしてから抜けます。これによって、撮影間隔が最低でも 5 秒開きます。

実際にはカメラからデータを読み込み、SD カードに書き出す時間が案外長い (数十秒位) ので、だいたい 30 秒間隔位に撮影することになります。

以上で、Arduino Uno と JPEG TTL カメラ、SD カードモジュールを組み合わせて、監視カメラっぽいものが作れました。

1 2

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 基礎からの IoT 入門