🤣

機材費8000円で始めるIoTカメラ入門(ArduCam編)

2024/02/17に公開

はじめに

記事をご覧くださりありがとうございます。
フリーランス学生エンジニアのたつのぶです🐉

今回の記事は、「機材費8000円で始めるIoTカメラ入門」
ということで、だいたい5秒おきに画像を送信するIoTカメラを作ってみた内容になっています。
機材リストやソースコードも載せているので気軽にレッツTry✌~~

それでは本題に入っていきます。

利用例

  • 防犯カメラ
  • 子供の見守りカメラ
  • ペットのリモート監視
  • etc...

できたもの

※システムの構成図

※実際にブラウザから見たイメージです。

5秒おきにサーバデータを更新する仕様になっています✋
※配線したイメージです。

①機材を調達しよう・配線しよう!

機材名 価格
ESP32-DevKitC-32E ESP32-WROOM-32E開発ボード 4MB ¥1,600
500万画素オートフォーカスSPIカメラモジュール ¥6,480

②ESP32のファームウェアを書き込む

自分の環境に合わせて下記3つを変更ください。
const char* ssid = "ssidkey";←接続するWIFIのSSIDを記述
const char* password = "pass";←接続するWIFIのパスワードを記述
onst char* URL = "endpoint"; ←送信先サーバのURLを記述

base64形式で画像データとして送信しています。

ソースコード
camFirm.ino
#include <WiFi.h>
#include <HTTPClient.h>
#include "Arducam_Mega.h"
const char* ssid = "ssidkey";
const char* password = "pass";
const char* URL = "endpoint";
CAM_IMAGE_MODE imageMode = CAM_IMAGE_MODE_QVGA;
const int CS_PIN = 17;
Arducam_Mega myCAM(CS_PIN);
void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi...");
    }
    Serial.println("Connected to WiFi");
    myCAM.begin();
}
void svrPost(String postdata){
  if(WiFi.status()== WL_CONNECTED){   //Check WiFi connection status     
           HTTPClient http;   
           http.begin(URL);  //Specify destination for HTTP request
           http.addHeader("Content-Type", "text/plain");             //Specify content-type header
           int httpResponseCode = http.POST("{ \"img\": \"" + String(postdata) + "\"}");   //Send the actual POST request
           if(httpResponseCode>0){
              String response = http.getString();                       //Get the response to the request
              Serial.println(httpResponseCode);   //Print return code
              Serial.println(response);           //Print request answer
           }else{
              Serial.print("Error on sending POST: ");
              Serial.println(httpResponseCode);
           }
           http.end();  //Free resources
       }else{
           Serial.println("Error in WiFi connection");   
       }
}
String ImageToBase64()
{
  int i = 0;
  String encodedData = "";
  uint8_t imageData = 0;
  uint8_t imageDataNext = 0;
  uint8_t headFlag = 0;
  // 画像撮影
  myCAM.takePicture(imageMode, CAM_IMAGE_PIX_FMT_JPG);
  size_t bufferSize = myCAM.getReceivedLength(); // 画像データの残りサイズを取得
  uint8_t* buffer = new uint8_t[bufferSize];
  while (myCAM.getReceivedLength())
  {
    imageData = imageDataNext;
    imageDataNext = myCAM.readByte();
    if (headFlag == 1)
    {
      buffer[i++] = imageDataNext;
      if (i >= bufferSize)
      {
        // エラー処理を追加
        Serial.println("バッファサイズが不足しています!");
        delete[] buffer; // メモリ解放
        return "";
      }
    }
    if (imageData == 0xff && imageDataNext == 0xd8)
    {
      headFlag = 1;
      buffer[i++] = imageData;
      buffer[i++] = imageDataNext;
    }
    if (imageData == 0xff && imageDataNext == 0xd9)
    {
      headFlag = 0;
      // BASE64 エンコードして文字列に追加
      encodedData += base64::encode(buffer, i);
      i = 0;
      break;
    }
  }
  // メモリ解放
  delete[] buffer;
  return encodedData;
}
void loop() {
  svrPost(ImageToBase64());
  delay(5000);  // 5秒ごとにキャプチャしてPOST
}

③画像保存用のサーバスクリプトを実装

たった五行の記述でサーバに画像を保存することができます🤗
今回は、指定ディレクトリにtest.jpgで毎回保存していましたが、保存ファイル名をタイムスタンプにすることで画像を蓄積させることも可能です!また、DBに保存するのもいいかもしれません。

ソースコード
img_rec.php
<?php
  $postdata = file_get_contents('php://input');
  $datajson = (array)json_decode($postdata, true);
  $data =  $datajson['img'];
  $img = base64_decode($data);
  file_put_contents('./folder/test.jpg', $img);
?>

④画像表示用のHTMLコードを実装

ソースコード
view_cam.html
<!DOCTYPE html>
<html>
  <head>
   <title>CAM View</title>
    <script>
      document.addEventListener('DOMContentLoaded', function(){
        const RELOAD_SPAN = 2000;
        function reload(){
          document.getElementById('figure').src = './folder/test.jpg' + '?' + Date.now();
	  //画像を回転する場合に利用↓
          //var d = 180;
          //var e = document.getElementById("figure");
          //e.style.transform = "rotate(" + d + "deg)";
        }
        setInterval(reload, RELOAD_SPAN);
      });
    </script>
  </head>
  <body>
    <h1>CAM View</h1>
    <img id="figure" width="50%" height="50%" src="./folder/test.jpg"><br>
  </body>
</html>

最後に

いかがだったでしょうか。
受信側をpythonにすることでAI画像処理もできます💪
改良して試してみてください🤗

Discussion