質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.58%

Arduinoカメラで撮影した画像を3G回線でサーバーにアップロードする監視カメラを作りたい

受付中

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 3,775

前提・実現したいこと

10分毎にカメラで撮影しSDカードに保存、その画像を3G回線で
サーバーにアップロードする監視カメラのような装置を作りたいと考えています。

発生している問題・エラーメッセージ

・ファイル名は変更されていくが、プログラムを立ち上げて一ループ目にに撮影した画像をアップロードし続ける。

・長い時間ループを回すとhttpPOST error1...が出てくる。

・アップロードされた画像にノイズが入る。

該当のソースコード

// This is a basic snapshot sketch using the VC0706 library.
// On start, the Arduino will find the camera and SD card and
// then snap a photo, saving it to the SD card.
// Public domain.

// If using an Arduino Mega (1280, 2560 or ADK) in conjunction
// with an SD card shield designed for conventional Arduinos
// (Uno, etc.), it's necessary to edit the library file:
//   libraries/SD/utility/Sd2Card.h
// a non-Mega, Uno-style board.

#include <Adafruit_VC0706.h>
#include <SPI.h>
#include <SD.h>

//3GIM header
#include "a3gim2.h"

// comment out this line if using Arduino V23 or earlier
//#include <SoftwareSerial.h>         

// uncomment this line if using Arduino V23 or earlier
// #include <NewSoftSerial.h>       

// SD card chip select line varies among boards/shields:
// Adafruit SD shields and modules: pin 10
// Arduino Ethernet shield: pin 4
// Sparkfun SD shield: pin 8
// Arduino Mega w/hardware SPI: pin 53
// Teensy 2.0: pin 0
// Teensy++ 2.0: pin 20
#define chipSelect 53

//3GIM
#define BODY_BUFFER 950
char body[BODY_BUFFER]; // バッファ
#define IMGEQ "img="

// POST send parameter
const char *server = "**********.jp"; // サーバ名
const char *path = "*******.php"; // PHPファイル

// 送信書式
const char *header = "Content-Type: application/x-www-form-urlencoded";
const int port =  80;

int IS=strlen(IMGEQ);
char res[100];

// Pins for camera connection are configurable.
// With the Arduino Uno, etc., most pins can be used, except for
// those already in use for the SD card (10 through 13 plus
// chipSelect, if other than pin 10).
// With the Arduino Mega, the choices are a bit more involved:
// 1) You can still use SoftwareSerial and connect the camera to
//    a variety of pins...BUT the selection is limited.  The TX
//    pin from the camera (RX on the Arduino, and the first
//    argument to SoftwareSerial()) MUST be one of: 62, 63, 64,
//    65, 66, 67, 68, or 69.  If MEGA_SOFT_SPI is set (and using
//    a conventional Arduino SD shield), pins 50, 51, 52 and 53
//    are also available.  The RX pin from the camera (TX on
//    Arduino, second argument to SoftwareSerial()) can be any
//    pin, again excepting those used by the SD card.
// 2) You can use any of the additional three hardware UARTs on
//    the Mega board (labeled as RX1/TX1, RX2/TX2, RX3,TX3),
//    but must specifically use the two pins defined by that
//    UART; they are not configurable.  In this case, pass the
//    desired Serial object (rather than a SoftwareSerial
//    object) to the VC0706 constructor.

// Using SoftwareSerial (Arduino 1.0+) or NewSoftSerial (Arduino 0023 & prior):
#if ARDUINO >= 100
// On Uno: camera TX connected to pin 2, camera RX to pin 3:
SoftwareSerial cameraconnection = SoftwareSerial(69, 3);
// On Mega: camera TX connected to pin 69 (A15), camera RX to pin 3:
//SoftwareSerial cameraconnection = SoftwareSerial(69, 3);
//#else
//NewSoftSerial cameraconnection = NewSoftSerial(2, 3);
#endif

Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);

// Using hardware serial on Mega: camera TX conn. to RX1,
// camera RX to TX1, no SoftwareSerial object is required:
//Adafruit_VC0706 cam = Adafruit_VC0706(&Serial1);

 int file_count = 1;
  char filename[16];


void setup() {

  // When using hardware SPI, the SS pin MUST be set to an
  // output (even if not connected or used).  If left as a
  // floating input w/SPI on, this can cause lockuppage.
#if !defined(SOFTWARE_SPI)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  if(chipSelect != 53) pinMode(53, OUTPUT); // SS on Mega
#else
  if(chipSelect != 10) pinMode(10, OUTPUT); // SS on Uno, etc.
#endif
#endif

  Serial.begin(9600);

  //-------------- 3GSA接続 ------------
  Serial.println("-----------------");
  Serial.println("3gsa ready : Wait about 40 sec...");
  while( !(a3gs.start() == 0 && a3gs.begin()==0))
  {
    Serial.print(".");
    delay(1000);
    }
  Serial.println("3gsa connected");
  Serial.println("-----------------");
  Serial.println("VC0706 Camera snapshot ");


  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }  


  // Try to locate the camera
  if (cam.begin()) {
    Serial.println("Camera Found:");
  } else {
    Serial.println("No camera found?");
    return;
  }
  // Print out the camera version information (optional)
  char *reply = cam.getVersion();
  if (reply == 0) {
    Serial.print("Failed to get version");
  } else {
    Serial.println("-----------------");
    Serial.print(reply);
    Serial.println("-----------------");
  }


  // Set the picture size - you can choose one of 640x480, 320x240 or 160x120 
  // Remember that bigger pictures take longer to transmit!

  //cam.setImageSize(VC0706_640x480);        // biggest
  cam.setImageSize(VC0706_320x240);        // medium
  //cam.setImageSize(VC0706_160x120);          // small

  // You can read the size back from the camera (optional, but maybe useful?)
  uint8_t imgsize = cam.getImageSize();
  Serial.print("Image size: ");
  if (imgsize == VC0706_640x480) Serial.println("640x480");
  if (imgsize == VC0706_320x240) Serial.println("320x240");
  if (imgsize == VC0706_160x120) Serial.println("160x120");

  Serial.println("Snap in 3 secs...");
  delay(3000);


   while(1){//-------------- ループ開始 ------------

  if (! cam.takePicture()) 
    Serial.println("Failed to snap!");
  else 
    Serial.println("Picture taken!");


 sprintf(filename, "IMG%02d.JPG", file_count++); 


                    if( file_count > 10){
                      file_count = 1; // Overwrite 
                      }

  // Open the file for writing
  File imgFile = SD.open(filename, FILE_WRITE| O_TRUNC);

  // Get the size of the image (frame) taken  
  uint16_t jpglen = cam.frameLength();
  Serial.print("Storing ");
  Serial.print(jpglen, DEC);
  Serial.print(" byte image.");

  int32_t time = millis();
  pinMode(8, OUTPUT);
  // Read all the data up to # bytes!
  byte wCount = 0; // For counting # of writes
  while (jpglen > 0) {
    // read 32 bytes at a time;
    uint8_t *buffer;
    uint8_t bytesToRead = min(32, jpglen); // change 32 to 64 for a speedup but may not work with all setups!
    buffer = cam.readPicture(bytesToRead);
    imgFile.write(buffer, bytesToRead);
    if(++wCount >= 64) { // Every 2K, give a little feedback so it doesn't appear locked up
      Serial.print('.');
      wCount = 0;
    }
    //Serial.print("Read ");  Serial.print(bytesToRead, DEC); Serial.println(" bytes");
    jpglen -= bytesToRead;
  }
  imgFile.close();

//------------ SDメモリー読込み3GSA書出し --------------
  File fp = SD.open(filename ,FILE_READ| O_TRUNC);
  int len = sizeof(res);
  int i=strlen(IMGEQ);
  sprintf(body,"%s",IMGEQ);//POST引き渡し変数名設定
  uint8_t b;

  while(fp.available()) {//------------読み取り可能なbyteがある場合入る --------------
     b = fp.read();
     body[i++] = b/16 + (b/16>9?'A'-10:'0'); // バイナリ―から文字変換(上位)
     body[i++] = b%16 + (b%16>9?'A'-10:'0'); // バイナリ―から文字変換(下位)
     delay(10); 
     //time = millis() - time;
         if( i>=BODY_BUFFER ) {
               if(a3gs.httpPOST(server,port,path,header,body,res,&len,false)!=0)
                    Serial.println("httpPOST error1...");
                    else Serial.print(".");
               i=strlen(IMGEQ);
               sprintf(body,"%s",IMGEQ); //POST引き渡し変数名設定
                     }
      }
fp.close();

if(i>strlen(IMGEQ)) {
  body[IS +i] = 0x00 ; // 残りバッファの3GSA書出し
  if(a3gs.httpPOST(server,port,path,header,body,res,&len,false)!=0)
     Serial.println("httpPOST error2..."); else Serial.print(".");
      }

  sprintf(body,"img=%s",filename); // ファイル名の書出し(php側でファイル名変更)

  if(a3gs.httpPOST(server,port,path,header,body,res,&len,false)!=0){
     Serial.println(" file name send error");
     }else {
      Serial.print(" Completed send '"); Serial.print(filename); Serial.println("' file");
      }

  Serial.println("done!");
  Serial.print(time); Serial.println(" ms elapsed");

  cam.reset();

  delay(600000);
  }

}

void loop() {
}

試したこと

・最初はループ関数の中で、写真撮影→SDに保存→サーバーにpostといった流れで
処理させていましたが、サーバーへのpostが上手くいかないようでhttpPOST error1...となりアップロードできませんでした。

・バッファサイズを半分にしたり大きくしたりと試してみましたが、結果は変わりませんでした。

補足情報(言語/FW/ツール等のバージョンなど)

・マイコン:Arduino mega2560
・カメラ:TTLシリアルJPEGカメラ
・3Gモジュール:3GIM、3Gシールド

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

0

ソースを見て気になるのが"loop"内で10分毎の処理をせず、"setup"でdelay(600000)なんて処理をしている点。

まず問題を切り分ける必要が。

あくまでも"setup"は初期化処理。
SDの処理なども"loop"内で。定期的にサーバーと通信できているか?が問題の気がします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/02 08:57

    ご回答ありがとうございます。

    やはりsetup内でloopさせるのは無茶ですね。
    loop内で処理させるようにもう一度考えてみます。

    キャンセル

0

私も同じ事を現在しています。

恐らく#define BODY_BUFFER 950の値が大きいかもしれません。
3GIMは1024バイトしか一度に送信出来ません。
HEX値の2バイト文字列に変換しているので、2048バイト送信を送信していると思います。

BODY_BUFFERの値をまずは100とかにして試してみてはいかがでしょうか?

しかし、このhttpPOSTに時間がかかるのが大変です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/03 08:55

    ご回答ありがとうございます。ご連絡が遅くなり、申し訳ありません。

    BODY_BUFFERの値を100から10ずつ徐々に上げて動作を見ていますが、httpPOST error1...がでてしまいpost出来ていないようです。

    送信する画像の容量など関係するのでしょうか?

    キャンセル

  • 2017/08/03 09:08

    まずは、問題の切り分けが必要なので、a3gim2.cppの35行目にあるデバッグフラグを立ててログを確認してみてはいかがでしょうか?

    #define DEBUG 1

    760行目からhttpPOSTに関する処理があるので、
    どこでエラーになっているか分かるかと思いますよ。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.58%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • Cに関する質問
  • Arduinoカメラで撮影した画像を3G回線でサーバーにアップロードする監視カメラを作りたい