24-02-2018, 22:03
tagi
Arduino sim800, identyfikacja numeru przychodzącego, softwareserial odczyt danych
Witam
Chcę zrobić alarm używając Arduino. Sprawa banalna, czujniki, syrena parę prostych IFów... ale jak go wyłączyć, rozbroić? Fajnie by było użyć do tego telefonu, skoro każdy go ma ze sobą. I takich gotowych rozwiązani jest multum. tyle ze opierają swoje działanie na internecie albo smsach. Odpada. już przez sam fakt że odbezpieczenie alarmu wymaga kilku ruchów na ekranie. Nie każdy ma smartfona, nie każdy ma internet i wogóle pisanie smsa żeby wejść do lokalu - uważam za chybiony pomysł. Puszczenie "dzwonka" nie wystarczy? Tylko takiego rozwiązania nie znalazłem.
Założenia:
Alarm ma powiadamiać zdalnie o naruszeniu. W zasadzie wystarczy nawiązanie rozmowy, ale może być sms, z informacją który czujnik zadziałał. Rozbrajanie alarmu ma być realizowane za pomocą dowolnego telefonu. wstępnie był pomysł aby każda osoba dzwoniąca na numer alarmu go rozbrajała, ale co z telemarketerami? No to może dzwonek wejście do lokalu i w ciągu 30 sekund potwierdzenie rozbrojenia przyciskiem? Nie... Na bank da się to zrobić identyfikując numer. Musi być tak, aby alarm odbezpieczały tylko wybrane numery.
Hardware:
Arduino NANO. modem, moduł o nazwie SIM800. czujniki pir, albo mikrofalowe, wyświetlacz lcd, przekaźnik uruchamiający syrenę, buzer. Ze względu na różnice napięć, jedną z nóżek sim800 trzeba podłączać przez "dzielnik napięcia" zrobiony z rezystora 3k2 i 4k7 ohm. sim800 ma nieładny zwyczaj pobierania bardzo dużego prądu w momencie pierwszego logowania się do sieci, więc trzeba mu przy samym zasilaniu zapiąć duuży kondensator. czytałem ze 1500mikro wystarczy, u mnie nie zawsze wystarczał. więc dałem 3300mikro. Arduino jest zasilane z 5V, sim800 z baterii, wiec nie zalecam przekraczania 4.2V. (mój jest zasilany z 18650)
Software:
(jeśli potrafisz to zrobić prościej - napisz proszę jak)
punktem wyjścia jest zestawienie komunikacji z PC po hardwarowym serialu przez kabel usb, a z sim800 po softwarowym serialu, po zdefiniowanych pinach. znaki przychodzące z (klawiatury PC) hard-seriala wysyłane są do (sim800) soft seriala. i na odwrót. znaki wysyłane z soft seriala(sim800) są wysyłane na hard-serial(ekran PC) Znaki. to ważne słowo. Nieda się więc szukać w tym co widzimy na ekranie numeru telefonu, bo to zlepek pojedyńczych znaków. Czy trzeba analizować ciągle kolejne ciągi znaków? Czy nie spowoduje to "zamulenia" arduino? Ja to "obszedłem" tak: Mój numer telefonu to 508xxxxx. Więc wystarczy że w transmisji z seriala będę szukał "piątki" i 8 kolejnych znaków. trop okazał sie słuszny. jeśli program znajdzie "piątkę" to do ciągu o nazwie "numer_telefonu" dopisuje (matematycznie dodaje) każdy kolejny znak. tak dostałem swój numer, który mogłem porównać z wprowadzonym do programu. Można było dopisać w programie kilka numerów telefonu od porównywania. to nie problem. problem był taki, że wszystkie musiały się zaczynać od "piątki" Przed numerem telefonu jest "clip:" więc zacząłem "łapać wysyłane znaki od dwukropka i zapisałem do zmiennej "numer_telefonu". następnie odczytałem (porównałem) zmienną z pominięciem 3 pierwszych znaków.
Czy istnieje inna metoda? W zasadzie tak. Znalazłem program, naprawdę profesjonalny program zarządzający otwieraniem bramy. Jednak tam wykorzystano inny system identyfikacji, gdyż sam pogram na arduino miał być uniwersalny dla każdej bramy, więc nie mógł zawierać numerów telefonu.... czyli numery muszą być zapisane na karcie sim. ów program wymaga modyfikowanej biblioteki sim900h, którą ja jeszcze musiałem zmodyfikować aby soft-serial działał na tych a nie innych pinach. Czy to nie lepsze rozwiązanie? To zależy. ja raz ustalę jakie numery otwierają alarm, więc to mi nie robi różnicy. Mogę żonglowac kartami sim, co moze przełożyć sie na niższe koszty. no i chyba dośc istotna sprawa, ten program w okrojonej wersji zajmuje 29% pamięci i 49% pamięci zmiennych, mój (okrojony) 11 i 14%. Ale sam pomysł naprowadził mnie na inne rozwiązanie.
rozwiązanie problemu nr 2
Wszystkie numery telefonu które miały otwierać alarm, zapisałem na karcie sim, nadając im nazwy rozpoczynające się od ciągu trzech identycznych (żadko spotykanych) znaków i kolejnej cyfry. więc dajmy na to
508xxxxxx "+(-001"
508yyyyyy "+(-002"
508zzzzzz "+(-003".
Następne program miał za zadanie znaleźć znak "=", jeśli to znalazł to czekać na"(" a następnie na "-". ciąg trzech konkretnych znaków (z całej tabeli ascii) uważam za wystarczający do odblokowania alarmu. trudno to nazwać identyfikacją numeru, ale działa.
Problemy
Komunikacja po serialach nie jest idealna. dość często trafiały mi się jakieś błędy, najczęściej objawiające się rzędami odwróconych znaków zapytania, a czasami gubieniem wysyłanych znaków. z gubieniem znaków poradziłem sobie wstawiając delaye(10-50) a ze znakami zapytania... podnosząc prędkość transmisji do 57600. Nie pytajcie mnie dlaczego. Najczęściej spotyka sie na serialach w arduino 9600, czasem nawet 4800, a mnie rzędy pytajników zaczęły się kurczyć przy 37tyś cośtam a zniknęły na 57tyś. Niestety, czasami pierwszy dzwonek nie identyfikował się poprawnie. Aby uzyskać potwierdzenie identyfikowania zdecydowałem że "podniosę" słuchawkę w sim800, piknę coś dtmf-em i odłożę. 2 sekundy to 1 grosz - pomijalny koszt (wspomniana biblioteka sim900h potrzebuje 5 sekund (ciszy) na zainicjowanie piknięcia dtmfem. nie chodzi o grosiki ale wydłuża to czas zabawy z telefonem) Tu uwaga - po ATA ma NIE być spacji - długo się z tym męczyłem.
Arduino sim800, identyfikacja numeru przychodzącego, softwareserial odczyt danych
Witam
Chcę zrobić alarm używając Arduino. Sprawa banalna, czujniki, syrena parę prostych IFów... ale jak go wyłączyć, rozbroić? Fajnie by było użyć do tego telefonu, skoro każdy go ma ze sobą. I takich gotowych rozwiązani jest multum. tyle ze opierają swoje działanie na internecie albo smsach. Odpada. już przez sam fakt że odbezpieczenie alarmu wymaga kilku ruchów na ekranie. Nie każdy ma smartfona, nie każdy ma internet i wogóle pisanie smsa żeby wejść do lokalu - uważam za chybiony pomysł. Puszczenie "dzwonka" nie wystarczy? Tylko takiego rozwiązania nie znalazłem.
Założenia:
Alarm ma powiadamiać zdalnie o naruszeniu. W zasadzie wystarczy nawiązanie rozmowy, ale może być sms, z informacją który czujnik zadziałał. Rozbrajanie alarmu ma być realizowane za pomocą dowolnego telefonu. wstępnie był pomysł aby każda osoba dzwoniąca na numer alarmu go rozbrajała, ale co z telemarketerami? No to może dzwonek wejście do lokalu i w ciągu 30 sekund potwierdzenie rozbrojenia przyciskiem? Nie... Na bank da się to zrobić identyfikując numer. Musi być tak, aby alarm odbezpieczały tylko wybrane numery.
Hardware:
Arduino NANO. modem, moduł o nazwie SIM800. czujniki pir, albo mikrofalowe, wyświetlacz lcd, przekaźnik uruchamiający syrenę, buzer. Ze względu na różnice napięć, jedną z nóżek sim800 trzeba podłączać przez "dzielnik napięcia" zrobiony z rezystora 3k2 i 4k7 ohm. sim800 ma nieładny zwyczaj pobierania bardzo dużego prądu w momencie pierwszego logowania się do sieci, więc trzeba mu przy samym zasilaniu zapiąć duuży kondensator. czytałem ze 1500mikro wystarczy, u mnie nie zawsze wystarczał. więc dałem 3300mikro. Arduino jest zasilane z 5V, sim800 z baterii, wiec nie zalecam przekraczania 4.2V. (mój jest zasilany z 18650)
Software:
(jeśli potrafisz to zrobić prościej - napisz proszę jak)
punktem wyjścia jest zestawienie komunikacji z PC po hardwarowym serialu przez kabel usb, a z sim800 po softwarowym serialu, po zdefiniowanych pinach. znaki przychodzące z (klawiatury PC) hard-seriala wysyłane są do (sim800) soft seriala. i na odwrót. znaki wysyłane z soft seriala(sim800) są wysyłane na hard-serial(ekran PC) Znaki. to ważne słowo. Nieda się więc szukać w tym co widzimy na ekranie numeru telefonu, bo to zlepek pojedyńczych znaków. Czy trzeba analizować ciągle kolejne ciągi znaków? Czy nie spowoduje to "zamulenia" arduino? Ja to "obszedłem" tak: Mój numer telefonu to 508xxxxx. Więc wystarczy że w transmisji z seriala będę szukał "piątki" i 8 kolejnych znaków. trop okazał sie słuszny. jeśli program znajdzie "piątkę" to do ciągu o nazwie "numer_telefonu" dopisuje (matematycznie dodaje) każdy kolejny znak. tak dostałem swój numer, który mogłem porównać z wprowadzonym do programu. Można było dopisać w programie kilka numerów telefonu od porównywania. to nie problem. problem był taki, że wszystkie musiały się zaczynać od "piątki" Przed numerem telefonu jest "clip:" więc zacząłem "łapać wysyłane znaki od dwukropka i zapisałem do zmiennej "numer_telefonu". następnie odczytałem (porównałem) zmienną z pominięciem 3 pierwszych znaków.
Czy istnieje inna metoda? W zasadzie tak. Znalazłem program, naprawdę profesjonalny program zarządzający otwieraniem bramy. Jednak tam wykorzystano inny system identyfikacji, gdyż sam pogram na arduino miał być uniwersalny dla każdej bramy, więc nie mógł zawierać numerów telefonu.... czyli numery muszą być zapisane na karcie sim. ów program wymaga modyfikowanej biblioteki sim900h, którą ja jeszcze musiałem zmodyfikować aby soft-serial działał na tych a nie innych pinach. Czy to nie lepsze rozwiązanie? To zależy. ja raz ustalę jakie numery otwierają alarm, więc to mi nie robi różnicy. Mogę żonglowac kartami sim, co moze przełożyć sie na niższe koszty. no i chyba dośc istotna sprawa, ten program w okrojonej wersji zajmuje 29% pamięci i 49% pamięci zmiennych, mój (okrojony) 11 i 14%. Ale sam pomysł naprowadził mnie na inne rozwiązanie.
rozwiązanie problemu nr 2
Wszystkie numery telefonu które miały otwierać alarm, zapisałem na karcie sim, nadając im nazwy rozpoczynające się od ciągu trzech identycznych (żadko spotykanych) znaków i kolejnej cyfry. więc dajmy na to
508xxxxxx "+(-001"
508yyyyyy "+(-002"
508zzzzzz "+(-003".
Następne program miał za zadanie znaleźć znak "=", jeśli to znalazł to czekać na"(" a następnie na "-". ciąg trzech konkretnych znaków (z całej tabeli ascii) uważam za wystarczający do odblokowania alarmu. trudno to nazwać identyfikacją numeru, ale działa.
Problemy
Komunikacja po serialach nie jest idealna. dość często trafiały mi się jakieś błędy, najczęściej objawiające się rzędami odwróconych znaków zapytania, a czasami gubieniem wysyłanych znaków. z gubieniem znaków poradziłem sobie wstawiając delaye(10-50) a ze znakami zapytania... podnosząc prędkość transmisji do 57600. Nie pytajcie mnie dlaczego. Najczęściej spotyka sie na serialach w arduino 9600, czasem nawet 4800, a mnie rzędy pytajników zaczęły się kurczyć przy 37tyś cośtam a zniknęły na 57tyś. Niestety, czasami pierwszy dzwonek nie identyfikował się poprawnie. Aby uzyskać potwierdzenie identyfikowania zdecydowałem że "podniosę" słuchawkę w sim800, piknę coś dtmf-em i odłożę. 2 sekundy to 1 grosz - pomijalny koszt (wspomniana biblioteka sim900h potrzebuje 5 sekund (ciszy) na zainicjowanie piknięcia dtmfem. nie chodzi o grosiki ale wydłuża to czas zabawy z telefonem) Tu uwaga - po ATA ma NIE być spacji - długo się z tym męczyłem.
Kod:
// napisał: ToMasz
// bierz co chcesz do swoich projektów
// Dziel się z innymi, ale wspomnij o autorze
#include <SoftwareSerial.h> // do obslugi rx i tx z sim800
SoftwareSerial serialSIM800(3,4); //ustawienia pinow Rxi Tx do komunikacji z sim800
#include <LiquidCrystal_I2C.h> // do obslugi wyswietlacza LCD
LiquidCrystal_I2C lcd(0x3f, 2,1,0,4,5,6,7); // ustawienie adresu LCD I2C
int i=1; //zmienna potrzebna do petli for
char znak=' '; // pojedynczy znak wczytywany z seriala
String numer=""; // numer telefonu poskladany z pojedynczych znakow
void setup() {
Serial.begin(57600); //start komunikacji przez USB
while(!Serial); // Potrzebne do komunikacji prze USB
serialSIM800.begin(57600); // start komunikacji z sim800
// na 57600 najlepiej to dziala. na duzo nizszych prędkosciach
// czasami wyswietlaly sie znaki zapytania. na wyzszych - gubily znaki
pinMode(9, OUTPUT); // tu jest podlaczona diodka z rezystorem 500ohm
digitalWrite(9, HIGH); // migamy sobie diodka
delay(500); // przy starcie
digitalWrite(9, LOW); // w celu sprawdzeia czy dziala
lcd.begin(16,2); // initialize the lcd
lcd.setBacklightPin(3, POSITIVE); //na pinie 3 LCD (nie arduino) bedzie swiatlo
lcd.setBacklight(HIGH); //zalaczamy swiatelko
lcd.setCursor(0,0); // kursor na poczatek ekranu
lcd.clear(); // czyscimy ewentualne smieci
Serial.println("Komunikacja software serial dziala"); //Taki tam testowy napis seeriala
serialSIM800.write("AT\r"); //na wszelki wypadek budzimy modem do zycia
//serialSIM800.write("AT+CBC \r"); //stan baterii procent naladowania, mili wolt
//serialSIM800.write("AT+COPS? \r"); // u jakiego operoatora jeses?
//serialSIM800.write("AT+CSQ \r"); // zasieg. umnie 30 to maks
}
void loop() {
if(serialSIM800.available()){ //jesli sa jakies dane na porcie sim800
znak=(serialSIM800.read()); // odczytaj jeden znak
Serial.write(znak); // wyslij hardware serialem = wyswietl go na ekranie pc
} // koniec IFa odczytujacego dane Z sim800
delay(10);
if(znak==':'){ // jesli odczytales dwukropek, to chyba leci identyfikacja numeru
Serial.println("znalazlem numer telefonu!!!!");
//digitalWrite(9, HIGH); /// z radosci zapal diodke (pomaga debugowac)
for (i=1; i<12; i++){ //skoro "leci" numer dzwoniacego
znak=(serialSIM800.read()); // odczytaj dokladnie 12 kolejnych znakow
delay(10); // tak na wszelki wypadek
numer=numer+znak; // i zapisz cale 12 znakow od dwukropka do Stringu "numer"
} // koniec petli for
Serial.println(numer.substring(2)); // pomin dwukropek, cudzyslow i wyswietl tylko numer
lcd.print(numer.substring(2)); // rowniez na ekranie lcd
if (numer.substring(2)=="508508508"){ // jesli numer dzwoniacy jest taki sam jak podany
digitalWrite(9, HIGH); // zaswiec diodke
serialSIM800.write("ATA\r"); // odbierz rozmowe aby potwierdzic identyfikacje
delay(500); // zagraj melodyjke
serialSIM800.write("AT+VTS=1\r"); // dzwiekami DTMF
delay(1000);
serialSIM800.write("AT+VTS=9\r");
delay(1000);
serialSIM800.write("ATH\r"); //zakoncz rozmowe
}
// sprzatamy po sobie:
lcd.setCursor(0,0); // kursor wraca na poczatek w oczekiwaniu na nowy numer tel
digitalWrite(9, LOW); // gasimy diodke
numer=""; // kasujemy numer
} // koniec IFa identyfikujacego numer telefonu
if(Serial.available()){ // jesli cos jest pisane na klawiaturze
serialSIM800.write(Serial.read()); // to przeslij to do sim800
} //koniec ifa sprawdzajacego czy cos jest pisane na klawiaturze
} //koniec loop