Présentation
Pour optimiser nos chances de
retrouver le ballon sonde nous allons inclure un module GSM
compatible avec Arduino le SIM800L. Ce module nous enverra par SMS les coordonnées GPS du ballon sonde. Pour le câblage nous allons utiliser 5 pattes :
|
![]() |
Les commandes ATPour programmer ce module et envoyer des SMS nous allons utiliser les commandes AT suivantes : AT+CMGF=1 <CR> : permet d’activer le mode texte pour l’envoi du SMS. Cette commande renvoie le code OK en cas de réussite. Le temps d’attente maximal est de 1 secondes. AT+CMGS=\"+336xxxxxxxx\"<CR>Ceci est le texte du SMS<CTRL-Z>
Ci-contre le programme minimaliste : il envoi le SMS sans vérifier les réponses du SIM800L. On utilisera ce sous programme dans notre programme ballon sonde |
void SMS() {
Sgsm.println("AT+CMGF=1"); // SMS en mode texte
delay(50);
Sgsm.print("AT+CMGS=\""); Sgsm.print(numero); Sgsm.println("\"");
delay(200); // Il est indispensable de faire une pause entre le numéro et le corps du message
Sgsm.print("Ceci est le message SMS à envoyer.");
Sgsm.write(26); // Caractère de fin 26 <Ctrl-Z>
Sgsm.println();
}
|
Notre sous programme SMS()
Ce sous programme est appelé par une boucle cadencée à 2s (représentée par la variable n).
Nous profitons de cette cadence pour éviter la fonction delay et ralentir le programme principal. Ainsi l'exécution de ce sous programme ne requiert que quelques ms.
Pour économiser les piles, nous mettons en service le module durant 30s puis hors service durant 90s. Nous envoyons un SMS toutes les 120s.
Au delà de 9000 m (présence du réseau improbable), nous mettons hors service le module grâce à la patte RST mise à GND.
/* 1) Zone 1 : les déclarations */
// 1.b) Les Constantes et #define
#define Sgsm Serial2
#define numero "+336xxxxxxxx" // Mettre ici le numéro que l'on souhaite appeler
// 1.c) Les variables globales
int RST=2; // Pour éteindre la carte GSM SIM800L
/* 2) Zone 2 : Initialisation (le setup) */
void setup() {
Sgsm.begin(9600);
}
/* 3) Zone 3 : le Programme Principal */
void loop() {
SMS();
}
/* 4) Zone 4 : les sous programmes (ou fonctions) */
void SMS() {
int sms = n%60; // Pour envoyer un SMS tout les 2*60 = 120s
if (Alti>9000){ // Si Altitude >9000 m on éteint le GSM
pinMode(RST,OUTPUT);
digitalWrite(RST,LOW);
return;}
if (sms==1) {
pinMode(RST,INPUT); // On allume le GSM en mettant RST en haute impédance, attendre au moins 6s pour se connecter au réseau
return;}
if (sms==10) Sgsm.println("AT+CMGF=1"); // Au bout de 20s sous tension on envoie le SMS
if (sms==11) { // Composition n° au bout de 22s
Sgsm.print("AT+CMGS=\""); Sgsm.print(numero); Sgsm.println("\"");
}
if (sms==12) { // Il est préférable d'attendre (ici 2s) avant d'envoyer le corps du message
Sgsm.print("Temps = "); Sgsm.print(2*n);Sgsm.print(" s");
Sgsm.print(" : https://maps.google.fr/maps?q="); Sgsm.print(N,5); Sgsm.print(","); Sgsm.print(E,5);
Sgsm.print(" Alti=");Sgsm.print(Alti);Sgsm.print(" m");
Sgsm.print(" P= ");Sgsm.print(int(Pext));Sgsm.print(" hPa");
Sgsm.print(" T= ");Sgsm.print(Text,1);Sgsm.print(" C");
Sgsm.write(26); // Caractère de fin 26 <Ctrl-Z>
Sgsm.println("");
}
if (sms==15) { // Puis au bout de 30s on éteint le GSM
pinMode(RST,OUTPUT);
digitalWrite(RST,LOW); }
}
Allumer et éteindre une LED par SMS
Pour mieux comprendre comment communique un SIM800 avec un Arduino voici un programme qui permet à un Arduino de recevoir un ordre par SMS : led on ou led off.
Ce programme analyse le message reçu, récupère le numéro du téléphone à l'origine du SMS et renvoie un SMS de confirmation de l'ordre au téléphone.
/* Allumer une LED par SMS
Pour allumer la LED envoyer led on
pour éteindre la LED envoyer led off
*/
/* 1) Zone 1 : les déclarations */
// 1.a) Les bibliothèques et création d'objets
//#include <SoftwareSerial.h>
//int Txd = 6, Rxd = 7; // SIM800
//SoftwareSerial gsm(Txd, Rxd); // RX, TX : il faut relier Rx de l'Arduino au Tx du SIM800
#define gsm Serial1 // Si utilisation MEGA
// 1.c) Les variables globales
int led =13;
String reponse, numeroSMS, SMS;
unsigned long t0;
/* 2) Zone 2 : Initialisation (le setup) */
void setup() {
pinMode(led,OUTPUT);
Serial.begin(9600);
gsm.begin(9600);
delay(2000);
Serial.println("Initialisation...");
gsm.println("AT");
while (!message("OK",1000,0)) gsm.println("AT");
gsm.println("AT+CNUM"); // Affiche n° de la carte SIM utilisée
message("OK",20000,1);
Serial.print ("Qualite reseau : ");
gsm.println("AT+CSQ"); // Qualité du réseau, pb si CSQ = 0
message("OK",10000,1);
gsm.println("AT+CMGF=1"); // Mode Texte
message("OK",1000,0);
gsm.println("AT+CMGD=1,4"); // effacer les SMS en mémoire dans la carte SIM
message("OK",2000,0); // car on lit toujours le message N°1 de la carte SIM...
}
/* 3) Zone 3 : le Programme Principal */
void loop() {
if (message("+CMTI:",20000,0)) LireSMS(); // Si nouveau SMS disponible SIM800 envoie +CMTI:
}
/* 4) Zone 4 : les sous programmes (ou fonctions) */
void LireSMS(){
gsm.println("AT+CMGF=1"); // Mode Texte
message("OK",1000,0);
gsm.println("AT+CMGR=1"); // Lit le premier message disponible sur la carte SIM
message("OK",2000,1);
// Récupérer N° de telephone emetteur pour lui répondre
int test=reponse.indexOf("+33");
numeroSMS = reponse.substring(test,test+12);
Serial.println("SMS recu depuis : " + numeroSMS);
// Analyse du message reçu
if (reponse.indexOf("led on")>0) {
SMS = "Ordre recu : Allumer LED !";
digitalWrite(led,1);}
else {
if (reponse.indexOf("led off")>0){
SMS = "Ordre recu : Eteindre LED !";
digitalWrite(led,0);}
else SMS = "Ordre non compris !";}
gsm.println("AT+CMGD=1,4"); // effacer les SMS de la Carte SIM
message("OK",1000,0);
Serial.println(SMS);
Serial.println("");
// Envoyer la confirmation de l'ordre par SMS
Serial.println("Envoi message confirmation");
gsm.println("AT+CMGS=\""+ numeroSMS +"\"");
message(">",1000,0);
gsm.println(SMS);
gsm.write(26); // Caractère de fin 26 <Ctrl-Z>
gsm.println("");
message("+CMGS:",10000,1); }
/* Sous Programme message(attente, timeout, affiche)
Après avoir envoyé une instruction AT au module SIM800,celui-ci répond.
message("OK", 1000,1) :
Vérifie que la réponse contient le terme "OK" (attente)
Il attend au maximum 1000ms (timeout) la réponse
Affiche (affiche=1) la réponse et le temps mis pour l'obtenir
ou n'affiche pas (affiche=0) sauf si la réponse attendue n'est pas correcte
renvoie vrai si le message contient OK en moins de 1000 ms
*/
boolean message(String attente, unsigned int timeout, boolean affiche) {
t0 = millis();
reponse="";
while (millis() - t0 < timeout) {
while(gsm.available()) reponse.concat(char(gsm.read()));
if (reponse.indexOf(attente)>0){ // Lit encore 100 ms le port série
delay (100); // pour être sur de ne rien louper...
while(gsm.available()) reponse.concat(char(gsm.read()));
break;}}
if (affiche || reponse.indexOf(attente)==-1 ) {
Serial.print("Attente = "+ attente +" "+ reponse.indexOf(attente)+" duree ");
Serial.print(millis()-t0); Serial.println(" ms");
Serial.println(reponse);}
if (reponse.indexOf(attente)>0) return true;
else return false;
}
Envoyer des mesures et recevoir des consignes par internet
Nous pouvons utiliser aussi notre module SIM800L pour envoyer des données sur internet grâce aux fonctions GPRS (General Packet Radio Service , protocole réseau, 2G+)
/* Envoyer les mesures d'un DHT22 par GPRS
Nous allons envoyer des données (température et humidité mesurée par le DHT22) par l'URL
http://tpil.projet.perso.sfr.fr/DHT22/communique2.php?t=19.2&h=51
Cette adresse envoie t=19,2°C et H = 51%
le script communique2.php traite cette adresse afin d'écrire une réponse de confirmation qui contient aussi
une consigne haute et une consigne basse pour simuler un système de chauffage...
Pour changer les consignes par internet :
http://tpil.projet.perso.sfr.fr/DHT22/capteur.php
http://tpil.projet.perso.sfr.fr/DHT22/
*/
/* 1) Zone 1 : les déclarations */
// 1.a) Les bibliothèques et création d'objets
//#include <SoftwareSerial.h>
//int Txd = 6, Rxd = 7; // SIM800
int Reset =8;
//SoftwareSerial gsm(Txd, Rxd); // RX, TX : il faut relier Rx de l'Arduino au Tx du SIM800
#define gsm Serial1 // Si utilisation MEGA
#define SERIAL_BUFFER_SIZE 256 // augmenter la taile du buffer serie
#include "DHT.h"
#define DHTPIN 11 // la sortie du DHT22 est reliée à D11 de notre Arduino
#define DHTTYPE DHT22 // DHT 22
DHT dht(DHTPIN, DHTTYPE); // Création de l'objet dht
// 1.c) Les variables globales
String reponse,Chs,Cbs,heure;
unsigned long t0;
int test,hum,Ch,Cb;
float temp;
/* 2) Zone 2 : Initialisation (le setup) */
void setup() {
pinMode(Reset,INPUT);
pinMode(12,OUTPUT);
pinMode(13,OUTPUT);
digitalWrite(12,0);
digitalWrite(13,1);
Serial.begin(9600);
gsm.begin(9600);
gsm.begin(9600);
dht.begin();
delay(2000);
Serial.println("Initialisation...");
gsm.println("AT");
while (!message("OK",1000,0)) gsm.println("AT");
gsm.println("AT+CNUM");
message("OK",1000,1);
setupGPRS();
}
/* 3) Zone 3 : le Programme Principal */
void loop() {
Serial.print ("Qualite reseau (Pb si < 10) : ");
gsm.println("AT+CSQ"); // Qualité du réseau
if (message("OK",1000,0)){
test=reponse.indexOf("+CSQ:");
Serial.println(reponse.substring(test,test+10));}
hum = dht.readHumidity();
temp = dht.readTemperature();
if (isnan(temp) || isnan(hum)|| hum==0){temp=22.5;hum=45;} // Si pas de capteur
Requete(); // envoi de la requete
delay(10000);
}
/* 4) Zone 4 : les sous programmes (ou fonctions) */
void setupGPRS() { //Réglage mode GPRS et protocole IP
Serial.print( "Setup");
gsm.println("AT+HTTPTERM");
message("OK",2000,0);
// Serial.print("Protocole IP : ");
gsm.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");
message("OK",10000,0);
gsm.println("AT+SAPBR=3,1,\"APN\",\"free\"");
message("OK",10000,0);
// Serial.println("Suppression de la fonction echo : ");
// gsm.println("ATE0");
// message("OK",2000);
gsm.println("AT+SAPBR=1,1");
message("OK",2000,0);
gsm.println("AT+CGATT=1");
message("OK",2000,0);
}
void Requete() { // HTTP GET
gsm.println("AT+HTTPINIT");
message("OK",2000,0);
Serial.println("Parametre URL: ");
gsm.print("AT+HTTPPARA=\"URL\",\"http://tpil.projet.perso.sfr.fr/DHT22/communique2.php?t=");
gsm.print(temp,1);
gsm.print("&h=");gsm.print(hum);gsm.println("\"");
message("OK",5000,1);
Serial.print("Mode GET : ");
gsm.println("AT+HTTPACTION=0");
if (message("+HTTPACTION: 0,200",20000,0)){
Serial.println(" Message envoye !");
gsm.println("AT+HTTPREAD");
message("/html",10000,5);
test=reponse.indexOf("<p>");
heure=reponse.substring(test+3,test+11);
test=reponse.indexOf("Ch=");
Ch=reponse.substring(test+3,test+6).toInt();
test=reponse.indexOf("Cb=");
Cb=reponse.substring(test+3,test+6).toInt();
Serial.println("Heure de confirmation : " + heure);
Serial.print("Consignes lues : ");
Serial.println("Ch = "+ String(Ch) + "\tCb = "+String(Cb));
Serial.println();
// Serial.print( "Fin HTTP : ");
gsm.println("AT+HTTPTERM");
message("OK",2000,0);
}
else reset();
}
boolean message(String attente, unsigned int timeout, boolean affiche) {
t0 = millis();
reponse="";
while (millis() - t0 < timeout) {
while(gsm.available()) reponse.concat(char(gsm.read()));
if (reponse.indexOf(attente)>0){
delay (100);
while(gsm.available()) reponse.concat(char(gsm.read()));
break;}}
if (affiche || reponse.indexOf(attente)==-1 ) {
Serial.print("Attente = "+ attente +" "+ reponse.indexOf(attente)+" duree ");
Serial.print(millis()-t0); Serial.println(" ms");
Serial.println(reponse);}
if (reponse.indexOf(attente)>0) return true;
else return false;
}
void reset() {
pinMode(Reset,OUTPUT);
digitalWrite(Reset,LOW);
Serial.println ("Remise a Zero");
delay(5000);
pinMode (Reset,INPUT);
Serial.println("Reset logiciel !");
Serial.flush(); // Pour afficher le messsage avant le reset
asm volatile (" jmp 0"); // Reset de la carte Arduino
// delay(6000);
// gsm.println("AT");
// while (!message("OK",1000,0)) gsm.println("AT");
// setupGPRS();
}