タイトル
M5stack basicを用いて、COM.LTE Module(SIM7600G)によりデータ送信をする方法がわかりません。
詳しい状況の説明
Arduino言語により、m5stack basicを用いたCOM.LTE Module(SIM7600G)の簡易的な通信システムを制作しています。
データはGoogleスプレッドシートに表示させたいと考えています。
wifi通信を用いた場合では、意図した通りにGoogleスプレッドシートにデータが表示されました。
ところが、COM Xを用いた際には表示されないため困っています。
通信強度とインターネット接続状況を確認するために、
COM.LTEModule(SIM7600G)の公式HPよりArduino Example Code
(https://docs.m5stack.com/en/module/comx_lte)
に記載されていたサンプルコードを用いました。
ATコマンドを用いたプログラムのため、ネットワークの登録状況を確認するコマンドの「AT+CREG?」を使用しました。結果は
AT+CREG?
+CREG?:0,3
OK
となったためインターネットには接続できていると考えています。
ですがデータ通信を行うことができませんでした。
wifi通信を用いた場合ではGoogleスプレッドシートにデータが表示されました。
データ送信はHTTPリクエストのPOST通信を使用。以下の記事を参考にしました。
(https://msr-r.net/m5stack-googlesheets/)
COM XのLTEを用いた形でデータ送信を完成させたいと考えておりますが
どのようにすれば良いのかアドバイスをいただけないでしょうか。
使用しているUIFlowやArduinoライブラリのバージョン
Arduino IDE 2.3.3
コード
[M5stack basic のコード]
#include <M5Stack.h>
#include <stdint.h>
#include <vector>
#include "TFTTerminal.h"
#include <WiFi.h> //serial通信のinclude
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
TFT_eSprite Disbuff = TFT_eSprite(&M5.Lcd);
TFT_eSprite TerminalBuff = TFT_eSprite(&M5.Lcd);
TFTTerminal terminal(&TerminalBuff);
TaskHandle_t xhandle_lte_event = NULL;
SemaphoreHandle_t command_list_samap;
const int capacity = JSON_OBJECT_SIZE(2); //serial通信をする
StaticJsonDocument<capacity> json_request;
char buffer[255];
const char url = "*****";
unsigned long counter = 0;
unsigned long tick = 0;
const char data = "Hello World";
const String sim_apn = "ppsim.jp";
const String sim_user = "pp@sim";
const String sim_pass = "jpn";
typedef enum {
kQUERY_MO = 0,
KTEST_MO,
kASSIGN_MO,
kACTION_MO,
kQUERY_MT,
kTEST_MT,
kASSIGN_MT,
kACTION_MT,
kINFORM
} LTEMsg_t;
typedef enum {
kErrorSendTimeOUT = 0xe1,
kErrorReError = 0xe2,
kErroeSendError = 0xe3,
kSendReady = 0,
kSending = 1,
kWaitforMsg = 2,
kWaitforRead = 3,
kReOK
} LTEState_t;
struct ATCommand {
uint8_t command_type;
String str_command;
uint16_t send_max_number;
uint16_t max_time;
uint8_t state;
String read_str;
uint16_t _send_count;
uint16_t _send_time_count;
} user;
using namespace std;
vector<ATCommand> serial_at;
String zmmi_str;
void LTEModuleTask(void* arg) {
int Number = 0;
String restr;
while (1) {
xSemaphoreTake(command_list_samap, portMAX_DELAY);
if (Serial2.available() != 0) {
String str = Serial2.readString();
restr += str;
if (restr.indexOf("\r\n") != -1) {
}
if (restr.indexOf("+ZMMI:") != -1) {
zmmi_str = restr;
} else if ((restr.indexOf("OK") != -1) ||
(restr.indexOf("ERROR") != -1)) {
Serial.print(restr);
if (restr.indexOf("OK") != -1) {
if ((serial_at[0].command_type == kACTION_MO) ||
(serial_at[0].command_type == kASSIGN_MO)) {
serial_at.erase(serial_at.begin());
Serial.printf("erase now %d\n", serial_at.size());
} else {
serial_at[0].read_str = restr;
serial_at[0].state = kWaitforRead;
}
} else if (restr.indexOf("ERROR") != -1) {
serial_at[0].state = kErrorReError;
} else {
}
restr.clear();
}
}
if (serial_at.empty() != true) {
Number = 0;
switch (serial_at[0].state) {
case kSendReady:
Serial.printf(serial_at[0].str_command.c_str());
Serial2.write(serial_at[0].str_command.c_str());
serial_at[0].state = kSending;
break;
case kSending:
if (serial_at[0]._send_time_count > 0) {
serial_at[0]._send_time_count--;
} else {
serial_at[0].state = kWaitforMsg;
}
/* code */
break;
case kWaitforMsg:
if (serial_at[0]._send_count > 0) {
serial_at[0]._send_count--;
serial_at[0]._send_time_count = serial_at[0].max_time;
Serial.printf(serial_at[0].str_command.c_str());
Serial2.write(serial_at[0].str_command.c_str());
restr.clear();
serial_at[0].state = 1;
} else {
serial_at[0].state = kErrorSendTimeOUT;
}
/* code */
break;
case kWaitforRead:
/* code */
break;
case 4:
/* code */
break;
case kErrorSendTimeOUT:
/* code */
break;
case 0xe2:
/* code */
break;
default:
break;
}
}
xSemaphoreGive(command_list_samap);
delay(10);
}
}
void AddMsg(String str, uint8_t type, uint16_t sendcount, uint16_t sendtime) {
struct ATCommand newcommand;
newcommand.str_command = str;
newcommand.command_type = type;
newcommand.max_time = sendtime;
newcommand.send_max_number = sendcount;
newcommand.state = 0;
newcommand._send_count = sendcount;
newcommand._send_time_count = sendtime;
xSemaphoreTake(command_list_samap, portMAX_DELAY);
serial_at.push_back(newcommand);
xSemaphoreGive(command_list_samap);
}
uint8_t readSendState(uint32_t number) {
xSemaphoreTake(command_list_samap, portMAX_DELAY);
uint8_t restate = serial_at[number].state;
xSemaphoreGive(command_list_samap);
return restate;
}
uint32_t getATMsgSize() {
xSemaphoreTake(command_list_samap, portMAX_DELAY);
uint32_t restate = serial_at.size();
xSemaphoreGive(command_list_samap);
return restate;
}
String ReadMsgstr(uint32_t number) {
xSemaphoreTake(command_list_samap, portMAX_DELAY);
String restate = serial_at[number].read_str;
xSemaphoreGive(command_list_samap);
return restate;
}
bool EraseFirstMsg() {
xSemaphoreTake(command_list_samap, portMAX_DELAY);
serial_at.erase(serial_at.begin());
xSemaphoreGive(command_list_samap);
return true;
}
uint16_t GetstrNumber(String Str, uint32_t* ptrbuff) {
uint16_t count = 0;
String Numberstr;
int indexpos = 0;
while (Str.length() > 0) {
indexpos = Str.indexOf(",");
if (indexpos != -1) {
Numberstr = Str.substring(0, Str.indexOf(","));
Str = Str.substring(Str.indexOf(",") + 1, Str.length());
ptrbuff[count] = Numberstr.toInt();
count++;
} else {
ptrbuff[count] = Str.toInt();
count++;
break;
}
}
return count;
}
vector<String> restr_v;
uint16_t GetstrNumber(String StartStr, String EndStr, String Str) {
uint16_t count = 0;
String Numberstr;
int indexpos = 0;
Str = Str.substring(Str.indexOf(StartStr) + StartStr.length(),
Str.indexOf(EndStr));
Str.trim();
restr_v.clear();
while (Str.length() > 0) {
indexpos = Str.indexOf(",");
if (indexpos != -1) {
Numberstr = Str.substring(0, Str.indexOf(","));
Str = Str.substring(Str.indexOf(",") + 1, Str.length());
restr_v.push_back(Numberstr);
count++;
} else {
restr_v.push_back(Numberstr);
;
count++;
break;
}
}
return count;
}
String getReString(uint16_t Number) {
if (restr_v.empty()) {
return String("");
}
return restr_v.at(Number);
}
uint16_t GetstrNumber(String StartStr, String EndStr, String Str,
uint32_t* ptrbuff) {
uint16_t count = 0;
String Numberstr;
int indexpos = 0;
Str = Str.substring(Str.indexOf(StartStr) + StartStr.length(),
Str.indexOf(EndStr));
Str.trim();
while (Str.length() > 0) {
indexpos = Str.indexOf(",");
if (indexpos != -1) {
Numberstr = Str.substring(0, Str.indexOf(","));
Str = Str.substring(Str.indexOf(",") + 1, Str.length());
ptrbuff[count] = Numberstr.toInt();
count++;
} else {
ptrbuff[count] = Str.toInt();
count++;
break;
}
}
return count;
}
uint32_t numberbuff[128];
String readstr;
bool isLTEConnected() {
AddMsg("AT+CREG?\r\n", kQUERY_MT, 1000, 1000);
while ((readSendState(0) == kSendReady) || (readSendState(0) == kSending) || (readSendState(0) == kWaitforMsg)) {
delay(50);
}
String response = ReadMsgstr(0);
EraseFirstMsg();
// CREG応答が「+CREG: 0,1」「+CREG: 0,2」「+CREG: 0,3」であれば、ネットワークに登録されている
if (response.indexOf("+CREG: 0,1") != -1 || response.indexOf("+CREG: 0,2") != -1 || response.indexOf("+CREG: 0,3") != -1 ) {
terminal.println("LTE connected to network.");
return true;
} else {
terminal.println("LTE not connected to network.");
return false;
}
}
bool isInternetConnected() {
HTTPClient http;
// GoogleのURLで接続確認
if (!http.begin("http://www.google.com")) {
terminal.println("HTTPClient init failed");
return false;
}
int httpCode = http.GET(); // GETリクエストを送信
if (httpCode == 200) {
terminal.println("Internet is connected.");
http.end();
return true;
} else {
terminal.printf("Internet connection failed. HTTP Code: %d\n", httpCode);
http.end();
return false;
}
}
uint8_t restate;
void setup() {
// put your setup code here, to run once:
M5.begin(true, true, true, false);
Serial2.begin(115200, SERIAL_8N1, 5, 13);
Disbuff.createSprite(320, 20);
Disbuff.fillRect(0, 0, 320, 20, BLACK);
Disbuff.drawRect(0, 0, 320, 20, Disbuff.color565(36, 36, 36));
Disbuff.pushSprite(0, 0);
TerminalBuff.createSprite(120, 220);
TerminalBuff.fillRect(0, 0, 120, 220, BLACK);
TerminalBuff.drawRect(0, 0, 120, 220, Disbuff.color565(36, 36, 36));
TerminalBuff.pushSprite(0, 20);
terminal.setGeometry(0, 20, 120, 220);
pinMode(2, OUTPUT);
digitalWrite(2, 0);
Disbuff.setTextColor(WHITE);
Disbuff.setTextSize(1);
for (int i = 0; i < 100; i++) {
Disbuff.fillRect(0, 0, 320, 20, Disbuff.color565(36, 36, 36));
Disbuff.pushSprite(0, 0);
Disbuff.setCursor(7, 7);
Disbuff.printf("Reset Module %02d", i);
Disbuff.pushSprite(0, 0);
delay(10);
}
digitalWrite(2, 1);
xTaskCreate(LTEModuleTask, "LTEModuleTask", 1024 * 2, (void*)0, 4,
&xhandle_lte_event);
command_list_samap = xSemaphoreCreateMutex();
xSemaphoreGive(command_list_samap);
AddMsg("AT+CSQ\r\n", kQUERY_MT, 1000, 1000);
while ((readSendState(0) == kSendReady) || (readSendState(0) == kSending) ||
(readSendState(0) == kWaitforMsg))
delay(50);
restate = readSendState(0);
readstr = ReadMsgstr(0).c_str();
EraseFirstMsg();
terminal.print(readstr);
AddMsg("AT+CREG?\r\n", kQUERY_MT, 1000, 1000);
while ((readSendState(0) == kSendReady) || (readSendState(0) == kSending) ||
(readSendState(0) == kWaitforMsg))
delay(50);
restate = readSendState(0);
readstr = ReadMsgstr(0).c_str();
EraseFirstMsg();
terminal.print(readstr);
AddMsg("AT+CGDCONT = 1, \"IP\", \"ppsim.jp\"\r\n", kASSIGN_MT, 1000, 1000);
while ((readSendState(0) == kSendReady) || (readSendState(0) == kSending) ||
(readSendState(0) == kWaitforMsg))
delay(50);
restate = readSendState(0);
readstr = ReadMsgstr(0).c_str();
EraseFirstMsg();
terminal.print(readstr);
AddMsg("AT+CGAUTH = 1, \"pp@sim\", \"jpn\"\r\n", kASSIGN_MT, 1000, 1000);
while ((readSendState(0) == kSendReady) || (readSendState(0) == kSending) ||
(readSendState(0) == kWaitforMsg))
delay(50);
restate = readSendState(0);
readstr = ReadMsgstr(0).c_str();
EraseFirstMsg();
terminal.print(readstr);
// LTE接続確認
if (isLTEConnected()) {
// インターネット接続確認
if (isInternetConnected()) {
terminal.println("SIM card is connected to the internet.");
} else {
terminal.println("SIM card is not connected to the internet.");
}
} else {
terminal.println("No LTE network connection.");
}
}
void loop() {
M5.update();
if (M5.BtnA.wasPressed()) {
terminal.println("A button OK");
counter++;
tick = millis();
json_request["counter"] = counter;
json_request["tick"] = tick;
serializeJson(json_request, Serial);
Serial.println("");
serializeJson(json_request, buffer, sizeof(buffer));
terminal.println(buffer);
delay(500);
HTTPClient http;
if (!http.begin(url)) {
terminal.println("HTTPClient init failed");
return; // 接続失敗の場合は処理を中断
}
http.addHeader("Content-Type", "application/json");
delay(500);
terminal.println("post ready");
int status_code = http.POST((uint8_t*)buffer, strlen(buffer));
Serial.printf("status_code=%d\r\n", status_code);
if (status_code != 200) {
terminal.printf("HTTP POST failed, status code: %d\n", status_code);
} else {
Stream* resp = http.getStreamPtr();
DynamicJsonDocument json_response(255);
deserializeJson(json_response, *resp);
serializeJson(json_response, Serial);
Serial.println();
}
http.end();
}
/*
if (M5.BtnB.wasPressed()) {
delay(1000);
esp_sleep_enable_timer_wakeup(10000);
esp_sleep_enable_ext0_wakeup((gpio_num_t)M5.BtnA.wasPressed(), 0);
esp_deep_sleep_start();
}
*/
if (M5.BtnC.wasPressed()) {
while(1){
AddMsg("AT+CSQ\r\n", kQUERY_MT, 1000, 1000);
while ((readSendState(0) == kSendReady) || (readSendState(0) == kSending) ||
(readSendState(0) == kWaitforMsg))
delay(50);
restate = readSendState(0);
readstr = ReadMsgstr(0).c_str();
EraseFirstMsg();
terminal.print(readstr);
AddMsg("AT+CREG?\r\n", kQUERY_MT, 1000, 1000);
while ((readSendState(0) == kSendReady) || (readSendState(0) == kSending) ||
(readSendState(0) == kWaitforMsg))
delay(50);
restate = readSendState(0);
readstr = ReadMsgstr(0).c_str();
EraseFirstMsg();
terminal.print(readstr);
delay(500);
M5.update();
if (M5.BtnA.wasPressed()) {
AddMsg("ATD13800088888;\r\n", kQUERY_MT, 1000, 1000);
while ((readSendState(0) == kSendReady) ||
(readSendState(0) == kSending) ||
(readSendState(0) == kWaitforMsg))
delay(50);
Serial.printf("Read state = %d \n", readSendState(0));
readstr = ReadMsgstr(0).c_str();
Serial.print(readstr);
while (1) {
M5.update();
if (M5.BtnA.wasPressed()) break;
delay(100);
}
EraseFirstMsg();
AddMsg("AT+CHUP\r\n", kASSIGN_MO, 1000, 1000);
}
if (M5.BtnB.wasPressed()) {
delay(1000);
esp_sleep_enable_timer_wakeup(10000);
esp_sleep_enable_ext0_wakeup((gpio_num_t)M5.BtnA.wasPressed(), 0);
esp_deep_sleep_start();
}
}
}
}
[Googleスプレッドシートのコード]
function doGet(e) {
let id = '*****';
let sheetName = 'シート1';
var result;
if (e.parameter == undefined) {
result = 'Parameter undefined';
} else {
var sheet = SpreadsheetApp.openById(id).getSheetByName(sheetName);
var newRow = sheet.getLastRow() + 1;
var rowData = [];
rowData[0] = new Date();
rowData[1] = e.parameter.chipid;
rowData[2] = e.parameter.val0;
rowData[3] = e.parameter.val1;
rowData[4] = e.parameter.val2;
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
result = 'Ok';
}
return ContentService.createTextOutput(result);
}
ターミナルコマンド
[シリアルモニタ]
`` command ``
OK
AT+CSQ
AT+CSQ
AT+CSQ
+CSQ: 20,99
OK
AT+CREG?
+CREG: 0,3
OK
AT+CGDCONT = 1, "IP", "ppsin.jp"
OK
AT+CGAUTH = 1, "pp@sin", "jpn"
ERROR
AT+CREG?
+CREG: 0,3
OK
("counter":1,"tick":98705]
status_code=-1
[M5stack basic の画面]
`` command ``
OK
+CREG: 0,3
OK
OK
LTE connected to net
work.
Internet connection
failed. HTTP Code:-1
SIM card is not connected to the internet.
A button OK
("counter" : 1, "tick" : 98705)
post ready
HTTP POST failed, status code : -1