WaffleとGroveのシリアルカメラをソフトウェアシリアルで繋ぐ

[こちら](https://qiita.com/mine820/items/8811e198ac7b43e8b475)の記事で書いたように、そう簡単にはWaffleとGroveのシリアルカメラがつながらないことがわかりました。
ならば、なんとかしてつないでやろうじゃないか、という奮闘記がこちらになります。

# 変換モジュールの購入
RS-232とTTLを変換してあげないことにはどうにもならないことはわかったので、その部分を自作しようかと考えたが、ハード素人には敷居が高かったので、すぐに諦めて購入することにしました。

いろいろとネットで探してみたところ、[これ](https://www.robotshop.com/jp/ja/max3232-rs232-to-ttl-adapter.html)が一番お手軽そう。
1個だけ購入すると送料の比率がバカみたいだが、本当に使えるのかもよくわからないので、とりあえず1つ。
※基盤ではなくチップの情報は[こちら](https://www.maximintegrated.com/jp/products/interface/transceivers/MAX3232.html/tb_tab0)

待つこと数日。
無事届きました。
![DSC_0008.JPG](https://qiita-image-store.s3.amazonaws.com/0/130771/6cb3e510-86f1-b321-fb22-e44f861a6714.jpeg)

届いて、意外だったのが、その大きさ。
小さい．．．
いや、いいんですよ、小さくて。

# 接続
さて、ここからひとつひとつ問題を解決していきます。

## 準備
まずは、どうやってWaffleとこの基盤を繋ぐか。また、どうやって、シリアルカメラとこの基盤を繋ぐか。

接続としては、イメージとしてはこんな感じになるはず。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/c680b47a-3bcc-c6d1-15aa-041bb29d184e.png)

実際には、基盤とピンヘッダをくっつけて、ブレッドボードとジャンプワイヤを使って繋げばいいのかな？
てことで、ピンヘッダとブレッドボードとジャンプワイヤを購入することに。
![DSC_0005.JPG](https://qiita-image-store.s3.amazonaws.com/0/130771/e1506e21-ebde-f5ad-9650-3845f7933830.jpeg) ![DSC_0006.JPG](https://qiita-image-store.s3.amazonaws.com/0/130771/8e774e9f-1d90-9fa2-f852-c95856fe59de.jpeg)

嬉しいことに、ジャンプワイヤに「バネ付き」ってのがあって、これがあればピンヘッダがいらない。（はんだ付けもいらない！）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/7b508194-51ad-d39c-97af-4ba2f5d27d01.png)

## 接続
早速イメージに従ってつないでみました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/4d553721-7856-bd5e-316e-f21ed3f0ef48.png)

一応、Groveのケーブルも使用しています。
（端子を間違えないようにするため）

# 実行
プログラムを流し込んで、動きを確かめてみます。
とりあえず画像の取得は行わず、最初のハンドシェイク（SYNC-ACK）のやり取りがちゃんとできているか確認します。

```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=D5,tx=D6

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

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

  initialize();
}
/*********************************************************************/
void loop() {
  // ...
}
/*********************************************************************/
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"
    Serial.println("Waffle[SYNC]->Camera");
    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) 
    {
      Serial.println("Camera[ACK]->Waffle");
      // 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){
        Serial.println("Camera[SYNC]->Waffle");
        break; 
      }
    }
  }  
  // Send "ACK"
  Serial.println("Waffle[ACK]->Camera");
  cmd[1] = 0x0e | cameraAddr;
  cmd[2] = 0x0d;
  sendCmd(cmd, 6); 

  Serial.println("\nCamera initialization done.");
}
```

で、動かしてみたところ、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/d31bd9f5-04cc-9036-e0af-b3ebe0997ac1.png)
つながらない．．．
いろいろ試行錯誤してみますが、つながらない．．．

# 意外な発見
いろいろ調べているうちに、ひょんなことから[こんなサイト](https://www.aliexpress.com/item/New-Color-JPEG-Color-UART-TTL-Serial-Port-Digtial-Camera-Module-with-OV528-communicaiton-protocol/32763627374.html)を発見。
全く同じ基盤に見えますが、インターフェースはTTLとなっています。
下の方にコネクタピンの順番が書いてありますが、これも違っている．．．

物は試しと、つないで見ました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/075d9264-e91e-03f8-09c5-7bf3906adde0.png)

すると．．．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/982dc333-eead-9e29-faae-bdf397e2af89.png)
つながった！！！

<font color="FF0000">**このカメラ、RS-232ではなくてTTLでした！
しかもピンの並びが違う！！**</font>

【注意】カメラ同包のケーブルで繋がりそうですが、向きを間違えると基盤から煙が出て壊れてしまいますので、十分確認してから試してください。
（受け側にノッチがないので、反対向きにも刺せてしまいます（間違った向きのほうが刺さりやすいです（苦笑）））
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/1cfc6e81-d6c7-adf7-01cc-ef0abc2cf1a5.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/62eb0c58-26cc-ccfc-0141-69b230fe946b.png)
この並びが正解です。
（Waffle（Arduino）側のRX,TXの設定を間違えないように）

# 結果
無事つながりました。
MAX3232とかいらなかったです。
でもそれらで試せたからわかったと言えるのかも。

わかってしまえば簡単だったのですが、ずいぶん遠回り（無駄な時間とコスト）をかけてしまいました．．．