Hello. All
having. problem sending. sms. commands
project: location tracker. operates. by 3. sms commands
L- location (shows. location when hit it. on phone)
T - tracking. Live S - stop. tracking ( T & S are beyond. this. scope. of this post)
equipment :XIAO esp32 c6, - SIM 7600 g-h - TP4056. - buck. converter
SIM card - Hologram. for. now. im. focusing. on troubleshooting. of. sending. receiving. sms
no power. issue. steady. read. light. green. light. blkinks.
following. AT commands. i. sent. and. responses ( took. me. hours. to. succed...)
Testing modem...
AT
OK
AT+CMGF=1
OK
AT+CNMI=2,1
OK
SMS + GPS tracker ready.
----------------------------------------------
some. number. and. message. body.
Message (Enter to send message to 'XIAO_ESP32C6' on '/dev/cu.usbmodem21201')
Both NL & CR
115200 baud
+CMTI: "SM",1
AT+CMGR=1
+CMGR: "REC UNREAD","467190002980389","","26/04/29,04:25:10+08"
hello. please. send. my. message
OK
AT+CMGL="ALL"
+CMGL: 1,"REC READ","467190002980389","","26/04/29,04:25:10+08"
hello. please. send. my. message
+CMGL: 0,"REC UNREAD","467190002980389","","26/04/28,19:22:50+08"
Lsome. number. and. message. body.
Message (Enter to send message to 'XIAO_ESP32C6' on '/dev/cu.usbmodem21201')
Both NL & CR
115200 baud
+CMTI: "SM",1
AT+CMGR=1
+CMGR: "REC UNREAD","467190002980389","","26/04/29,04:25:10+08"
hello. please. send. my. message
OK
AT+CMGL="ALL"
L
____________________________________
AT
OK
AT+CMGF=1
OK
AT+CNMI=2,1
OK
SMS + GPS tracker ready.
+
+________________________________________
so. seems. like. the. modem respons. sends/. receives. sms. but. something. is. still. wrong. Also. on. hologram. dashboard. it. says sms. semds. and. i. can. see L. in received. messages (. by the. way. purchased a. hologram phone. number)
Thank. you. for. your. help!!
code
#include <Arduino.h> #include <HardwareSerial.h> // ===================================================== // PINS // ===================================================== static const int SIM7600_PWRKEY_PIN = D0; static const int SIM7600_TX_PIN = D6; static const int SIM7600_RX_PIN = D7; static const int MOTION_PIN = D4; // ===================================================== // SERIAL // ===================================================== HardwareSerial sim7600(1); // ===================================================== // USER SETTINGS // ===================================================== const char *OWNER_NUMBER = "467190002980389"; // ===================================================== // TIMING // ===================================================== const unsigned long MOTION_COOLDOWN_MS = 60000; const unsigned long TRACK_INTERVAL_MS = 30000; const unsigned long GPS_RETRY_DELAY_MS = 2000; const int GPS_MAX_TRIES = 8; // ===================================================== // STATE // ===================================================== bool trackingActive = false; unsigned long lastMotionAlert = 0; unsigned long lastTrackUpdate = 0; String modemBuffer = ""; // ===================================================== // GPS STRUCT // ===================================================== struct GPSData { bool valid; float lat; float lon; String latStr; String lonStr; }; // ===================================================== // FUNCTION DECLARATIONS // ===================================================== void powerOnSIM7600(); String sendAT(const String &cmd, const String &expect, unsigned long timeout); bool sendSMS(const String &number, const String &message); String extractSmsBody(const String &raw); String extractSmsSender(const String &raw); bool isOwnerNumber(const String &sender); float convertDegMinToDecimal(String dm, String hemi); GPSData parseCGPSINFO(const String &resp); GPSData readGPS(); String buildGoogleMapsLink(const GPSData &gps); void sendLocationSMS(); void handleMotionAlert(); void handleLiveTracking(); void processSmsSlot(int slot); // ===================================================== // MODEM POWER // ===================================================== void powerOnSIM7600() { pinMode(SIM7600_PWRKEY_PIN, OUTPUT); digitalWrite(SIM7600_PWRKEY_PIN, HIGH); delay(200); digitalWrite(SIM7600_PWRKEY_PIN, LOW); delay(300); digitalWrite(SIM7600_PWRKEY_PIN, HIGH); delay(6000); } // ===================================================== // AT HELPER // ===================================================== String sendAT(const String &cmd, const String &expect, unsigned long timeout) { while (sim7600.available()) { sim7600.read(); } sim7600.println(cmd); String response = ""; unsigned long start = millis(); while (millis() - start < timeout) { while (sim7600.available()) { char c = (char)sim7600.read(); response += c; if (expect.length() > 0 && response.indexOf(expect) != -1) { return response; } } } return response; } // ===================================================== // SEND SMS // ===================================================== bool sendSMS(const String &number, const String &message) { sendAT("AT+CMGF=1", "OK", 3000); while (sim7600.available()) { sim7600.read(); } sim7600.print("AT+CMGS=\""); sim7600.print(number); sim7600.print("\"\r"); String prompt = ""; unsigned long start = millis(); while (millis() - start < 8000) { while (sim7600.available()) { char c = (char)sim7600.read(); prompt += c; if (prompt.indexOf(">") != -1) { sim7600.print(message); sim7600.write(26); String result = ""; unsigned long sendStart = millis(); while (millis() - sendStart < 15000) { while (sim7600.available()) { char r = (char)sim7600.read(); result += r; if (result.indexOf("OK") != -1) return true; if (result.indexOf("ERROR") != -1) return false; } } } } } return false; } // ===================================================== // SMS PARSING // ===================================================== String extractSmsBody(const String &raw) { int headerEnd = raw.indexOf('\n'); if (headerEnd == -1) return ""; String body = raw.substring(headerEnd + 1); body.trim(); int okPos = body.lastIndexOf("OK"); if (okPos != -1) { body = body.substring(0, okPos); } body.trim(); return body; } String extractSmsSender(const String &raw) { int idx = raw.indexOf("+CMGR:"); if (idx == -1) return ""; int lineEnd = raw.indexOf('\n', idx); String header = (lineEnd == -1) ? raw.substring(idx) : raw.substring(idx, lineEnd); int q1 = header.indexOf('"'); if (q1 == -1) return ""; int q2 = header.indexOf('"', q1 + 1); if (q2 == -1) return ""; int q3 = header.indexOf('"', q2 + 1); if (q3 == -1) return ""; int q4 = header.indexOf('"', q3 + 1); if (q4 == -1) return ""; return header.substring(q3 + 1, q4); } bool isOwnerNumber(const String &sender) { if (sender.length() == 0) return false; return sender.indexOf(OWNER_NUMBER) != -1; } // ===================================================== // GPS HELPERS // ===================================================== float convertDegMinToDecimal(String dm, String hemi) { if (dm.length() < 4) return 0.0; int dot = dm.indexOf('.'); if (dot == -1) return 0.0; int degDigits = (dot > 4) ? 3 : 2; float degrees = dm.substring(0, degDigits).toFloat(); float minutes = dm.substring(degDigits).toFloat(); float decimal = degrees + (minutes / 60.0); if (hemi == "S" || hemi == "W") { decimal = -decimal; } return decimal; } GPSData parseCGPSINFO(const String &resp) { GPSData gps = {false, 0.0, 0.0, "", ""}; int idx = resp.indexOf("+CGPSINFO:"); if (idx == -1) return gps; int endLine = resp.indexOf('\n', idx); String line = (endLine == -1) ? resp.substring(idx) : resp.substring(idx, endLine); line.trim(); int colon = line.indexOf(':'); if (colon == -1) return gps; String data = line.substring(colon + 1); data.trim(); int p1 = data.indexOf(','); if (p1 == -1) return gps; int p2 = data.indexOf(',', p1 + 1); if (p2 == -1) return gps; int p3 = data.indexOf(',', p2 + 1); if (p3 == -1) return gps; int p4 = data.indexOf(',', p3 + 1); if (p4 == -1) return gps; String rawLat = data.substring(0, p1); String ns = data.substring(p1 + 1, p2); String rawLon = data.substring(p2 + 1, p3); String ew = data.substring(p3 + 1, p4); rawLat.trim(); ns.trim(); rawLon.trim(); ew.trim(); if (rawLat.length() == 0 || rawLon.length() == 0) return gps; gps.lat = convertDegMinToDecimal(rawLat, ns); gps.lon = convertDegMinToDecimal(rawLon, ew); gps.latStr = String(gps.lat, 6); gps.lonStr = String(gps.lon, 6); gps.valid = true; return gps; } GPSData readGPS() { GPSData gps = {false, 0.0, 0.0, "", ""}; sendAT("AT+CGPS=1", "OK", 5000); for (int i = 0; i < GPS_MAX_TRIES; i++) { delay(GPS_RETRY_DELAY_MS); String resp = sendAT("AT+CGPSINFO", "OK", 6000); Serial.println("----- CGPSINFO RAW -----"); Serial.println(resp); Serial.println("------------------------"); gps = parseCGPSINFO(resp); if (gps.valid) return gps; } return gps; } String buildGoogleMapsLink(const GPSData &gps) { return "https://maps.google.com/?q=" + gps.latStr + "," + gps.lonStr; } // ===================================================== // ACTIONS // ===================================================== void sendLocationSMS() { GPSData gps = readGPS(); if (!gps.valid) { sendSMS(OWNER_NUMBER, "GPS fix not available yet."); return; } String msg = "Location: " + buildGoogleMapsLink(gps); sendSMS(OWNER_NUMBER, msg); } void handleMotionAlert() { if (digitalRead(MOTION_PIN) != HIGH) return; unsigned long now = millis(); if (now - lastMotionAlert < MOTION_COOLDOWN_MS) return; lastMotionAlert = now; sendSMS(OWNER_NUMBER, "ALERT: Motion detected."); } void handleLiveTracking() { if (!trackingActive) return; unsigned long now = millis(); if (now - lastTrackUpdate < TRACK_INTERVAL_MS) return; lastTrackUpdate = now; sendLocationSMS(); } // ===================================================== // SMS SLOT PROCESSOR // ===================================================== void processSmsSlot(int slot) { sendAT("AT+CMGF=1", "OK", 3000); String raw = sendAT("AT+CMGR=" + String(slot), "OK", 5000); Serial.println("----- CMGR RAW -----"); Serial.println(raw); Serial.println("--------------------"); String upper = raw; upper.toUpperCase(); if (upper.indexOf("\nL") != -1 || upper.indexOf("\r\nL") != -1 || upper.endsWith("L")) { sendLocationSMS(); } else if (upper.indexOf("\nT") != -1 || upper.indexOf("\r\nT") != -1 || upper.endsWith("T")) { trackingActive = true; sendSMS(OWNER_NUMBER, "Live tracking started."); } else if (upper.indexOf("\nS") != -1 || upper.indexOf("\r\nS") != -1 || upper.endsWith("S")) { trackingActive = false; sendSMS(OWNER_NUMBER, "Live tracking stopped."); } else { sendSMS(OWNER_NUMBER, "Unknown command. Use L, T, or S."); } sendAT("AT+CMGD=" + String(slot), "OK", 3000); } // ===================================================== // SETUP // ===================================================== void setup() { Serial.begin(115200); delay(5000); Serial.println("Testing... Serial is alive!"); pinMode(MOTION_PIN, INPUT); powerOnSIM7600(); sim7600.begin(115200, SERIAL_8N1, SIM7600_RX_PIN, SIM7600_TX_PIN); delay(3000); Serial.println("Testing modem..."); Serial.println(sendAT("AT", "OK", 3000)); Serial.println(sendAT("AT+CMGF=1", "OK", 3000)); Serial.println(sendAT("AT+CNMI=2,1", "OK", 3000)); Serial.println("SMS + GPS tracker ready."); } // ===================================================== // LOOP // ===================================================== void loop() { while (sim7600.available()) { char c = (char)sim7600.read(); modemBuffer += c; Serial.write(c); int idx = modemBuffer.indexOf("+CMTI:"); if (idx != -1) { int comma = modemBuffer.lastIndexOf(','); if (comma != -1) { int slot = modemBuffer.substring(comma + 1).toInt(); if (slot > 0) { processSmsSlot(slot); } } modemBuffer = ""; } if (modemBuffer.length() > 160) { modemBuffer = ""; } } handleMotionAlert(); handleLiveTracking();