Untitled

 avatar
unknown
plain_text
10 months ago
5.2 kB
14
Indexable
#include <SoftwareSerial.h>

// -------------------- Pins --------------------
const int trigPin = 7;
const int echoPin = 6;

const int gsmRx = 8;  // Arduino RX <= SIM800 TX
const int gsmTx = 9;  // Arduino TX => SIM800 RX (use divider!)
SoftwareSerial gsm(gsmRx, gsmTx);

// ---- Buzzer (powered from 5V pin, switched via D4) ----
const int buzzerPin = 4; // buzzer - to D4, buzzer + to 5V

// -------------------- Config --------------------
const char phoneNumber[] = "+1234567890"; // <-- replace with your phone number
const int floodLevel_cm = 10;              // alert if distance < this
const unsigned long smsCooldown = 60000UL; // 1 minute between SMS
const int samples = 5;                     // smoothing samples

// -------------------- State --------------------
unsigned long lastSmsTime = 0;
bool highWaterLatched = false;

// -------------------- Helpers --------------------
bool waitFor(const char* token, unsigned long timeoutMs) {
  unsigned long start = millis();
  size_t idx = 0;
  while (millis() - start < timeoutMs) {
    while (gsm.available()) {
      char c = (char)gsm.read();
      if (c == token[idx]) {
        idx++;
        if (token[idx] == '\0') return true;
      } else {
        idx = (c == token[0]) ? 1 : 0;
      }
    }
  }
  return false;
}

void flushGSM() {
  while (gsm.available()) Serial.write(gsm.read());
}

bool sendAT(const char *cmd, const char *expect, unsigned long timeoutMs = 2000) {
  gsm.println(cmd);
  bool ok = waitFor(expect, timeoutMs);
  flushGSM();
  return ok;
}

bool initGSM() {
  Serial.println(F("Initializing GSM..."));
  for (int i = 0; i < 5; i++) {
    gsm.println(F("AT"));
    if (waitFor("OK", 1000)) break;
    delay(500);
  }

  sendAT("ATE0", "OK", 1000);          // echo off
  sendAT("AT+CMEE=2", "OK", 1000);     // verbose errors
  sendAT("AT+CMGF=1", "OK", 1000);     // text mode
  sendAT("AT+CSCS=\"GSM\"", "OK", 1000);

  // Wait for network registration
  for (int tries = 0; tries < 20; tries++) {
    gsm.println(F("AT+CREG?"));
    if (waitFor("+CREG:", 1000)) {
      if (waitFor(",1", 200) || waitFor(",5", 200)) {
        flushGSM();
        Serial.println(F("Network registered."));
        return true;
      }
    }
    flushGSM();
    delay(1000);
  }
  Serial.println(F("Network registration failed (timeout)."));
  return false;
}

bool sendSMS(const char* number, const char* msg) {
  Serial.println(F("Sending SMS..."));
  gsm.print(F("AT+CMGS=\""));
  gsm.print(number);
  gsm.println(F("\""));

  // Wait for '>' prompt
  if (!waitFor(">", 5000)) {
    flushGSM();
    Serial.println(F("No '>' prompt; SMS aborted."));
    return false;
  }

  gsm.print(msg);
  gsm.write(26); // Ctrl+Z
  bool gotRef = waitFor("+CMGS:", 15000);
  bool gotOK  = waitFor("OK", 5000);
  flushGSM();

  if (gotRef && gotOK) {
    Serial.println(F("SMS sent OK."));
    return true;
  } else {
    Serial.println(F("SMS send failed."));
    return false;
  }
}

// -------------------- Ultrasonic --------------------
long readDistanceOnce() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(3);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  unsigned long duration = pulseIn(echoPin, HIGH, 30000UL);
  if (duration == 0) return -1;
  return (long)(duration * 0.034 / 2.0); // cm
}

long readDistanceSmoothed() {
  long vals[samples];
  int count = 0;
  for (int i = 0; i < samples; i++) {
    long d = readDistanceOnce();
    if (d > 0 && d < 400) vals[count++] = d;
    delay(20);
  }
  if (count == 0) return -1;

  // simple sort for median
  for (int i = 1; i < count; i++) {
    long key = vals[i];
    int j = i - 1;
    while (j >= 0 && vals[j] > key) { vals[j + 1] = vals[j]; j--; }
    vals[j + 1] = key;
  }
  return vals[count / 2];
}

// -------------------- Buzzer control --------------------
void buzzerOn() {
  digitalWrite(buzzerPin, LOW); // sink current to GND (buzzer + tied to 5V)
}

void buzzerOff() {
  digitalWrite(buzzerPin, HIGH); // stop current (both sides at 5V)
}

// -------------------- Arduino --------------------
void setup() {
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(buzzerPin, OUTPUT);
  buzzerOff(); // start silent

  Serial.begin(9600);
  gsm.begin(9600);

  delay(1000);
  initGSM();

  Serial.println(F("SIM800L Flood Alert System Ready"));
}

void loop() {
  long distance = readDistanceSmoothed();
  if (distance < 0) {
    Serial.println(F("Invalid reading."));
    buzzerOff(); // keep silent on invalid read
    delay(1000);
    return;
  }

  Serial.print(F("Distance (cm): "));
  Serial.println(distance);

  bool waterHigh = (distance > 0 && distance < floodLevel_cm);

  // SMS on first entry to high water (with cooldown)
  if (waterHigh && !highWaterLatched && (millis() - lastSmsTime > smsCooldown)) {
    bool ok = sendSMS(phoneNumber, "FLOOD ALERT! Water level is HIGH.");
    if (ok) lastSmsTime = millis();
    highWaterLatched = true;
  }

  // Reset latch when water clearly recedes
  if (!waterHigh && distance > (floodLevel_cm + 2)) {
    highWaterLatched = false;
  }

  // Drive buzzer: continuous ON when water high
  if (waterHigh) {
    buzzerOn();
  } else {
    buzzerOff();
  }

  delay(200); // small delay for loop
}
Editor is loading...
Leave a Comment