Untitled

 avatar
unknown
plain_text
10 months ago
5.4 kB
13
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