工作と競馬2

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

SORACOMのIoT SIM plan-D D-300MBとLTE-M Shield for Arduinoを使ってみる(2) --- ESP-WROOM-32との組み合わせ ---

概要

LTE-M Shield for ArduinoをESP-WROOM-32と組み合わせ、動作を確認した。画像の送信がどうにか行えそうな見通しが立った。

  • 2021/09/18追記
    • BG96へ一度に書き込むデータ量
    • BG96とのボーレート変更



背景と目的

前回、SORACOMのIoT SIM plan-D D-300MBとLTE-M Shield for Arduinoを使って、データを送信することができた。今回は、ESP-WROOM-32(以下、ESP32)と組み合わせて、大きいサイズのデータを送れるか動作を確認する。



詳細

0. やりたいこと

  • LTE-M Shield for Arduinoとの間のシリアルのボーレートを115200bpsまで上げられるかを確認する
  • 画像ファイル等を想定した数100kB程度のデータが送信できるか確認する


1. 配線

ピンク字が接続先ESP32側端子の名前。基本的に電源とリセット端子とシリアル用GPIOだけ。GPIO16,17は、後述のHardwareSerialで使用する。

dragino/NB-IoT回路図より抜粋


2. LTE-M Shield for Arduinoとの間のシリアルのボーレートをどのくらいまで上げられるか

前回、ArduinoUNOとの組み合わせでは57600bpsまで(SoftwareSerial使用)しか使えなかった。なので、ESP32と組み合わせてどのくらいまで使えるか試したところ、

HardwareSerialを使うことで、230400bpsで通信可能 (2021/09/18更新)

ということが分かった。関連するソースコードだけ抜き出せば、

#define BAUDRATE 230400 // 2021/09/18更新
#include <HardwareSerial.h>

// オブジェクト作成
HardwareSerial LTE_M_shieldUART(2);

// シリアルポートを渡す
TinyGsm modem(LTE_M_shieldUART);

となる。ちなみに、SoftwareSerialでは、うまくいかなかった。低速なら動くかもしれないが。

また、230400bps以外に460800、921600を試してみたところ、うまく書き込めないのだが、ボーレート設定に対するレスポンスではOKが返ってきているので、もしかするとハードウェア周りを注意して実装すれば通信可能かもしれない。(今は実験のため、ブレッドボードや10cm弱の配線を使ってやっている。)


3. 画像ファイル等を想定した数100kB程度のデータが送信できるか確認する

LTE-M Shield for Arduinoを使ってやりたいこととして、カメラで撮影した画像の送信を考えている。以前作成した成長記録用カメラでは、1枚あたり200-300kBの画像となるのでこのくらいのサイズのデータを送信できるか試しておきたい。

今回は、カメラを動かす環境がないので、疑似画像データとして300kB程度の適当なjpgファイルのデータをソースコードに埋め込んで、それを読み取って送信してみることにした。条件は以下。

  • 送信先: SORACOM Beamエンドポイント
  • SORACOM Beamからの転送先: AWS

3.1 結果まとめ

  1. ESP32からLTE-M Shield for Arduinoへシリアルで送る際、1度に送信できるサイズは1460byte(2021/09/18更新)が限界らしい
  2. それ以上のデータを送りたい場合は、Serial.writeとSerial.flushを組み合わせて分割して書き込むとうまくいく(実はこのときも同じ問題にぶつかったためそのノウハウを活用)。しかし、細切れで渡すことで、ESP32からLTE-M Shield for Arduinoの実質の通信速度がだいたい10kB/s弱となった。(2021/09/18更新)
  3. レスポンスステータスコードが400になるが、SORACOM Beamからの転送先のAWSではちゃんとデータが受け取れている

3.2 分割して書き込む

今回画像データを送信するためBody部分が数100kBと大きい。(payloadという変数に入っている)したがって、以下のようにBody部分を1460byte(2021/09/18更新)に細切れにして送信している。

  /* connect */
  // 8888はSORACOM Beamエンドポイントの都合
  if (!ctx.connect(ENDPOINT, 8888)) {
    CONSOLE.println(F("failed."));
    delay(3000);
    return;
  }

  size_t contentLength = strlen(payload);
  CONSOLE.println(contentLength);
  
  /* send request */
  char hdr_buf[511];
  ctx.println(F("POST / HTTP/1.1"));
  sprintf_P(hdr_buf, PSTR("Host: %s"), ENDPOINT);
  ctx.println(hdr_buf);
  ctx.println("Connection: Close");
  ctx.println(F("Content-Type: application/json"));
  sprintf_P(hdr_buf, PSTR("Content-Length: %d"), contentLength);
  ctx.println(hdr_buf);
  ctx.println();
  // ボディ
  // 一度に大きなデータをprintlnするとうまくいかない
  // mバイトに分割してwriteする
  int m = 1460; // 1460byteが限界(2021/09/18更新)
  int i, j = 0;
  uint8_t * p = (uint8_t *) malloc(m);
  while (true) {
    for (i = 0; i < m; i++) {
      p[i] = payload[i + j * m];
      if (i + j * m == contentLength - 1) break;
    }
    ctx.write(p, m);
    ctx.flush();
    // CONSOLE.printf("j=%d, length=%d\n", j, i); // 確認用
    if (i + j * m == contentLength - 1) break;
    j++;
  }
  // 空行を最後に
  ctx.println(); // 2つprintlnがないとだめ 
  ctx.println(); 

3.3 一度に書き込めない理由

推測だが、LTE-M Shield for Arduinoの受信バッファのサイズではないかと考える。

https://auroraevernet.ru/upload/iblock/538/538e779e251d00d8aa99ebad4c479d5c.pdf

これかも。AT+QISENDコマンドで、1460byteまでしか一度に送信できなそう?

2021/09/18 その通りだった。

3.4 レスポンスステータスコードが400

AWS側では正しく処理されているので、SORACOM Beamエンドポイントとして400を返しているように見える。送信できてしまったので、今回はとりあえずいいとして、いずれは解決したい。



まとめと今後の課題

LTE-M Shield for ArduinoとESP32を組み合わせて、シリアルの速度、大きなサイズのデータ送信を確認できた。通信速度が遅いことが課題としてあるので、今後解決できないか継続的に取り組む必要がある。ひとまず、通信速度は満足できるレベルではないが、一応どうにか画像の送信が実用になりそうなので、OKとする。(2021/09/18更新)