Arduino UNO + SIM900A - hugobossbb - 11-03-2020
Cześć, pracuje nad małym projektem alarmu sterowanego telefonem.
Alarm ma się składać z:
- Arduino uno
- SIM900A
- kontaktron na drzwiach
- przekaźnik SSR do źródła światła.
Założenie jest takie:
1. Po starcie systemu przychodzi sms z info o starcie.
2. Arduino czeka na polecenie włączenia alarmu.
3. Jak przyjdzie sms "ALARM ON" alarm ma się aktywować
4. Alarm jest aktywny i jak ktoś otworzy drzwi ma się zaświecić światło i przyjść sms o wejściu.
5. W międzyczasie jak alarm jest aktywny na sms "STATUS" przychodzi aktualny stan alarmu.
6. Można też zdalnie sms "ALARM OFF" dezaktywować alarm.
Trochę kodu już napisałem ale utknąłem.
Nie do końca wiem jak ogarnąć żeby w czasie aktywacji alarmu była możliwość odpytania statusu lub dezaktywacji alarmu. Jak wrzucę if w sekcje w której aktywuje alarm to z niej nie wyjdzie wiec nie będzie można dezaktywować alarm.
Nie wiem czy to dobrze wytłumaczyłem
Konstruktywna krytyka mile widziana
Dodatkowo myślałem jeszcze żeby można było sms sprawdzać zasięg (żeby przychodził w sms zwrotnym) wiem że jest komenda AT (AT+CSQ) ale nie wiem jak zrobić żeby po wysyłce sms "ZASIEG" zwracany był wynik na sms.
Tutaj moje dotychczasowe wypociny jak na razie wszytko działa:
Kod: #include <SoftwareSerial.h>
SoftwareSerial SIM900A(2,3); //piny na których jest podłączona komunikacja z modułem GSM
String textMessage; //deklaracja zmiennej do sms
String alarmState = "OFF"; //zmienna do przechowywania statusu alarmu
const int relay = 12; //do pinu 12 podpięty przekaźnik
String phone = "XXXXXXXXX"; //zmienna z numerem tel do powiadomień
void setup() {
pinMode(relay, OUTPUT); // ustawienie pinu 12 jako wyjście
digitalWrite(relay, LOW); // ustawienie poziomu niskiego
Serial.begin(9600);
while(!Serial);
SIM900A.begin(9600);
delay(5000);
sendSMS(phone,"START SYSTEMU");
}
void sendSMS(String phone, String message)
{
SIM900A.print("AT+CMGF=1\r\n"); // komenda AT do wysyłania SMS
delay(1000);
SIM900A.println("AT+CMGS=\"+48" + phone + "\"\r\n"); // numer telefonu w formacie +48xxxxxxxxx
delay(1000);
SIM900A.println(message); // wiadomość
delay(1000);
SIM900A.println((char)26); // komenda AT z końcem linii a ^Z, ASCII code 26
delay(1000);
SIM900A.println();
delay(100);
}
void loop(){
if(SIM900A.available()>0){
textMessage = SIM900A.readString();
Serial.print(textMessage);
delay(10);
}
if(textMessage.indexOf("ALARM ON")>=0){
digitalWrite(relay, HIGH);
alarmState = "ON";
Serial.println("ALARM AKTYWOWANY");
textMessage = "";
}
if(textMessage.indexOf("ALARM OFF")>=0){
digitalWrite(relay, LOW);
alarmState = "OFF";
Serial.println("ALARM DEZAKTYWOWANY");
textMessage = "";
}
if(textMessage.indexOf("STATUS")>=0){
String message = "ALARM JEST " + alarmState;
sendSMS(phone,message);
Serial.println("Status ALARMU");
textMessage = "";
}
}
RE: Arduino UNO + SIM900A - MERASerwis - 12-03-2020
1. Pozbądź się delay.
2. Sprawdzaj status operacji z SIM900.
3. Po resecie uC sprawdzaj w jakim stanie jest SIM900 i odpowiednio reaguj.
4. W loop() sprawdzaj w jakim stanie jest SIM900 i odpowiednio reaguj.
RE: Arduino UNO + SIM900A - hugobossbb - 12-03-2020
Dzięki za rady!
Jakieś podpowiedzi jak to zrobić?
Przejrzałem masę kodów w sieci do SIM800/900 itp. i we wszystkich były delay wiec nie bardzo wiem jak się tego pozbyć.
RE: Arduino UNO + SIM900A - MERASerwis - 12-03-2020
(12-03-2020, 13:21)hugobossbb napisał(a): Jakieś podpowiedzi jak to zrobić? https://forbot.pl/blog/kurs-arduino-ii-wielozadaniowosc-opoznienia-z-millis-id18418
(12-03-2020, 13:21)hugobossbb napisał(a): Przejrzałem masę kodów w sieci do SIM800/900 itp. i we wszystkich były delay wiec nie bardzo wiem jak się tego pozbyć. Do w sieci masz demo a nie użyteczny kod.
Obawiam się też, że 32kB FLASH i 2kB RAM to za mało na porządna obsługę SIM900. Robiłem to na mega1284, nie pamiętam ile potrzeba RAM ale FLASH ponad 40kB no, chyba, że kod napiszesz na sztukę i pogodzisz się z tym, że czasem się zawiesi.
Używasz softwareserial, to złe rozwiązanie. Użyj mikrokontrolera z wymaganą liczba UART. Mega będzie ok, ale tańsze są STM32, taki Bluepill kosztuje 13..15zł, klon mega blisko 50zł. Na Bluepill jest STM32F103, który ma zależnie od wersji 64 lub 128kB FLASH, 20kB RAM. UART chyba 3, 2xI2C, 2xSPI, RTC, 2xWDG timerów trochę mało 4 ale wszystkie 16-bit + naturalnie "systemowy" wbudowany w architektóre ARM. Nie ma problemu z debugowaniem, programator/debuger (klon ST-Link v2) 13zł, oryginał (klon ST-Link v3) 50zł. ST robi tez płytki NUCLEO/DISCOVERY ze złączem arduino. Koszt NUCLEO razem z debugerem ok 50zł. Dla porównania, do AVR oryginalny debuger kilka stówek, oryginalne UNO ponad 90zł, mega 160zł.
RE: Arduino UNO + SIM900A - hugobossbb - 15-03-2020
Cześć, trochę poprawiłem kod i usunąłem większość delay()
Ale nadal nie mam pomysłu jak ogarnąć załączanie alarmu i jednoczesne odbieranie smsów.
Musze pokombinować i jakoś ułożyć to sobie w głowie
Powoli małymi krokami
Kod: #include <GSM.h>
GSM gsmAccess;
GSM_SMS sms;
char remoteNumber[20]; // Holds the emitting number
char phone[20] = "XXXXXXXXX";
String txtMsg = "";
void setup()
{
Serial.begin(9600);
// connection state
boolean notConnected = true;
// Start GSM shield
// If your SIM has PIN, pass it as a parameter of begin() in quotes
while(notConnected)
{
if(gsmAccess.begin()==GSM_READY)
notConnected = false;
else
{
Serial.println("Not connected");
delay(1000);
}
}
Serial.println("GSM initialized");
smsSend(phone,"START SYSTEMU");
}
void loop()
{
char c;
// If there are any SMSs available()
if (sms.available())
{
// Get remote number
sms.remoteNumber(remoteNumber, 20);
Serial.println(remoteNumber);
// This is just an example of message disposal
// Messages starting with # should be discarded
if(sms.peek()=='#')
{
Serial.println("Discarded SMS");
sms.flush();
}
// Read message bytes and print them
while(c=sms.read())
txtMsg += c;
Serial.println(txtMsg);
// delete message from modem memory
sms.flush();
}
delay(1000);
}
void smsSend(char phone[20], String message)
{
// send the message
sms.beginSMS(phone);
sms.print(message);
sms.endSMS();
}
RE: Arduino UNO + SIM900A - Agregacik - 15-03-2020
Nie wiem czy Ci tym pomogę, ale przesyłam kod alarmu, który kiedyś wymyśliłem na arduino nano i SIM800L
Są to moje wypociny pewnie z przed dwóch lat więc specjalistów proszę o wyrozumiałość. Wtedy jeszcze raczkowałem a teraz uczę się chodzić .
Kod: #include <SoftwareSerial.h>
#include <OneWire.h>
#include <DallasTemperature.h>
SoftwareSerial SMS(10, 11);
#define termometry A1 //pin do którego podłączone są termometry
#define woltomierz A2 //pin z którego czytana jest wartość napiecia akumulatora
#define napSieci A3 //pin z którego czytana jest obecność sieci 230V
String siec = "BRAK";
String nap ;
float napiecie = 0;//Napięcie akumulatora 12V (10,5V -14V) zakes od 0V do 15V
//byte siec = 0; //stan sieci ustawione wstępnie na 0 czyli brak
int tempWew; // temperatura wewnętrzna (zmienna)
int tempKotla; // temperatura kotła (zmienna)
OneWire oneWire(termometry); //Podłączenie do pinu termometry
DallasTemperature sensors(&oneWire); //Przekazania informacji do biblioteki
//unikalne adresy czujników 18B20
//Trzeba je odczytać programem Plik → Przykłady → OneWire → DS18x20,
DeviceAddress termometrWewnetrzny = { 0x28, 0x61, 0x64, 0x12, 0x78, 0x74, 0x38, 0xE0 };
DeviceAddress termometrKotla = { 0x28, 0x61, 0x64, 0x12, 0x7B, 0xC3, 0x92, 0xB9 };
//DeviceAddress termometrKotla = { 0x28, 0x61, 0x64, 0x12, 0x7B, 0xCB, 0x20, 0x41 };
//unsigned long aktualnyCzas = 0 ;
unsigned long zapamietanyCzas = 0 ;
char incomingByte;
String inputString;
String stanAlarmu ;
int relay = 13; // Wyjście do sterowania przekaźnikiem
String text0; //deklaracja zmiennej wysyłana smsem
//zmienne podstawiane do "text" w zależnosci od alarmu czy potwierdzenia akcji
const String text1 = "wykryto ruch pom 1\n";
const String text2 = "zanik ruchu pom 1\n";
const String text3 = "wykryto ruch pom 2\n";
const String text4 = "zanik ruchu pom 2\n";
const String text5 = "wykryto ruch pom 3\n";
const String text6 = "zanik ruchu pom 3\n";
//char* text7;
String text8 = "ALARM START";
const String text9 = "OK";
//numery na które bedą wysyłane smsy i sprawdzane czy z tych numerów przychodzą poecenia
char* numer;
char* numer1;
char* numer2;
char* numerA1;
char* numerA2;
//wskaźniki czujek ruchu zapami
byte stan;
byte stanzap1;
byte stanzap2;
byte stanzap3;
byte alarm; //blokada alarmu 0 , czuwanie alarmu 1 , ustawia to program SMSem
byte a = 5; //taki wskaźnik do pomiarów napiecia na akumulatorze
byte s = 1; //taki wskaźnik czy jest sieć
byte k = 0; // taki wskaźnik do pomiaru temperatury kotła
byte tw = 0; //taki wskaźnik do pomiaru temperatury pomieszczenia
void setup()
{
//zerowanie sim800L
pinMode (2 , OUTPUT);
digitalWrite (2, LOW);
delay (1000);
digitalWrite (2, HIGH);
delay (5000); // czs na inicjację sim80L po zerowaniu
sensors.begin(); //Inicjalizacja czujnikow temperatury
pinMode(napSieci, INPUT);
pinMode(relay, OUTPUT);
digitalWrite(relay, LOW); // Stan wyjścia przekaźnikowego po uruchomieniu układu
SMS.begin(9600); // start UARTa programowego nazwanego SMS
Serial.begin(9600); // start UARTa serial monitora
delay(100);
pinMode(12, INPUT);
//Wstepne ustawienie wskaźników czujek ruchu
stan = 0;
stanzap1 = 0;
stanzap2 = 0;
stanzap3 = 0;
alarm = 1; //ustawienie alarmu w stan czuwania czyli aktywny
//nemery na które wysyłne będą smsy
numer1 = "AT+CMGS=\"+48xxxxxxxxx\"\r";
numer2 = "AT+CMGS=\"+48yyyyyyyyy\"\r";
//Te numery będą sprawdzane czy z nich przyszedł sms
numerA1 = "+48xxxxxxxxx";
numerA2 = "+48yyyyyyyyy";
//sprawdzenie komunikacji z sim800L
while (!SMS.available()) {
SMS.println("AT");
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected!");//potwierdzenia że OK
SMS.println ("ATE0");//wyłączenie echa
delay (1000);
SMS.println ("ATQ1");//wyłączenie potwierdzeń
delay (1000);
SMS.println("AT+CMGF=1"); //Ustawiamy SMSy w tryb tekstowy
delay(1000);
SMS.println("AT+CNMI=1,2,0,0,0"); //Procedura, która obsługuje nadchodzące wiadomości
delay(1000);
SMS.println("AT+CMGL=\"REC UNREAD\""); // Komdenda odczytu nowych wiadomości
delay(5000);
}
// Pętla...........................
void loop()
{
czujniki (); //sprawdzenie stanu czujników i przy wykryciu zmiany wysłanie SMSa
recievemessage(); //czy przyszedł SMS
//wykonanie pomiarów i sprawdzenie stanu sieci co określony czas
if (millis () - zapamietanyCzas > 20000UL)
{
pomiary ();
//wydrukPomiarowNaSerial ();
zapamietanyCzas = millis () ;
}
}
//Podprogramy................................
void czujniki () {
text0 = "";
stan = digitalRead(12); //odczyt stanu czujnika 1
if ((stan == 1) && (stanzap1 == 0)) {
text0 = text0 + text1;
stanzap1 = 1;
}
if ((stan == 0) && (stanzap1 == 1)) {
text0 = text0 + text2;
stanzap1 = 0;
}
stan = digitalRead(12); //odczyt stanu czujnika 2
if ((stan == 1) && (stanzap2 == 0)) {
text0 = text0 + text3;
stanzap2 = 1;
}
if ((stan == 0) && (stanzap2 == 1)) {
text0 = text0 + text4;
stanzap2 = 0;
}
stan = digitalRead(12); //odczyt stanu czujnika 3
if ((stan == 1) && (stanzap3 == 0)) {
text0 = text0 + text5;
stanzap3 = 1;
}
if ((stan == 0) && (stanzap3 == 1)) {
text0 = text0 + text6;
stanzap3 = 0;
}
//tutaj zapada decyzja czy wysłać SMSa o zmianie stanu czujek ruchu
if ((alarm == 1) && (text0 != "")) {
wysPow ();
}
}
void sendmessage()
{
SMS.println(numer);
delay(1000);
SMS.println(text0);// wysyłany tekst
delay(100);
SMS.println((char)26);// ASCII code of CTRL+Z
delay(5000);
}
void recievemessage()
{
if (SMS.available()) {
delay(100);
// Serial Buffer
while (SMS.available()) {
incomingByte = SMS.read();
inputString += incomingByte;
}
delay(10);
inputString.toUpperCase(); // Zmiana wszystkich liter na wielkie w odebranej wiadomości
//Sprawdzenie czy SMS przyszedł dozwolonego numeru
//i ustawienie numeru do odesłania SMSa
byte z = 0 ;
if (inputString.indexOf(numerA1) > -1) {
numer = numer1;
z = 1;
}
if (inputString.indexOf(numerA2) > -1) {
numer = numer2;
z = 1;
}
//Gdy Z==1 czytamy dalej wiadomość i sprawdzamy co nadawca chce od systemu
if (z == 1) {
//Serial.print("z = ");
//Serial.println(z);
//Serial.println("numer OK");
if (inputString.indexOf("ON") > -1) {
digitalWrite(relay, HIGH);
}
if (inputString.indexOf("OFF") > -1) {
digitalWrite(relay, LOW);
}
//sterowanie alarmem
if (inputString.indexOf("ALARMSTART") > -1) {
alarm = 1; //załaczenie alarmu
//Serial.print ("alarm START alarm = ");
//Serial.println (alarm);
text8 = "ALARM START"; //tekst dodawany do stringa przy wysyłaniu stanu
text0 = text9;
sendmessage();
}
if (inputString.indexOf("ALARMSTOP") > -1) {
alarm = 0; //wyłączanie alarmu
//Serial.print ("alarm STOP alarm = ");
//Serial.println (alarm);
text8 = "ALARM STOP";//tekst dodawany do stringa przy wysyłaniu stanu
text0 = text9;
sendmessage();
}
//Sprawdzenie stanu systemu alarmowego
if (inputString.indexOf("STAN") > -1) {
stanAlarmu = text8 + "\nRuch " + String (stanzap1) + String (stanzap2) + String (stanzap3) + "\nSiec " + siec + "\nAkum " + String (napiecie) + " V\nAkum " + nap + "\nTemp kotla " + String (tempKotla) + "*C\nTemp pom " + String (tempWew) + "*C";
text0 = stanAlarmu;
sendmessage();
}
z = 0;
}
delay(50);
// Tutaj kasujemy wiadomości w modemie, aby oszczędzać pamięć
if (inputString.indexOf("OK") == -1) {
SMS.println("AT+CMGDA=\"DEL ALL\"");
delay(1000);
//Serial.println ("wiadomości skasowane");
}
inputString = "";
}
}
void pomiary () {
napiecie = analogRead(woltomierz) * (15.0 / 1024.0); //Przeliczenie wartości na napięcie
Serial.println(napiecie);
if ((napiecie < 12) && (napiecie >= 10.5) ) {
nap = "NAPIECIE NISKIE";
if ( a != 3 ) {
text0 = nap;
wysPow ();
a = 3 ;
}
}
if ( (napiecie < 13) && (napiecie >= 12) ) {
nap = "BRAK LADOWANIA";
if ( a != 4 ) {
text0 = nap;
wysPow () ;
a = 4 ;
}
}
if (napiecie < 10.5) {
nap = "NAPIECIE KRYTYCZNE";
if ( a != 2 ) {
text0 = nap;
wysPow () ;
a = 2 ;
}
}
if (napiecie >= 13 ) {
nap = "NAPIECIE OK";
if ( a != 5 ) {
text0 = nap;
wysPow();
a = 5 ;
}
}
sensors.requestTemperatures(); //Pobranie temperatury czujnik
tempWew = sensors.getTempC(termometrWewnetrzny);
if ((tempWew < 5) && ( tw == 0 )) {
text0 = "TEMP POM NISKA";
wysPow ();
tw = 1;
}
if ((tempWew > 6) && (tw == 1)) {
text0 = "TEMP POM OK";
wysPow ();
tw = 0;
}
//Pomiar temperatury kotła i wysłanie SMSa jak jest za wysoka
tempKotla = sensors.getTempC(termometrKotla);
if ((tempKotla > 80) && ( k == 0 )) {
text0 = "TEMP KOTLA WYSOKA";
wysPow ();
k = 1;
}
if ((tempKotla < 70) && ( k == 1)) {
text0 = "TEMP KOTLA OK";
wysPow ();
k = 0;
}
//sprawdzenie czy jest sieć i wysłanie wiadomości
if (1 == digitalRead(napSieci)) {
siec = "OK";
if ((1 == digitalRead(napSieci)) && (s == 0)) {
text0 = "Siec OK";
wysPow ();
s = 1;
}
}
if (0 == digitalRead(napSieci)) {
siec = "BRAK";
if ((0 == digitalRead(napSieci)) && (s == 1)) {
text0 = "Brak sieci";
wysPow ();
s = 0;
}
}
}
void wysPow ()
{
numer = numer1;
sendmessage();
//numer = numer2;
//sendmessage();
}
/*
void wydrukPomiarowNaSerial (){
Serial.println ("AKUMULATOR " + nap);
Serial.println ("napięcie sieci " + siec );
Serial.println("Aktualna temperatura 0 = " + String(tempWew) + " *C" );
//Serial.print(tempWew);
//Serial.println(" *C");
Serial.print("Aktualna temperatura 1 = ");
Serial.print(tempKotla);
Serial.println(" *C");
Serial.print("Napięcie ");
Serial.print(napiecie);
Serial.println(" V");
Serial.println ();
}
*/
Może podpatrzysz i zastosujesz coś u siebie. Ja korzystałem z komend AT w komunikacji z SIM600L
Alarm miał posiadać 3 czujniki ruchu oraz kontrolował stan zasilania centrali alarmowej oraz temperatury w pomieszczeniu oraz temperaturę na kotle CO na paliwo stałe. Przy wykryciu ruchu podczas aktywnego alarmu miał wysłać SMSa i po zaniku ruchu też, ponadto przy zmianie pozostałych parametrów poza ustalone granice.
Alarm można było aktywować i dezaktywować zdalnie SNSem w każdym stanie można było "poprosić" o status
Alarm działał na płytce stykowej, ale nie doczekał się ostatecznej realizacji.
Zapewne wiele mu brakuje ale brak zapotrzebowania nie wymuszał jego rozwoju czy zmian.
RE: Arduino UNO + SIM900A - hugobossbb - 18-03-2020
Dzięki Panowie trochę z każdego kodu wykorzystałem i powstało coś takiego
Coraz bliżej celu
I coraz więcej się ucze
Kod: #define LED_R 4
#define LED_G 5
#define czujnik 12
#include <AltSoftSerial.h>
AltSoftSerial altSerial;
String textMessage; //Zmienna do przechowywania wiadomosci tekstowej
volatile byte stanAlarmu = 0;
bool czySMS = false;
String numer = "xxxxxxxxx";
String message = "";
void setup()
{
Serial.begin(9600);
Serial.println("---------- START SYSTEMU -----------");
altSerial.begin(9600);
altSerial.print(F("AT+CMGF=1\r")); // ustawienie gsm na text mode
delay(100);
altSerial.print(F("AT+CNMI=2,2,0,0,0\r"));
delay(100);
pinMode(LED_R, OUTPUT);
pinMode(LED_G, OUTPUT);
pinMode(czujnik, INPUT);
digitalWrite(LED_R,LOW);
digitalWrite(LED_G,LOW);
}
void loop()
{
unsigned long ms = millis();
char c;
while (Serial.available()) {
c = Serial.read();
altSerial.write(c);
}
altSerial.flushOutput();
while (altSerial.available()) {
c = altSerial.read();
textMessage = altSerial.readString();
textMessage.toUpperCase();
Serial.print(c);
Serial.print(textMessage);
}
if(textMessage.indexOf(F("ALARM_ON"))>=0){
Serial.println(F("Alarm ON"));
textMessage = "";
stanAlarmu = 1;
}
if(textMessage.indexOf(F("ALARM_OFF"))>=0){
Serial.println(F("Alarm OFF"));
textMessage = "";
stanAlarmu = 0;
}
if(textMessage.indexOf(F("STAN"))>=0){
Serial.println(F("Sprawdzanie stanu alarmu"));
switch (stanAlarmu) {
case 0:
message = "Alarm jest OFF";
break;
case 1:
message = "Alarm jest ON";
break;
}
sendSMS(numer,message);
textMessage = "";
}
switch (stanAlarmu) {
case 0: //czuwanie wylaczone
Serial.println("Alarm wylaczony - brak czuwania");
digitalWrite(LED_G,LOW);
digitalWrite(LED_R,LOW);
czySMS = false;
break;
case 1: //czuwanie wlaczone
Serial.println("Alarm wlaczony - czuwanie");
digitalWrite(LED_G,HIGH);
digitalWrite(LED_R,LOW);
czySMS = false;
if (digitalRead(czujnik) == HIGH) {
stanAlarmu = 2;
}
break;
case 2: // ALARM
Serial.println("ALARM !!!");
digitalWrite(LED_G,LOW);
digitalWrite(LED_R,HIGH);
if (czySMS == false){
sendSMS(numer,"ALARM!!!");
czySMS = true;
}
break;
}
}
void sendSMS(String phone, String message)
{
altSerial.print("AT+CMGF=1\r\n"); // komenda AT do wysyłania SMS
delay(1000);
altSerial.println("AT+CMGS=\"+48" + phone + "\"\r\n"); // numer telefonu w formacie +48xxxxxxxxx
delay(1000);
altSerial.println(message); // wiadomość
delay(1000);
altSerial.println((char)26); // komenda AT z końcem linii a ^Z, ASCII code 26
delay(1000);
altSerial.println();
delay(100);
}
|