Sim900 et PHP ( Bdd sql )

Bonjour à tous,
je profite du confinement pour avancer sur mes projets.
je souhaite surveiller la température et le niveau d'eau dans un garage.
Pas de Wi-Fi mais de la 4G.
je me suis donc orienté sur un Sim900 avec une carte "free" à 2 €
le module sim900 fonctionne en SMS
ma page en PHP fonctionne très bien depuis un PC
Bonjour à tous, je profite du confinement pour avancer sur mes projets je souhaite surveiller la température et le niveau d'eau dans un garage.Pas de Wi-Fi mais de ces 4 G.je me suis donc orienté sur un Sim900 avec une carte gratuite à 2 € ma page en PHP fonctionne très bien depuis un PC je souhaite donc que ce soit mon Arduino qui lui envoie les valeurs mais j'ai une erreur dans mon script ...

#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(7, 8);

void setup()
{
  //Allumer la carte SIM900
  pinMode(9, OUTPUT);
  digitalWrite(9, HIGH);
  delay(300);

  gprsSerial.begin(9600);
  Serial.begin(9600);

  Serial.println("boot");
  delay(2000);
  gprsSerial.flush();
  Serial.flush();

  // cherche le nombre de reseau mobile
  gprsSerial.println("AT + CGATT ? ");
  delay(100);
  toSerial();

  // Profil GPRS
  gprsSerial.println("AT + SAPBR = 3, 1, \"CONTYPE\",\"GPRS\"");
  delay(2000);
  toSerial();

  // Config APN
  gprsSerial.println("AT+SAPBR=3,1,\"APN\",\"mms.free.fr\"");
  delay(2000);
  toSerial();

  // Connection au GPRS
  gprsSerial.println("AT+SAPBR=1,1");
  delay(2000);
  toSerial();
}


void loop()
{
  // initialisation du service HTTP
  gprsSerial.println("AT+HTTPINIT");
  delay(2000);
  toSerial();

  // adresse serveur
  gprsSerial.println("AT+HTTPPARA=\"URL\",\"http://***.fr/http/temp.php?temp=33&niveau=33\""); //Envoi de valeur fixe pour debug
  /*
    gprsSerial.print("AT+")
    gprsSerial.print("HTTPPARA=\"URL\",");
    gprsSerial.print("\"http://***.fr/http/temp.php"); // envoi des variables
    gprsSerial.print("?temp=");
    gprsSerial.print(temp);
    gprsSerial.print("&niveau=");
    gprsSerial.print(niveau);
    gprsSerial.println("\"");
  */
  delay(2000);
  toSerial();

  // Lancer la session
  //  0 = GET, 1 = POST, 2 = HEAD
  gprsSerial.println("AT+HTTPACTION=0");
  delay(6000);
  toSerial();

  // lis les donnees
  gprsSerial.println("AT+HTTPREAD");
  delay(1000);
  toSerial();

  //Fermer la session
  gprsSerial.println("");
  gprsSerial.println("AT+HTTPTERM");
  toSerial();
  delay(300);

  gprsSerial.println("");
  delay(10000);
}

void toSerial()
{
  while (gprsSerial.available() != 0)
  {
    Serial.write(gprsSerial.read());
  }
}

sur mon terminal en sortie j'ai :

boot

NORMAL POWER DOWN
⸮⸮⸮⸮
ERROR

ERROR

OK

OK

OK

+HTTPACTION:0,601,0

OK

OK

OK

OK

OK

+HTTPACTION:0,601,0

OK

OK

OK

OK

OK

+HTTPACTION:0,601,0

j'ai egalement un doute sur la ligne :

  //  0 = GET, 1 = POST, 2 = HEAD
  gprsSerial.println("AT+HTTPACTION=0");

entre le Get et le post

J'ai essayé de mettre un maximum de commentaire.
Merci de votre aide

Arnaud

a mon avis le langage de commande AT n'aime pas les espaces, essayez de tout coller

  gprsSerial.println("AT + CGATT ? ");
..
  gprsSerial.println("AT + SAPBR = 3, 1, \"CONTYPE\",\"GPRS\"");

===>

  gprsSerial.println("AT+CGATT?");
..
  gprsSerial.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");

votre fonction toSerial() va vider le buffer super vite ,potentiellement plus vite que les caractères n'arrivent. ce n'est pas la bonne façon de lire le port série. il faut attendre la répons compléte (souvent terminée par "OK\r\n" ou un timeout par exemple)

et avec tous les délais que vous avez un peu partout, si plus de 64 caractères arrivent pendant ce temps vous allez en perdre .

cette URL est louche [color=red]http://[/color]***.fr/[color=red]http/temp.php[/color]?temp=33&niveau=33

Bonjour J-M-L

Merci de ta reponse

j'ai supprimé les espaces, j'ai toujours mes erreurs mais j'ai PSNWID en plus

NORMAL POWER DOWN
⸮⸮⸮⸮⸮
ERROR

ERROR

*PSNWID: "208","01", "Orange F", 0, "Orange F", 0


OK

OK

+HTTPACTION:0,601,0

OK

pour toserial =>

while (gprsSerial.available() != 0)

je pensais que le while etait suffisant :frowning: que me conseil tu ?

cette URL est louche http://***.fr/http/temp.php?temp=33&niveau=33

que trouve tu de louche ? les *** est ip de mon serveur que je ne souhaite pas revélé et dans le dossier http il ouvre la page temp.php qui elle ajoute mes données " temp & niveau" en base SQL
Bonne fin de journée

je pensais que le while etait suffisant :frowning: que me conseil tu ?

le while va vider le buffer, mais il se peut que des caractères soient en train d'arriver. Une fois le buffer vide, comme votre arduino tourne super vite par rapport aux 9600 bauds de l'arrivée des données le while se termine avant potentiellement d'avoir tout reçu. Ce que je conseille, c'est ce que j'ai dit "il faut attendre la réponse complète (souvent terminée par "OK\r\n" ou un timeout par exemple)"

que trouve tu de louche ?

lje trouvais louche le second http mais si c'est comme cela que vous avez configuré votre répertoire et que vous avez bien un dosser http dans le root directory du serveur web alors c'est OK


Les 2 première erreurs viennent de votre phase de boot sans doute. Modifiez le début du setup pour vérifier et rajoutez un de vos toSerial(); juste après la configuration

void setup()
{
  //Allumer la carte SIM900
  pinMode(9, OUTPUT);
  gprsSerial.begin(9600);
  Serial.begin(9600);

  Serial.println("*** activation");
  digitalWrite(9, HIGH);
  delay(300);  delay(2000);
  toSerial();

  Serial.println("*** boot");
  delay(2000);
...

la ligne *PSNWID: "208","01", "Orange F", 0, "Orange F", 0 est un bon signe, et le 208/01 c'est bien Orange.

les ordres que j'enverrais (de mémoire):

AT+SAPBR=3,1,"CONTYPE","GPRS"
AT+SAPBR=3,1,[color=red]"APN","free"[/color]
AT+SAPBR=1,1
AT+HTTPINIT
AT+HTTPPARA="CID",1
AT+HTTPPARA="URL","http://[color=blue]***[/color].fr/http/temp.php?temp=33&niveau=33"
AT+HTTPACTION=0
AT+HTTPREAD
AT+HTTPTERM

essayez en câblant cela en dur, avec un délai de 2 secondes après chaque commande sauf après HTTPACTION=0 où il faut attendre plus et faites une lecture de la réponse sur le port série avant d'enchaîner la requête suivante (pas top mais pour démarrer c'est OK)

la partie "APN","free" serait à vérifier (vous voulez utiliser l'APN Internet pas celui des MMS).

Mais êtes vous chez Orange ou Free au travers d'Orange ?

Chez Free les caractéristiques sont les suivantes pour l'APN Internet
Nom : Free
APN : free
MCC : 208
MNC : 15

hors votre MCC/MCC était 208/01 (celui d'orange).

il vous manque le "Bearer profile identifier" (envoyé avec AT+HTTPPARA="CID",1) qui je crois est obligatoire

PS/ question subsidiaire: vous avez bien alimenté votre Modem séparément avec une alimentation qui est capable de fournir 2Ampères au moins ?

AT+HTTPPARA="CID",1)
j'ai ajouté également le toserial pour la phase de boot
j'ai bien une carte sim FREE comme declaré dans l apn
je pense quelle me revoit les apn orange car je dois passer par leur reseaux
quelle est la difference entre apn mms et internet ?
Le module a bien sont alimentation independante en 2,5 A
mon code avec toute les modifications :

#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(7, 8);

void setup()
{
  //Allumer la carte SIM900
  pinMode(9, OUTPUT);
  gprsSerial.begin(9600);
  delay(300);
  Serial.begin(9600);
  delay(300);


  Serial.println("Activation");
  digitalWrite(9, HIGH);
  delay(2000);
  toSerial();

  Serial.println("boot");
  delay(2000);
  gprsSerial.flush();
  Serial.flush();

  // cherche le nombre de reseau mobile
  gprsSerial.println("AT+CGATT?");
  delay(100);
  toSerial();

  // Profil GPRS
  gprsSerial.println("AT+SAPBR=3 1,\"CONTYPE\",\"GPRS\"");
  delay(2000);
  toSerial();

  // Config APN
  gprsSerial.println("AT+SAPBR=3,1,\"APN\",\"free\"");
  delay(2000);
  toSerial();

  // Connection au GPRS
  gprsSerial.println("AT+SAPBR=1,1");
  delay(2000);
  toSerial();
}


void loop()
{
  // initialisation du service HTTP
  gprsSerial.println("AT+HTTPINIT");
  delay(2000);
  toSerial();

    // configuration du service HTTP
  gprsSerial.println("AT+HTTPPARA=\"CID\",1");
  delay(2000);
  toSerial();

  // adresse serveur
  gprsSerial.println("AT+HTTPPARA=\"URL\",\"http://****.fr/http/temp.php?temp=33&niveau=33\""); //Envoi de valeur fixe pour debug
  /*
    gprsSerial.print("AT+")
    gprsSerial.print("HTTPPARA=\"URL\",");
    gprsSerial.print("\"http://***.fr/http/temp.php"); // envoi des variables
    gprsSerial.print("?temp=");
    gprsSerial.print(temp);
    gprsSerial.print("&niveau=");
    gprsSerial.print(niveau);
    gprsSerial.println("\"");
  */
  delay(2000);
  toSerial();

  // Lancer la session
  //  0 = GET, 1 = POST, 2 = HEAD
  gprsSerial.println("AT+HTTPACTION=0");
  delay(6000);
  toSerial();

  // lis les donnees
  gprsSerial.println("AT+HTTPREAD");
  delay(1000);
  toSerial();

  //Fermer la session
  gprsSerial.println("");
  gprsSerial.println("AT+HTTPTERM");
  toSerial();
  delay(300);

  gprsSerial.println("");
  delay(10000);
}

void toSerial()
{
  while (gprsSerial.available() != 0)
  {
    Serial.write(gprsSerial.read());
  }
}

le code de sorties

Activation
boot 
NORMAL POWER DOWN
⸮⸮⸮⸮⸮
error
error
error
*PSNWID: "208","01", "Orange F", 0, "Orange F", 0
OK
OK
OK
OK
+HTTPACTION:0,601,0

Le premier error apparait en même temps que la led NET commence a clignoter

Merci a toi

Arnaud

pour être sûr prenez cette fonction toSerial()

void toSerial(const uint32_t timeout=2000UL)
{
  uint32_t t0 = millis();
  while (millis() - t0 <= timeout) {
    if (gprsSerial.peek() != -1) {
      Serial.write(gprsSerial.read());
    }
  }
}

si vous l'appelez sans param elle imprime tout ce qui arrive pendant 2 secondes sinon vous pouvez passer en paramètre le temps d'écoute.

Avez cette fonction,allongez le délai du début

  Serial.println("Activation");
  digitalWrite(9, HIGH);
  toSerial(10000UL); // 10 secondes

c'est pour voir si les erreurs proviennent du boot de la carte où d'ailleurs

apn mms et internet

l'APN mms c'est pour les MMS et l'APN internet c'est pour faire de l'internet :slight_smile:

Pour le moment mettez tout dans le setup, ne bombardez pas dans la loop et attendez 10 secondes au moins sur le read

  gprsSerial.println("AT+HTTPREAD");
  toSerial(10000UL); // 10 secondes

Bonjour,

D'abord un grand merci pour ton aide et ta patience !

Le toSerial modifier a TOUT changé!

Le code fonctionne j'ai également corrigé une virgule dans ("AT+SAPBR=3,1,"CONTYPE","GPRS"");

qui me donnais la dernière erreur

en sortie j'obtiens
Activation
Boot
OK
OK
OK
OK
OK
OK
+HTTPACTION:0,200,437

#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(7, 8);

int temp = 0;
int niveau = 0;

void setup()
{
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);

  //Allumer la carte SIM900
  pinMode(9, OUTPUT);
  gprsSerial.begin(9600);
  delay(300);
  Serial.begin(9600);
  delay(300);


  Serial.println("Activation");
  digitalWrite(9, HIGH);
  delay(2000);
  toSerial();
}


void loop()
{ 
  Serial.println("boot");
  gprsSerial.flush();
  Serial.flush();
  delay(500);

  // cherche le nombre de reseau mobile
  gprsSerial.println("AT+CGATT?");
  delay(2000);
  toSerial();

  // Profil GPRS
  gprsSerial.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");
  delay(2000);
  toSerial();

  // Config APN
  gprsSerial.println("AT+SAPBR=3,1,\"APN\",\"free\"");
   delay(2000);
  toSerial();
  // Connection au GPRS
  gprsSerial.println("AT+SAPBR=1,1");
  delay(2000);
  toSerial();

  // initialisation du service HTTP
  gprsSerial.println("AT+HTTPINIT");
  delay(2000);
  toSerial();

  // configuration du service HTTP
  gprsSerial.println("AT+HTTPPARA=\"CID\",1");
  delay(2000);
  toSerial();

  // adresse serveur
  gprsSerial.print("AT+");
  gprsSerial.print("HTTPPARA=\"URL\",");
  gprsSerial.print("\"http://***.fr/temp.php"); // envoi des variables
  gprsSerial.print("?temp=");
  gprsSerial.print(temp);
  gprsSerial.print("&niveau=");
  gprsSerial.print(niveau);
  gprsSerial.println("\"");
  delay(2000);
  toSerial();

  // Lancer la session
  //  0 = GET, 1 = POST, 2 = HEAD
  gprsSerial.println("AT+HTTPACTION=0");
  delay(2000);
  toSerial();

  // lis les donnees
  gprsSerial.println("AT+HTTPREAD");
  delay(6000);
  // delay(10000UL); // 10 secondes
  toSerial();

  //Fermer la session
  gprsSerial.println("");
  gprsSerial.println("AT+HTTPTERM");
  toSerial();
  delay(2000);

  gprsSerial.println("");
  delay(2000);

   temp = digitalRead(A0);
   Serial.print("temp = ");
    Serial.println(temp);
  niveau = digitalRead(A1);
   Serial.print("niveau = ");
    Serial.println(niveau);
    delay(2000);
}
void toSerial()
{
  const uint32_t timeout = 2000UL;
  uint32_t t0 = millis();
  while (millis() - t0 <= timeout) {
    if (gprsSerial.peek() != -1) {
      Serial.write(gprsSerial.read());
    }
  }
}

je vous donne donc la version final si vous avez besoin

Cool!

Vous n’avez pas besoin de faire delay() avant le toSerial puisque la fonction attend déjà deux secondes si vous l’appelez sans paramètres.

Maintenant il faut écrire un petit bout de code à la place de toSerial() qui écoute pour voir s’il reçoit le OK et dans ce cas pas la peine d’attendre la fin du timeout