Odkaz na první část návodu zde.

Jak jsem slíbil, pokračuji ve svém předchozím článku o GPS loggeru. Tentokrát je rozšířen o GSM modul. Toto šikovné zapojení se může stát základem nějaké pohyblivé meteosondě. Arduino opět sbírá data z teploměru, tlakoměru, vlhkoměru, GPS polohu, nadmořskou výšku, rychlost, počet satelitů… a vypisuje je po sériové lince do USB portu. Tyto údaje opět ukládá na SD kartu, do textového souboru MERENI.txt. Případnou špatnou inicializaci modulů, odpojené čidlo či chybu na SD kartě obdržíme jako chybovou hlášku na sériové lince.

Připojený GSM modul mi umožňuje bezdrátovou, dálkovou komunikaci pomocí mobilních sítí GSM 900MHz, do nadm. Výšky cca 1-2km od povrchu, kam mají teoreticky dané sítě dosah. Pomocí připojeného modulu, mi Arduino odesílá zpět, po prozvonění ze známého čísla,  SMS zprávy s GPS polohou a Meteo hodnotami a tato činnost je opět vypsána po sériové lince. SMS je psaná co nejúsporněji a neodesílá mi veškeré údaje, musí se vejít do max. velikosti 160 znaků. Dále mohu naopak ze zvoleného čísla odeslat ve 2 tvarech SMS zprávy do modulu a ten zareaguje 0,5s impulsem na pinech 2 nebo 3.  A jako zpětnou vazbu dostanu SMS odpověď o vykonané činnosti. To lze využít pro nějaké ovládání 2 relé. Tak je i nutné sepsat tvar SMS zpráv. Tedy pro sepnutí relé 1 napíši text SMS zprávy: RELE1 a  Arduino pošle na pin 2 krátký impuls, společně s tím i odešle zpět zprávu ve tvaru: Odpojeno RELE1. Opět je vypsána hláška po sériové lince. To samé platí i pro rele 2 na pinu 3. Na kontaktním poli mi relé nahrazují dvě LED diody s rezistory 9k9, které mi přišly pod ruku. Pro zapojení relátek je nutné tyto impulzy zesílit pomocí dvou NPN tranzistorů (viz. Schéma pro tranzistory pod textem).

 GPS Data logger s GSM modulem

 GPS Data logger s GSM modulem

Na obrázku vidíte SMS zprávy: první dvě jsou odeslány Arduinem po zavolání ze zvoleného čísla. Ty ve žlutém rámečku jsem odeslal ze stejného tel. čísla já a jako odpověď mi dorazily SMSky Odpojeno RELE1 a 2. Pro napájení Arduina stačí napětí z USB, ale GSM modul potřebuje kolem 4V a až 2A, to USB nedá. Tak jsem si postavil z několika vyřazených baterek z mobilu a staré nabíječky jednoduchý zdroj na 12AH 4,1V. Na pin Vin na desce Arduina by mělo stačit přivést + pól baterie do desky a dostaneme tak nezávislý zdroj. Prakticky jsem tohle zapojení zatím ale neověřil. Tak nemohu garantovat 100% činnost na 5V.

 GPS Data logger s GSM modulem

Teď k samotnému programu, nebudu jej dopodrobna popisovat, protože je již okomentován. Jen pro přesnost, na začátku jsou implementovány potřebné knihovny. Každý modul/čidlo má definovány proměnné/piny a inicializovány knihovny. Ve smyčce void setup je zahájena komunikace a případně vypsány chybové hlášky. Smyčka void loop pak načte hodnoty z GPS modulu a čidla, vytvoří z nich zprávu a tu pošle po sériové lince i uloží na SD kartu ve formě textového dokumentu MERENI.txt. Dále je vytvořena SMS a odeslána na vámi zvolené tel. Číslo. V programu je vykřížkováno jako:

 char mojeCislo[16] = "+420xxxxxxxxx";

Zde dosadíte SVOJE číslo, na které chcete posílat SMS. Pro činnost GSM modulu si nezapomeňte pořídit i druhou, nabitou simkartu a v mobilním telefonu jej pak uložte do kontaktů, třeba pod jménem Arduino nebo jinak, to je na vás. Jen podotýkám, dodržte přesný tvar SMS zpráv pro ovládání relé. Program porovná text zprávy, s tím co mu přišlo a jestli se texty shodují (rozdíl znaků = 0), tak se na okamžik sepne jedno z relé.

Pro sepnutí relé 1, je nutné poslat SMS ve tvaru:

RELE1

A jako odpověď dostanete:

Odpojeno RELE1

Pro sepnutí relé 2, je nutné poslat SMS ve tvaru:

RELE2

A jako odpověď dostanete:

Odpojeno RELE2

Pro změnu textu SMS je nutno tuto změnu učinit i v programu.  Tedy zde:

char mojeZprava1[delkaZpravy] = "RELE1";

char mojeZprava2[delkaZpravy] = "RELE2";

Nahradíte text RELE1, nebo RELE2 za požadovaný tvar. A samozřejmě tento text je nutné pak dodržet i při odeslání zprávy z vašeho telefonu. Dále by bylo vhodné upravit i text v řádcích Serial.print(…RELE1/2) , aby se po sériové lince opět odesílal správný tvar o vykonané činnosti.

SMS s odpovědí o odpojení RELE1 a 2 se dá změnit v řádku:

String dataString2(" Odpojeno RELE1 ");

String dataString3(" Odpojeno RELE2 ");

Případnou změnu formátu odeslané SMS s Meteo údaji, které se odesílají zpět na váš mobil po prozvonění, učiňte v řádcích dataString4. Zde si můžete nakombinovat odesílané údaje dle libosti. Tedy některé hodnoty vyměnit za jiné, případně odmazat. Jen je nutné dodržet délku 160 znaků.

Seznam potřebných knihoven:

  • SoftwareSerial.h
  • SPI.h
  • Wire.h
  • SD.h
  • TinyGPS.h
  • GPRS_Shield_Arduino.h
  • sim900.h
  • Adafruit_BME280.h
  • Adafruit_Sensor.h
//GPS GSM SD data logger s teplomerem, tlakomerem a vlhkomerem

//Knihovny
#include <SoftwareSerial.h>
#include <SPI.h>
#include <Wire.h>
#include <SD.h>
#include <TinyGPS.h>
#include <GPRS_Shield_Arduino.h>
#include <sim900.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

//SD
// nastavení pinu CS pro SD kartu - pevně dané shieldem
const int sd_CS = 53;

//GPS NEO-6M
// nastavení propojovacích pinů
#define TX1 18
#define RX1 19
// inicializace GPS
TinyGPS gps;
// vytvoření dočasných proměnných pro načtení dat z GPS modulu
float zSirka, zDelka;
unsigned long stariDat;
int rok;
byte mesic, den, hodina, minuta, sekunda, setinaSekundy;
// vytvoření proměnné pro vytištění data a času
char datumCas[32];
// vytvoření dočasných proměnných pro načtení informací o komunikaci s GPS modulem
bool novaData = false;
unsigned long znaky;
unsigned short slova, chyby;

// SIM 900 GSM Shield
// nastavení pinu ovladacich rele 1 a 2
#define pinRele1 2
#define pinRele2 3
// nastaveni komunikace se SIM modulem,
#define pinTX 11
#define pinRX 10
#define pinPower 9
#define rychlostSim 9600
// vytvoření proměnné s detekovaným číslem
char mojeCislo[16] = "+420*********";
// vytvoření proměnných pro práci s SMS
#define delkaZpravy 160
char smsZprava[delkaZpravy];
int smsIndex = 0;
char telCislo[16];
char casDatum[24];
// inicializace SIM900 modulu z knihovny
GPRS sim900(pinTX, pinRX, rychlostSim);

//BME280
// nastavení adresy senzoru
#define BME280_ADRESA (0x76)
// inicializace senzoru BME z knihovny
Adafruit_BME280 bme;

void setup() {
  // zahajeni komunikace s PC
   Serial.begin(9600);
  // zahajeni komunikace s GPS
   Serial1.begin(9600);
  // kontrola napájení modulu SIM900,
  // v případě vypnutého modulu ho zapneme
  if(!sim900.checkPowerUp()) {
    sim900.powerUpDown(pinPower);
  }
  // kontrola připojené SD karty
  if(!SD.begin(sd_CS)) {
    Serial.println("SD karta neni pripojena nebo je vadna!");
    }
  // chybova hlaska pokud není GSM modul správně nainicializován a pockani
  // SIM modul
  if(!sim900.init()) {
    Serial.println("Chyba inicializace GSM, cekam 5 vterin!");
    delay(5000);
  }
  else {
    Serial.println("Inicializace GSM uspesna, cekam 2 vteriny kvuli GPS modulu!");
    delay(2000);
  }
}
void loop() {
// po dobu jedné vteřiny budeme kontrolovat příjem dat z GPS
for (unsigned long start = millis(); millis() - start < 1000;) {
    // kontrola aktivity softwarové komunikace
    while (Serial1.available()) {
      // vytvoření proměnné pro uložení načtených dat z GPS
      char c = Serial1.read();
      //Serial.write(c); // pro výpis přijatých dat odkomentujte tento řádek
      // dekódování přijaté zprávy s kontrolou platných dat
      if (gps.encode(c)) {
        // pokud jsou přijatá data platná, nastavíme proměnnou pro tištění dat
        novaData = true;
      }
    }
  }
  // pokud proběhl příjem nových dat, vytiskneme všechny dostupné informace
  if (novaData) {
    // načtení GPS pozice do proměnných
    gps.f_get_position(&zSirka, &zDelka, &stariDat);
    // vytištění informací po sériové lince
    Serial.println(" ::Dostupne GPS udaje:: ");
    // vytištění informací po sériové lince
    Serial.print(" Zemepisna sirka: ");
    // nejprve zkontrolujeme, jestli máme platné údaje
    // (zSirka == TinyGPS::GPS_INVALID_F_ANGLE),
    // pokud nejsou validní (platné), vytiskneme nulu,
    // v opačném případě vytiskneme obsah proměnné s přesností 6 desetinných míst,
    // podobným způsobem se pracuje i s ostatními údaji
    Serial.println(zSirka == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : zSirka, 6);
    Serial.print(" Zemepisna delka: ");
    Serial.println(zDelka == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : zDelka, 6);
    Serial.print(" Pocet satelitu: ");
    Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
    Serial.print(" Presnost: ");
    Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
    Serial.print(" Stari dat: ");
    Serial.println(stariDat == TinyGPS::GPS_INVALID_AGE ? 0 : stariDat);
    Serial.print(" Nadmorska vyska m.n.m: ");
    Serial.println(gps.f_altitude() == TinyGPS::GPS_INVALID_F_ALTITUDE ? 0 : gps.f_altitude());
    Serial.print(" Rychlost v km/h: ");
    Serial.println(gps.f_speed_kmph() == TinyGPS::GPS_INVALID_F_SPEED ? 0 : gps.f_speed_kmph());
    // načtení data a času z GPS modulu do proměnných
    gps.crack_datetime(&rok, &mesic, &den, &hodina, &minuta, &sekunda, &setinaSekundy, &stariDat);
    // kontrola platnosti dat
    if (stariDat == TinyGPS::GPS_INVALID_AGE) {
      Serial.println("Nelze nacist datum a cas.");
      Serial.println();
    } else {
      Serial.print(" Datum a cas: "); 
      // poskládání celé zprávy do proměnné datumCas a poté její vytištění,
      // %02d znamená desetinné číslo uvedené za uvozovkami s přesností na 2 číslice
      sprintf(datumCas, "%02d/%02d/%02d %02d:%02d:%02d", mesic, den, rok, hodina, minuta, sekunda);
      Serial.println(datumCas);
      Serial.println();
    }
  }
  // načtení a vytištění informací o komunikaci s GPS modulem
  gps.stats(&znaky, &slova, &chyby);
  Serial.print(" Detekovane znaky: ");
  Serial.print(znaky);
  Serial.print(", slova: ");
  Serial.print(slova);
  Serial.print(", chyby pri kontrole dat: ");
  Serial.print(chyby);
  Serial.println();
  // kontrola chyb při komunikaci skrze detekci přijatých znaků
  if (znaky == 0) {
    Serial.println(); // vytištění prázdného řádku
    Serial.println(" Chyba pri prijmu dat z GPS, zkontrolujte zapojeni! ");
    Serial.println();
  }
// v případě chyby senzoru je vypsána hláška po sériové lince
if (!bme.begin(BME280_ADRESA)) {
    Serial.println(" BME280 senzor nenalezen, zkontrolujte zapojeni! ");
    Serial.println(); // vytištění prázdného řádku
    } else {
    Serial.println();
    // výpis všech dostupných informací ze senzoru BMP
    // výpis teploty
    Serial.println(" ::Dostupne meteorologicke udaje:: ");
    // výpis teploty
    Serial.print(" Teplota °C: ");
    Serial.println(bme.readTemperature());
    // výpis relativní vlhkosti
    Serial.print(" Relativni vlhkost %: ");
    Serial.println(bme.readHumidity());
    // výpis tlaku s přepočtem na hektoPascaly
    Serial.print(" Tlak hPa.: ");
    Serial.println(bme.readPressure() / 100.0F);
    // vytištění prázdného řádku
    Serial.println();
    } 
// otevření souboru na SD kartě s názvem mereni.txt
File zapisDat = SD.open("mereni.txt", FILE_WRITE);
// vytvoreni textu mereni.txt
String dataString1("GPS UDAJE ");
dataString1 += (" Zem.sirka: ");
dataString1 += String(zSirka == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : zSirka, 6);
dataString1 += (" Zem.delka: ");
dataString1 += String(zDelka == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : zDelka, 6);
dataString1 += (" Satelity: ");
dataString1 += String(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
dataString1 += (" Nadm.vyska: ");
dataString1 += String(gps.f_altitude() == TinyGPS::GPS_INVALID_F_ALTITUDE ? 0 : gps.f_altitude());
dataString1 += (" Rychlost km/h: ");
dataString1 += String(gps.f_speed_kmph() == TinyGPS::GPS_INVALID_F_SPEED ? 0 : gps.f_speed_kmph());
dataString1 += (" Datum cas: ");
dataString1 += String(datumCas);
dataString1 += String(" METEO UDAJE ");
dataString1 += (" Teplota C: ");
dataString1 += String(bme.readTemperature());
dataString1 += (" Rel.vlhkost %: ");
dataString1 += String(bme.readHumidity());
dataString1 += (" Tlak hPa.: ");
dataString1 += String(bme.readPressure() / 100.0F);
// v případě, že je soubor bez problémů vytvořen (pokud neexistuje),
// nebo otevřen (pokud existuje), zapiš do něj dataString a ukonči zápis
if (zapisDat) {
    zapisDat.println(dataString1);
    zapisDat.close();
    Serial.println(" Zapis na kartu uspesny. ");
    Serial.println();
    }
    // v případě chyby při otevírání souboru vypiš chybu
    else {
    Serial.println(" Chyba pri otevreni souboru mereni.txt ! ");
    Serial.println();
    }        
// kontrola SMS zpráv - načtení počtu nepřečtených zpráv
  smsIndex = sim900.isSMSunread();
  // pokud existuje alespoň jedna nepřečtená zpráva,
  // provedeme její přečtení a detekci textu
  if (smsIndex > 0) {
    // načtení SMS zprávy do proměnných ve funkci
    sim900.readSMS(smsIndex, smsZprava, delkaZpravy);
    // vymazání aktuálně přečtené zprávy
    sim900.deleteSMS(smsIndex);
    // vytištění informací o přijaté SMS zprávě
    Serial.print("Od cisla: ");
    Serial.println(telCislo);  
    Serial.print("Zprava: ");
    Serial.println(smsZprava);
    // kontrola přijetí SMS zprávy od našeho nastaveného čísla
    // strcmp porovná 2 stringy a nula znamená počet odlišných znaků
    if (strcmp(telCislo, mojeCislo)==0) {
      // Ovladani 2 rele pomoci SMS
      // proměnná s detekovaným textem v SMS zprávě
      char mojeZprava1[delkaZpravy] = "RELE1";
      char mojeZprava2[delkaZpravy] = "RELE2";
      // kontrola přijetí detekovaného textu
      if (strcmp(smsZprava, mojeZprava1)==0) {
        Serial.println("Prijata zprava RELE1");
        digitalWrite(pinRele1, HIGH);
        delay(500);
        digitalWrite(pinRele1, LOW);
        Serial.println(" Odpojeno RELE1 ");
        // vytvoreni SMS zpravy
        String dataString2(" Odpojeno RELE1 ");
        // převedení textu na proměnnou kompatibilní se SIM modulem
        dataString2.toCharArray(smsZprava, 160);
        // poslání SMS zprávy na nastavené číslo
        sim900.sendSMS(telCislo, smsZprava);
        Serial.println(" Odeslana SMS: Odpojeno RELE1. ");
        Serial.println();
      }
      else if (strcmp(smsZprava, mojeZprava2)==0) {
        Serial.println(" Prijata zprava RELE2 ");
        digitalWrite(pinRele2, HIGH);
        delay(500);
        digitalWrite(pinRele2, LOW);
        Serial.println(" Odpojeno RELE2 ");
        // vytvoreni SMS zpravy
        String dataString3(" Odpojeno RELE2 ");
        // převedení textu na proměnnou kompatibilní se SIM modulem
        dataString3.toCharArray(smsZprava, 160);
        // poslání SMS zprávy na nastavené číslo
        sim900.sendSMS(telCislo, smsZprava);
        Serial.println(" Odeslana SMS: Odpojeno RELE2. ");
        Serial.println();
      }
      else {
        Serial.println(" Prijata neznama zprava. ");
      }
    }
    else {
        Serial.println(" Prijata neznama zprava od neznameho cisla. ");
    }
  }
  // kontrola příchozího hovoru s uložením čísla do proměnné
  if(sim900.isCallActive(telCislo)) {
    // vytištění informací o příchozím hovoru
    Serial.print(" Vola cislo: ");
    Serial.println(telCislo);
    // pauza po dobu 1 sekundy a následné zavěšení hovoru
    delay(1000);
    sim900.hangup();
    // kontrola hovoru od našeho nastaveného čísla
    if (strcmp(telCislo, mojeCislo)==0) {
      // vytištění informace o poslání zprávy
      Serial.println(" Zname cislo, odeslana SMS. ");
      // vytvoreni SMS zpravy
      String dataString4("Sirka:");
      dataString4 += String(zSirka == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : zSirka, 6);
      dataString4 += (" Delka:");
      dataString4 += String(zDelka == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : zDelka, 6);
      dataString4 += (" Vyska:");
      dataString4 += String(gps.f_altitude() == TinyGPS::GPS_INVALID_F_ALTITUDE ? 0 : gps.f_altitude());
      dataString4 += (" Rychlost:");
      dataString4 += String(gps.f_speed_kmph() == TinyGPS::GPS_INVALID_F_SPEED ? 0 : gps.f_speed_kmph());
      dataString4 += (" Datum Cas:");
      dataString4 += String(datumCas);
      dataString4 += (" Teplota C:");
      dataString4 += String(bme.readTemperature());
      dataString4 += (" Vlhkost %:");
      dataString4 += String(bme.readHumidity());
      dataString4 += (" Tlak hPa.:");
      dataString4 += String(bme.readPressure() / 100.0F);
      // převedení textu na proměnnou kompatibilní se SIM modulem
      dataString4.toCharArray(smsZprava, 160);
      // poslání SMS zprávy na nastavené číslo
      sim900.sendSMS(telCislo, smsZprava);
    }
    else {
      // vytištění informací o volání neznámého čísla
      Serial.println(" Nezname cislo - bez odezvy. ");
      Serial.print(" Ulozene : ");
      Serial.println(mojeCislo);
      Serial.print(" Volajici: ");
      Serial.println(telCislo);
    }
  }
delay(2000);
}

 Schéma pro tranzistory:

 GPS Data logger s GSM modulem

 Schéma celkové:

 GPS Data logger s GSM modulem

Zapojte dle schématu, nezapomeňte propájet propojku JP na desce SIM 900. Bez ní by nefungovalo zapínání pinem 9.

FB gp tw

Další podobné články