Kamoš ma poprosil, či by som vedel vyrobiť ovládanie na garážovú bránu cez mobil. WiFi sa použiť nedala, takže som vybral SIM900 modul z čínskej ľudovodemokratickej republiky za cca 13€ a pustil sa do toho. Najskôr návrh – chcel som sa vyhnúť potrebe preprogramovať zariadenie keď treba zmeniť/doplniť/zmazať číslo v zozname oprávnených čísel. Čísla teda putovali do EEPROM a cez SMS sa dá zoznam upravovať. No a potom jednoducho len zatelefonovať na číslo v zariadení, a ak ste vyvolení, sezam sa otvorí 🙂 Na výstupe je relé, ktoré na pol sekundy zopne a simuluje stlačenie tlačítka, ktoré je vnútri garáže na manuálne otvorenie.
Fyzické zapojenie je jednoduché, lebo som vybral SIM900 modul ktorý je vo formáte Arduino shieldu. Na záver som doplnil napájanie Arduina priamo z GSM shieldu – je tam síce len 4.1V, ale to MCU v pohode stačí. Na napájanie treba adaptér ktorý skutočne vie dodať 2A, lebo presne toľko v špičkách odoberá GSM modul, hlavne pri registrovaní do siete. Dá sa to vykryť aj vhodným elektrolytom (povedzme 2200uF / 6.3V a viac). Najskôr som sa so shieldom zoznámil priamo cez USB/UART prevodník, vyskúšal čo treba, exportoval debug výstupy a až potom som začal programovať.
Pin D9 sa používa na zapnutie GSM modulu, D7/D8 na sériovú komunikáciu cez SoftSerial s rýchlosťou 19200 Bd. Kamoš pracuje v Rakúsku a to ma donútilo napísať program tak, aby nevyžadoval fixnú dĺžku telefónneho čísla, takže medzinárodná predvoľba môže byť kľudne +1 aj +421. Nijako som neošetroval chyby registrácie do siete – možno keď sa niečo ukáže v prevádzke. Na správu zoznamu treba poslať SMS v nasledovnej forme (zmenené voči aktuálnej implementácii):
- PRIDAJ +421911123456
- VYMAZ +421905987654
- VYNULUJ
- POSLI
Ak by bolo treba dodatočné zabezpečenie, zrejme by sa dalo do SMS pridávať aj časť IMEI alebo niečo podobne unikátne. PRIDAJ pridá ďalšie číslo do zoznamu povolených (nekontroluje či tam už náhodou nie je!), VYMAZ číslo zo zoznamu odstráni (nahradí ho hviezdičkami ****). VYNULUJ vyprázdni zoznam a dá len jedno natvrdo nakódované číslo (majiteľ). POSLI odošle odosielateľovi SMS aktuálny zoznam povolených čísel. To by malo bohato stačiť na správu. Pri zavolaní modul hneď „zloží“. Žiadne info SMS sa neposielajú – lebo na čo. No a tu je môj program – takmer nekomentovaný, napol po anglicky – tak študujte, čudujte sa a upravujte 🙂 Prípadne otázky do diskusie.
PS: skoro rok som sem nič nepridal, to je ostuda…
#include <SoftwareSerial.h>
#include <EEPROM.h>
#define pinGSMstart 9
#define pinGSM_TX 7
#define pinGSM_RX 8
#define pinRelay 3
#define pinRelayGND 5
String allowed_callers;
String SMS_sender;
int idx = 0;
char ee_data;
char currentLine[500] = "";
int currentLineIndex = 0;
bool nextLineIsMessage = false;
SoftwareSerial SIM900(pinGSM_TX, pinGSM_RX);
void setup(){
Serial.begin(115200);
Serial.println();
Serial.println(F("====================="));
Serial.println(F("GSM remote v1.0 "));
Serial.println(F("====================="));
Serial.print(F("Allowed callers: "));
do {
ee_data = EEPROM.read(idx);
if (ee_data == '+'){
do {
allowed_callers += ee_data;
idx++;
ee_data = EEPROM.read(idx);
} while (ee_data != '$');
allowed_callers += "$";
}
idx++;
} while (ee_data != '#');
Serial.println(allowed_callers);
Serial.println();
SIM900.begin(19200);
Serial.println(F("Power on"));
pinMode(pinRelay, OUTPUT);
pinMode(pinRelayGND, OUTPUT);
digitalWrite(pinRelay, LOW);
digitalWrite(pinRelayGND, LOW);
pinMode(pinGSMstart, OUTPUT);
digitalWrite(pinGSMstart, LOW);
delay(1000);
digitalWrite(pinGSMstart, HIGH);
Serial.println(F("Starting GSM module"));
delay(2000);
digitalWrite(pinGSMstart, LOW);
Serial.println(F("Waiting for network"));
delay(20000);
Serial.println(F("Setting up..."));
SIM900.println("AT+CSCS=\"GSM\"");
delay(300);
SIM900.println("AT+CMGF=1");
delay(300);
SIM900.println("AT+CLIP=1");
delay(300);
SIM900.println("AT+CNMI=2,2,0,0,0");
delay(300);
Serial.println(F("GSM module configured and ready"));
}
void sendCallers(){
Serial.println(F("Send list of authorized callers"));
SIM900.println("AT+CMGS=\"" + SMS_sender + "\"");
delay(100);
SIM900.println(allowed_callers);
delay(100);
SIM900.println((char)26);
delay(100);
SIM900.println();
}
void loop(){
if (SIM900.available() > 0){
char incoming = SIM900.read();
if (incoming == '\r' || incoming == '\n'){
String lastLine = String(currentLine);
if (lastLine.startsWith("+CMT:")){
Serial.print(F("SMS RCVD: "));
SMS_sender = lastLine.substring(7, lastLine.indexOf('"', 8));
Serial.println(lastLine);
nextLineIsMessage = true;
} else if (lastLine.startsWith("+CLIP:")){
Serial.print(F("CALL RCVD: "));
String caller = lastLine.substring(8, lastLine.indexOf('"', 9));
Serial.println(caller);
if (allowed_callers.indexOf(caller) >= 0){
Serial.println(F("Allowed caller"));
digitalWrite(pinRelay, HIGH);
delay(1000);
digitalWrite(pinRelay, LOW);
} else {
Serial.println(F("Not allowed caller!"));
}
SIM900.println("ATH"); // zlozit hovor
delay(100);
} else if (lastLine.length() > 0){
if (nextLineIsMessage){
Serial.print(F("SMS DATA: "));
Serial.println(lastLine);
String new_number = lastLine.substring(11);
idx = 0;
if (lastLine.indexOf("PRIDAJ ") >= 0){ // pridat cislo do zoznamu povolenych
while (EEPROM.read(idx) != '#') idx++;
byte len = new_number.length();
for (byte x = 0; x < len; x++) EEPROM.write(idx + x, new_number[x]);
EEPROM.write(idx + len, '$');
EEPROM.write(idx + len + 1, '#');
allowed_callers += new_number;
allowed_callers += "$";
Serial.println("Adding new authorized caller: " + new_number);
sendCallers();
} else if (lastLine.indexOf("VYMAZ ") >= 0){ // odstranit cislo zo zoznamu povolenych
Serial.println(F("Removing authorized caller"));
int start = allowed_callers.indexOf(new_number);
for (byte i = 0; i <= new_number.length(); i++) allowed_callers.setCharAt(start + i, '*');
for (int ee_addr = 0; ee_addr < 512; ee_addr++) EEPROM.write(ee_addr, '#');
for (int ee_addr = 0; ee_addr < allowed_callers.length(); ee_addr++) EEPROM.write(ee_addr, allowed_callers[ee_addr]);
sendCallers();
} else if (lastLine.indexOf("VYNULUJ") >= 0){
Serial.println(F("Reseting authorized callers"));
for (int ee_addr = 0; ee_addr < 512; ee_addr++) EEPROM.write(ee_addr, '#');
char* master = "+421905111111$#";
for (int ee_addr = 0; ee_addr < 15; ee_addr++) EEPROM.write(ee_addr, master[ee_addr]);
allowed_callers = master;
allowed_callers += "$";
Serial.println(F("Reset list of callers and delete all SMS"));
SIM900.println("AT+CMGD=1,4");
delay(100);
sendCallers();
} else if (lastLine.indexOf("POSLI") >= 0){
sendCallers();
}
nextLineIsMessage = false;
}
}
for (int i = 0; i < sizeof(currentLine); ++i) currentLine[i] = (char)0;
currentLineIndex = 0;
} else {
currentLine[currentLineIndex++] = incoming;
}
}
}
Formát dát v EEPROM – položka začína znakom +, končí $. Koniec zoznamu je #. Vymazané číslo ***.
+prvecislo$+druhecislo$***********+stvrtecislo$########
Ukážka výstupu na sériovej konzole po štarte modulu a prijatej SMS a hovore:
RDY
+CFUN: 1
+CPIN: READY
+CREG: 0
+CREG: 2
Call Ready
+CREG: 1
*PSNWID: "231","06", "O2 - SK", 0, "O2-SK", 0
*PSUTTZ: 2019, 1, 1, 10, 38, 55, "+4", 1
DST: 1
AT+CSCS="GSM"
OK
AT+CMGF=1
OK
AT+CLIP=1
OK
AT+CNMI=2,2,0,0,0
OK
+CMT: "+421915mojecislo","","19/01/01,11:12:25+04"
PRIDAJ +421901987654
RING
+CLIP: "+421915mojecislo",145,"",,"",0
NO CARRIER
Pridaj komentár