IMA4 2017/2018 P17 : Différence entre versions

De Wiki de Projets IMA
(Semaine 4)
(Semaine 4)
Ligne 421 : Ligne 421 :
 
Code :  
 
Code :  
  
<pre>//This example implements a simple sliding On/Off button. The example
+
<pre>
// demonstrates drawing and touch operations.
 
//
 
//Thanks to Adafruit forums member Asteroid for the original sketch!
 
//
 
 
#include <Adafruit_GFX.h>
 
#include <Adafruit_GFX.h>
 
#include <SPI.h>
 
#include <SPI.h>
Ligne 431 : Ligne 427 :
 
#include <Adafruit_ILI9341.h>
 
#include <Adafruit_ILI9341.h>
 
#include <Adafruit_STMPE610.h>
 
#include <Adafruit_STMPE610.h>
 
// This is calibration data for the raw touch data to the screen coordinates
 
#define TS_MINX 150
 
#define TS_MINY 130
 
#define TS_MAXX 3800
 
#define TS_MAXY 4000
 
  
 
#define STMPE_CS 8
 
#define STMPE_CS 8
Ligne 444 : Ligne 434 :
 
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
 
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
  
boolean RecordOn = false;
+
#define D_X0 160
 +
#define D_Y0 260
 +
#define D_X1 60
 +
#define D_Y1 260
 +
#define D_X2 110
 +
#define D_Y2 300
 +
 
 +
 
 +
#define G_X0 160
 +
#define G_Y0 60
 +
#define G_X1 60
 +
#define G_Y1 60
 +
#define G_X2 110
 +
#define G_Y2 20
  
#define FRAME_X 210
 
#define FRAME_Y 180
 
#define FRAME_W 100
 
#define FRAME_H 50
 
  
#define REDBUTTON_X FRAME_X
+
#define H_X0 60
#define REDBUTTON_Y FRAME_Y
+
#define H_Y0 100
#define REDBUTTON_W (FRAME_W/2)
+
#define H_X1 60
#define REDBUTTON_H FRAME_H
+
#define H_Y1 220
 +
#define H_X2 20
 +
#define H_Y2 160
  
#define GREENBUTTON_X (REDBUTTON_X + REDBUTTON_W)
 
#define GREENBUTTON_Y FRAME_Y
 
#define GREENBUTTON_W (FRAME_W/2)
 
#define GREENBUTTON_H FRAME_H
 
  
void drawFrame()
+
#define B_X0 180
 +
#define B_Y0 100
 +
#define B_X1 180
 +
#define B_Y1 220
 +
#define B_X2 220
 +
#define B_Y2 160
 +
 
 +
void droite()
 
{
 
{
   tft.drawRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, ILI9341_BLACK);
+
   tft.fillTriangle(D_X0,D_Y0,D_X1,D_Y1,D_X2,D_Y2,ILI9341_GREEN);
 +
  tft.setCursor(D_X1+13,D_Y0);
 +
 
 +
  tft.setTextColor(ILI9341_BLACK);
 +
  tft.setTextSize(2);
 +
  tft.println("droite");
 
}
 
}
  
void redBtn()
+
void gauche()
{  
+
{
   tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ILI9341_RED);
+
  tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ILI9341_BLUE);
+
   tft.fillTriangle(G_X0,G_Y0,G_X1,G_Y1,G_X2,G_Y2,ILI9341_GREEN);
  drawFrame();
+
   tft.setCursor(G_X1+13,G_Y1-13);
   tft.setCursor(GREENBUTTON_X + 6 , GREENBUTTON_Y + (GREENBUTTON_H/2));
+
   tft.setTextColor(ILI9341_BLACK);
   tft.setTextColor(ILI9341_WHITE);
 
 
   tft.setTextSize(2);
 
   tft.setTextSize(2);
   tft.println("ON");
+
   tft.println("gauche");
   RecordOn = false;
+
}
 +
void haut()
 +
{
 +
 +
   tft.fillTriangle(H_X0,H_Y0,H_X1,H_Y1,H_X2,H_Y2,ILI9341_GREEN);
 +
 
}
 
}
 +
void bas()
 +
{
  
void greenBtn()
+
   tft.fillTriangle(B_X0,B_Y0,B_X1,B_Y1,B_X2,B_Y2,ILI9341_GREEN);
{
+
   tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ILI9341_GREEN);
 
  tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ILI9341_BLUE);
 
  drawFrame();
 
  tft.setCursor(REDBUTTON_X + 6 , REDBUTTON_Y + (REDBUTTON_H/2));
 
  tft.setTextColor(ILI9341_WHITE);
 
  tft.setTextSize(2);
 
  tft.println("OFF");
 
  RecordOn = true;
 
 
}
 
}
  
Ligne 501 : Ligne 508 :
 
   }
 
   }
  
   tft.fillScreen(ILI9341_BLUE);
+
   tft.fillScreen(ILI9341_PINK);
   // origin = left,top landscape (USB left upper)
+
    
  tft.setRotation(1);
 
  redBtn();
 
 
}
 
}
  
 
void loop()
 
void loop()
 
{
 
{
   // See if there's any  touch data for us
+
    
  if (!ts.bufferEmpty())
+
  droite();
  { 
+
gauche();
    // Retrieve a point  
+
haut();
    TS_Point p = ts.getPoint();  
+
bas();
    // Scale using the calibration #'s
+
 
    // and rotate coordinate system
+
}
    p.x = map(p.x, TS_MINY, TS_MAXY, 0, tft.height());
+
</pre>
    p.y = map(p.y, TS_MINX, TS_MAXX, 0, tft.width());
 
    int y = tft.height() - p.x;
 
    int x = p.y;
 
 
 
    if (RecordOn)
 
    {
 
      if((x > REDBUTTON_X) && (x < (REDBUTTON_X + REDBUTTON_W))) {
 
        if ((y > REDBUTTON_Y) && (y <= (REDBUTTON_Y + REDBUTTON_H))) {
 
          Serial.println("Red btn hit");
 
          redBtn();
 
        }
 
      }
 
    }
 
    else //Record is off (RecordOn == false)
 
    {
 
      if((x > GREENBUTTON_X) && (x < (GREENBUTTON_X + GREENBUTTON_W))) {
 
        if ((y > GREENBUTTON_Y) && (y <= (GREENBUTTON_Y + GREENBUTTON_H))) {
 
          Serial.println("Green btn hit");
 
          greenBtn();
 
        }
 
      }
 
    }
 
 
 
    Serial.println(RecordOn);
 
  } 
 
}</pre>
 
  
 
=Fichiers Rendus=
 
=Fichiers Rendus=

Version du 14 février 2018 à 15:06


Présentation générale

  • Titre du projet : SafeWatch
  • Description : Montre connectée simple d'utilisation permettant de réorienter les personnes en difficulté.

Objectifs

De plus en plus de personnes se retrouvent seules en vieillissant, aussi bien chez elles qu’à l’extérieur. Nous sommes là pour faire le lien entre les deux. Notre montre, simple d’utilisation, vous permettra de rentrer chez vous au plus vite et d’appeler vos proches ou même les urgences en cas de nécessité. Cette montre dispose de trois boutons. Le premier permet de retrouver son chemin, le deuxième d’appeler ses proches et les urgences en cas de non-réponse et le troisième de revenir à la fonction horloge. Cette montre est reliée à une application installée sur le téléphone de la personne référente, application qui reçoit les appels et affiche la position de la montre.

Positionnement par rapport à l'existant

Notre montre permet, en plus de la géolocalisation et de l’appel des proches, de rediriger les personnes jusqu’à leur logement.

Analyse du projet

Analyse du premier concurrent

Arkea assistance :

  • Montre connectée qui permet de déclencher à tout moment et en tous lieux une alerte en cas de besoin.
  • Principe d’utilisation : Vous appuyez, vous êtes géolocalisé, nous vous écoutons
  • Abonnement à une téléassistance
  • Prix montre + abonnement = 13,45+24,90 par mois
  • Inconvénients : montre tactile (peu pratique pour les personnes âgées), ne permet pas d’appeler les proches, pas d'orientation via GPS, prix de l’abonnement élevé.

Analyse du second concurrent

Libr’Alert :

  • Une montre avec bouton SOS, très légère au design élégant
  • Système de géolocalisation intégré
  • Un dispositif que vous avez toujours à portée de main
  • La réception et gestion des appels 24h/24 et 7j/7 par notre centrale d’écoute.
  • La géolocalisation de l’appel d’urgence afin de pouvoir orienter les secours vers le bon endroit.
  • Prix : 34,90€ par mois
  • Inconvénients : pas de GPS, pas de possibilité de contacter les proches

Scénario d'usage du produit ou du concept envisagé

Fait divers : Une personne agée a été retrouvée, dix jours après sa disparition, en état de décomposition, dans un buisson non loin de chez elle. Cette femme d’un certain âge s’était perdue. Cause simple malheureusement trop fréquente. C’est dans ce cadre que la SafeWatch devient indispensable.

En effet, avec notre montre, la vieille dame aurait pu, dans un moment de lucidité, appuyer sur le bouton « appel d’un référent » afin d'envoyer un message automatique joignant sa position à un proche référent. Elle aurait pu aussi appuyer sur « retour maison » lui indiquant avec des flèches de direction le chemin pour revenir à son domicile. Sa vie tenant sur une simple pression d’un bouton de notre montre.

Mari esseulé, en état de peur face à la possibilité de perdre sa femme, aurait pu avec notre montre, la retrouver. En effet, grâce à notre option GPS dans la montre, sa femme aurait été localisée plus facilement et plus rapidement, et ainsi être encore en vie lors de sa découverte. Aujourd’hui, nous en sommes sûr il aurait aimé investir dans notre SafeWatch.

Réponse à la question difficile

Comment la montre se recharge-t-elle ?

Grace à un chargeur par induction (on pose sa montre à plat sur une plaque qui va recharger la batterie)

Comment éviter l'abus d'appel au référent ?

Cette montre reste réservée aux personnes pas encore totalement séniles qui sont conscientes que cet appareil va les aider. De plus, si le référent se rend compte que la personne abuse de l'option appel c'est de sa responsabilité de lui retirer la montre. Un son sera émis lorsqu'une touche sera activée

Réalisation du projet

Choix techniques : matériel et logiciel

Afin de pouvoir réaliser les fonctions citées ci-dessus , nous utiliserons le matériel suivant :

  • Arduino UNO et 3 boutons poussoirs.
  • Géolocalisation : GPS Adafruit v3.
  • Appeler des proches ou les urgences : bouclier GSM Arduino.
  • Affichage d'horloge et de l'orientation GPS vers domicile : 2.8" TFT LCD shield w/Touchscreen.

Calendrier prévisionnel

Liste des tâches à effectuer

Tâche 1 : Réalisation du prototype

  • 1.1 Montage sur plaque d'essai et test de l'ensemble
  • 1.2 Conception de la carte électronique rassemblant le matériel
  • 1.3 Réalisation de la carte et son boîtier en s'assurant que cela ressemblera à une montre vu le volume des boucliers

Tache 2 : Géolocalisation

  • 2.1 Envoi de la position en appuyant sur le bouton poussoir 1
  • 2.2 Affichage de la position déjà envoyée , à l'aide d'une application mobile (envoi lien Google Maps)
  • 2.3 Afficher un message d'envoi de la position sur LCD


Tache 3 : Orientation vers le domicile

  • Afficher les flèches d'orientation sur l’écran en fonction de la position


Tache 4 : Appeler le référent

  • 4.1 Configuration du bouclier GSM
  • 4.2 Appeler le référent en appuyant sur bouton poussoir 2
  • 4.3 Envoi SMS personnalisé (Optionnel)
  • 4.4 Afficher un message d'envoi d'appel sur LCD

Tache 5 : Horloge

  • Afficher l'horloge sur LCD en appuyant sur le bouton poussoir 3

Feuille d'heures

Tâche Prélude Heures S1 Heures S2 Heures S3 Heures S4 Heures S5 Heures S6 Heures S7 Heures S8 Heures S9 Heures S10 Total
Analyse du projet 0
Choix du matériel 6h
Réalisation de la tache 2 : Géolocalisation ( manque de la sous-tache 2.4) 8h 6h
Tache 3 en cours 2h

Avancement du Projet

Prologue

Montage protoype :

Montage: Arduino+ GSM + GPS


Partie GPS :

  • NMEA sentence :

Un GPS nous permet d'avoir plusieurs types de NMEA sentence , on s’intéressera qu'à $GPRMC et $GPGGA qui donnent la latitude et la longitude et l'altitude.

* The recommanded minimum sentence C : RMC

Exemple : $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A

$GPRMC ,temps,etat_fix,latitude ,point_cardinal,longitude ,point_cardinal,vitesse_gps,track_angle,datev,ariation_magnétique,checksum


etat_fix = A:Active ou V:void
track_angle=la direction du véhicule en mouvement


* Global Positioning System Fix Data

Exemple : $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47

$GPGGA ,temps,latitude,point_cardinal,longitude,point_cardinal,qualité_fix,nb_sattelites,GDOP,altitude ,hauteur_geoid,,checksum

qualité_fix: 0 = invalid / 1 = GPS fix (SPS)/ ...

GDOP : Geometric dilution of precision = indicateur sur le positionnement des satellites.

Pour récupérer les NMEA sentences , je branche les pins TX et RX du GPS au pin 0 et 1 de l'Arduino . Cela me permet d'établir une communication série avec l'ordinateur en passant par Arduino , le GPS envoie la data sans programmer l'Arduino :

Gps 1.png

Semaine 1

Puisque je m'intéresse uniquement à $GPRMC et $GPGGA, le code suivant me permettra de les récupérer et afficher les paramètres de position .

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h> 
SoftwareSerial mySerial(3, 2); 
Adafruit_GPS GPS(&mySerial); 
String NMEA1;  
String NMEA2;  
char c;        

void setup()  {
Serial.begin(115200);  
GPS.begin(9600);       
GPS.sendCommand("$PGCMD,33,0*6D"); 
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); 
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   
delay(1000);  } 

void loop(){
readGPS();
}

void readGPS(){  
clearGPS();    
while(!GPS.newNMEAreceived()) { 
c=GPS.read();  }
GPS.parse(GPS.lastNMEA());  
NMEA1=GPS.lastNMEA();      
while(!GPS.newNMEAreceived()) {  
c=GPS.read();}
GPS.parse(GPS.lastNMEA());
NMEA2=GPS.lastNMEA();
Serial.println(NMEA1);
Serial.println(NMEA2);
Serial.println("");
Serial.println(NMEA1);
Serial.println(NMEA2);
Serial.println("");
Serial.print("\nTime: ");
Serial.print(GPS.hour, DEC); Serial.print(':');
Serial.print(GPS.minute, DEC); Serial.print(':');
Serial.print(GPS.seconds, DEC); Serial.print('.');
Serial.println(GPS.milliseconds);
Serial.print("Date: ");
Serial.print(GPS.day, DEC); Serial.print('/');
Serial.print(GPS.month, DEC); Serial.print("/20");
Serial.println(GPS.year, DEC);
Serial.print("Fix: "); Serial.print((int)GPS.fix);
Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
if (GPS.fix) {
Serial.print("Location: ");
Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
Serial.print(", "); 
Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
Serial.print("Location (in degrees, works with Google Maps): ");
Serial.print(GPS.latitudeDegrees, 4);
Serial.print(", "); 
Serial.println(GPS.longitudeDegrees, 4);
Serial.print("Speed (knots): "); Serial.println(GPS.speed);
Serial.print("Angle: "); Serial.println(GPS.angle);
Serial.print("Altitude: "); Serial.println(GPS.altitude);
Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
}
}

void clearGPS() {  
while(!GPS.newNMEAreceived()) 
{
c=GPS.read();
}
GPS.parse(GPS.lastNMEA());
while(!GPS.newNMEAreceived()) {
c=GPS.read(); }
GPS.parse(GPS.lastNMEA());}
Gps fix 0 1.png

Le résultat obtenu montre que le fix n'est pas bon , d'où le manque des paramètre . Pour avoir un fix bon , il faut etre à l'extérieur .

Gps khdem.png

semaine 2

Maintenant que j'ai la position , il faut l'envoyer par SMS .

Partie GSM

le code ci-dessous envoie la position (sous forme de lien vers google maps) un fois le bouton est appuyé.

#include <GSM.h>
#include <Adafruit_GPS.h>
#include<AltSoftSerial.h>//utilisation de AltSoftSerial pour eviter le conflit des librairies GSM et GPS pour utiliser SoftwareSerial.h
AltSoftSerial mySerial(3, 2); 
Adafruit_GPS GPS(&mySerial);// objet GPS  

#define PINNUMBER "1234"// code pin 
GSM gsmAccess; 
GSM_SMS sms;// objet sms
  
const int buttonPin = 8;
int buttonState = 0; 
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
Serial.begin(9600);
boolean notConnected = true;
Serial.println("Initialisation GSM en cours ...");
//test d'initialisation GSM
while (notConnected) {
if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
notConnected = false;
} else {
Serial.println("non connecté");
delay(1000);
}
Serial.println("GSM initialisé: appuyez sur le bouton pour envoyé la position par sms ");
}

}
void loop() {
buttonState = digitalRead(buttonPin);
char* remoteNum="0760153353"; // num destinataire 
String latitude = String(GPS.latitudeDegrees);
String longitude= String(GPS.longitudeDegrees);
// envoie du message
if (buttonState == LOW) {
Serial.println("envoie de la position en cours ...\n");
sms.beginSMS(remoteNum);
sms.print("lien google maps: http://maps.google.com/?q="+latitude+","+longitude);
sms.endSMS();
Serial.println("\nPosition envoyée:lien google maps: http://maps.google.com/?q="+latitude+","+longitude);
}
}

Resultat:

Gsm test.png

Remarque : la latitude et la longitude valent "0" car le fix du GPS n'est pas bon .

semaine 3

Code mis-à-jour de manière à appeler le référent une fois le bouton 2 est appuyé:

#include <GSM.h>
#include <Adafruit_GPS.h>
#include<AltSoftSerial.h>//utilisation de AltSoftSerial pour eviter le conflit des librairies GSM et GPS pour utiliser SoftwareSerial.h
AltSoftSerial mySerial(3, 2); 
GSMVoiceCall appel;
Adafruit_GPS GPS(&mySerial);// objet GPS  
#define PINNUMBER "1234"// code pin 
GSM gsmAccess; 
GSM_SMS sms;// objet sms
const int buttonPin1 = 12;
const int buttonPin2 = 8;
int buttonState1=0;
int buttonState2 = 0; 
void setup() {
pinMode(buttonPin2, INPUT_PULLUP);
pinMode(buttonPin1, INPUT_PULLUP);
Serial.begin(9600);
boolean notConnected = true;
Serial.println("Initialisation GSM en cours ...");
//test d'initialisation GSM
while (notConnected) {
if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
notConnected = false;
Serial.println("GSM initialisé: appuyez sur le bouton 1 pour appeler le référent  ");
Serial.println("GSM initialisé: appuyez sur le bouton 2 pour envoyer la position par sms ");
}
else {
Serial.println("non connecté");
delay(1000);
}
}
}
void loop() {
buttonState2 = digitalRead(buttonPin2);
buttonState1 = digitalRead(buttonPin1);
char* remoteNum="0618659369"; // num destinataire 
String latitude = String(GPS.latitudeDegrees);
String longitude= String(GPS.longitudeDegrees);
//envoi du message
if (buttonState2 == LOW){
Serial.println("envoie de la position en cours ...\n");
sms.beginSMS(remoteNum);
sms.print("lien google maps: http://maps.google.com/?q="+latitude+","+longitude);
sms.endSMS();
Serial.println("\nPosition envoyée:lien google maps: http://maps.google.com/?q="+latitude+","+longitude);
}
//appel au référent 
if (buttonState1 == LOW) {
if (appel.voiceCall(remoteNum)){
Serial.print("\n appel en cours... \n");
Serial.println("le référent a décroché, parlez ! si vous voulez raccrocher appuyer de nouveau sur le bouton 1");
while(buttonState2 !=LOW && (appel.getvoiceCallStatus()==TALKING));
delay(100);
appel.hangCall();  
}
Serial.print("\n fin d'appel \n");
}
}

Remarque : Code compile mais redondance d'appel sans pourvoir raccrocher du coté de l'appelant: d'autres essais à effectuer après obtention de carte SIM .

Semaine 4

Partie LCD : Affichage des flèches d'orientation .

Travail sur papier :

Travail papier.jpg

La résolution du LCD est de 240x320 .

Les quatres fleches partagent l'ecran , elles seront affichées toutes à la fois . La flèche concerné va clignoter .

L'interet d'afficher les mots "droite" , "gauche" est de ne pas confondre les sens des flèches si on tourne l’écran. Normalement la connaissance d'un sens nous permettera de reconnaitre les autres .


Lcd fleches.jpg


Code :

#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_STMPE610.h>

#define STMPE_CS 8
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
#define TFT_CS 10
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

#define D_X0 160
#define D_Y0 260
#define D_X1 60
#define D_Y1 260
#define D_X2 110
#define D_Y2 300


#define G_X0 160
#define G_Y0 60
#define G_X1 60
#define G_Y1 60
#define G_X2 110
#define G_Y2 20


#define H_X0 60
#define H_Y0 100
#define H_X1 60
#define H_Y1 220
#define H_X2 20
#define H_Y2 160


#define B_X0 180
#define B_Y0 100
#define B_X1 180
#define B_Y1 220
#define B_X2 220
#define B_Y2 160

void droite()
{
  tft.fillTriangle(D_X0,D_Y0,D_X1,D_Y1,D_X2,D_Y2,ILI9341_GREEN);
  tft.setCursor(D_X1+13,D_Y0);
  
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(2);
  tft.println("droite");
}

void gauche()
{
 
  tft.fillTriangle(G_X0,G_Y0,G_X1,G_Y1,G_X2,G_Y2,ILI9341_GREEN);
  tft.setCursor(G_X1+13,G_Y1-13);
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(2);
  tft.println("gauche");
}
void haut()
{
 
  tft.fillTriangle(H_X0,H_Y0,H_X1,H_Y1,H_X2,H_Y2,ILI9341_GREEN);
 
}
void bas()
{

  tft.fillTriangle(B_X0,B_Y0,B_X1,B_Y1,B_X2,B_Y2,ILI9341_GREEN);
 
}

void setup(void)
{
  Serial.begin(9600);
  tft.begin();
  if (!ts.begin()) { 
    Serial.println("Unable to start touchscreen.");
  } 
  else { 
    Serial.println("Touchscreen started."); 
  }

  tft.fillScreen(ILI9341_PINK);
  
}

void loop()
{
  
 droite();
 gauche();
 haut();
 bas();
  
}

Fichiers Rendus