WaffleにGroveのシリアルカメラキットを接続したかったが、そのままではつながらないことがわかった

Arduino互換ボード『Waffle』にGroveのシリアルカメラキットをつなごうとしているがうまくいかないので、その奮闘記をログとして残しておきます。

**【注意】うまくいく方法がわかりました。[こちら](https://qiita.com/mine820/items/d8e3069eedd7eed99f51)の記事を参照してください。（以下の情報には間違いがあります）**

# Waffleとは
[こちら](https://qiita.com/mine820/items/5feb63c095d8f4a2e0e4)を参照のこと。

# シリアルカメラモジュールとは
[こちら](http://wiki.seeedstudio.com/Grove-Serial_Camera_Kit/)を参照のこと。

# 接続ポート
今回は、WaffleのD5ポートに繋ぐこととします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/0997669d-4c5e-c4d4-8236-ae83e573b689.png)

使用するケーブルは、シリアルカメラキットに含まれているものではなく、ストレートです。
この件に関しては[こちら](https://qiita.com/mine820/items/e2e3b0fe0f8489210184)を参照してください。

接続後はこんな感じになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/e1db6c59-2df3-e093-7b7e-dfda30a1facf.png)

# プログラム
カメラとの接続は、ハードウェアリシアルではなくて、ソフトウェアシリアルを使用します。

```c
#include <SoftwareSerial.h>

#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(5, 6);  //rx,tx

const byte cameraAddr = (CAM_ADDR << 5);  // addr
```

WaffleのD5ポートは、D5がPD5に、D6がPD6につながっていますので、カメラ側の「送信」「受信」に合わせて、受信をD5、送信をD6とします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/d4e16c77-5054-3200-ec27-80372958d844.png)

次に、初期化（setup()）で、カメラの初期化を行います。

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

  initialize();
}
```

まず、PCへのモニター出力の通信速度を115,200bpsで設定しています。（これは特に意味はありません）
次に、カメラと接続しているソフトウェアシリアルの通信速度を9,600bpsに設定しています。
カメラの仕様上は115,200bpsまで行けそうですが、今回の接続はUARTではない（RS-232を使用）ので9,600bpsにしておきます。

```c
/*********************************************************************/
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) 
  {
    // Send "SYNC"
    sendCmd(cmd,6);
    // Read "ACK"
    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) 
    {
      // Read "SYNC"
      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; 
    }
  }  
  // Send "ACK"
  cmd[1] = 0x0e | cameraAddr;
  cmd[2] = 0x0d;
  sendCmd(cmd, 6); 
  //Serial.println("\nCamera initialization done.");
}
```

初期化の関数内で、カメラとハンドシェイクを行っています。
　Waffle「SYNC」→カメラ「ACK」→カメラ「SYNC」→Waffle「ACK」
となっています。

# 問題発生
ところがこの初期化処理がうまく動きません。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/9d10309d-f124-8cae-d8c7-fdbd1ae86aa8.png)

残念ながら、現状は、Waffleから「SYNC」を送り、カメラから返事（6バイト）が返ってきているのですが、なぜかすべて0になっています。（0x00が6つ）
これは正式な電文ではないので、どこかでうまく受け取れていないようです。

ただ、ちゃんと6バイト返している（返してきているバイト数は確認済み）ところから考えて、以下の可能性があると予想しています。

- ビットが立っている（5V）はずが立っていなくて（電圧が低くて）、0と判断されている（ハード側の問題）

## RS-232
そもそも、カメラ側のインターフェースはRS-232なのですが、こちらの規格は以下のような電圧差でビットのON/OFFを判断しています。
![http://www.automationmedia.com/Images/KB_RS232_signals.gif](https://qiita-image-store.s3.amazonaws.com/0/130771/fa8c5e2f-c174-6bc7-8eb9-2e39c8cbd50c.png)

つまり、+3V～+13Vだったら0、-3V～-13Vだったら1ということになります。（※出力の場合は+5V～+15Vが0、-5V～-15Vが1）
ちなみに、Groveは0V～0.8Vが0で+2V～+5Vが1になります。

つまり、Waffleからカメラへの送信信号はなんとかカメラ側で読めるのですが、カメラ側からWaffle側への送信信号は読めないということになります。

この間の変換（RS-232－TTL変換）を行うのが[MAX232](https://www.maximintegrated.com/jp/products/interface/transceivers/MAX232.html)等のチップになるようです。

# 結論
ということで、間に変換をかまさないとダメのようです。

※工作は辛いから、[こんな感じ](https://www.robotshop.com/jp/ja/max3232-rs232-to-ttl-adapter.html?gclid=Cj0KCQjwuafdBRDmARIsAPpBmVVJSkpI9KXu3GVk1rVe6LYkZtIAM3HW9kqDoNU52Ss5fGi1nqkz_6IaAuzzEALw_wcB)のものを利用すればいいのかな？