SIM800L et LCD

Bonsoir,

sur un sim800L j’essaye de récupéré le niveau de signal.

Comme ça sur le Serial je recupere des valeurs de 14 à 17 en déplacent le module (“logique”)

#include <SoftwareSerial.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4); 
SoftwareSerial mySerial(32, 33);
void setup()
{
  Serial.begin(9600);
  mySerial.begin(9600);
  delay(1000);
  lcd.init();
  lcd.backlight() ;
}

void loop()
{
    mySerial.println("AT+CSQ"); //Signal quality test, value range is 0-31 , 31 is the best
    updateSerial();
    delay(2000);
}

void updateSerial()
{
  while(mySerial.available()) 
  {
   Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

Par contre avec cette ligne en + pour afficher la valeur sur le LCD elle reste affiché à 10:

#include <SoftwareSerial.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4); 
SoftwareSerial mySerial(32, 33);
void setup()
{
  Serial.begin(9600);
  mySerial.begin(9600);
  delay(1000);
  lcd.init();
  lcd.backlight() ;
}

void loop()
{
    mySerial.println("AT+CSQ"); //Signal quality test, value range is 0-31 , 31 is the best
    updateSerial();
    delay(2000);
}

void updateSerial()
{
  while(mySerial.available()) 
  {
    lcd.setCursor(0,0); // lcd.setCursor(ligne,colonne)
    lcd.print(mySerial.read());
  }
}

Une idée ?

Merci

Dans ton while, fais

char c=mySerial.read();
Serial.print (c) ;
lcd.setCursor(0,0);
lcd.print(c);

pour voir ce que tu obtiens dans ta liaison série

Sur le terminal j'ai la "bonne valeur" 12 ou 13 ou 16 etc

par contre sur le lcd j'ai juste 5barres en 0,0

@+

par contre dans le terminal il me répond :

+CSQ: 14,0

OK

donc je pense que je doit récupéré que la valeur entre le : et le retour à la ligne,

quelle est la fonction adéquate ?

Merci

Elle est dans ta signature !
Tu fais un if(c==':')
Et quand c'est bon, tu sélectionnes les caractères que tu veux conserver.

Bosoir

j'ai essayer :

void updateSerial()
{
  while(mySerial.available()) 
  {
    //Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
    char c=mySerial.read();

if(c==':'){
char c=mySerial.read();
}

mais j'ai que le : qui est affiché sur le serial.

J'ai rajouter un while :

void updateSerial()
{
  while(mySerial.available()) 
  {
    //Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
    char c=mySerial.read();

if(c==':'){
  while(mySerial.available()) 
  {
  char d=mySerial.read();
  Serial.print (d) ;
}}

mais du coup il me sort tout :

Call Ready
AT+CSQ

+CSQ: 16,0

OK

Pour être sûr de bien comprendre ce que tu veux. Lorsque tu as ça

+CSQ: 14,0

OK

Tu veux récupérer la valeur 14 ? C'est bien ça ?

Si oui, essaye ça

void updateSerial()
{
  while(mySerial.available())
  {
    //Serial.write(mySerial.read());
    char c=mySerial.read();

if(c==':'){
mySerial.read();
mySerial.read();
char dizaine = mySerial.read();
char unite = mySerial.read();
int valeur = (dizaine - '0')*10+unite-'0';
Serial.println (valeur) ;
}
}
}

Bonjour lesept

Merci cela fonctionne parfaitement

@+

En voyant le post de bricofoy je me suis mis en tete de récupéré l'heure via le module.

via la commande AT+CCLK? il me retourne :

AT+CCLK?

  +CCLK: "20/02/10,13:59:40+04"

du coup j'ai modifier le code fournis pas lesept en rajoutant une condition pour être sur qu'on retourne la commande avec un 'K' et puis le ':' .

loop()
{
  mySerial.println("AT+CCLK?");
  delay(100);
  while (mySerial.available())
  {
    char c = mySerial.read();
    if (c == 'K') {
      char c = mySerial.read();
      if (c == ':') {
        mySerial.read();
        char sep   =  mySerial.read();    //retourne le "
        char annee = mySerial.read();   //retourne le 2
        char annee1 = mySerial.read(); //retourne le 0
        char sep1   =  mySerial.read();  //retourne le /
        char mois = mySerial.read();     //retourne le 0
        char mois1 = mySerial.read();   //retourne le 2

        etc.....

      }
    }

  }
}

Je me suis dit qu'il faut tout lire en char puis convertir en byte ou int.

bonne idée ou il y a plus simple ?

@+

Tu peux mettre les caractères reçus dans un String au fur et à mesure de leur arrivée et utiliser les fonctions de recherche et de transformation de la classe String pour extraire ce que tu veux.

Ça doit aussi pouvoir se faire avec un tableau de char à la place du String.

Bonjour lesept

Top la classe String !

Je rebutait dessus, mais c'est vraiment sympa...

Merci

Mais à utiliser avec modération, car elle a tendance a fragmenter la mémoire. Donc pour une utilisation au début ou de temps en temps dans la loop, ça va. Si ton programme crée des String ou les change (taille notamment) régulièrement pendant l'exécution, tu risques d'avoir des erreurs ou des crashes dus à la mémoire.

Ah.. Je fais un datalogger et je pensais l'utilisé en remplacement d'un DS3231 pour synchroniser le temps...

Je vais garder le DS3231, il donne la T° en +... et utiliser l'heure du réseaux via le SIM800L pour régler l'heure du RTC dans le setup()

@+

Oui, c’est une solution.
Si tu veux éliminer la RTC, tu devrais rester sur l’utilisation de tableaux de char et abandonner le String. Je te l’ai proposé car c’est une solution de facilité, mais elle a des inconvénients.

Pour les fonctions sur les tableaux de char, voir ici

Je vais garder le RTC et régler son heure dans le setup() . comme ça pas de dérive ou de reprogrammation en cas de pile défectueuse. moins de risque de plantage du programme.

plus simple

@+

Le code fonctionne bien, mais si j'envoie une 2ème commande dans le buffer pour indiquer une date différente, elle n'est pas prise en compte, je pensais vider le stringOne avec un stringOne = ""; mais sans succès

unsigned long previousMillis = 0;
const long interval = 5000;
char bufferReception;
int etatBuffer;
String stringOne = "";
byte n;
String jourString, moisString, anneeString, heureString, minutesString, secondeString;
int jour, mois, annee, heure, minutes, seconde;


void setup()
{
  Serial.begin(9600);
}

void loop()
{
  unsigned long currentMillis = millis();

  etatBuffer = Serial.available();

  while (etatBuffer > 0)
  { bufferReception = Serial.read();
    stringOne = stringOne + bufferReception;
    etatBuffer = Serial.available();
  }



  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    n = stringOne.indexOf("/", 0);
    anneeString = stringOne.substring(n - 2, n);
    moisString = stringOne.substring(n + 1, n + 3);
    jourString = stringOne.substring(n + 4, n + 6);
    heureString = stringOne.substring(n + 7, n + 9);
    minutesString = stringOne.substring(n + 10, n + 12);
    secondeString = stringOne.substring(n + 13, n + 15);

    jour = jourString.toInt();
    mois = moisString.toInt();
    annee = anneeString.toInt();
    heure = heureString.toInt();
    minutes = minutesString.toInt();
    seconde = secondeString.toInt();

    Serial.print(jour); Serial.print("/");
    Serial.print(mois); Serial.print("/");
    Serial.print(annee);
    Serial.print("    ");
    Serial.print(heure); Serial.print(":");
    Serial.print(minutes); Serial.print(":");
    Serial.println(seconde);

  }

}

Une idée ? merci

C'est bon... j'ai rajouter un drapeau :slight_smile:

Bonjour

Le pin (3) RST de la sim800 relier au GND "éteint" celui-ci.

J'ai mis un pin sur l'esp pour faire ça.

Mais si l'esp est éteint la pin ne fait plus son taff, normal...

Une idée pour palier ce problème ?

comme la communication est “série”, le plus simple reste quand même d’utiliser les techniques de gestion du port Série → petit tuto sur le sujet

j’avais fait ce code il y a un certain temps en exemple qui utilise sscanf() pour extraire des infos. ça tournait sur un MEGA avec le SIM800 connecté sur le Serial3 (défini par #define gsm Serial3).
Sur un UNO faudrait définir gsm comme un port Sowftare Serial.

#define gsm Serial3

const char * ATString = "AT";
const char * OKString = "\r\nOK\r\n";

const uint32_t oneSecond = 1000ul;

const byte maxMessageSize = 200;
char GSM_MessageLine[maxMessageSize + 1]; // +1 as we want to be able to store the trailing '\0'

// --------------------------------------
// gsmPrintlnATCommand executes an AT commmand by adding at the end a CR LF
// then it checks if endMarker string is receivedon the GSM Serial port
// for max duration ms returns a boolean stating if the marker was found
// with the verbose option, the output from the GSM is also printed to Serial
// --------------------------------------

boolean gsmPrintlnATCommand(const char * command, const char * endMarker, unsigned long duration, boolean verbose)
{
  gsm.println(command);
  return waitForString(endMarker, duration, verbose);
}

// --------------------------------------
// gsmPrintATCommand or gsmpWriteATCommand is used when you don't want to send the CR LF
// at the end of the commmand line; use it to build up a multi part command
// same syntax as print as they are Variadic Macros using print or write
// --------------------------------------
#define gsmPrintATCommand(...) gsm.print(__VA_ARGS__)
#define gsmWriteATCommand(...) gsm.write(__VA_ARGS__)


// --------------------------------------
// read a line from gsm, ignore '\r' and returns true if '\n' is found
// --------------------------------------

boolean getGSMLine()
{
  static byte indexMessage = 0;
  boolean incomingMessage = true;

  while (gsm.available() && incomingMessage) {
    int c = gsm.read();
    if (c != -1) {
      // Serial.write((uint8_t) c); // si vous voulez voir ce qui arrive
      switch (c) {
        case '\n':
          GSM_MessageLine[indexMessage] = '\0'; // trailing NULL char for a correct c-string
          indexMessage = 0; // get ready for next time
          incomingMessage = false;
          break;
        case '\r': // don't care about this one
          break;
        default:
          if (indexMessage <= maxMessageSize - 1) GSM_MessageLine[indexMessage++] = (char) c; // else ignore it..
          break;
      }
    }
  }
  return !incomingMessage;
}

// --------------------------------------
// waitForString wait max for duration ms whilst checking if endMarker string is received
// on the GSM Serial port returns a boolean stating if the marker was found
// --------------------------------------

boolean waitForString(const char * endMarker, unsigned long duration, boolean verbose)
{
  int localBufferSize = strlen(endMarker);
  char localBuffer[localBufferSize];
  int index = 0;
  boolean endMarkerFound = false;
  unsigned long currentTime;

  memset(localBuffer, '\0', localBufferSize); // clear buffer

  currentTime = millis();
  while (millis() - currentTime <= duration) {
    if (gsm.available() > 0) {
      if (index == localBufferSize) index = 0;
      localBuffer[index] = (uint8_t) gsm.read();
      if (verbose) Serial.print((char) localBuffer[index]);
      endMarkerFound = true;
      for (int i = 0; i < localBufferSize; i++) {
        if (localBuffer[(index + 1 + i) % localBufferSize] != endMarker[i]) {
          endMarkerFound = false;
          break;
        }
      }
      index++;
    }
    if (endMarkerFound) break;
  }
  return endMarkerFound;
}


void setup()
{
  Serial.begin(115200);
  gsm.begin(57600);  // test 1200 , 2400, 4800, 9600, 19200, 38400, 57600, 115200.
  // for SIM800L and autobauding Serial and gsm should have the same baud rate and max is 57600

  // prévoir éventuellement AT+CPIN=xxxx pour rentrer le PIN

  // we wait until the module answers to AT command with an OK
  bool waitForBoot = true;
  while (waitForBoot) {
    if (gsmPrintlnATCommand(ATString, OKString, oneSecond, false)) {
      Serial.println(F("GPRS Modem OK"));
      waitForBoot = false;
    } else {
      Serial.write('.');
      delay(oneSecond);
    }
  }
  Serial.println("Initialisation OK");
}


void loop()
{
  // on lit une commande AT que l'utilisateur tape sur la console série et on l'envoie au gsm
  while (Serial.available()) {
    int r = Serial.read();
    if (r != -1) {
      gsm.write((uint8_t) r);
    }
  }

  if (getGSMLine()) {
    // ici on peut tester si la réponse est quelque chose d'intéressant

    // ********************************************
    // par exemple analyse de la réponse à AT+CSQ
    if (!strncmp(GSM_MessageLine, "+CSQ:", 5)) { // 5 parce que "+CSQ:" c'est 5 caractères, on compare le début de la chaîne
      int rssi, ber;
      if ( sscanf(GSM_MessageLine, "+CSQ: %d,%d", &rssi, &ber) == 2) {
        Serial.print(F("Qualité de reception = ")); Serial.println(rssi);
        Serial.print(F("Code Erreur = ")); Serial.println(ber);
      }
    }

    // ********************************************
    // Autres test...
    else if (!strncmp(GSM_MessageLine, "+TOTO:", 6)) {


    } else {
      Serial.println(GSM_MessageLine); // sinon on imprime simplement la réponse
    }
  }
}

humm je me suis mal exprimé

je voudrait éteindre le Sim800 quand l’esp est éteint, le Sim800 est alimenter par une pile 18650.

j’ai raccordé la pin(3) RST sur la pin 25 de l’esp.

pour le démarrer je passe la pin de l’esp à l’etat haut et pour l’éteindre je le passe a l’etat bas.

Mais si je coupe l’esp le SIM800 continu de fonctionner.