From d1125b765155d4cae5e363755de3e7e50f03929d Mon Sep 17 00:00:00 2001 From: sam rolfe Date: Sat, 23 Aug 2025 07:28:01 +1000 Subject: [PATCH] Script connects to hologram --- CAR_GPS_TRACKER.ino | 336 ++++++++++++++++++++++++++++++++------------ 1 file changed, 244 insertions(+), 92 deletions(-) diff --git a/CAR_GPS_TRACKER.ino b/CAR_GPS_TRACKER.ino index aac0a4d..008ed6c 100644 --- a/CAR_GPS_TRACKER.ino +++ b/CAR_GPS_TRACKER.ino @@ -1,123 +1,275 @@ -#include // Using HardwareSerial2 for better performance +#include +#include // --- SIM7080G Pin Definitions --- -// Make sure these match your board's actual connections. -// If using the Waveshare example's pins 10,11 this would need SoftwareSerial. -// We are using HardwareSerial2 here (pins 16, 17) for efficiency if available. #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 (as before) +#define PWRKEY_PIN 4 // ESP32 GPIO4 connected to SIM7080G PWRKEY + +// --- Network Configuration --- +const char *HOLOGRAM_APN = "hologram"; + +// --- Global Variables --- +String currentIMEI = ""; // --- Function Prototypes --- -// REVISED: powerUp function based on Waveshare example timing -void powerUp(); -// REVISED: sendCommandAndPrintAllResponse - will simply print all modem output -String sendCommandAndPrintAllResponse(String command, unsigned long timeoutMs = 3000); +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); // For debugging output to PC - while (!Serial) { - delay(10); // Wait for Serial Monitor to connect - } - Serial.println("--- Starting SIM7080G Basic Communication Test ---"); - Serial.println("Configuring Serial2 for LTE module at 115200 baud."); + Serial.begin(115200); + while (!Serial) { + delay(10); + } + Serial.println("--- Starting ESP32 to SIM7080G GPS Test (Final) ---"); - // Initialize Serial2 for communication with the SIM7080G - Serial2.begin(115200, SERIAL_8N1, LTE_RX_PIN, LTE_TX_PIN); + Serial2.begin(115200, SERIAL_8N1, LTE_RX_PIN, LTE_TX_PIN); - // Set PWRKEY pin mode and ensure it's LOW initially as per Waveshare setup. - pinMode(PWRKEY_PIN, OUTPUT); - digitalWrite(PWRKEY_PIN, LOW); // Important to ensure a known initial state - delay(1000); // Small delay to stabilize + powerOffModule(); + delay(3000); + powerOnModule(); - Serial.println("Attempting Modem Power Up sequence..."); - powerUp(); // Call the revised powerUp sequence + // 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 = ""; - Serial.println("Power Up sequence initiated. Waiting for modem to become responsive (up to 120 seconds)..."); - unsigned long modemReadyStartTime = millis(); - const unsigned long MODEM_READY_TIMEOUT = 120 * 1000; // Total 120 seconds timeout + 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(); + } + } - // Loop to repeatedly send "AT" and check for any response - Serial.println("Repeatedly sending 'AT' to check for responsiveness..."); - while (millis() - modemReadyStartTime < MODEM_READY_TIMEOUT) { - String response = sendCommandAndPrintAllResponse("AT", 1500); // Send AT, wait 1.5s for any response - if (response.indexOf("OK") != -1) { - Serial.println("Modem is responsive! Continuing initial checks."); - break; - } - Serial.print("Modem not yet responsive ("); - Serial.print((millis() - modemReadyStartTime) / 1000); - Serial.println("s elapsed). Retrying..."); - delay(2000); // Wait 2 seconds before retrying AT command - } + if (!moduleBooted) { + Serial.println("Module did not complete initial boot. Halting."); + while (true) + ; + } + Serial.println("\nInitial boot successful!"); - if (millis() - modemReadyStartTime >= MODEM_READY_TIMEOUT) { - Serial.println("Modem did not become responsive within timeout. Check wiring, module power, and PWRKEY sequence."); - while(true); // Halt if modem fails to become responsive - } + // 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); - Serial.println("\n--- Basic AT Command Tests ---"); - delay(1000); // Small delay before next command - sendCommandAndPrintAllResponse("ATI", 3000); // Get product ID - delay(1000); - sendCommandAndPrintAllResponse("AT+CMEE=1", 1000); // Enable verbose errors - delay(1000); - sendCommandAndPrintAllResponse("AT+CPIN?", 3000); // Check SIM status - delay(1000); + // 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); - Serial.println("\n--- Setup complete. Monitor loop output for continuous checks. ---"); + // 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() { - // Continuously check basic modem status to see if it remains responsive - Serial.println("\n--- Loop: Continuous Basic Checks ---"); - sendCommandAndPrintAllResponse("AT", 1000); - delay(5000); // Check every 5 seconds + Serial.println("\n--- Requesting GPS Location ---"); + getGpsLocation(); + delay(30000); // Wait 30 seconds before the next request } +void getGpsLocation() { + String response = sendATCommand("AT+CGPSINFO", 5000); -// REVISED: powerUp function based on Waveshare example timing -void powerUp(){ - Serial.println("Applying power pulse to PWRKEY_PIN (GPIO4)..."); - digitalWrite(PWRKEY_PIN, HIGH); // Ensure HIGH first (idle state) - delay(100); // Small stabilization delay + if (response.indexOf("+CGPSINFO:") != -1) { + response.replace("+CGPSINFO: ", ""); + response.trim(); - digitalWrite(PWRKEY_PIN, LOW); // Pull PWRKEY low - delay(2000); // Hold low for 2 seconds (as per Waveshare example) - digitalWrite(PWRKEY_PIN, HIGH); // Release PWRKEY (set HIGH) - // The long boot delay is handled in setup() to monitor responsiveness - Serial.println("PWRKEY pulse complete. Module should now be booting."); + 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 --- -// REVISED: sendCommandAndPrintAllResponse function for raw modem output debugging -String sendCommandAndPrintAllResponse(String command, unsigned long timeoutMs) { - Serial.print("Sending: "); - Serial.println(command); +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); +} - // Clear Serial2 receive buffer before sending command - while (Serial2.available()) { - Serial2.read(); - } +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); +} - Serial2.println(command); // Send command to the modem +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 rawResponse = ""; - unsigned long startTime = millis(); - - while (millis() - startTime < timeoutMs) { - if (Serial2.available()) { - char c = (char)Serial2.read(); - rawResponse += c; - startTime = millis(); // Reset timeout as long as data is being received - } - delay(1); // Small delay to prevent busy-waiting - } +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 ""; +} - Serial.println("--- Raw Modem Response Received ---"); - Serial.println(rawResponse); // Print everything received (raw, untrimmed) - Serial.println("-----------------------------------"); - - return rawResponse; // Return the raw response for checking in setup/loop +// 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; } \ No newline at end of file