#include #include // --- SIM7080G Pin Definitions --- #define LTE_RX_PIN 16 // ESP32 GPIO16 connected to SIM7080G TX #define LTE_TX_PIN 17 // ESP32 GPIO17 connected to SIM7080G RX #define PWRKEY_PIN 4 // ESP32 GPIO4 connected to SIM7080G PWRKEY // --- Network Configuration --- const char *HOLOGRAM_APN = "hologram"; // --- Global Variables --- String currentIMEI = ""; // --- Function Prototypes --- void powerOnModule(); void powerOffModule(); String sendATCommand(String command, unsigned long timeoutMs = 3000); String getIMEI(); bool activatePDPContextAndBearer(); void getGpsLocation(); // Function to get and print GPS data void setup() { Serial.begin(115200); while (!Serial) { delay(10); } Serial.println("--- Starting ESP32 to SIM7080G GPS Test (Final) ---"); Serial2.begin(115200, SERIAL_8N1, LTE_RX_PIN, LTE_TX_PIN); powerOffModule(); delay(3000); powerOnModule(); // Step 1: "Nudge and Listen" for the initial boot-up. Serial.println( "Waiting for initial module boot (90s timeout)..."); unsigned long startTime = millis(); unsigned long lastNudgeTime = 0; const unsigned long NUDGE_INTERVAL = 3000; bool moduleBooted = false; String bootResponse = ""; while (millis() - startTime < 90000 && !moduleBooted) { while (Serial2.available()) { char c = Serial2.read(); Serial.write(c); bootResponse += c; if (bootResponse.indexOf("SMS Ready") != -1) { moduleBooted = true; break; } } if (moduleBooted) { break; } if (millis() - lastNudgeTime > NUDGE_INTERVAL) { Serial2.println("AT"); lastNudgeTime = millis(); } } if (!moduleBooted) { Serial.println("Module did not complete initial boot. Halting."); while (true) ; } Serial.println("\nInitial boot successful!"); // Step 2: Apply the proven network configuration from your manual test. Serial.println("\nApplying network configuration..."); sendATCommand("AT+CMEE=1", 1000); sendATCommand("AT+CNMP=38", 5000); sendATCommand("AT+CMNB=3", 5000); // Step 3: Perform the full CFUN reset cycle to apply settings. Serial.println("Applying settings with full CFUN reset..."); sendATCommand("AT+CFUN=0", 5000); delay(5000); sendATCommand("AT+CFUN=1", 10000); // Step 4: Wait for the modem to apply settings and find the network. Serial.println( "Waiting 45 seconds for modem to apply settings and find network..."); delay(45000); Serial.println("\nChecking network status..."); currentIMEI = getIMEI(); // Step 5: Check for network registration. unsigned long networkRegStartTime = millis(); bool networkRegistered = false; while (millis() - networkRegStartTime < 120000 && !networkRegistered) { String regResponse = sendATCommand("AT+CGREG?", 3000); if (regResponse.indexOf("+CGREG: 0,1") != -1 || regResponse.indexOf("+CGREG: 0,5") != -1) { networkRegistered = true; } if (networkRegistered) { Serial.println("Network registration successful!"); break; } Serial.println("Not yet registered. Retrying..."); delay(5000); } if (!networkRegistered) { Serial.println("Failed to register to network. Halting."); while (true) ; } // --- GPS INITIALIZATION --- Serial.println("\n--- Turning on GPS ---"); sendATCommand("AT+CGPS=1", 1000); // Turn on the GPS receiver Serial.println( "GPS is on. It may take several minutes to get the first fix."); Serial.println("\n--- Setup complete. Starting main loop. ---"); } void loop() { Serial.println("\n--- Requesting GPS Location ---"); getGpsLocation(); delay(30000); // Wait 30 seconds before the next request } void getGpsLocation() { String response = sendATCommand("AT+CGPSINFO", 5000); if (response.indexOf("+CGPSINFO:") != -1) { response.replace("+CGPSINFO: ", ""); response.trim(); if (response.startsWith(",")) { Serial.println("GPS has no fix yet."); return; } int firstComma = response.indexOf(','); String latDDMM = response.substring(0, firstComma); int secondComma = response.indexOf(',', firstComma + 1); String nsIndicator = response.substring(firstComma + 1, secondComma); int thirdComma = response.indexOf(',', secondComma + 1); String lonDDMM = response.substring(secondComma + 1, thirdComma); int fourthComma = response.indexOf(',', thirdComma + 1); String ewIndicator = response.substring(thirdComma + 1, fourthComma); double latitude = 0.0; if (latDDMM.length() > 2) { double degrees = latDDMM.substring(0, 2).toDouble(); double minutes = latDDMM.substring(2).toDouble(); latitude = degrees + (minutes / 60.0); if (nsIndicator == "S") { latitude = -latitude; } } double longitude = 0.0; if (lonDDMM.length() > 3) { double degrees = lonDDMM.substring(0, 3).toDouble(); double minutes = lonDDMM.substring(3).toDouble(); longitude = degrees + (minutes / 60.0); if (ewIndicator == "W") { longitude = -longitude; } } Serial.print("Latitude: "); Serial.println(latitude, 6); Serial.print("Longitude: "); Serial.println(longitude, 6); } else { Serial.println("Failed to get GPS info from module."); } } // --- All other helper functions remain the same --- void powerOnModule() { Serial.println("Executing SIM7080G power-on sequence..."); pinMode(PWRKEY_PIN, OUTPUT); digitalWrite(PWRKEY_PIN, HIGH); delay(100); digitalWrite(PWRKEY_PIN, LOW); delay(2000); digitalWrite(PWRKEY_PIN, HIGH); } void powerOffModule() { Serial.println("Executing SIM7080G power-off sequence..."); pinMode(PWRKEY_PIN, OUTPUT); digitalWrite(PWRKEY_PIN, HIGH); delay(100); digitalWrite(PWRKEY_PIN, LOW); delay(2000); digitalWrite(PWRKEY_PIN, HIGH); } String sendATCommand(String command, unsigned long timeoutMs) { Serial.print("Sending: "); Serial.println(command); while (Serial2.available()) { Serial2.read(); } Serial2.println(command); String response = ""; unsigned long startTime = millis(); while (millis() - startTime < timeoutMs) { while (Serial2.available()) { char c = (char)Serial2.read(); response += c; startTime = millis(); if (response.endsWith("OK\r\n") || response.endsWith("ERROR\r\n") || response.endsWith("FAIL\r\n")) { response.trim(); return response; } } } response.trim(); return response; } String getIMEI() { String response = sendATCommand("AT+CGSN", 5000); int currentPos = 0; while (currentPos < response.length()) { int nextNewline = response.indexOf('\n', currentPos); String line = (nextNewline == -1) ? response.substring(currentPos) : response.substring(currentPos, nextNewline); currentPos = (nextNewline == -1) ? response.length() : nextNewline + 1; line.trim(); if (line.length() == 15) { bool allDigits = true; for (int i = 0; i < line.length(); i++) { if (!isDigit(line.charAt(i))) { allDigits = false; break; } } if (allDigits) { return line; } } } return ""; } // This function is no longer called in setup, but is kept for future use bool activatePDPContextAndBearer() { Serial.println("Defining PDP Context..."); String response = sendATCommand( "AT+CGDCONT=1,\"IP\",\"" + String(HOLOGRAM_APN) + "\"", 5000); if (response.indexOf("OK") == -1) return false; Serial.println("Activating PDP Context..."); response = sendATCommand("AT+CGACT=1,1", 10000); if (response.indexOf("OK") == -1) return false; Serial.println("Waiting 5 seconds for IP assignment..."); delay(5000); Serial.println("Checking IP address..."); response = sendATCommand("AT+CGPADDR=1", 5000); if (response.indexOf("+CGPADDR: 1,") == -1) return false; return true; }