ESP32-S3-WROOM1とSIM7080G（LILYGO®T-SIM7080G-S3）でIOT開発（2.9日目）

# ネットワークに接続できない。

かれこれ2週間くらいネットワークに接続できずに悩んでいる。

GoogleとChatGPTで調べまくったが一向に先に進まない。ぐぬぬぬ！

## 先に結論(繋がった)

買ったSIMカードの相性が悪かった。

最初に買ったSIMカードはこれ

https://www.amazon.co.jp/gp/product/B0BSBKNCWV/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1

AICOMの丸紅ネットワークソリューションズの回線で、NB-Iotには対応していない。

２つ目の楽天モバイルのSIMもダメだった。

３つ目ドコモのSIMもダメだった。

４つ目のソラコムのSIM（plan-KM1）KDDI系は繋がった。

## 使っている機材

LILYGO®T-SIM7080G-S3
https://ja.aliexpress.com/item/1005005188988179.html

## サンプルコード
https://github.com/Xinyuan-LilyGO/LilyGo-T-SIM7080G
~~~
/**
 * @file      MinimalModemNBIOTExample.ino
 * @author    Lewis He (lewishe@outlook.com)
 * @license   MIT
 * @copyright Copyright (c) 2022  Shenzhen Xin Yuan Electronic Technology Co., Ltd
 * @date      2022-09-16
 *
 */
#include <Arduino.h>
#define XPOWERS_CHIP_AXP2101
#include "XPowersLib.h"
#include "utilities.h"

XPowersPMU  PMU;

// See all AT commands, if wanted
#define DUMP_AT_COMMANDS

#define TINY_GSM_RX_BUFFER 1024

#define TINY_GSM_MODEM_SIM7080
#include <TinyGsmClient.h>
#include "utilities.h"


#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(Serial1, Serial);
TinyGsm        modem(debugger);
#else
TinyGsm        modem(SerialAT);
#endif

const char *register_info[] = {
    "Not registered, MT is not currently searching an operator to register to.The GPRS service is disabled, the UE is allowed to attach for GPRS if requested by the user.",
    "Registered, home network.",
    "Not registered, but MT is currently trying to attach or searching an operator to register to. The GPRS service is enabled, but an allowable PLMN is currently not available. The UE will start a GPRS attach as soon as an allowable PLMN is available.",
    "Registration denied, The GPRS service is disabled, the UE is not allowed to attach for GPRS if it is requested by the user.",
    "Unknown.",
    "Registered, roaming.",
};


enum {
    MODEM_CATM = 1,
    MODEM_NB_IOT,
    MODEM_CATM_NBIOT,
};

void getPsmTimer();


// const char apn[] = "";
const char gprsUser[] = "sora"; //SIMがソラコムの場合
const char gprsPass[] = "sora"; //SIMがソラコムの場合
bool  level = false;

// Server details to test TCP/SSL
const char server[]   = "vsh.pp.ua";
const char resource[] = "/TinyGSM/logo.txt";

//!! Set the APN manually. Some operators need to set APN first when registering the network.
//!! Set the APN manually. Some operators need to set APN first when registering the network.
//!! Set the APN manually. Some operators need to set APN first when registering the network.
// Using 7080G with Hologram.io , https://github.com/Xinyuan-LilyGO/LilyGo-T-SIM7080G/issues/19
// const char *apn = "hologram";

const char *apn = "soracom.io";　//SIMがソラコムの場合

void setup()
{

    Serial.begin(115200);

    //Start while waiting for Serial monitoring
    while (!Serial);

    delay(3000);

    Serial.println();

    /*********************************
     *  step 1 : Initialize power chip,
     *  turn on modem and gps antenna power channel
    ***********************************/
    if (!PMU.begin(Wire, AXP2101_SLAVE_ADDRESS, I2C_SDA, I2C_SCL)) {
        Serial.println("Failed to initialize power.....");
        while (1) {
            delay(5000);
        }
    }
    //Set the working voltage of the modem, please do not modify the parameters
    PMU.setDC3Voltage(3000);    //SIM7080 Modem main power channel 2700~ 3400V
    PMU.enableDC3();

    //Modem GPS Power channel
    PMU.setBLDO2Voltage(3300);
    PMU.enableBLDO2();      //The antenna power must be turned on to use the GPS function

    // TS Pin detection must be disable, otherwise it cannot be charged
    PMU.disableTSPinMeasure();


    /*********************************
     * step 2 : start modem
    ***********************************/

    Serial1.begin(115200, SERIAL_8N1, BOARD_MODEM_RXD_PIN, BOARD_MODEM_TXD_PIN);

    pinMode(BOARD_MODEM_PWR_PIN, OUTPUT);
    pinMode(BOARD_MODEM_DTR_PIN, OUTPUT);
    pinMode(BOARD_MODEM_RI_PIN, INPUT);

    int retry = 0;
    while (!modem.testAT(1000)) {
        Serial.print(".");
        if (retry++ > 6) {
            // Pull down PWRKEY for more than 1 second according to manual requirements
            digitalWrite(BOARD_MODEM_PWR_PIN, LOW);
            delay(100);
            digitalWrite(BOARD_MODEM_PWR_PIN, HIGH);
            delay(1000);
            digitalWrite(BOARD_MODEM_PWR_PIN, LOW);
            retry = 0;
            Serial.println("Retry start modem .");
        }
    }
    Serial.println();
    Serial.print("Modem started!");


    /*********************************
     * step 3 : Check if the SIM card is inserted
    ***********************************/
    String result ;


    if (modem.getSimStatus() != SIM_READY) {
        Serial.println("SIM Card is not insert!!!");
        return ;
    }

    // Disable RF
    modem.sendAT("+CFUN=0");
    if (modem.waitResponse(20000UL) != 1) {
        Serial.println("Disable RF Failed!");
    }

    /*********************************
     * step 4 : Set the network mode to NB-IOT
    ***********************************/

    modem.setNetworkMode(38);    //use LTE only ※ここの変更は重要

    modem.setPreferredMode(1);   //use CAT-M only　※ここの変更は重要

    uint8_t pre = modem.getPreferredMode();

    uint8_t mode = modem.getNetworkMode();

    Serial.printf("getNetworkMode:%u getPreferredMode:%u\n", mode, pre);


    //Set the APN manually. Some operators need to set APN first when registering the network.
    modem.sendAT("+CGDCONT=1,\"IP\",\"", apn, "\"");
    if (modem.waitResponse() != 1) {
        Serial.println("Set operators apn Failed!");
        return;
    }

    //!! Set the APN manually. Some operators need to set APN first when registering the network.
    modem.sendAT("+CNCFG=0,1,\"", apn, "\"");
    if (modem.waitResponse() != 1) {
        Serial.println("Config apn Failed!");
        return;
    }

    // Enable RF
    modem.sendAT("+CFUN=1");
    if (modem.waitResponse(20000UL) != 1) {
        Serial.println("Enable RF Failed!");
    }

    /*********************************
    * step 5 : Wait for the network registration to succeed
    ***********************************/
    RegStatus s;
    do {
        s = modem.getRegistrationStatus();
        if (s != REG_OK_HOME && s != REG_OK_ROAMING) {
            Serial.print(".");
            PMU.setChargingLedMode(level ? XPOWERS_CHG_LED_ON : XPOWERS_CHG_LED_OFF);
            level ^= 1;
            delay(1000);
        }

    } while (s != REG_OK_HOME && s != REG_OK_ROAMING) ;

    Serial.println();
    Serial.print("Network register info:");
    Serial.println(register_info[s]);





    // Activate network bearer, APN can not be configured by default,
    // if the SIM card is locked, please configure the correct APN and user password, use the gprsConnect() method
    modem.sendAT("+CNACT=0,1");
    if (modem.waitResponse() != 1) {
        Serial.println("Activate network bearer Failed!");
        return;
    }

    // if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
    //     return ;
    // }

    bool res = modem.isGprsConnected();
    Serial.print("GPRS status:");
    Serial.println(res ? "connected" : "not connected");

    String ccid = modem.getSimCCID();
    Serial.print("CCID:");
    Serial.println(ccid);

    String imei = modem.getIMEI();
    Serial.print("IMEI:");
    Serial.println(imei);

    String imsi = modem.getIMSI();
    Serial.print("IMSI:");
    Serial.println(imsi);

    String cop = modem.getOperator();
    Serial.print("Operator:");
    Serial.println(cop);

    IPAddress local = modem.localIP();
    Serial.print("Local IP:");
    Serial.println(local);

    int csq = modem.getSignalQuality();
    Serial.print("Signal quality:");
    Serial.println(csq);

    /*********************************
    * step 6 : Send HTTP request
    ***********************************/
    TinyGsmClient client(modem, 0);
    const int     port = 80;
    Serial.printf("Connecting to", server);
    if (!client.connect(server, port)) {
        Serial.println("... failed");
    } else {
        // Make a HTTP GET request:
        client.print(String("GET ") + resource + " HTTP/1.0\r\n");
        client.print(String("Host: ") + server + "\r\n");
        client.print("Connection: close\r\n\r\n");

        // Wait for data to arrive
        uint32_t start = millis();
        while (client.connected() && !client.available() &&
                millis() - start < 30000L) {
            delay(100);
        };

        // Read data
        start          = millis();
        char logo[640] = {
            '\0',
        };
        int read_chars = 0;
        while (client.connected() && millis() - start < 10000L) {
            while (client.available()) {
                logo[read_chars]     = client.read();
                logo[read_chars + 1] = '\0';
                read_chars++;
                start = millis();
            }
        }
        Serial.println(logo);
        Serial.print("#####  RECEIVED:");
        Serial.print(strlen(logo));
        Serial.println("CHARACTERS");
        client.stop();
    }

    /*********************************
    * step 6 : Send HTTPS request
    ***********************************/
    TinyGsmClientSecure secureClient(modem, 1);
    const int           securePort = 443;
    Serial.printf("Connecting securely to", server);
    if (!secureClient.connect(server, securePort)) {
        Serial.println("... failed");
    } else {
        // Make a HTTP GET request:
        secureClient.print(String("GET ") + resource + " HTTP/1.0\r\n");
        secureClient.print(String("Host: ") + server + "\r\n");
        secureClient.print("Connection: close\r\n\r\n");

        // Wait for data to arrive
        uint32_t startS = millis();
        while (secureClient.connected() && !secureClient.available() &&
                millis() - startS < 30000L) {
            delay(100);
        };

        // Read data
        startS          = millis();
        char logoS[640] = {
            '\0',
        };
        int read_charsS = 0;
        while (secureClient.connected() && millis() - startS < 10000L) {
            while (secureClient.available()) {
                logoS[read_charsS]     = secureClient.read();
                logoS[read_charsS + 1] = '\0';
                read_charsS++;
                startS = millis();
            }
        }
        Serial.println(logoS);
        Serial.print("#####  RECEIVED:");
        Serial.print(strlen(logoS));
        Serial.println("CHARACTERS");
        secureClient.stop();
    }
}

void loop()
{
    while (Serial1.available()) {
        Serial.write(Serial1.read());
    }
    while (Serial.available()) {
        Serial1.write(Serial.read());
    }
}

~~~

## ハマったところ

こちらの記事を参考に、

https://qiita.com/github0013@github/items/30481b51827b990b545c

手動でネットワーク接続の設定をしてあげると、

~~~
AT+CEREG?

+CEREG: 1,2
~~~

と、表示され一歩前進（実はしていない）。

+CEREG: 1,2 という応答は、携帯モデムに対してATコマンド AT+CEREG? を送信した結果を示しています。

この応答の意味は以下の通りです（ChatGPT）：

>+CEREG: 1,2 : CEREGレジスタの値が1であり、セルラーネットワークの登録ステータスが2（サーチ中）であることを示します。
これは、モデムがセルラーネットワークに登録しようとしているが、まだ登録が完了していない状態を示しています。セルラーネットワークへの登録は、モデムが正常に通信を行うために必要なステップであり、一時的にサーチ中になることがあります。
モデムは、セルラーネットワークのサービス範囲内でネットワークを探索し、登録を試みます。このプロセスが成功すると、登録ステータスは1（ホームネットワークに登録済み）または5（ローミングネットワークに登録済み）に変わります。
セルラーネットワークの登録が完了するまで、モデムは通信を行うことができません。そのため、登録が成功するまで待つ必要があります。登録が成功したかどうかは、再度ATコマンドを送信して登録ステータスを確認することで確認できます。

手動で適切に設定してやると繋がらないSIMも繋がるのかもしれない。

今回の問題解決はAPNの設定やコードの問題でなくSIMの相性問題だった。

どのSIMカードもスマホ（iphone）ではすんなり繋がるので、SIMカードを疑っていなかった。

## ソラコムSIM（plan-KM1）で、すんなり繋がる

ソースコードは同じです。

シリアルモニタの表示結果

~~~

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x15 (USB_UART_CHIP_RESET),boot:0x28 (SPI_FAST_FLASH_BOOT)
Saved PC:0x420299b6
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3808,len:0x44c
load:0x403c9700,len:0xbe4
load:0x403cc700,len:0x2a68
entry 0x403c98d4

AT
AT
AT
AT
.AT
AT
AT
AT
.AT

+CFUN: 1
AT

+CPIN: READY
AT

OK

Modem started!AT+CPIN?
AT+CPIN?

+CPIN: READY

OK
AT+CFUN=0
AT+CFUN=0

+CPIN: NOT READY

OK
AT+CNMP=38
AT+CNMP=38

OK
AT+CMNB=1
AT+CMNB=1

OK
AT+CMNB?
AT+CMNB?

+CMNB: 1

OK
AT+CNMP?
AT+CNMP?

+CNMP: 38

OK
getNetworkMode:38 getPreferredMode:1
AT+CGDCONT=1,"IP","soracom.io"
AT+CGDCONT=1,"IP","soracom.io"

OK
AT+CNCFG=0,1,"soracom.io"
AT+CNCFG=0,1,"soracom.io"

OK
AT+CFUN=1
AT+CFUN=1

OK
AT+CEREG?
AT+CEREG?

+CEREG: 0,0

OK
AT+CGREG?
AT+CGREG?

+CGREG: 0,0

OK
.AT+CEREG?

+CPIN: READY

SMS Ready
AT
AT+CEREG?

+CEREG: 0,2

OK
ATE0
AT

OK
AT+CMEE=0
ATE0

OK
AT+CLTS=1

OK
AT+CBATCHK=1

OK
AT+CPIN?

OK

+CPIN: READY

OK
AT+CGREG?

+CGREG: 0,2

OK
.AT+CEREG?

*PSUTTZ: 23/08/07,04:20:28","+36",0

+CTZV: 36

+CEREG: 0,1

OK

Network register info:Registered, home network.
AT+CNACT=0,1

OK
AT+CNACT=0,0

+APP PDP: 0,ACTIVE

OK
AT+CGATT=0

+APP PDP: 0,DEACTIVE

OK
AT+CGDCONT=1,"IP","soracom.io"

OK
AT+CGATT=1

OK
AT+CGNAPN

+CGNAPN: 1,"soracom.io"

OK
AT+CNCFG=0,1,"soracom.io","sora","sora"

ERROR
AT+CNACT=0,1

OK

+APP PDP: 0,ACTIVE

*PSUTTZ: 23/08/07,04:20:30","+36",0
AT+CGATT?

+CGATT: 1

OK
AT+CNACT?

+CNACT: 0,1,"10.128.211.196"
+CNACT: 1,0,"0.0.0.0"
+CNACT: 2,0,"0.0.0.0"
+CNACT: 3,0,"0.0.0.0"

OK
AT+CNACT=0,0

+APP PDP: 0,ACTIVE

OK
AT+CGATT=0

+APP PDP: 0,DEACTIVE

OK
AT+CGDCONT=1,"IP","soracom.io"

OK
AT+CGATT=1

OK
AT+CGNAPN

+CGNAPN: 1,"soracom.io"

OK
AT+CNCFG=0,1,"soracom.io","sora","sora"

ERROR
AT+CNACT=0,1

OK

+APP PDP: 0,ACTIVE

*PSUTTZ: 23/08/07,04:20:30","+36",0
AT+CGATT?

+CGATT: 1

OK
AT+CNACT?

+CNACT: 0,1,"10.128.211.196"
+CNACT: 1,0,"0.0.0.0"
+CNACT: 2,0,"0.0.0.0"
+CNACT: 3,0,"0.0.0.0"

OK
GPRS status:connected
AT+CCID

**********

OK
CCID:**********
AT+GSN

**********

OK
IMEI:**********
AT+CIMI

**********

OK
IMSI:**********
AT+COPS?

+COPS: 0,0,"KDDI",7

OK
Operator:KDDI
AT+CNACT?

+CNACT: 0,1,"10.128.211.196"
+CNACT: 1,0,"0.0.0.0"
+CNACT: 2,0,"0.0.0.0"
+CNACT: 3,0,"0.0.0.0"

OK
Local IP:10.128.211.196
AT+CSQ

+CSQ: 99,99

OK
Signal quality:99
Connecting toAT+CACLOSE=0

ERROR
AT+CACID=0

OK
AT+CASSLCFG=0,SSL,0

OK
AT+CAOPEN=0,0,"TCP","vsh.pp.ua",80

+CAOPEN: 0,0

OK
AT+CASEND=0,32

>GET /TinyGSM/logo.txt HTTP/1.0
 
OK
AT+CASEND=0,17

>Host: vsh.pp.ua
 
OK
AT+CASEND=0,21

>Connection: close

 
OK
AT+CARECV?

OK
AT+CASTATE?

+CASTATE: 0,1

OK

+CADATAIND: 0

+CASTATE: 0,0
AT+CARECV?

+CARECV: 0,568

OK
AT+CASTATE?

+CASTATE: 0,0

OK
AT+CARECV=0,568

+CARECV: 568,HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Mon, 07 Aug 2023 04:20:32 GMT
Content-Type: text/plain; charset=UTF-8
Content-Length: 121
Connection: close
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With
Cross-Origin-Resource-Policy: cross-origin
Accept-Ranges: bytes
Cache-Control: public, max-age=86400
Last-Modified: Wed, 27 Sep 2017 09:03:12 GMT
ETag: W/"79-15ec2936080"


  _____            _____  _____  _____
    |  | |\ | \_/ |  ___ |_____ |  |  |
    |  | | \|  |  |_____| _____||  |  |


K
AT+CARECV?

OK
AT+CASTATE?

+CASTATE: 0,0

OK
AT+CARECV?

OK
AT+CASTATE?

+CASTATE: 0,0

OK
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Mon, 07 Aug 2023 04:20:32 GMT
Content-Type: text/plain; charset=UTF-8
Content-Length: 121
Connection: close
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With
Cross-Origin-Resource-Policy: cross-origin
Accept-Ranges: bytes
Cache-Control: public, max-age=86400
Last-Modified: Wed, 27 Sep 2017 09:03:12 GMT
ETag: W/"79-15ec2936080"


  _____            _____  _____  _____
    |  | |\ | \_/ |  ___ |_____ |  |  |
    |  | | \|  |  |_____| _____||  |  |


#####  RECEIVED:568CHARACTERS
~~~

## その他のエラー

何度もUSBを抜いたりさしたりしてCOMポートが10か所以上使用中になった。

・COMポート10を使うと書き込みが上手くいかないことがあった。

・シリアルモニタに何も表示されないエラー。

・SIMカードの認識がされないエラーなどが発生した。

対策方法、一度デバイスマネージャーから使用していないポートを削除する。使用しているCOMを一旦無効化して有効化すると正常に動き出す。


## やっとネットワークに接続できた（感想）

２週間くらい悩み続けトライ＆エラーで地獄のような日々でした。接続が上手くいったときは嬉しすぎて涙が出そうになりました。

SIM7080Gの代理店に対応するSIMカードを教えてくださいと質問を送ったところ、

>大変恐縮ながら、弊社は法人格のお客様のみ
ご対応させて頂いております。
ご了承のほどお願いいたします。

の３行が返ってくるのみでした。「あらゆるモノをインターネットに繋いで社会を豊かにしようというスローガンで商売しているけど、金にならない個人とは繋がりたくねぇーんだわ。」という意味で私は受け取りました。間違っていたらごめんなさい。金にならないヤツと繋がったところで金にならないのだから、ビジネスにならないのは理解できます。しかし初見の対応がこうだと改めて法人を名乗る気にもならない。

一方で、ソラコムさんはデータシートを送ったら、動作の保証まではできないが動くであろうSIMカードを教えてくださいました。ソラコムさんの神対応に感激しました。プライオリティーサポートも月額10,780円からあるので、IoT開発に挑戦したいならサポートを受けるのもありかもしれません。

どちらの企業の対応が正解かはわかりませんが、企業にリソース（金にならないことにも対応できる余裕）がないと将来の芽を摘むなぁ～と感じた今日この頃です。戒めやね。