Script connects to hologram
This commit is contained in:
@ -1,123 +1,275 @@
|
|||||||
#include <HardwareSerial.h> // Using HardwareSerial2 for better performance
|
#include <ArduinoJson.h>
|
||||||
|
#include <HardwareSerial.h>
|
||||||
|
|
||||||
// --- SIM7080G Pin Definitions ---
|
// --- 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_RX_PIN 16 // ESP32 GPIO16 connected to SIM7080G TX
|
||||||
#define LTE_TX_PIN 17 // ESP32 GPIO17 connected to SIM7080G RX
|
#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 ---
|
// --- Function Prototypes ---
|
||||||
// REVISED: powerUp function based on Waveshare example timing
|
void powerOnModule();
|
||||||
void powerUp();
|
void powerOffModule();
|
||||||
// REVISED: sendCommandAndPrintAllResponse - will simply print all modem output
|
String sendATCommand(String command, unsigned long timeoutMs = 3000);
|
||||||
String sendCommandAndPrintAllResponse(String command, unsigned long timeoutMs = 3000);
|
String getIMEI();
|
||||||
|
bool activatePDPContextAndBearer();
|
||||||
|
void getGpsLocation(); // Function to get and print GPS data
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200); // For debugging output to PC
|
Serial.begin(115200);
|
||||||
while (!Serial) {
|
while (!Serial) {
|
||||||
delay(10); // Wait for Serial Monitor to connect
|
delay(10);
|
||||||
}
|
}
|
||||||
Serial.println("--- Starting SIM7080G Basic Communication Test ---");
|
Serial.println("--- Starting ESP32 to SIM7080G GPS Test (Final) ---");
|
||||||
Serial.println("Configuring Serial2 for LTE module at 115200 baud.");
|
|
||||||
|
|
||||||
// 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.
|
powerOffModule();
|
||||||
pinMode(PWRKEY_PIN, OUTPUT);
|
delay(3000);
|
||||||
digitalWrite(PWRKEY_PIN, LOW); // Important to ensure a known initial state
|
powerOnModule();
|
||||||
delay(1000); // Small delay to stabilize
|
|
||||||
|
|
||||||
Serial.println("Attempting Modem Power Up sequence...");
|
// Step 1: "Nudge and Listen" for the initial boot-up.
|
||||||
powerUp(); // Call the revised powerUp sequence
|
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)...");
|
while (millis() - startTime < 90000 && !moduleBooted) {
|
||||||
unsigned long modemReadyStartTime = millis();
|
while (Serial2.available()) {
|
||||||
const unsigned long MODEM_READY_TIMEOUT = 120 * 1000; // Total 120 seconds timeout
|
char c = Serial2.read();
|
||||||
|
Serial.write(c);
|
||||||
// Loop to repeatedly send "AT" and check for any response
|
bootResponse += c;
|
||||||
Serial.println("Repeatedly sending 'AT' to check for responsiveness...");
|
if (bootResponse.indexOf("SMS Ready") != -1) {
|
||||||
while (millis() - modemReadyStartTime < MODEM_READY_TIMEOUT) {
|
moduleBooted = true;
|
||||||
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;
|
break;
|
||||||
}
|
}
|
||||||
Serial.print("Modem not yet responsive (");
|
}
|
||||||
Serial.print((millis() - modemReadyStartTime) / 1000);
|
if (moduleBooted) {
|
||||||
Serial.println("s elapsed). Retrying...");
|
break;
|
||||||
delay(2000); // Wait 2 seconds before retrying AT command
|
}
|
||||||
|
if (millis() - lastNudgeTime > NUDGE_INTERVAL) {
|
||||||
|
Serial2.println("AT");
|
||||||
|
lastNudgeTime = millis();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (millis() - modemReadyStartTime >= MODEM_READY_TIMEOUT) {
|
if (!moduleBooted) {
|
||||||
Serial.println("Modem did not become responsive within timeout. Check wiring, module power, and PWRKEY sequence.");
|
Serial.println("Module did not complete initial boot. Halting.");
|
||||||
while(true); // Halt if modem fails to become responsive
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println("\n--- Basic AT Command Tests ---");
|
if (!networkRegistered) {
|
||||||
delay(1000); // Small delay before next command
|
Serial.println("Failed to register to network. Halting.");
|
||||||
sendCommandAndPrintAllResponse("ATI", 3000); // Get product ID
|
while (true)
|
||||||
delay(1000);
|
;
|
||||||
sendCommandAndPrintAllResponse("AT+CMEE=1", 1000); // Enable verbose errors
|
|
||||||
delay(1000);
|
|
||||||
sendCommandAndPrintAllResponse("AT+CPIN?", 3000); // Check SIM status
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
Serial.println("\n--- Setup complete. Monitor loop output for continuous checks. ---");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- 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() {
|
void loop() {
|
||||||
// Continuously check basic modem status to see if it remains responsive
|
Serial.println("\n--- Requesting GPS Location ---");
|
||||||
Serial.println("\n--- Loop: Continuous Basic Checks ---");
|
getGpsLocation();
|
||||||
sendCommandAndPrintAllResponse("AT", 1000);
|
delay(30000); // Wait 30 seconds before the next request
|
||||||
delay(5000); // Check every 5 seconds
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getGpsLocation() {
|
||||||
|
String response = sendATCommand("AT+CGPSINFO", 5000);
|
||||||
|
|
||||||
// REVISED: powerUp function based on Waveshare example timing
|
if (response.indexOf("+CGPSINFO:") != -1) {
|
||||||
void powerUp(){
|
response.replace("+CGPSINFO: ", "");
|
||||||
Serial.println("Applying power pulse to PWRKEY_PIN (GPIO4)...");
|
response.trim();
|
||||||
digitalWrite(PWRKEY_PIN, HIGH); // Ensure HIGH first (idle state)
|
|
||||||
delay(100); // Small stabilization delay
|
|
||||||
|
|
||||||
digitalWrite(PWRKEY_PIN, LOW); // Pull PWRKEY low
|
if (response.startsWith(",")) {
|
||||||
delay(2000); // Hold low for 2 seconds (as per Waveshare example)
|
Serial.println("GPS has no fix yet.");
|
||||||
digitalWrite(PWRKEY_PIN, HIGH); // Release PWRKEY (set HIGH)
|
return;
|
||||||
// The long boot delay is handled in setup() to monitor responsiveness
|
|
||||||
Serial.println("PWRKEY pulse complete. Module should now be booting.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
// REVISED: sendCommandAndPrintAllResponse function for raw modem output debugging
|
double latitude = 0.0;
|
||||||
String sendCommandAndPrintAllResponse(String command, unsigned long timeoutMs) {
|
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.print("Sending: ");
|
||||||
Serial.println(command);
|
Serial.println(command);
|
||||||
|
|
||||||
// Clear Serial2 receive buffer before sending command
|
|
||||||
while (Serial2.available()) {
|
while (Serial2.available()) {
|
||||||
Serial2.read();
|
Serial2.read();
|
||||||
}
|
}
|
||||||
|
Serial2.println(command);
|
||||||
Serial2.println(command); // Send command to the modem
|
String response = "";
|
||||||
|
|
||||||
String rawResponse = "";
|
|
||||||
unsigned long startTime = millis();
|
unsigned long startTime = millis();
|
||||||
|
|
||||||
while (millis() - startTime < timeoutMs) {
|
while (millis() - startTime < timeoutMs) {
|
||||||
if (Serial2.available()) {
|
while (Serial2.available()) {
|
||||||
char c = (char)Serial2.read();
|
char c = (char)Serial2.read();
|
||||||
rawResponse += c;
|
response += c;
|
||||||
startTime = millis(); // Reset timeout as long as data is being received
|
startTime = millis();
|
||||||
|
if (response.endsWith("OK\r\n") || response.endsWith("ERROR\r\n") ||
|
||||||
|
response.endsWith("FAIL\r\n")) {
|
||||||
|
response.trim();
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
delay(1); // Small delay to prevent busy-waiting
|
}
|
||||||
|
}
|
||||||
|
response.trim();
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println("--- Raw Modem Response Received ---");
|
String getIMEI() {
|
||||||
Serial.println(rawResponse); // Print everything received (raw, untrimmed)
|
String response = sendATCommand("AT+CGSN", 5000);
|
||||||
Serial.println("-----------------------------------");
|
int currentPos = 0;
|
||||||
|
while (currentPos < response.length()) {
|
||||||
return rawResponse; // Return the raw response for checking in setup/loop
|
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;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user