4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Groveのシリアルカメラ「OV528」を調べてみる

Last updated at Posted at 2018-09-17

Arduinoにシリアルカメラ「OV528」をGroveコネクタ経由で接続しようとしたところ、そう簡単にはつながらないことがわかったので、とりあえず調べた内容をメモとして残しておきます。

【後日談】無事繋がりましたので、こちらをご参照ください

ちなみに、使用するArduinoはDuemilanove互換のボードで、センサー等とのコネクタはGroveのみです。
image.png

よくあるサンプルコード

調べるとまず見つかるのはこのgithubページ
ここには2種類のソースコードが載っており、1つはハードウェアシリアル用、もう一つがソフトウェアシリアル用。
ただどちらも、ArduinoからSDカードシールドを経由して、カメラとプッシュボタンをつなぐという仕組みは一緒。
image.png

いや、私がやりたいことではSDカードやプッシュボタンは必要ない! なんてことができない。
ここから調べまくりです。

こちらにハードウェアシリアルでのサンプルがあるのですが、私の環境(ESP32ではない)ではうまく動かず...

イメージとしては、ソフトウェアシリアルを使って、カメラから画像を取得します

#include <SoftwareSerial.h>

#define PIC_PKT_LEN    128        //data length of each read, dont set this too big because ram is limited
#define PIC_FMT_VGA    7
#define PIC_FMT_CIF    5
#define PIC_FMT_OCIF   3
#define CAM_ADDR       0
#define CAM_SERIAL     softSerial

#define PIC_FMT        PIC_FMT_VGA

SoftwareSerial softSerial(9, 10);  //rx,tx ※この番号で合っているのか怪しい

const byte cameraAddr = (CAM_ADDR << 5);  // addr
unsigned long picTotalLen = 0;            // picture length

/*********************************************************************/
void setup() {
  Serial.begin(115200);
  CAM_SERIAL.begin(9600);       //cant be faster than 9600, maybe difference with diff board.

  initialize();
}
/*********************************************************************/
void loop() {
  int n = 0;
  while(1){
      {
        delay(200);
        if (n == 0) preCapture();
        Capture();
        GetData();
      }
      n++ ;
    }
}
/*********************************************************************/
void clearRxBuf()
{
  while (CAM_SERIAL.available()) 
  {
    CAM_SERIAL.read(); 
  }
}
/*********************************************************************/
void sendCmd(char cmd[], int cmd_len)
{
  for (char i = 0; i < cmd_len; i++) CAM_SERIAL.write(cmd[i]); 
}
/*********************************************************************/
int readBytes(char *dest, int len, unsigned int timeout)
{
  int read_len = 0;
  unsigned long t = millis();
  while (read_len < len)
  {
    while (CAM_SERIAL.available()<1)
    {
      if ((millis() - t) > timeout)
      {
        return read_len;
      }
    }
    *(dest+read_len) = CAM_SERIAL.read();
    Serial.write(*(dest+read_len));
    read_len++;
  }
  return read_len;
}
/*********************************************************************/
void initialize()
{   
  char cmd[] = {0xaa,0x0d|cameraAddr,0x00,0x00,0x00,0x00} ;  
  unsigned char resp[6];

  Serial.print("initializing camera...");
  
  while (1) 
  {
    sendCmd(cmd,6);
    if (readBytes((char *)resp, 6,1000) != 6)
    {
      Serial.print(".");  // ※ここから進まない
      continue;
    }
    if (resp[0] == 0xaa && resp[1] == (0x0e | cameraAddr) && resp[2] == 0x0d && resp[4] == 0 && resp[5] == 0) 
    {
      if (readBytes((char *)resp, 6, 500) != 6) continue; 
      if (resp[0] == 0xaa && resp[1] == (0x0d | cameraAddr) && resp[2] == 0 && resp[3] == 0 && resp[4] == 0 && resp[5] == 0) break; 
    }
  }  
  cmd[1] = 0x0e | cameraAddr;
  cmd[2] = 0x0d;
  sendCmd(cmd, 6); 
  //Serial.println("\nCamera initialization done.");
}
/*********************************************************************/
void preCapture()
{
  char cmd[] = { 0xaa, 0x01 | cameraAddr, 0x00, 0x07, 0x00, PIC_FMT };  
  unsigned char resp[6]; 
  
  // ※省略
}
void Capture()
{
  char cmd[] = { 0xaa, 0x06 | cameraAddr, 0x08, PIC_PKT_LEN & 0xff, (PIC_PKT_LEN>>8) & 0xff ,0}; 
  unsigned char resp[6];

  // ※省略
}
/*********************************************************************/
void GetData()
{
  unsigned int pktCnt = (picTotalLen) / (PIC_PKT_LEN - 6); 
  if ((picTotalLen % (PIC_PKT_LEN-6)) != 0) pktCnt += 1;
  
  char cmd[] = { 0xaa, 0x0e | cameraAddr, 0x00, 0x00, 0x00, 0x00 };  
  unsigned char pkt[PIC_PKT_LEN];

  // ...
}

しかし、初期化ができない...
image.png

同じことで悩んでいる人、および、解決方法を探す

が、見つからない。

Arduino Duemilanoveのページをよくよく読み直してみると、Serialポートは1つ(0, 1 pin)しかなさそう。
ということで、他のデジタルポートで繋げないか、調査を続行。

更に調べていくと、ソフトウェアシリアルで頑張ろうとしている人を発見
そこで「RS-232CではなくでTTLでつなげ」的な文章を見つけました。
「MAX232」???
コレが使えるぐらいなら、Groveを選ばないし...ということで、ここでくじける..._| ̄|○

別の方法を探すが...

初心に返り、カメラの仕様を探します。
カメラの型番は「OV528」なので、これが仕様のドキュメントとなります。

※この資料はプロトコルの資料なので、ここより本来の目的から脱線していきます

コマンド

OV528には11のコマンドが用意されています。
image.png
詳細はドキュメントを参照してください。

ちなみに、エラーだった場合のコードは以下のようになっているようです。
image.png

ハンドシェイク

ホスト側から「SYNC」を送ると、カメラ側から「ACK」が返ってきて、さらにカメラ側から「SYNC」が送られてくるので、ホスト側から「ACK」を返すと接続OKです。
(ホストから25回ぐらい「SYNC」を送らないと「ACK」が返ってこないらしい)

それ以外のコマンドは、ホスト側から送ればちゃんと返事が返ってくるようです。

画像の取得(RAWデータ)

画像取得の手順は以下のとおりです。

  1. Initial(Preview, VGA)
  2. Snapshot(uncompressed picture)
  3. Get picture(Snapshot picture)
    ※ここでデータが送られてくる
  4. ACK

なお、画像には「Snapshot」と「Preview」があり、上記の流れはSnapshotの場合で、Previewの場合は「2. Snapshot」を省略し、「4. ACK」のあとに「3. Get Picture」を繰り返せばOK。

で、何だったっけ?

調べたかったのはコマンドではなくてつなぎ方だったのですが、単純な話ではなさそうなので、もうちょっと頑張ってみることにします。
いい手をご存知の方、アドバイスを頂けると助かります!
【未完】

参考サイト

https://os.mbed.com/media/uploads/jplunkett/cj-ov528_protocol.pdf
https://forum.arduino.cc/index.php?topic=293520.0
https://dotstud.io/blog/nefrybt-pepper-monitoring-system/
https://github.com/Seeed-Studio/Grove_Serial_Camera_Kit
http://wiki.seeedstudio.com/Grove-Serial_Camera_Kit/

4
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?