/*
For the purposes of this program I have modified GSM-GPRS-GPS-Shield library from
https://github.com/open-electronics/GSM-GPRS-GPS-Shield.
This code is runnig on Arduino Nano clone and SIM800L modem.
For proper communication with SIM800L parameters need to be set:
-GSM.cpp
#define _GSM_TXPIN_
#define _GSM_RXPIN_
-GSM.h
#define GSM_ON
If your SIM card require PIN code, open GSM.cpp,
find SendATCmdWaitResp(F("AT+CPIN=XXXX"), 500, 50, "READY", 5); uncomment and fill XXXX
http://theveel.com/
Kamil Kaleta
*/
#include "SIM900.h"
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <EEPROM.h>
#include "sms.h"
#include "call.h"
CallGSM call;
SMSGSM sms;
const int RELAY1 = A0;
const int RELAY2 = A1;
const int callsAddr = 0;
const int openingAddr = 1;
//I`m counting calls and relay opening
//Liczę przychodzące rozmowy oraz uruchomienie przekaźnika
int calls = 1;
int opening = 1;
char spos;
char number[13];
char sim_number[13];
char reply[210];
char stat;
char message[159];
//Comment to disable debug with Serial.
//Zakomentowanie wyłączy konsolę Serial
#define LOCAL_DEBUG
//Comment line below to disable sms sent (when testing/debuging)
//Zakomentowanie wyłączy wysyłanie wiadomości SMS np podczas debugowania
#define SMS_ON
void setup()
{
spos = -1;
Serial.begin(9600);
Serial.println(F("> GSM Shield testing"));
if (gsm.begin(2400)) {
Serial.println(F("> Status READY"));
}
else Serial.println(F("> Status IDLE"));
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH);
gsm.SimpleWriteln(F("AT+CMEE=2"));
checkSMS();
};
void loop()
{
byte b = call.CallStatus();
if (b == CALL_INCOM_VOICE) {
#ifdef LOCAL_DEBUG
Serial.print(F("> Incomming phone call from "));
#endif
if (call.CallStatusWithAuth(number, 1, 100) == CALL_INCOM_VOICE_AUTH) {
#ifdef LOCAL_DEBUG
Serial.println(F(" Allowed <"));
#endif
//Pick up, wait a second, hang up and close/open relay, increase opening counter
//Odbierz rozmowę, poczekaj chwilę, rozłącz rozmowę i zamknij/otwórz przekaźnik, inkrementuj licznik otwarć
call.PickUp();
delay(100);
call.HangUp();
digitalWrite(RELAY1, LOW);
delay(1000);
digitalWrite(RELAY1, HIGH);
opening = EEPROM.read(openingAddr) + 1;
EEPROM.update(openingAddr, opening);
} else {
#ifdef LOCAL_DEBUG
Serial.println(F(" Forbidden <"));
#endif
call.PickUp();
delay(100);
call.HangUp();
}
calls = EEPROM.read(callsAddr) + 1;
EEPROM.update(callsAddr, calls);
} else {
checkSMS();
}
};
void pinInterrupt(void) {
detachInterrupt(1);
}
void sleepNow(void)
{
//Arduino is awake by SIM800L. Check data from modem, starts loop and go sleep again.
//Modem RING pin is connected to D1 pin (interrupt1)
//Arduino jest wybudzane przez modem SIM800L, uruchamia pętlę i ponownie zasypia
//Pin RING modemu podłączony jest do pinu D1 Arduino (przerwanie1)
//Without this modem will continue sending +creg reply which will wake up arduino for no reason
//Bez tej komendy modem będzie cyklicznie wybudzał arduino
gsm.SendATCmdWaitResp("AT+CREG=0", 2000, 50, "OK", 2, reply );
#ifdef LOCAL_DEBUG
Serial.println(F("< Fell asleep >"));
#endif
attachInterrupt(1, pinInterrupt, LOW);
delay(100);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
sleep_disable();
#ifdef LOCAL_DEBUG
Serial.println(F("n< Woke up >"));
#endif
//Important delay
//Ważne opóźnienie
delay(2000);
}
void checkSMS() {
#ifdef LOCAL_DEBUG
Serial.println(F("> Check text Messages"));
#endif
gsm.SendATCmdWaitResp("AT+CREG=2", 2000, 50, "OK", 2, reply );
delay(1000);
spos = sms.IsSMSPresent(SMS_ALL);
Serial.println(spos);
message[0] = '';
number[0] = '';
sim_number[0] = '';
reply[0] = '';
byte admNrValid = 0;
if ((int)spos > 0) {
//Check if there is a contact on position 1 simcard, it`s where it keeps Administrator phone number
//Sprawdź czy na 1 pozycji karty SIM znajduje się kontakt - na pierwszej pozycji przechowywany jest numed administratora
if (1 == gsm.GetPhoneNumber(1, number)) {
#ifdef LOCAL_DEBUG
Serial.print(F("n@ Administrator phone numbern@ ")); Serial.println(number);
#endif
admNrValid = 1;
} else {
#ifdef LOCAL_DEBUG
Serial.print(F("> No Administrator phone number!"));
#endif
}
//Ckeck if Authorized SMS (from Admin, whitch is positin 1 on sim card)
//Sprawdź czy SMS autoryzacyjny - czy nadawcą jest Administrator
stat = sms.GetAuthorizedSMS((int)spos, number, 13, message, 160, 1, 1);
#ifdef LOCAL_DEBUG
Serial.print(F("n########## SMS ############n# Position on list:"));
Serial.println((int)spos);
Serial.print(F("# From:"));
Serial.println((char *)number);
Serial.print(F("# Message:"));
Serial.println(message);
#endif
if (stat == GETSMS_AUTH_SMS) {
//Split sms body to keywords
//Podziel wiadomość SMS na komendy
char delimiters[] = ";";
char* valPosition;
valPosition = strtok(message, delimiters);
char* smsWords[] = {0, 0, 0};
int i;
while (valPosition != NULL) {
smsWords[i] = valPosition;
#ifdef LOCAL_DEBUG
Serial.print(F("# smsWords["));
Serial.print(i); Serial.print(F("] = "));
Serial.println(smsWords[i]);
#endif
valPosition = strtok(NULL, delimiters);
i++;
}
/*
SMS keywords
Wyciągniete słowa kluczowe z SMSa
smsWords[0]=[C]ontact, [A]dmin
smsWords[1]=[A]add, [D]elete, [F]ind,[A]tt,[U]ssd
smsWords[2]=phoneNumber,[A]ll,atCommand, ussdCode
smsWords[3]=contatName
smsWords[4]=[N]otify
Available sms commands
Dostępne komendy SMS
C;A;xxxxxxxxx;John Doe;N - will add (if not exist) John Doe contact and send him a message
C;A;xxxxxxxxx;John Doe - will add (if not exist) John Doe contact
C;D;xxxxxxxxx - will delete contact with number xxxxxxxxx (if exist)
C;D;A - will delete ALL contacts (Administrator too)
C;F;xxxxxxxxx - will find if number xxxxxxxxx exist on phonebook
A;A;AT+CBC - will execute AT command (e.g. AT+CBC) and send modem answer
A;U;someCode - will execute USSD code
A;I - will send replay message with some details
*/
//Parse incomming message
//Dekodowanie wiadomości SMS
if (strcmp(smsWords[0], "C") == 0)
{
#ifdef LOCAL_DEBUG
Serial.println(F("[C]ontact"));
#endif
if (strcmp(smsWords[1], "A") == 0)
//[C]ontact-[A]dd
{
#ifdef LOCAL_DEBUG
Serial.println(F("[C]ontact-[A]dd"));
#endif
byte p = isPhoneNumber(smsWords[2]);
if (p > 0)
{
char smsBody[160] = {0};
strcat(smsBody, "Phone number ");
strcat(smsBody, smsWords[2]);
strcat(smsBody, " ALREADY found on position ");
char buffer [20];//iteger as char
itoa ( p, buffer, 10);
strcat(smsBody, buffer);
#ifdef SMS_ON
//Send SMS with smsBody to Administrator (1 simcard contact position)
//Wyślij SMS do Administratora (kontakt na 1 pozycji karty SIM)
sms.SendSMS(1, smsBody);
#endif
#ifdef LOCAL_DEBUG
Serial.print("nSMS ");
Serial.println(smsBody);
#endif
} else {
#ifdef LOCAL_DEBUG
Serial.print(F("Have NOT found given number.I will try to add "));
Serial.println(smsWords[2]);
#endif
if (1 == gsm.WritePhoneNumber(0, smsWords[2], smsWords[3]))
{
byte b = isPhoneNumber(smsWords[2]);
if (strcmp(smsWords[4], "N") == 0)
//NOTIFY USER
{
#ifdef SMS_ON
//Send SMS to b, which is new contact simcard index
//Wyślij SMS do b, gdzie b to index dodawanego kontaktu
sms.SendSMS(b, "Your phone number has been registered");
#endif
#ifdef LOCAL_DEBUG
Serial.print(F("[SMS] "));
Serial.println(F("Your phone number has been registered."));
#endif
}
char smsBody[160] = {0};
strcat(smsBody, "Phone number ");
strcat(smsBody, smsWords[2]);
strcat(smsBody, " has been registered on position ");
char buffer [20];//iteger as char
itoa ( b, buffer, 10);
strcat(smsBody, buffer);
#ifdef SMS_ON
sms.SendSMS(1, smsBody);
#endif
#ifdef LOCAL_DEBUG
Serial.print(F("n[SMS] "));
Serial.println(smsBody);
#endif
}
}
} else if (strcmp(smsWords[1], "D") == 0)
//[C]ontact-[D]elete
{
#ifdef LOCAL_DEBUG
Serial.println(F("[C]ontact-[D]elete"));
#endif
if (strcmp(smsWords[2], "A") == 0) {
//[C]ontact-[D]elete-[A]ll
#ifdef LOCAL_DEBUG
Serial.println(F("[C]ontact-[D]elete-[A]ll"));
#endif
for (int i = 1; i < 251; i++) {
gsm.DelPhoneNumber(i);
}
gsm.SendATCmdWaitResp("AT+CPBR=1,250", 20000, 50, "OK", 5, reply );
#ifdef SMS_ON
sms.SendSMS(number, (char *)reply);
#endif
#ifdef LOCAL_DEBUG
Serial.print(F("[SMS] "));
Serial.println((char *)reply);
#endif
} else {
//Will delete single contact but is number on phonebook?
//Usuwa kontakt jeżlei znajdzie na karcie SIM
byte p = isPhoneNumber(smsWords[2]);
if (p > 0)
{
if (1 == gsm.DelPhoneNumber(p)) {
char smsBody[160] = {0};
strcat(smsBody, "Number ");
strcat(smsBody, sim_number);
strcat(smsBody, " found on position ");
char buffer[4];
sprintf(buffer, "%d", p); //p to char
strcat(smsBody, buffer);
strcat(smsBody, ", and deleted");
#ifdef SMS_ON
sms.SendSMS(1, smsBody);
#endif
#ifdef LOCAL_DEBUG
Serial.print(F("[SMS] "));
Serial.println(smsBody);
#endif
} else {
char smsBody[160] = {0};
strcat(smsBody, "Found number ");
strcat(smsBody, sim_number);
strcat(smsBody, " on position ");
strcat(smsBody, p);
strcat(smsBody, ", but couldn't delete");
#ifdef SMS_ON
sms.SendSMS(1, smsBody);
#endif
#ifdef LOCAL_DEBUG
Serial.print(F("[SMS] "));
Serial.println(smsBody);
#endif
}
}
}
} else if (strcmp(smsWords[1], "F") == 0)
//[C]ontact-[F]ind
{
#ifdef LOCAL_DEBUG
Serial.println(F("[C]ontact-[F]ind"));
#endif
byte p = isPhoneNumber(smsWords[2]);
if (p > 0)
{
char smsBody[160] = {0};
strcat(smsBody, "Phone number ");
strcat(smsBody, smsWords[2]);
strcat(smsBody, " found on position ");
char buffer [20];
itoa ( p, buffer, 10);
strcat(smsBody, buffer);
#ifdef SMS_ON
sms.SendSMS(1, smsBody);
#endif
#ifdef LOCAL_DEBUG
Serial.print(F("[SMS] "));
Serial.println(smsBody);
#endif
} else {
char smsBody[160] = {0};
strcat(smsBody, "Phone number ");
strcat(smsBody, smsWords[2]);
strcat(smsBody, " has not been found");
#ifdef SMS_ON
sms.SendSMS(1, smsBody);
#endif
#ifdef LOCAL_DEBUG
Serial.print(F("[SMS] "));
Serial.println(smsBody);
#endif
}
}
} else if (strcmp(smsWords[0], "A") == 0) {
#ifdef LOCAL_DEBUG
Serial.println(F("[A]dministrator"));
#endif
if (strcmp(smsWords[1], "A") == 0)
//[A]dministrator-[A]T
{
#ifdef LOCAL_DEBUG
Serial.println(F("[A]dministrator-[A]T"));
#endif
gsm.SendATCmdWaitResp(smsWords[2], 5000, 50, "OK", 5, reply );
#ifdef SMS_ON
if (strlen((char *)reply) > 159)
sms.SendSMS(1, "AT Response too long for message");
else
sms.SendSMS(1, (char *)reply);
#endif
#ifdef LOCAL_DEBUG
Serial.print(F("[SMS] "));
Serial.println((char *)reply);
#endif
} else if (strcmp(smsWords[1], "U") == 0) {
//[A]dministrator-[U]SSD
#ifdef LOCAL_DEBUG
Serial.println(F("[A]dministrator-[U]SSD"));
#endif
char atussd[20] = {0};
strcat(atussd, "AT+CUSD=1,"");
strcat(atussd, smsWords[2]);
strcat(atussd, """);
char st = (gsm.SendATCmdWaitResp(atussd, 5000, 100, "CUSD", 3, reply));
if (2 == gsm.WaitResp(10000, 100, "CUSD")) {
char b[160];
memcpy(b, gsm.comm_buf + 2, strlen(gsm.comm_buf));
b[160] = '';
#ifdef SMS_ON
if (strlen(gsm.comm_buf) < 160)
sms.SendSMS(1, b);
else
sms.SendSMS(1, "USSD response to long for SMS message");
#endif
#ifdef LOCAL_DEBUG
Serial.print(F("[SMS] "));
Serial.println((char *)(gsm.comm_buf));
#endif
} else {
Serial.print(F("Something wrong with USSD command"));
Serial.println(reply);
#ifdef SMS_ON
sms.SendSMS(1, reply);
#endif
}
} else if (strcmp(smsWords[1], "I") == 0) { /////[A]dministrator-[I]nfo
char st[1];
st[0] = '';
char str_perc[3];
str_perc[0] = '';
char str_vol[6]; //4
str_vol[0] = '';
#ifdef LOCAL_DEBUG
Serial.println(F("[A]dministrator-[I]nfo"));
#endif
reply[0] = '';
opening = EEPROM.read(openingAddr);
calls = EEPROM.read(callsAddr);
char calls_;
char smsBody[160] = {0};
strcat(smsBody, "Calls: ");
char buffer[10];
sprintf(buffer, "%d", calls);
strcat(smsBody, buffer);
strcat(smsBody, ", Opening: ");
sprintf(buffer, "%d", opening);
strcat(smsBody, buffer);
if (1 == gsm.getBattInf(st, str_perc, str_vol)) {
strcat(smsBody, "n");
strcat(smsBody, "Batt ");
strcat(smsBody, str_perc);
strcat(smsBody, ", ");
strcat(smsBody, str_vol);
}
if (1 == (gsm.readCellTimeDate(reply))) {
strcat(smsBody, "n");
strcat(smsBody, reply);
}
#ifdef SMS_ON
sms.SendSMS(1, smsBody);
#endif
#ifdef LOCAL_DEBUG
Serial.print(F("[SMS] "));
Serial.println(smsBody);
#endif
}
}
#ifdef LOCAL_DEBUG
Serial.print(F("####### Authorized ########n"));
#endif
} else {
#ifdef LOCAL_DEBUG
Serial.print(F("###### NOT Authorized #####n"));
#endif
if (!admNrValid) {
//Very first SMS (1 simcard position was empty, so I will set sender as Administrator)
//Pierwszy SMS (pozycja 1 na karcie SIM jest pusta, więc ustawiam nadawcę jako Administratora)
#ifdef LOCAL_DEBUG
Serial.print(F(">> "));
Serial.print(number);
Serial.println(F(", set as Administrator number"));
Serial.print(F("###########################n"));
#endif
gsm.WritePhoneNumber(1, number, "Administrator");
#ifdef SMS_ON
sms.SendSMS(1, "You are Administrator now");
#endif
} else {
//This SMS is NOT Authorized SMS and the Administrator is set. I`m FFD it to the Administrator.
//SMS nieautoryzacyjny i już wpisany numer Administratora. Przesyłam do administratora, niech czyta.
char smsBody[160] = {0};
strcat(smsBody, "From: ");
strcat(smsBody, (char *)number);
strcat(smsBody, ", ");
strcat(smsBody, message);
#ifdef SMS_ON
sms.SendSMS(1, smsBody);
#endif
#ifdef LOCAL_DEBUG
Serial.print(F("[SMS] "));
Serial.println(smsBody);
#endif
}
}
//Now message must be removed
//Na koniec usuwam wiadomość SMS
#ifdef LOCAL_DEBUG
Serial.print(F("n!!!!!!!!!!!!!!!!!!!!!!!!!!!n! deleting messages n! on position "));
Serial.println((int)spos);
int d = 1;
for (int i = 0; i < 5; i++) {
delay(1000);
if (sms.DeleteSMS((int)spos) == 1)
{
Serial.println(F("! successfully completed"));
d = 0;
break;
} else
Serial.println(F("try delete message"));
}
if (d)
{
Serial.println(F("! !failed n! try kill em all"));
//This should not happen, but just in case delate all messages
//Nie powinno mieć miejsca, na wszelki wypadek usuwam wszystkie wiadomości SMS
gsm.SimpleWriteln(F("AT+CMGDA = "DEL ALL""));
}
Serial.print(F("!!!!!!!!!!!!!!!!!!!!!!!!!!!nn"));
#endif
} else
{
#ifdef LOCAL_DEBUG
Serial.println(F("> No SMS"));
#endif
sleepNow();
}
}
byte isPhoneNumber(char *what_nr) {
int found = 0;
//250 max amount contacts on my SIM card phonebook, this loop below costs you 40 seconds
//250 to maksymalna ilość kontaktów na mojej karcie SMS, ta pętla poniżej kosztuje 40 sekund
for (byte i = 1; i < 251; i++) {
// Serial.print("*");
// if ((i % 25) == 0)
// Serial.print("n");
if (1 == gsm.GetPhoneNumber(i, sim_number)) {
if (strstr(sim_number, what_nr))
{
found = i;
break;
}
}
}
return found;
}
Bardzo fajny projekt, przydatna rzecz.
Dzięki Leszek. Co ważne działa i żyje swoim życiem. Moje sąsiadki korzystają regularnie-bo maja tylko jednego pilota do bramy. Ja się wdzwaniam minutę przed dojechaniem do bramy i czeka na mnie otwarta :)
Niestety za cholerę nie potrafię tego uruchomić… Mozna jakis kontakt telefoniczny ? Chętnie bym kupił takie działające urządzonko… Pozdrawiam.
Jakaś lista podzespołów, schemat?
Listę sprzętu dopisałem dziś rano. Na schemat nie mam zwyczajnie czasu. Trzeba pracować żeby zarobić na przesyłki z Aliexpress :) Nie ukrywam że część softwareowa zajęła mi bardzo dużo czasu i to na niej skupiam opis. Podpięcia wynikają bezpośrednio z kodu. Oczywiście jak ktoś nie znajdzie to zapraszam do komentarzy.
Świetny projekt, zasłużone 5! Zachęcam do zobaczenia moich zmagań z komunikacją gsm TU LINK :)
Dzięki, widziałem już Twój artykuł i nawet oceniłem ;)
Myślałem o czymś podobnym. Ale zorganizowałem to inaczej. Przekaźnik podobnie zwiera styki w domofonie, ale mam inną komunikację. Mózgiem jest raspberry. Mam na nim inne rzezczy, i do tego też go wykorzystałem. Plus jest taki, że już go mam i nie potrzebuję nic nowego. Ale mam go zasilanego z gniazdka. Na raspi stoi serwer www (właśnie on jest używany do tych ‘innych rzeczy’), widoczny jest z zewnątrz. Zrobiłem prostą aplikację na smartfona, w której klikam ‘otwórz’ albo ‘zamknij’. Każde kliknięcie zmienia stan pinu połączonego z przekaźnikiem. I na tej podstawie przekaźnik zwiera albo rozwiera domofon.
Plus mam taki, że sprzęt praktycznie miałem już w domu. Rozbudowałem tylko istniejący system.
Minus, muszę mieć w smartfonie internet włączony.
Kolejny projekt typu “chwalimy się – nie pokazujemy szczegółów”.
Pomysł fajny, projekt fajny ale sorry, dla majsterkowicza, który chciałby skorzystać albo czegoś się nauczyć jest prawie bezwartościowy :(
Andy, jakich szczegółów nie pokazuję? Omawiam praktycznie cały kod. Niemało, prawie 600 linijek. Mam pisać że puls ładowarki łączę z plusem arduino? Twój komentarz też jest dla mnie ‘prawie bezwartościowy’, bo nie wiem co mam poprawić. Jeżeli jest faktycznie zapotrzebowanie na schemat, to proszę pisać w komentarzach lub założyć temat na forum. Pewnie znajdę godzinę żeby go narysować.
Projekt jest ciekawy, ale nie przydatny dla użytkowników, którzy chcieliby go powtórzyć (brak schematu połączeń). Założenie oszczędzania energii zostało sprowadzone tylko do usypiania arduino. Dlaczego nie jest usypiany najbardziej prądożerny element układu jakim jest sim800l? Sim800l posiada różne tryby oszczędzania energii, które należało umiejętnie zaaplikować w kodzie programu. Proszę poczytać o poleceniu “CSCLK”. Jeżeli jednym z złożeń projektu była oszczędność energii to należało: zastosować przekaźniki bistabilne i arduino 3.3V bez usb, wywalić moduł ładowania i DC boost converter. Gdyby autor pomyślał wcześniej i zamiast sim800l kupił sim800c (koszt na ali około 5$) z pinem VMCU to konwerter stanów logicznych też byłby nie potrzebny. Wprowadzenie poprawek, które wymieniłem powyżej pozwoliłaby układowi na kilkutygodniową pracę przy zasilaniu z jednego ogniwa 18650. Przy opisywaniu projektu zabrakło też podstawowej informacji jaki jest pobór prądu (proszę podać taką informację).
Pisałem o oszczędzaniu baterii nie o pracy przez kilka tygodni. Jesteś pewien że SIM800L poprawnie implementuje CSCLK? Jak wybudzić modem przy połączeniu przychodzącym? Żeby to zrobić trzeba podać DTR z… czego? Nie sądzę żeby modem w trybie uśpienia potrafił sam się wybudzić. O schemacie już pisałem w komentarzu, szkoda że nie czytałeś. O DC boosterze i konieczności jego użycia też jest w tekście. Argument że mogłem użyć innych części – jak dla mnie kulą w płot. Moje projekty powstają spontanicznie i składam z tego co mam pod ręką. A części zamawiam w Chinach, wiec czas oczekiwania to koło miesiąca. Szkoda że nie znalazłeś w moim projekcie nic pozytywnego. Poza tym, nie_przydatny piszemy razem. Pozdrawiam.
1. Kilka komentarzy wyżej napisałeś, że cyt. “Jeżeli jest faktycznie zapotrzebowanie na schemat, to proszę pisać w komentarzach” więc napisałem, że w opisie projektu zabrakło schematu połączeń. 2. Napisałeś też, że cyt. “są komentarze że modem SIM800L może potrzebować nawet 2A podczas logowania do sieci”. Komentarze w tym przypadku mówią prawdę, ale takie rzeczy sprawdza się specyfikacji. 3. Kolejny cytat ” Jesteś pewien że SIM800L poprawnie implementuje CSCLK? Jak wybudzić modem przy połączeniu przychodzącym? Żeby to zrobić trzeba podać DTR z… czego?” Tak jestem pewien, że sim800l poprawnie obsługuje tryby oszczędzające energię, ponieważ sam z nich korzystam. Komentarze pod projektem to nie jest najlepsze miejsce na wykład, a szczególnie jak piszę się ze smartfona. Tak jak napisałem wcześniej sim800l posiada kilka trybów oszczędzających energię. Jeszcze raz polecam zapoznać się ze specyfikacją sim800l, a o ewentualne niejasności zapytać tutaj. Tak w skrócie. Sim800l możemy wprowadzić w Sleep Mode 1 i Sleep Mode 2. Zarówno przy sleep mode 1, jak i przy sleep mode 2 sim800l wybudza się automatycznie kiedy odbiera sms-a lub przychodzi połączenie głosowe. W tym czasie na pinie RI przez około 1 sekundę pojawia się stan niski. RI możemy użyć jako przerwanie, aby wybudzić arduino. Jak zapewne się domyśliłeś ustawienie trybu sleep mode 1 lub 2 nie odcina sim800l od sieci, ale różnice w oszczędności energii są bardzo duże. W sleep mode 2 zużycie energii w czasie monitorowania sieci wynosi tylko do 3 mA, a bez włączonego sleep mode minimum 13 mA. Przy Twoim projekcie oszczędzanie energii powinno być priorytetem, które można rozwiązać małym kosztem.
Na balkonie marznie już czujnik temperatury, (Arduino PM 3,3V 8Mhz) do stacji pogody. Ten to będzie miał szansę na kilka jak nie kilkadziesiąt tygodni pracy bez ładowania :) O trybach pracy uśpienia SIM800L czytałem kilka artykułów które opisywały wyłącznie kłopoty z tym związane. Więc na razie nie podejmuję tematu- przynajmniej do czasu zamówienia kolejnego modemu. Nie chcę demontować sterownika, bo po prostu już działa i co tu nie mówiąc – robi robotę.
Problem pojawi się gdy korzystając z SDR (np bladeRF x40) postawimy niedaleko własnego BTSa i podszyjemy się pod numer administratora :)
A pod jaki numer dokładnie chcesz się podszyć? Znasz ten z pozycji 1 mojej karty SIM? Poza tym skąd gwarancja że modem zaloguje się do twojego fałszywego BTSa?
Bo SIM800L domyślnie loguje się do BTSa z najwyższym RSSI, którego ID sieci się zgadza z tym na karcie SIM. Załatwia to antena kierunkowa wycelowana w moduł. Numer można poznać poprzez nasłuch ruchu sieciowego dla danego IMEI. IMEI mam na zdjęciu w artykule :) Ogólnie projekt bardzo mi się podoba, ale nie polegałbym na rzekomym bezpieczeństwie sieci 2G. Takowe praktycznie nie istnieje. Sensowniej byłoby nawiązać komunikację przez GPRS i dane przesyłać szyfrowane. Chociażby z użyciem MQTT. Niemniej muszę przyznać, że wdzwanianie się na numer modemu jest nieporównywalnie wygodniejsze.
Moduł wykorzystuje Arduino, można zatem zaimplementować szyfrowanie RSA i podpis cyfrowy (funkcja skrótu). Komunikacja jest tylko w jedną stronę. Klucz prywatny wgrywasz osobiście. Są odpowiednie algorytmy do generowania haseł jednorazowych (nadawca) i ich jednorazowej weryfikacji (odbiorca). Można też wykorzystywać rzeczy zmienne, ale znane dla obu stron (np. data, godzina jeśli do układu dodać by zegar RTC). Jest sporo sposobów by bardzo skutecznie zabezpieczyć transmisję :)
Oczywiście że nie. Nie do najmocniejszego RSSI ale najwyższej technologii. Lte zawsze wygra z 3G, z którym przegra 2G.
U jakiego operatora najtaniej wychodzi utrzymywać kartę SIM aktywną na odbieranie SMS-ów?
Play “rok ważności konta”
SMS 9gr.
W KLUCZ MOBILE po każdym zasileniu konto ważne jest rok, a sms-y w sieci KLUCZ MOBILE są za darmo! SMS-y wysyłane poza sieć są po 9 gr.
Najtaniej wychodzi w sieci KLUCZ MOBILE. Każde zasilenie przedłuża ważność konta o rok. SMS-y w sieci KLUCZ MOBILE są za darmo!
Ja korzystam z njumobile.
Projekt świetny – myślałem kiedyś nad czymś podobnym, tylko zamiast modułu GSM stara nokia, no ale to gra nie warta świeczki, jeżeli moduł kosztuje 15zł :D
Powiedz mi proszę czy wiesz, czy ciągłe ładowanie tym modułem nie wpływa negatywnie na pojemność baterii? Czy bez problemu można korzystać z niego cały czas, czy lepiej programowo załączać go np. mosfetem gdy napięcie aku spadnie poniżej jakiegoś poziomu?
Widzę, że autorowi projektu ciężko jest odpowiedzieć na Twoje pytanie. Przypomnę, że obiecał też umieszczenie schematu połączeń, ale go nie wstawił :)
Nie jest ciężko. Po prostu nie zaglądam do tematu co dziennie. Nie ma też maili o nowym komentarzu. woysz akumulatory powinny pracować w trybie buforowania, czyli być zasilane określonym napięciem konserwującym. W projekcie można się pokusić o mocniejszy zasilacz i całkowicie pozbyć się akumulatora. @nowy, mogę się jedynie usprawiedliwić, że pracuję nad fajną stacją pogodową i już powoli kończę. Przy okazji zrobię dwa schematy ;)
woysz masz rację. Nie wiem, jak ciągłe ładownie ogniw wpłynie na jego żywotność, ale wiem, że takie rozwiązanie nie jest dobrym pomysłem. Włączanie ładowania ogniwa powinno być sterowne programowo. W sim800l wartość napięcia zasilania można sprawdzić poleceniem AT+CBC.
Używając laptopa wyciągasz z niego akumulator? Jest cała masa urządzeń które dokujemy i przez cały czas ładują się w nich akumulatory.
intrygujące !, a skąd wiozłeś SIM800 za 15 zł no chyba popłynąłeś trochę za bardzo
Gdzie kupić SIM800L za 15,47zł? Wszędzie, gdzie szukałem to po ~30zł
Najlepiej podaj link do sklepu w którym się zaopatrzyłeś w komponenty. :)
AliExpress € 3,80
Wczoraj zamawiałem ;)
W jaki sposob (elektronicznie i programowo) zrealizowany jest pomiar naladowania baterii? Cos nie moge znalezc…
Hej, Bardzo fajny ten projekt ale po amatorskiej próbie jego sprawdzenia jak działa, pojawił się problem z wgraniem szkicu a własciwie biblioteki GSM-GPRS-GPS-Shield-GSMSHIELD którą należy pobrać i dodać do IDE. Czy mógłbyś podpowiedzieć w jaki sposób należy dodać tą bibliotekę? Za każdym razem kiedy próbuję dodać ją w formie ZIP, program krzyczy że jest to niepoprawna biblioteka. Dzięki z góry za szybką odpowiedź,
Pozdrawiam,
Około linii 464 gsm.getBattInf
Napięcie jest raportowane przez modem.
Witam ponownie. Udało się finalnie wgrać i bibliotekę i kod. Ważne aby przy wgrywaniu Arduino nie było podłączone do żadnego układu i w moim przypadku musiałem nacisnąć przycisk reset na płytce tuż przed wgraniem kodu. Po wgraniu pokazuje się informacja że jest mało pamięci ale całość działa bardzo fajnie.
DZIĘKI i kciuk w górę!
Witam,
próbuję skompilować powyższy kod ale w efekcie otrzymuję komunikat:
exit status 1
unterminated argument list invoking macro “F”
Rozwiązałeś problem?
Zrobiłem podobne sterowanie, ale uprościłem układ do minimum. Użyłem tylko modułu gsm Air200 i przekaźnika + zasilanie 5V z ładowarki. Włączanie i wyłączanie odbywa się za pomocą wiadomości sms. Dodałem także przywracanie wcześniej ustawionego stanu przekaźnika po wyłączeniu prądu.
Fajny projekt (:
Ale takie zamazywanie numerów nie wcale nie uniemożliwia ich odczytania. Trochę pracy w gimpie i można się domyślić co to za numer. Rozmycie też nie działa za dobrze.
Najlepiej jest zamazać je jednolitym kolorem. (:
Nie mój numer, nie mój problem ;) Ale pewnie masz rację. Zastanawiam się czy mój egzemplarz SIM800 MA jakiś feler. Średnio raz w miesiącu przestaje się wybudzać. Muszę restarować całość. Poza tym działa nieprzerwanie.
Problemem może być zasilanie, te moduły potrafią pobierać impulsowo do 2A prądu i są wrażliwe na zakłócenia zasilania.
Buforem jest ogniwo 18650. A po restarcie wszytko działa. Być może SIM800 kończy żywot. Jaki moduł GSM jest teraz na topie? Muszę przyznać że porzuciłem Arduino na rzecz ESP8266 i nie jestem w temacie. Jakieś Air200?
Dla zainteresowanych sterowanie przekaźnikiem za pomocą modułu gsm Air200. Skrypt umożliwia nie tylko sterowanie włącz/wyłącz, ale także sterowanie czasowe. Dodane jest zabezpieczenie przed niepowołanym włączeniem/wyłączeniem z innego numeru. Jest też możliwość sprawdzenia aktualnego stanu pinu oraz przywracanie wcześniej ustawionego stanu pinu po zaniku zasilania. O szczegółach można przeczytać na tej stronie https://www.elektroda.pl/rtvforum/viewtopic.php?p=17008021#17008021
Witam, czy biblioteki są jeszcze aktualne? po ściągnięciu i załadowaniu ukazują się inne nazwy i brak na przykład EEPROM