Untitled
unknown
plain_text
10 months ago
5.4 kB
15
Indexable
#include <SoftwareSerial.h>
/*
SIM800L Auto-Baud + Signal Monitor + AT Bridge
- Detects module baud rate (9600 / 115200 / 57600).
- Fixes to 9600 for stable operation (AT+IPR=9600).
- Polls AT+CSQ every 5s and prints RSSI, dBm, and quality.
- Live AT bridge: type AT commands in Serial Monitor.
- Recovers if module stops responding; optional hardware RST pin.
Wiring (UNO/Nano):
Arduino D9 (TX) -> SIM800 RX (use 2:1 divider, ~2.8–3.0 V)
Arduino D8 (RX) <- SIM800 TX
GND <-> GND
Power:
Stable 3.7–4.2 V, up to 2 A peak, with ≥470 µF capacitor close to module.
*/
// --- Pins ---
const int RX_PIN = 8; // Arduino RX <= SIM800 TX
const int TX_PIN = 9; // Arduino TX => SIM800 RX
SoftwareSerial gsm(RX_PIN, TX_PIN);
// Optional RST pin for SIM800 (active LOW). Set to -1 if not wired.
const int rstPin = -1;
// --- Timers ---
unsigned long lastPoll = 0;
const unsigned long pollIntervalMs = 5000;
unsigned long lastAnyResponse = 0;
const unsigned long noResponseRecoveryMs = 15000; // 15s
// --- Helpers ---
void flushGSMToPC() {
while (gsm.available()) {
char c = gsm.read();
Serial.write(c);
lastAnyResponse = millis();
}
}
void hardResetSIM800() {
if (rstPin < 0) return;
Serial.println(F("[RST] Pulsing SIM800 RST pin..."));
digitalWrite(rstPin, LOW);
delay(120);
digitalWrite(rstPin, HIGH);
delay(6000);
Serial.println(F("[RST] Done, retrying..."));
}
bool waitForOK(unsigned long timeoutMs = 1000) {
unsigned long start = millis();
String buf;
while (millis() - start < timeoutMs) {
while (gsm.available()) {
char c = gsm.read();
Serial.write(c);
buf += c;
lastAnyResponse = millis();
}
if (buf.indexOf("OK") >= 0) return true;
if (buf.indexOf("ERROR") >= 0) return false;
}
return false;
}
bool tryAT(unsigned long baud) {
gsm.end();
delay(50);
gsm.begin(baud);
delay(200);
for (int i = 0; i < 3; i++) {
gsm.println(F("AT"));
delay(200);
}
bool ok = waitForOK(1200);
if (ok) {
Serial.print(F("[BAUD] SIM800 responded at "));
Serial.println(baud);
}
return ok;
}
void fixBaudTo9600() {
gsm.println(F("AT+IPR=9600"));
if (waitForOK(1200)) {
Serial.println(F("[BAUD] Fixed to 9600."));
gsm.end();
delay(50);
gsm.begin(9600);
delay(200);
} else {
Serial.println(F("[BAUD] Could not fix baud (continuing)."));
}
}
bool autobaudAndInit() {
Serial.println(F("[INIT] Trying baud detect..."));
bool ok = tryAT(9600);
if (!ok) ok = tryAT(115200);
if (!ok) ok = tryAT(57600);
if (!ok) {
Serial.println(F("[INIT] No response. Check wiring, GND, power."));
return false;
}
gsm.println(F("ATE0")); waitForOK(800);
gsm.println(F("AT+CMEE=2")); waitForOK(800);
fixBaudTo9600();
gsm.println(F("AT"));
if (!waitForOK(800)) return false;
lastAnyResponse = millis();
Serial.println(F("[INIT] Ready. Type AT commands in Serial Monitor (9600 baud, NL+CR)."));
return true;
}
void interpretCSQ(const String& line) {
int p = line.indexOf(F("+CSQ:"));
if (p < 0) return;
int comma = line.indexOf(',', p);
if (comma < 0) return;
int start = line.indexOf(':', p);
if (start < 0) return;
int rssi = line.substring(start + 1, comma).trim().toInt();
String quality, dBmText = F("unknown");
if (rssi == 99) {
quality = F("No signal/unknown");
} else if (rssi == 31) {
quality = F("Excellent");
dBmText = F("-51 dBm or better");
} else if (rssi >= 2 && rssi <= 30) {
int dBm = -113 + (rssi * 2);
dBmText = String(dBm) + F(" dBm");
if (rssi <= 9) quality = F("Very weak");
else if (rssi <= 14) quality = F("Weak/usable");
else if (rssi <= 19) quality = F("Good");
else quality = F("Strong");
} else if (rssi == 1) {
quality = F("Barely detectable");
dBmText = F("-111 dBm");
} else if (rssi == 0) {
quality = F("No signal");
dBmText = F("-113 dBm");
}
Serial.print(F("[CSQ] RSSI=")); Serial.print(rssi);
Serial.print(F(" -> ")); Serial.print(dBmText);
Serial.print(F(" (")); Serial.print(quality); Serial.println(F(")"));
}
void pollSignal() {
gsm.println(F("AT+CSQ"));
unsigned long start = millis();
String buf;
while (millis() - start < 700) {
while (gsm.available()) {
char c = gsm.read();
Serial.write(c);
buf += c;
lastAnyResponse = millis();
}
}
interpretCSQ(buf);
}
// --- Arduino setup/loop ---
void setup() {
if (rstPin >= 0) {
pinMode(rstPin, OUTPUT);
digitalWrite(rstPin, HIGH);
}
Serial.begin(9600);
delay(200);
Serial.println(F("SIM800 Monitor + AT Bridge"));
if (!autobaudAndInit()) {
if (rstPin >= 0) {
hardResetSIM800();
autobaudAndInit();
}
}
}
void loop() {
// Pass PC -> SIM800
if (Serial.available()) gsm.write(Serial.read());
// Pass SIM800 -> PC
flushGSMToPC();
// Poll signal every 5s
if (millis() - lastPoll >= pollIntervalMs) {
lastPoll = millis();
Serial.println(F("\n--- Poll ---"));
gsm.println(F("AT")); waitForOK(400);
pollSignal();
}
// Recovery if no response
if (millis() - lastAnyResponse > noResponseRecoveryMs) {
Serial.println(F("\n[RECOVERY] No response, retrying autobaud..."));
if (!autobaudAndInit() && rstPin >= 0) {
hardResetSIM800();
autobaudAndInit();
}
lastAnyResponse = millis();
}
}Editor is loading...
Leave a Comment