Épreuve synthèse – volet B – 2022

16 Décembre 2022

Date: lundi, 19 décembre, 13h

Durée: 3 périodes (15h45)

À réaliser sous Wokwi


1 – À partir du système fonctionnel suivant:


1.1 – L’écran de simulation

NOTE: Prendre le temps de regarder la simulation au complet


1.2 – Le code source (sketch.ino)

#include "Streaming.h"
#include <LiquidCrystal_I2C.h>

// ********************************************************
// Les enum
enum codesAlarme {
  evenement_detection_mouvement,
  ACK_evenement_detection_mouvement,
  evenement_systeme_enligne,
  ACK_evenement_systeme_enligne
};
// ********************************************************

// ********************************************************
// Les constantes (MACRO)
#define   UART_CENTRALE               Serial3
#define   UART_SYSTEME_ALARME         Serial1
#define   UART_VITESSE_CONSOLE        9600
#define   UART_VITESSE_CENTRALE       115200
#define   UNE_SECONDE                 1000
#define   DEMI_SECONDE                500
#define   DELAI_TRANSMISSION_MESSAGE  UNE_SECONDE * 2
#define   BOUTON_DELAI_REBOND         50
#define   LCD_NB_LIGNE                4
#define   LCD_NB_COLONNE              20
#define   LCD_LIGNE1                  0
#define   LCD_LIGNE2                  1
#define   LCD_LIGNE3                  2
#define   LCD_LIGNE4                  3
#define   LCD_PREMIERE_COLONNE        0
#define   LCD_ADRESSE_I2C             0x27
#define   DETECTEUR_MOUVEMENT_ENTREE  7

// ********************************************************
// Déclaration des fonctions
void      initialisationDesAppareils();
// ********************************************************

// ********************************************************
// Variables Globales
LiquidCrystal_I2C ecranPrincipal(LCD_ADRESSE_I2C,LCD_NB_COLONNE,LCD_NB_LIGNE);
// ********************************************************

// ********************************************************
//                    Début du programme
// ********************************************************

// ********************************************************
void setup() 
// ********************************************************
{
  Serial.begin(UART_VITESSE_CONSOLE);   
  initialisationDesAppareils();

  ecranPrincipal.setCursor(0,1);
  ecranPrincipal << "Connexion ....";
 
 // NOTE: ===> Il faut remplacer 'connexionALaCentrale()' par 
 if (connexionALaCentrale()){
      ecranPrincipal.setCursor(0,2);
      ecranPrincipal << "Systeme en ligne"; 
  }

}

// ********************************************************
void loop() 
// ********************************************************
{
  bool alarmeON = true;
  afficherTempsEcoule();

  if (digitalRead(DETECTEUR_MOUVEMENT_ENTREE)) {
      Serial << "DETECTEUR_MOUVEMENT_ENTREE\n";
      ecranPrincipal.clear();
      ecranPrincipal << "Detection mouvement";
      Serial << "Aviser la centrale de l'intrusion\n";
      envoyerMessageVersLaCentrale(evenement_detection_mouvement);
      while(digitalRead(DETECTEUR_MOUVEMENT_ENTREE)); // S'assurer que le détecteur est détendu.
      ecranPrincipal.clear();
  }

} // loop()


// ********************************************************
void initialisationDesAppareils()
// ********************************************************
{

  ecranPrincipal.begin(LCD_NB_COLONNE,LCD_NB_LIGNE);
  ecranPrincipal.backlight();
  ecranPrincipal << "Initialisation...";

  UART_SYSTEME_ALARME.begin(UART_VITESSE_CENTRALE);
  UART_CENTRALE.begin(UART_VITESSE_CENTRALE);
  pinMode(DETECTEUR_MOUVEMENT_ENTREE, INPUT);

} // initialisationDesAppareils


// ************************************************************************
// NOTE:  Il faut intégrer cette fonction à envoyerMessageVersLaCentrale()
// et la supprimer (connexionALaCentrale). 
// ************************************************************************
boolean connexionALaCentrale()
// ************************************************************************
{
  byte codeAlarme;
  Serial << F("Tentative de connexion à la centrale ...") << endl;
  UART_SYSTEME_ALARME.write(evenement_systeme_enligne);
  delay(DELAI_TRANSMISSION_MESSAGE);

  if (UART_CENTRALE.available()){
    Serial << F("UART_CENTRALE.available()") << endl;
    codeAlarme = UART_CENTRALE.read();

    switch (codeAlarme)  {

      case evenement_systeme_enligne: 
      Serial << F("evenement_systeme_enligne") << endl;
      Serial << F("Succes: Connexion à la centrale ...") << endl;

      //afficherPageEcran(centraleSystemeEnLigne);
      return true;
      break;

      default:  
       
      Serial << "Evenement non traité" << endl;
             
      break;

    } // switch

  } // if available()

  return false;
} // connexionALaCentrale


// ********************************************************
boolean envoyerMessageVersLaCentrale(codesAlarme message)
// ********************************************************
{
  byte codeAlarme;
  Serial << F("envoyerMessageVersLaCentrale") << endl;
  UART_SYSTEME_ALARME.write(message);
  delay(DELAI_TRANSMISSION_MESSAGE);

  if (UART_CENTRALE.available()){
     Serial << F("UART_CENTRALE.available()") << endl;
     Serial << F("La centrale a reçu le message: ");
    codeAlarme = UART_CENTRALE.read();

    switch (codeAlarme)  {

      case evenement_detection_mouvement: 
 
      Serial << F("evenement_detection_mouvement") << endl;
      return true;
      break;

      default:  
      Serial << "Evenement non traité" << endl;
      break;

    } // switch

  } // if available()

  return false;
} // connexionALaCentrale


// ***************************************************
void afficherTempsEcoule() {
// ***************************************************
  static unsigned long depart = millis();

  if (millis() - depart < UNE_SECONDE) return;

  char bufferLigneLCD[21];   // Vecteur pour construire le message à afficher
  depart = millis();         // Réinitialiser le temps qui passe ...

  unsigned long tempsEcoule = millis() / 1000;
  int secondes =  tempsEcoule % 60;
  int minutes  =  (tempsEcoule / 60 ) % 60;
  int heures   =  (tempsEcoule / 3600 ) % 24;
  int jours    =  0;

  snprintf(bufferLigneLCD, LCD_NB_COLONNE + 1, "Actif: %03d, %02d:%02d:%02d", 0, heures, minutes, secondes );
  ecranPrincipal.setCursor(LCD_PREMIERE_COLONNE,LCD_LIGNE4);
  ecranPrincipal.print(bufferLigneLCD);
} // afficherTemps()

// ********************************************************
//                    Fin du programme
// ********************************************************

NOTE: Ce code source est fonctionnel et produit le résultat de l’animation de la simulation 1.1


1.3 – Le schéma du système (diagram.json)

{
  "version": 1.02,
  "author": "Alain Boudreault",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-mega", "id": "mega", "top": -16.21, "left": 449.2, "attrs": {} },
    {
      "type": "wokwi-lcd2004",
      "id": "lcd1",
      "top": -218.29,
      "left": 469.8,
      "attrs": { "pins": "i2c", "background": "blue", "color": "white" }
    },
    {
      "type": "wokwi-pir-motion-sensor",
      "id": "pir1",
      "top": -216.95,
      "left": 373.95,
      "attrs": {}
    }
  ],
  "connections": [
    [ "mega:19", "mega:14", "black", [ "v-16.99", "h-48" ] ],
    [ "mega:18", "mega:15", "black", [ "h9.69", "v-16.99", "h-47.57", "v16.99" ] ],
    [ "pir1:OUT", "mega:7", "black", [ "v15.38", "h-9.53", "v85.45", "h268.33" ] ],
    [ "mega:49", "mega:51", "black", [ "v0.51", "h-4.54" ] ],
    [
      "pir1:GND",
      "mega:GND.1",
      "black",
      [ "v17.09", "h-0.33", "v24.3", "h-0.09", "v21.41", "h-18.52", "v38.03", "h197.02" ]
    ],
    [ "lcd1:GND", "pir1:GND", "black", [ "h-0.09", "v123.66", "h-83.59" ] ],
    [ "lcd1:VCC", "pir1:VCC", "black", [ "v-9.83", "h-0.93", "v124.21", "h-102.21" ] ],
    [ "pir1:VCC", "mega:5V", "black", [ "v100.95", "h242.96", "v93.43", "h0.08" ] ],
    [ "lcd1:SDA", "mega:SDA", "black", [ "v104.88", "h-63.62", "v38.29", "h139.02" ] ],
    [ "lcd1:SCL", "mega:SCL", "black", [ "v95.38", "h-63.62", "v38.3", "h129.02" ] ]
  ],
  "dependencies": {}
}

2 – Apporter les modifications suivantes

2.1 – Ajouter une DEL rouge (LED).

2.2 – Allumer la DEL lorsque le détecteur de mouvement est activé.

2.3 – Modifier la fonction ‘envoyerMessageVersLaCentrale()‘.

La fonction doit retourner une valeur de type enumcodesAlarme‘ transmit par UART_CENTRALE . Par exemple, si la fonction ‘envoyerMessageVersLaCentrale‘ reçoit la valeur ‘evenement_detection_mouvement‘, ce code doit être transmit à UART_CENTRALE et UART_SYSTEME_ALARME attend la réponse. Cette réponse sera le code transmit avec comme préfix ‘ACK‘.

Par exemple: envoyerMessageVersLaCentrale(evenement_detection_mouvement) doit retourner ACK_evenement_detection_mouvement.

// Exemple
#define CODE_INVALIDE -1

placerIciLeBonType envoyerMessageVersLaCentrale(codesAlarme message)
{
  byte codeAlarme;
  Serial << F("envoyerMessageVersLaCentrale") << endl;
  UART_SYSTEME_ALARME.write(message);
  delay(DELAI_TRANSMISSION_MESSAGE);

  if (UART_CENTRALE.available()){
     Serial << F("UART_CENTRALE.available()") << endl;
     Serial << F("La centrale a reçu le message: ");
     codeAlarme = UART_CENTRALE.read();

    switch (codeAlarme)  {

      case evenement_detection_mouvement: 
 
          Serial << F("evenement_detection_mouvement") << endl;

          // *************** Section à compléter !!
          // A - La centrale doit transmettre le code de confirmation 'ACK_evenement_detection_mouvement'
          // B - Le système d'alarme attend la réponse de la centrale
          // C - Le système d'alarme lit la réponse de la centrale et la retourne (return).
          break;

      default:  Serial << "Evenement non traité" << endl;
                break;

    } // switch

  } // if available()

  return CODE_INVALIDE;
} // connexionALaCentrale

2.4 – Lorsque la valeur retournée par la fonction ‘envoyerMessageVersLaCentrale()‘ est égale à ‘ACK_evenement_detection_mouvement‘, il faut alors éteindre la DEL rouge. NOTE: Ne pas éteindre la DEL dans la fonction envoyerMessageVersLaCentrale().

2.5 – Afficher dans la console de déboggage que si la macro _TRACE_ est définie.


NOTE: Les points 2.1 à 2.5 étaient dans le formatif


2.6 – Combiner la fonction ‘connexionALaCentrale()‘ à la fonction ‘envoyerMessageVersLaCentrale()‘ puis supprimer ‘connexionALaCentrale()‘. Note: Dans la fonction setup(), il faut remplacer ‘connexionALaCentrale()‘ par ‘envoyerMessageVersLaCentrale()‘.

2.7a – Ajouter une DEL verte et un bouton (push Button).

2.7b – Le bouton enverra le message ‘evenement_bouton_panique‘ à la centrale sur son relâchement. Sur réception du message, la centrale retournera le message ‘ACK_evenement_bouton_panique‘ au système d’alarme. Sur réception du message ‘ACK_evenement_bouton_panique‘ par le système d’alarme, la DEL verte clignotera, continuellement, 2 fois/seconde de façon non bloquante (ne pas utiliser de délais).

2.8 – Déplacer vers le fichier ‘synthese.h‘ (à créer) tout ce qui est pertinent.

2.9 – Renseigner un bloc commentaire d’entête dans le fichier .ino.


3 – Remise

Dans LEA, un fichier .zip du projet, incluant un lien vers le projet Wokwi.


4 – Grille de correction

ÉtapePoids
2.1 – Ajouter DEL rouge1
2.2 – Allumer DEL rouge sur mouvement2
2.3 – Modifier la fonction ‘envoyerMessageVersLaCentrale()’5
2.4 – Éteindre DEL rouge sur réception ACK2
2.5 – Macro _TRACE_2
2.6 – Combiner les deux fonctions et suppression de connexionALaCentrale()10
2.7a – Ajouter bouton et DEL verte5
2.7b- Gestion du message ‘evenement_bouton_panique’ + clignoter DEL15
2.8 – synthese.h5
2.9 – Commentaire d’entête5