téléphone arduino avec sim808

Bonjour,

je suis débutant en programmation, mais j'ai quand même réussi à réaliser un téléphone avec un arduino mega, un sim808 et un clavier matriciel 4x4 et un afficheur deux lignes

pourriez-vous optimiser un peu mon programme ?

de plus, sur le sim808, il y a un vibreur.... quelqu'un aurait la fonction pour le contrôler ?

voici le code : ...accrochez vous.. ça doit être très mal codé et pas du tout optimisé mais je voulais quand même présenter quelque chose plutôt que de pomper un code sans le comprendre !

#include <Keypad.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
#include <sim900.h>
#include <Wire.h>
char Incomingch;
String data, Fdata, callnumber;
LiquidCrystal monEcran(30, 31, 32, 33, 34, 35);
SoftwareSerial gprs(10, 11);
const byte LIGNES = 4;
const byte COLONNES = 4;
const int L1 = 22;
const int L2 = 23;
const int L3 = 24;
const int L4 = 25;
const int C1 = 26;
const int C2 = 27;
const int C3 = 28;
const int C4 = 29;
char touches[LIGNES][COLONNES] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte BrochesLignes[LIGNES] = {L1, L2, L3, L4};
byte BrochesColonnes[COLONNES] = {C1, C2, C3, C4};
char clav;
String touche[10]; // variable de stockage de la valeur de la touche appuyée
String message;
String mess1;
int i = 0;
int sonne = 0;
int decr = 0;
Keypad clavier = Keypad( makeKeymap(touches), BrochesLignes, BrochesColonnes, LIGNES, COLONNES );

void setup()             {
  Serial.begin(9600);
  sim900_init(&gprs, 9600);
  gprs.print("AT+CMGF=1\r");
  delay(100);
  gprs.print("AT+CNMI=2,2,0,0,0\r");
  delay(2000);
  mess1 = "En reception";
  message = "Composez numero";
  affiche();
}

void loop()
{
  menu();
}

void menu()
{

  clav = clavier.getKey();
  if (clav == NO_KEY)
  { reception();
  }
  else
  {
    if (sonne != 1) {
      compose();
    }
  }
}

void appel() {
  gprs.print("ATD");
  gprs.print(message);
  gprs.print(";\r");
  gprs.println();
  clav = clavier.getKey();
  while (clav != 'B') {
    clav = clavier.getKey();
  }
  if (clav == 'B') {
    gprs.print("ATH\r");
    mess1 = "fin de l'appel";
    message = " ";
    affiche();
    delay(2000);
    mess1 = "En reception";
    message = "Composez numero";
    affiche();
    // menu();
  }
}





void affiche() {
  monEcran.begin(16, 2); //on initialise la communication avec 16 colonnes et deux lignes
  monEcran.clear(); // on efface l'écran
  monEcran.print(mess1); // on écrit Bonjour
  monEcran.setCursor(0, 1); //on passe à la ligne suivante
  monEcran.print(message); // on finit d'écrire
}

void compose() {
  while (clav != 'A' ) {
    clav = clavier.getKey();
    if (clav != NO_KEY) {
      if (clav != 'A' ) {
        if (clav != '*') {
          touche[i] = clav;
          i = i + 1;
          message = touche[0] + touche[1] + touche[2] + touche[3] + touche[4] + touche[5] + touche[6] + touche[7] + touche[8] + touche[9];
          mess1 = "numero en cours";
          affiche();
        }
        if (clav == '*') {
          if (i != 0) {
            i = i - 1;
          }
          touche[i] = " ";
          message = touche[0] + touche[1] + touche[2] + touche[3] + touche[4] + touche[5] + touche[6] + touche[7] + touche[8] + touche[9];
          mess1 = "numero en cours";
          affiche();

        }
      }
    }
  }

  if (clav == 'A') {

    delay(1000);
    i = 0;
    message = "+33" + touche[1] + touche[2] + touche[3] + touche[4] + touche[5] + touche[6] + touche[7] + touche[8] + touche[9];
    mess1 = "composition : ";
    affiche();
    appel();
  }

  if (clav == 'B') {
    i = 0;
    mess1 = "En reception";
    message = "Composez numero";
    menu();
  }
}

void reception()
{
  if (gprs.available())
  {
    Incomingch = gprs.read();
    String newchar = String (char(Incomingch));
    if (Incomingch == 10 || Incomingch == 13)
    {
      callnumber = data;
      if (callnumber.length() > 20) {
        callnumber.remove(0, 11);
        callnumber.remove(9, 15);
        callnumber = "0" + callnumber;
        mess1 = "APPEL ENTRANT";
        message = callnumber;
        affiche();
      }
      Fdata = data;
      if (Fdata == "RING") {
        sonne = 1;
        mess1 = "ca sonne";
        message = " ";
        affiche();
      }
      if (Fdata == "NO CARRIER") {
        sonne = 0;
        mess1 = "appel manque";
        message = " ";
        affiche();
        delay(2000);
        mess1 = "En reception";
        message = "Composez numero";
        affiche();
      }
      data = "";
    }
    else
    {
      String newchar = String (char(Incomingch));
      data = data + newchar;

    }
  }
  if (sonne == 1) {
    clav = clavier.getKey();
    if (clav == 'A') {
      gprs.print("ATA\r\n");
      decr = 1;
    }
    if (clav == 'B') {
      if (decr == 1) {
        gprs.print("ATH\r\n");
        mess1 = "fin d'appel";
        message = " ";
        affiche();
        delay(2000);
        mess1 = "En reception";
        message = "Composez numero";
        affiche();
        sonne = 0;
      }
      if (decr != 1) {
        gprs.print("ATH\r\n");
        mess1 = "Appel rejet";
        message = " ";
        affiche();
        delay(2000);
        mess1 = "En reception";
        message = "Composez numero";
        affiche();
        sonne = 0;
        decr = 0;
      }

    }
  }
}
1 Like

on ne va pas tout re-écrire.. si ça fonctionne correctement pour vous, c'est bien - bravo !

perso je traiterai cela comme une machine à états, je ne mettrais pas des clavier.getKey() partout et pour la robustesse j'écrirais une fonction qui envoie une commande et écoute la réponse du module pour pouvoir traiter les erreurs

oui pas faux :wink:

par contre auriez-vous de la doc sur le vibreur du sim808 ?

et pour terminer, je cherche a développer la partie sms et pour se faire, evidemment je n'ai pas de clavier.
j'ai donc pensé faire comme nokia il y a 20 ans de cela...

tu appuies une fois sur 1 sur a un A, 2 fois un B et 3 fois un C.

et si tu laisses plus longtemps tu passes à la lettre suivante,
tu appuies sur une autre touche que le 1, tu passes à la lettre suivante.

a mon avis il va falloir jongler avec des timers ?

vous en pensez quoi ??

fredo5962:
par contre auriez-vous de la doc sur le vibreur du sim808 ?

quel module avez vous exactement? (lien)

fredo5962:
et pour terminer, je cherche a développer la partie sms et pour se faire, evidemment je n'ai pas de clavier.
j'ai donc pensé faire comme nokia il y a 20 ans de cela...

tu appuies une fois sur 1 sur a un A, 2 fois un B et 3 fois un C.

et si tu laisses plus longtemps tu passes à la lettre suivante,
tu appuies sur une autre touche que le 1, tu passes à la lettre suivante.

a mon avis il va falloir jongler avec des timers ?

vous en pensez quoi ??

non juste avec millis() et un peu de logique (si appui rapide sur la même touche, passer au caractère suivant, si touche différente, validation de l'entrée précédente et début d'un nouveau caractère)

je vais pomper ton code et le garder dans un coin. (le temps est une matière rare)
sympa ce forum

bien cdt
merci !

ça me disait bien quelque chose, j'ai retrouvé un bout de code qui permet de gérer les touches selon le clavier téléphonique habituel
clavier.png
par exemple un appui sur 2 va faire 'a' puis 'b' puis 'c' puis '2' et recommencer.
le délai max entre 2 appuis est 1 seconde, sinon valide l'entrée précédente
un # valide le texte. Je n'ai pas codé de touche d'effacement mais ce ne serait pas trop dur à rajouter, je vous laisse faire cela :slight_smile:

// © J-M-L 2019 - for the Arduino Forum
// use as you see fit, maintain author and source reference
// http://forum.arduino.cc/index.php?topic=605654.msg4111098#msg4111098

#include <Keypad.h>

const byte ROWS = 4; // 4 rangées
const byte COLS = 4; // 4 colonnes

// les symboles associés
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {34, 36, 38, 40}; // les pins des rangées
byte colPins[COLS] = {35, 37, 39, 41}; // les pins des colonnes.
Keypad membraneKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);

const struct {
  char entreeKeypad;
  uint8_t nbCar;
  char correspondance[4];
} tableCorrespondance[] = {
  '2', 3, {'a', 'b', 'c', '\0'},
  '3', 3, {'d', 'e', 'f', '\0'},
  '4', 3, {'g', 'h', 'i', '\0'},
  '5', 3, {'j', 'k', 'l', '\0'},
  '6', 3, {'m', 'n', 'o', '\0'},
  '7', 4, {'p', 'q', 'r', 's'},
  '8', 3, {'t', 'u', 'v', '\0'},
  '9', 4, {'w', 'x', 'y', 'z'},
  '0', 1, {' ', '\0', '\0', '\0'}
};
uint8_t tailleTableCorrespondance = sizeof(tableCorrespondance) / sizeof(tableCorrespondance[0]);

const byte tailleMessage = 50;
char message[tailleMessage + 1]; // +1 pour le caractère null à la fin
const char finDeTexte = '#';



char caractereSuivant(const char entree, const char enCours)
{
  char resultat = '\0';
  boolean aUneCorrespondance = false;
  uint8_t indexCorrespondance = 0;

  for (uint8_t i = 0; i < tailleTableCorrespondance; i++) {
    if (tableCorrespondance[i].entreeKeypad == entree) {
      aUneCorrespondance = true;
      indexCorrespondance = i;
      break;
    }
  }

  if (aUneCorrespondance) {
    if ((enCours == '\0') || (entree == enCours)) resultat = tableCorrespondance[indexCorrespondance].correspondance[0];
    else {
      for (uint8_t i = 0; i < tableCorrespondance[indexCorrespondance].nbCar; i++) {
        if (tableCorrespondance[indexCorrespondance].correspondance[i] == enCours) {
          if ((i + 1) >= tableCorrespondance[indexCorrespondance].nbCar) {
            resultat = entree; // le chiffre
          } else {
            resultat = tableCorrespondance[indexCorrespondance].correspondance[i + 1];
          }
          break;
        }
      }
    }
  } else {
    resultat = entree;
  }
  return resultat;
}

bool nouveauCaractere(char &reponse, char &hypothese)
{
  const unsigned long attenteValidation = 1000; // 1 seconde
  static unsigned long chrono = 0;
  static char caractereEnCours = '\0';
  static char toucheEnCours = '\0';
  boolean action = false;

  reponse = '\0';

  if ((toucheEnCours != '\0') && (millis() - chrono >= attenteValidation)) {
    reponse = caractereEnCours;
    caractereEnCours = '\0';
    toucheEnCours = '\0';
  } else {
    char nouvelleTouche = membraneKeypad.getKey();
    if (nouvelleTouche != NO_KEY) {
      action = true;
      chrono = millis();
      if (nouvelleTouche == toucheEnCours) {
        caractereEnCours = caractereSuivant(nouvelleTouche, caractereEnCours);
      } else {
        if (toucheEnCours == '\0') {
          caractereEnCours = caractereSuivant(nouvelleTouche, '\0');
        } else {
          reponse = caractereEnCours;
          caractereEnCours = caractereSuivant(nouvelleTouche, '\0');
        }
        toucheEnCours = nouvelleTouche;
      }
    }
  }

  if (caractereEnCours == finDeTexte) {
    reponse = caractereEnCours;
    caractereEnCours = '\0';
    toucheEnCours = '\0';
  }

  hypothese = caractereEnCours;
  return action;
}

boolean nouveauTexte()
{
  boolean texteValide = false;
  static uint8_t pos = 0;
  char car, hypothese;

  if (nouveauCaractere(car, hypothese)) {
    Serial.print("("); Serial.print(hypothese); Serial.print(")");
  }

  if (car == finDeTexte) {
    message[pos] = '\0';
    texteValide = true;
    pos = 0;
  } else if ((car != '\0') && (pos < tailleMessage)) {
    Serial.print(car);
    message[pos++] = car; // sinon on ignore les autres
  }

  return texteValide;
}

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

void loop()
{
  if (nouveauTexte()) {
    Serial.print("\nTexte du SMS: ");
    Serial.println(message);
  }
}

OOOOH alors la.... MERCI !

oui c'est une bonne idée de rajouter une touche d'effacement ..... * par exemple...

je voudrais pas abuser ni tout abîmer votre code... alors si vous pouviez me le rajouter lol... après promis j’arrête d'abuser de votre gentillesse

en tout cas merci beaucoup c'est vraiment super ce que vous venez de m'apporter !

je vous laisse essayer !

vous testez dans la fonction nouveauTexte() si c'est l'étoile par exemple et si oui vous reculez d'un cran dans le tableau du message... (sans passer sous le début)

Bon aller, je m'y colle ! a vaincre sans périls.. on triomphe sans gloire....
je vous vous inventer un clavier avec des touches que personne n'a jamais vu :wink:

et bin non lol finalement.. facile... :wink:

if ((car != '\0') && (pos < tailleMessage)) {
if (car !=''){
Serial.print(car);
message[pos++] = car;
}
if (car =='
'){
Serial.print(car);
message[pos--] = " ";
}
}

en tout cas merci beaucoup.... c'est une avancée magnifique pour moi !

je vais maintenant bricoler pour faire afficher le programme sur un écran 2 lignes !

vous voyez, pas si difficile :slight_smile:

attention au pos--.. que va-t-il se passer si on a tout effacé ?

ah... oui exact... dans ce cas précis, il faut appuyer sur l'autre bouton magique ... vous voyez celui qui est soudé directement sur l'arduino sur lequel est ecrit 'RESET' :wink:

lol je corrige ca tout de suite :wink:

;D ;D

voila c'est mieux ainsi.

if (car =='*'){
Serial.print("efface");
if (pos >0){
message[pos--] = " "; }

j'ai d'abord tapé un caractere puis une série de *,puis des touches au hasard, l'arduino n'a pas bronché et j'ai bien récupéré le texte que j'attendais !

pour moi c'est ok et pour vous ?

Non attention au guillemets versus simple quote... un caractère c’est entre simple quote.

En fait il nya pas besoin de mettre un espace à la place ça sera écrasé par les nouveaux caractères ou la fin de chaîne, il suffit juste de reculer l’index

bonjour J-M-L;
j'ai essayé votre code, mais malheureusement il affiche tous les caractères de la meme touche alors que mon objectif c'est d'avoir un seul caractère!!!

avez-vous une idée????

moufidaaouachria:
bonjour J-M-L;
j'ai essayé votre code, mais malheureusement il affiche tous les caractères de la meme touche alors que mon objectif c'est d'avoir un seul caractère!!!

avez-vous une idée????

c'est quoi cette résurrection de post ? lisez les règles du forum, et créez un nouveau sujet dans lequel vous décrivez ce que vous voulez faire, ce que vous avez déjà fait et vous postez votre code...(avec les balises).

ok sorry