LoginSignup
1
4

More than 1 year has passed since last update.

[IoT] esp32 + SIM7600でネット通信

Last updated at Posted at 2022-09-05

問題

esp32を使ってSIMカード経由でネット通信がしたい

解決

T-PCIE 4MB 9102

esp32のベースモジュール

T-PCIE-SIM7600JC-H

SIMカードを刺す通信モジュール
ベースモジュールに差し込んでビスで留める

ATコマンド

製造元のページよりユーザー登録して、ログインして、これらのPDFをダウンロードする

  • SIM7500_SIM7600 Series_AT Command Manual_V3.00
  • SIM7500_SIM7600_Series_HTTP(S)_Application Note_V3.00
  • SIM7600_Series_PCIE_Hardware_Design_V1.03

参考

サンプルコード(VS Codeでplatform.ioを使っている)

どうも巷にあるサンプルコードではOCN ONEモバイルには素直に繋がらなかった

AT+COPS?で通信業者を探してから、AT+COPS=でちゃんとしてやらないとどうもネットワークを検索するばかりで繋がらなかった
一度つなげてしまえば、その後は巷にあるサンプルでも動き出す(というか多分設定がSIMに保存される?のでネットワークがすぐに見つかってる感じ?)

AT+COPS=で通信業者を自前で設定するコード

まず初回はこれでIPアドレスが取れるまでは確認しておく
ATコマンドの流れはここを参考にした

upload_port = /dev/cu.wchusbserial537D0225881は自分のものに変える

platformio.ini
; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
upload_port = /dev/cu.wchusbserial537D0225881
monitor_speed = 115200
build_flags = -DCORE_DEBUG_LEVEL=5
lib_deps = 
	vshymanskyy/TinyGSM@^0.11.5
	vshymanskyy/StreamDebugger@^1.0.1
main.cpp
#define SerialMon Serial
#define SerialAT Serial1

static const char *TAG = "SIM LTE";
const char *apn = "ocn.ne.jp";
const char *gprsUser = "mobileid@ocn";
const char *gprsPass = "mobile";

#define uS_TO_S_FACTOR 1000000ULL
#define TIME_TO_SLEEP 60

#define PIN_TX 27
#define PIN_RX 26
#define UART_BAUD 115200
#define PWR_PIN 4
#define LED_PIN 12
#define POWER_PIN 25
#define IND_PIN 36

// https://github.com/vshymanskyy/TinyGSM#diagnostics-sketch
// デバッグログを出す(TinyGsmClient内に記載)
#define TINY_GSM_DEBUG SerialMon
// SIM7600指定(TinyGsmClient内に記載)
#define TINY_GSM_MODEM_SIM7600
// その上で読み込む
#include <TinyGsmClient.h>

// デバッグ設定
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);

void setup() {
  // デバッグログ用
  SerialMon.begin(115200);

  // 基本モジュールからの電源供給
  pinMode(POWER_PIN, OUTPUT);
  digitalWrite(POWER_PIN, HIGH);
  delay(1000);

  // この操作はここの事だと思う
  // SIM7600_Series_PCIE_Hardware_Design_V1.03.pdf
  // 3.2 PERST#
  // The active low level time impulse on PERST# pin to reset module
  pinMode(PWR_PIN, OUTPUT);
  digitalWrite(PWR_PIN, HIGH);
  delay(500);
  digitalWrite(PWR_PIN, LOW);

  // モデムにATcommandを送る用
  SerialAT.begin(UART_BAUD, SERIAL_8N1, PIN_RX, PIN_TX);
  // 起動までにちょっとまっておかないとATコマンドが受け付けられない
  delay(5000);

  if (!modem.init()) {
    ESP_LOGD(TAG, "初期化失敗");
    return;
  }

  //////////////////////////////////////////////
  // ネットワーク、とりあえず全部ON(よく分かってない)
  //////////////////////////////////////////////
  // network
  modem.sendAT(GF("+CREG=1"));
  ESP_LOGD(TAG, "+CREG=1 %d", modem.waitResponse());

  // GPRS network
  modem.sendAT(GF("+CGREG=1"));
  ESP_LOGD(TAG, "+CGREG=1 %d", modem.waitResponse());

  // LTE network
  // https://atmarkit.itmedia.co.jp/ait/articles/1001/13/news105.html
  // LTEネットワークは、「進化したパケットシステム」という意味で「EPS(Evolved
  // Packet System)」とも呼ばれ
  modem.sendAT(GF("+CEREG=1"));
  ESP_LOGD(TAG, "+CEREG=1 %d", modem.waitResponse());

  //////////////////////////////////////////////
  // 通信業者指定
  //////////////////////////////////////////////
  // 検索(時間がかかる)
  modem.sendAT(GF("+COPS=?"));
  ESP_LOGD(TAG, "+COPS=? %d", modem.waitResponse(20000L, GF("+COPS:")));

  // 指定(ドコモ)
  modem.sendAT(GF("+COPS=1,2,\"44010\""));
  ESP_LOGD(TAG, "+COPS=1,2,\"44010\" %d", modem.waitResponse());

  // 設定状況確認
  modem.sendAT(GF("+COPS?"));
  ESP_LOGD(TAG, "+COPS? %d", modem.waitResponse());

  // APN接続
  modem.sendAT(GF("+CGAUTH=1,2,\""), gprsPass, GF("\",\""), gprsUser, '"');
  modem.waitResponse();
  // 設定状況確認
  modem.sendAT(GF("+CGAUTH?"));
  ESP_LOGD(TAG, "+CGAUTH? %d", modem.waitResponse(GF("+CGAUTH:")));

  ////////////////////////////////////////
  // TinyGsmClientSIM7600.h
  // bool gprsConnectImpl をそのままコピーした
  modem.sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"', ",\"0.0.0.0\",0,0");
  modem.waitResponse();

  modem.sendAT(GF("+CIPMODE=0"));
  modem.waitResponse();

  modem.sendAT(GF("+CIPSENDMODE=0"));
  modem.waitResponse();

  modem.sendAT(GF("+CIPCCFG=10,0,0,0,1,0,75000"));
  if (modem.waitResponse() != 1) {
    return;
  }

  modem.sendAT(GF("+CIPTIMEOUT="), 75000, ',', 15000, ',', 15000);
  modem.waitResponse();

  modem.sendAT(GF("+NETOPEN"));
  if (modem.waitResponse(75000L, GF(GSM_NL "+NETOPEN: 0")) != 1) {
    return;
  }
  // TinyGsmClientSIM7600.h
  // bool gprsConnectImpl
  ////////////////////////////////////////

  ESP_LOGD(TAG, "GPRS status: %s",
           modem.isGprsConnected() ? "接続中 ..." : "接続していない");

  IPAddress local = modem.localIP();
  ESP_LOGD(TAG, "Local IP: %s", local.toString().c_str());

  ESP_LOGD(TAG, "Signal Status: %d", modem.getRegistrationStatus());
}

void loop() {
  ESP_LOGD(TAG, "...");
  delay(1000);
}

上記で接続確認後は以下だけで動く

1点問題なのはTinyGsmClientSIM7600.hgprsConnectImpl+CGAUTHATコマンドのパラメータ順序が多分間違っていて、

  1. password
  2. user

という順序にTinyGsmClientSIM7600.hを書き換えないといけないのかなと思うが、今思うと他の人がそんな事をせずに素直に動いているのは不思議。

セルラーモデムの試食というページを読んでみると、APNの情報はSIMに保存しているのか?とも思うがよく分かってない。

アクセスポイント情報の登録
単にSIMカードをセットしただけでは動作しません。新しいSIMカードを使うときは、まず最初にアクセスポイント関するデータ(APN、ユーザ名、パスワード、認証方式)を設定する必要があるのです。

main.cpp
#include <Arduino.h>
#define SerialMon Serial
#define SerialAT Serial1

#define PIN_TX 27
#define PIN_RX 26
#define UART_BAUD 115200
#define PWR_PIN 4
#define POWER_PIN 25

// #define DUMP_AT_COMMANDS
#define TINY_GSM_DEBUG SerialMon
#define TINY_GSM_MODEM_SIM7600
#include <TinyGsmClient.h>

#define APN "ocn.ne.jp"
#define APN_USER "mobileid@ocn"
#define APN_PASS "mobile"

#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
Mobile::Mobile() : modem(debugger){};
#else
Mobile::Mobile() : modem(SerialAT){};
#endif

void setup() {
  // 基本モジュールからの電源供給
  pinMode(POWER_PIN, OUTPUT);
  digitalWrite(POWER_PIN, HIGH);
  delay(1000);

  // この操作はここの事だと思う
  // SIM7600_Series_PCIE_Hardware_Design_V1.03.pdf
  // 3.2 PERST#
  // The active low level time impulse on PERST# pin to reset module
  pinMode(PWR_PIN, OUTPUT);
  digitalWrite(PWR_PIN, HIGH);
  delay(500);
  digitalWrite(PWR_PIN, LOW);

  SerialAT.begin(UART_BAUD, SERIAL_8N1, PIN_RX, PIN_TX);
  // 起動までにちょっと待っておかないとATコマンドが受け付けられない
  delay(5000);

  // SIMにPINの設定があればinitに渡せる
  if (!modem.init()) {
    // AT→OKが出なかった
    // 上のdelayが短いとかが考えられる
    ESP_LOGE(MOBILE_TAG, "初期化失敗");
    return;
  }

  // SIM7500_SIM7600 Series_AT Command Manual_V3.00.pdf
  // 4.2.11 AT+CNMP Preferred mode selection
  if (!modem.setNetworkMode(2)) {
    ESP_LOGE(MOBILE_TAG, "ネットワーク選択設定失敗");
    return;
  }

  if (!modem.waitForNetwork()) {
    ESP_LOGE(MOBILE_TAG, "ネットワーク接続失敗");
    return;
  }

  //////////////////////////////////////////////////////////////////
  // TinyGsmClientSIM7600.h
  // https://i.gyazo.com/9399b27cfb442030991e60d51acf95ca.png
  //////////////////////////////////////////////////////////////////
  // sendAT(GF("+CGAUTH=1,2,\""), user, GF("\",\""), pwd, '"');
  //                               ↓                 ↓
  // sendAT(GF("+CGAUTH=1,2,\""), pwd, GF("\",\""), user, '"');
  //////////////////////////////////////////////////////////////////
  //   /*
  //    * GPRS functions
  //    */
  // protected:
  //   bool gprsConnectImpl(const char *apn, const char *user = NULL,
  //                        const char *pwd = NULL) {
  //     gprsDisconnect(); // Make sure we're not connected first

  //     // Define the PDP context

  //     // The CGDCONT commands set up the "external" PDP context

  //     // Set the external authentication
  //     if (user && strlen(user) > 0) {
  //       sendAT(GF("+CGAUTH=1,2,\""), pwd, GF("\",\""), user, '"');
  //       waitResponse();
  //     }

  // APNに接続
  if (!modem.gprsConnect(APN, APN_USER, APN_PASS)) {
    ESP_LOGE(MOBILE_TAG, "APN接続失敗");
    return;
  }

  for (auto c = 0; c < 20; c++) {
    delay(1000);
    const auto quality = modem.getSignalQuality();
    ESP_LOGI(MOBILE_TAG, "受信感度: %d", quality);

    if (quality < 99) {
      ESP_LOGI(MOBILE_TAG, "IPアドレス: %s",
               modem.localIP().toString().c_str());
      return;
    }
  }

}

void loop() {
  ESP_LOGD(TAG, "...");
  delay(1000);
}
1
4
0

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
1
4