データ通信を行うことができたので、共有させていただきます。
SIM7600のデータシートを参照し、通信を行うことができました。
COM.LTE Module(SIM7600G)を使用することで、長距離におけるデータ伝送が可能です。
使用する方がいましたら、参考にしてください。
Va10, Va11, Va12にセンサで取得したデータを代入することで、
観測機器を製作できます。
[ M5stack Basic code ]
#include <M5Stack.h>
#include <stdint.h>
#include <vector>
#include "TFTTerminal.h"
/*serial通信のinclude
#include <WiFi.h>
#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;
uint32_t numberbuff[128];
String readstr;
uint8_t restate;
char buffer[255];
uint32_t interval = 1; // unit:sec
uint16_t chipid = ESP.getEfuseMac() % 10000;
const char* deployid = "AKfycbw1vfUnV_E6B9O0tWaKMPKXkvahMsXIG-jrpk2SS2a1kGAAz59iQy1_p_H7kp7x8VnKsg";
const char *send_url = "https://script.google.com/macros/s/AKfycbyMcbm5u-ySil5s6LF6__EyyAVYMt9idkIRBaRBWk3ut3jR3A9VFe7lobGQE9qdBHuR/exec";
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);
while ((readSendState(0) == kSendReady) || (readSendState(0) == kSending) ||
(readSendState(0) == kWaitforMsg))
delay(50);
restate = readSendState(0);
readstr = ReadMsgstr(0).c_str();
EraseFirstMsg();
terminal.print(readstr);
}
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;
}
//データ送信プログラム
void addRowToGoogleSheetsdoGet(float val0, float val1, float val2) {
//URL
//String url = "https://script.google.com/macros/s/" + String(deployid) + "/exec?chipid=ESP" + String(chipid) + "&val0=" + String(val0) + "&val1=" + String(val1) + "&val2=" + String(val2);
String url = String(send_url) + "?chipid=ESP" + String(chipid) + "&val0=" + String(val0) + "&val1=" + String(val1) + "&val2=" + String(val2);
terminal.println("[HTTP] begin...");
terminal.println(url);
terminal.println("[HTTP] POST...");
// コンテンツタイプの設定
AddMsg("AT+HTTPPARA=\"CONTENT\",\"application/json\"\r\n", kASSIGN_MT, 1000, 1000);
// AT commmand : URLの設定 & http post(今回はURLにデータを追加している)
AddMsg("AT+HTTPPARA=\"URL\",\"" + url + "\"\r\n", kASSIGN_MT, 1000, 1000);
delay(1000);
terminal.println("[HTTP] GET...");
// HTTP GET リクエスト
AddMsg("AT+HTTPACTION=0\r\n", kASSIGN_MT, 5000, 5000);
delay(1000);
}
//データdopost送信プログラム
void addRowToGoogleSheetsdoPost(float val0, float val1, float val2) {
//URL
//String url = "https://script.google.com/macros/s/" + String(deployid) + "/exec?chipid=ESP" + String(chipid) + "&val0=" + String(val0) + "&val1=" + String(val1) + "&val2=" + String(val2);
//String url = String(send_url) + "?chipid=ESP" + String(chipid) + "&val0=" + String(val0) + "&val1=" + String(val1) + "&val2=" + String(val2);
String jsonPayload = "{\"chipid\":\"ESP" + String(chipid) +
"\", \"val0\":" + String(val0) +
", \"val1\":" + String(val1) +
", \"val2\":" + String(val2) + "}";
terminal.println("[HTTP] begin...");
terminal.println("[HTTP] POST...");
// HTTPヘッダーを設定
AddMsg("AT+HTTPPARA=\"URL\",\"" + String(send_url) + "\"\r\n", kASSIGN_MT, 1000, 1000);
AddMsg("AT+HTTPPARA=\"CONTENT\",\"application/json\"\r\n", kASSIGN_MT, 1000, 1000);
// データを送信
AddMsg("AT+HTTPDATA=" + String(jsonPayload.length()) + ",10000\r\n", kASSIGN_MT, 1000, 1000);
delay(100);
AddMsg(jsonPayload + "\r\n", kASSIGN_MT, 1000, 1000);
delay(100);
AddMsg("AT+HTTPACTION=1\r\n", kASSIGN_MT, 5000, 5000);
delay(1000);
terminal.println("[HTTP] GET...");
// HTTP GET リクエスト
AddMsg("AT+HTTPACTION=0\r\n", kASSIGN_MT, 5000, 5000);
delay(1000);
}
void setup() {
// put your setup code here, to run once:
M5.begin(true, true, true, false); //LCD, SDカード, serial, I2Cの有効無効
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);
terminal.println("Initializing SIM7600...");
// モジュール起動確認
AddMsg("AT\r\n", kQUERY_MT, 1000, 1000);
// 機能の追加(フルモード)
AddMsg("AT+CFUN=1\r\n", kQUERY_MT, 1000, 1000);
// LTE接続
AddMsg("AT+CGATT=1\r\n", kQUERY_MT, 1000, 1000);
// 通信強度
AddMsg("AT+CSQ\r\n", kQUERY_MT, 1000, 1000);
// インターネット登録状況
AddMsg("AT+CREG?\r\n", kQUERY_MT, 1000, 1000);
// APN設定
AddMsg("AT+CGDCONT = 1, \"IP\", \"" + sim_apn + "\"\r\n", kASSIGN_MT, 1000, 1000);
// 認証情報の設定 : 無くても良い
//AddMsg("AT+CGAUTH = 1, \"" + sim_user + "\", \"" + sim_pass + "\"\r\n", kASSIGN_MT, 1000, 1000);
// PDPコンテキスト有効化
AddMsg("AT+CGACT=1,1\r\n", kQUERY_MT, 1000, 1000);
// HTTP機能の初期化
AddMsg("AT+HTTPINIT\r\n", kQUERY_MT, 1000, 1000);
// PDPコンテキストを設定
AddMsg("AT+HTTPPARA=\"CID\",1\r\n", kQUERY_MT, 1000, 1000);
}
void loop() {
M5.update();
float val0 = random(0, 1000) / 10.0;
float val1 = random(0, 1000) / 10.0;
float val2 = random(0, 1000) / 10.0;
terminal.print("ESP");
terminal.println(chipid);
terminal.printf("[val0] %.1f\n[val1] %.1f\n[val2] %.1f\n", val0, val1, val2);
addRowToGoogleSheetsdoGet(val0, val1, val2);
//addRowToGoogleSheetsdoPost(val0, val1, val2);
delay(interval * 1000);
if (M5.BtnC.wasPressed()) {
terminal.println("Restarting...");
delay(1000);
esp_restart(); // ESP32をリセット
}
delay(1000);
esp_sleep_enable_timer_wakeup(10000);
esp_sleep_enable_ext0_wakeup((gpio_num_t)M5.BtnA.wasPressed(), 0);
esp_deep_sleep_start();
}
/*本来のhttp post方法(仮)-----------------------------------------------------
// URL を設定
AddMsg("AT+HTTPPARA=\"URL\",\"" + url + "\"\r\n", kASSIGN_MT, 1000, 1000);
// コンテンツのタイプを設定(JSON 例)
AddMsg("AT+HTTPPARA=\"CONTENT\",\"application/json\"\r\n", kASSIGN_MT, 1000, 1000);
// 送信データの準備(例:50バイトのデータを10秒以内に送信)
AddMsg("AT+HTTPDATA=50,10000\r\n", kASSIGN_MT, 1000, 1000);
delay(100); // 少し待機
// 送信する JSON データを設定(例)
AddMsg("{\"temperature\":25.5,\"humidity\":60}\r\n", kASSIGN_MT, 1000, 1000);
delay(100);
// HTTP POST を開始
AddMsg("AT+HTTPACTION=1\r\n", kASSIGN_MT, 1000, 1000);
delay(5000); // 応答待機
// レスポンスを取得(HTTP GET)
AddMsg("AT+HTTPREAD\r\n", kASSIGN_MT, 1000, 1000);
--------------------------------------------------------------------------------*/
[ Google Spread Sheet code ]
function doGet(e) {
Logger.log("Received GET request: " + JSON.stringify(e));
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
if (!sheet) {
return ContentService.createTextOutput("Error: Sheet not found").setMimeType(ContentService.MimeType.TEXT);
}
// パラメータを取得
var chipid = e.parameter.chipid || "Unknown";
var val0 = parseFloat(e.parameter.val0) || 0;
var val1 = parseFloat(e.parameter.val1) || 0;
var val2 = parseFloat(e.parameter.val2) || 0;
// スプレッドシートにデータを記録
sheet.insertRowBefore(2);
sheet.getRange(2, 1).setValue(new Date()); // 受信日時
sheet.getRange(2, 2).setValue(chipid);
sheet.getRange(2, 3).setValue(val0);
sheet.getRange(2, 4).setValue(val1);
sheet.getRange(2, 5).setValue(val2);
return ContentService.createTextOutput("Data received successfully").setMimeType(ContentService.MimeType.TEXT);
}
以下は本プログラムの動作及び、システム構成です。
COM.LTE_page-0001.jpg
COM.LTE_page-0002.jpg
COM.LTE_page-0003.jpg
COM.LTE_page-0004.jpg
COM.LTE_page-0005.jpg
COM.LTE_page-0006.jpg