Posto Libero (Table connectée)

De Wiki de Projets IMA

Le concept "Posto Libero" - Cahier des charges

Description du projet

Dans le cadre du module transversal Internet des Objets (IOT), nous avons choisi de réaliser une table connectée.

Cette table a pour but de faciliter la recherche de place libre (d'où le nom "Posto Libero") dans un lieu tel que un restaurant universitaire, une cafétéria ou une bibliothèque.

Pour cela, nous devrons mettre en place un dispositif capable de :

  • Détecter la présence d'une personne assise
    • En récupérant la distance entre une entité et la table
    • En faisant la différence entre une chaise et une personne
  • Mettre en évidence le nombre de places disponibles pour une table
    • En projetant le nombre de places disponibles au plafond
    • En changeant la couleur d'une LED au niveau du capteur
    • En répertoriant les places en temps réel sur une application ou un site internet

Pour mieux montrer notre idée, nous avons fait un dessin.

Table connectée
Poster disponible en PDF en A3 dans l'onglet livrable

Notre idée est de mettre un capteur sur chaque bord de la table. Ces capteurs permettent de détecter la présence de la personne. Les capteurs sont liés avec un arduino au milieu de la table par des câbles. L'arduino récupère des informations des capteurs. L'arduino est ensemble avec un XBee et à la distance nous avons un Raspberry Pi avec un autre XBee. Ces deux XBee réalisent une communication sans fil. Quand le Raspberry Pi reçoit des données il va les envoyer au serveur par réseau Internet. Sur la page html nous pouvons voir les places libres.

Choix techniques

Matériel

Nous aurons besoin :

  • 4x Capteur à infrarouge pour détecter une entité
    • Passive Infrared Proximity Motion Sensor (1x 03/01/2017) Datasheet
  • 4x Capteur de température pour différencier une personne et une chaise
  • 4x LED RGB pour visualiser la présence au niveau du capteur (1x 05/01/2017)
  • 1x Projecteur alphanumérique pour afficher le nombre de place au plafond
    • Serial 7 Segment display (1x 10/01/2017) Datasheet
  • 1x Arduino pour centraliser les capteurs d'une table (1x 05/01/2017)
  • 1x Raspberry Pi pour centraliser les Arduino et héberger un site internet (1x 05/01/2017)
  • 2x Module Zigbee pour la communication entre Arduino et Raspberry Pi (2x 05/01/2017)
  • 1x Un micro pour savoir si la table est bruyante
    • Adafruit AGC Electret Microphone Amplifier - MAX9814 (1x 10/01/2017) Datasheet Overview

Logiciel

  • Arduino IDE pour coder sur l'arduino
  • Raspbian pour héberger le serveur de centralisation
  • Solidworks pour modéliser et fabriquer nos modules

Table de suivi

Date de la séance Travaux réalisés
03/01/2017 Recherche du sujet, définition du cahier des charges
05/01/2017 Définition des objectifs, allumer une LED RGB sur arduino, détecter un mouvement
10/01/2017 Raspberry configuré, installation serveur apache, communication Zigbee
12/01/2017 Code HTML et PHP, amélioration communication Zigbee (Trame au lieu de caractères)
13/01/2017 Affichage 7 Segments, programme complet Arduino, début programme Raspberry
20/01/2017 Fin du programme Raspberry, test de fonctionnement, présentation orale

Avancement du projet

Travaux Avancement Commentaires
Prise en main Arduino : Allumer une LED RGB Terminé Être capable d'allumer la LED de la couleur que l'on souhaite
Détecter une personne via Arduino Terminé Être capable d'allumer la LED de différentes couleurs en fonction du capteur de présence
Afficher un numéro sur un 7-segment Terminé Être capable d'afficher des numéros sur un afficheur
Récupérer la valeur d'un micro Non débuté Être capable de récupérer la valeur du micro sur Arduino et moyenner le bruit
Configurer Raspbian sur Raspberry Pi Terminé Configurer interface ethernet et SSH
Communication sans-fil entre Arduino et Raspberry Pi Terminé Établir un programme capable de communiquer des valeurs entre les deux périphériques
Mise en place d'un serveur web sur Raspberry Pi Terminé Créer un serveur web accessible via l'adresse de la Raspberry Pi
Création d'une page php/html Terminé Créer une page web capable d'afficher toutes les valeurs sur le site internet
Programme principal sur Arduino Terminé Envoie les valeurs des capteurs, action sur les actionneurs
Programme principal sur Raspberry Pi Terminé Code récupérant les valeurs de l'Arduino
Support Capteurs/LEDs + Support Arduino Non débuté Concevoir des supports pour fixer les capteurs et l'Arduino sous une table

Détail des travaux réalisés

Allumer une LED RGB sur Arduino

Pour réaliser cette partie, nous avons utiliser un SparkFun RedBoard qui se compose un arduino UNO et une board. Ensuite nous avons programmé l'arduino avec le code montré.

const int RED_PIN = 9;
const int GREEN_PIN = 10;
const int BLUE_PIN = 11;

void setup() {     
  // Initialise le Pin comme une sortie | Initialize the digital pin as an output with pinMode()
  pinMode(RED_PIN, OUTPUT); 
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT); 
}

void loop() {
  digitalWrite(RED_PIN, HIGH);
  delay(500);
  digitalWrite(RED_PIN, LOW);
  digitalWrite(GREEN_PIN, HIGH);
  delay(500);
  digitalWrite(GREEN_PIN, LOW);
  digitalWrite(BLUE_PIN, HIGH);
  delay(500);
  digitalWrite(BLUE_PIN,LOW);
}

Ce code nous a permit de visualiser que tous les 500ms la LED change sa couleur.

Détecter une personne via Arduino

Pour aller un peu plus loin, nous avons aussi programmé le capteur PIR. L'idée est d'allumer la LED Rouge quand PIR détecte un mouvement et d'allumer la LED Vert quand il y a rien. Voici le code

//Constantes
const int RED_PIN = 9;
const int GREEN_PIN = 10;
const int CAPTOR_PIN = 2;
int val=0; 

void setup() {     
  // Initialise le Pin comme une sortie | Initialize the digital pin as an output with pinMode()
  pinMode(RED_PIN, OUTPUT); 
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(CAPTOR_PIN,INPUT);
}

void loop() {
 val = digitalRead(CAPTOR_PIN);  // read input value
 if (val == HIGH) {            // check if the input is HIGH
    digitalWrite(RED_PIN, HIGH);  // turn red LED ON
    digitalWrite(GREEN_PIN, LOW); // turn green LED off
 }else  {
    digitalWrite(GREEN_PIN, HIGH); // turn green on
    digitalWrite(RED_PIN, LOW);
  }
}

Nous avons bien observé que la LED a changé sa couleur quand il y avait un mouvement devant le capteur.

Détection d'un objet
Il n'y pas d'objet

Communication sans-fil entre Arduino et Raspberry Pi

Au niveau de cette partie nous avions besoin de deux XBee, un arduino et un FTDI. Dans un premier pas, nous avions programmer les deux XBee pour qu'ils puissent communiquer dans le même canal.

/** Constantes **/

#define SERIALDEV	"/dev/ttyUSB0"
#define BAUDRATE	B9600 

/**** Variables globales *****/

static struct termios sauvegarde;

/** Ouverture d'un port serie **/

int ouvertureSerie(char *periph,int vitesse)
{
struct termios nouveau;
int df=open(periph,O_RDWR|O_NOCTTY);
if(df<0) return -1;

tcgetattr(df,&sauvegarde); /* save current port settings */
bzero(&nouveau,sizeof(nouveau));
nouveau.c_cflag=CLOCAL|CREAD|vitesse|CS8;
nouveau.c_iflag=0;
nouveau.c_oflag=0;
nouveau.c_lflag=0;
nouveau.c_cc[VTIME]=0;
nouveau.c_cc[VMIN]=1;
tcflush(df, TCIFLUSH);
tcsetattr(df,TCSANOW,&nouveau);

return df;
}

/** Fermeture d'un port serie **/

void fermetureSerie(int df)
{
tcsetattr(df,TCSANOW,&sauvegarde);
close(df);
}

/** Programme principal **/

int main(int argc, char *argv[])
{
int ds;
ds=ouvertureSerie(SERIALDEV,BAUDRATE);
if(ds<0){
  fprintf(stderr,"Erreur sur la connexion série.\n");
  exit(-1);
  }

fprintf(stdout,"Configuration actuelle :\n");
fprintf(stdout,"----------------------\n");
xbeeModeCommande(ds);
xbeeRecupereVitesse(ds);
xbeeRecupereCanal(ds);

fprintf(stdout,"\nConfiguration par défaut :\n");
fprintf(stdout,"------------------------\n");
xbeeDefaut(ds);
xbeeRecupereVitesse(ds);
xbeeRecupereCanal(ds);

fprintf(stdout,"\nConfiguration spécifique :\n");
fprintf(stdout,"------------------------\n");
xbeeConfigureVitesse(ds,XBEE_VITESSE_9600);
xbeeConfigureCanal(ds,0x0B);
xbeeRecupereVitesse(ds);
xbeeRecupereCanal(ds);
xbeeSauver(ds);
xbeeSortir(ds);

fermetureSerie(ds);
return EXIT_SUCCESS;
}

Ensuite nous avons mit l'un de deux XBee sur la carte Arduino Shield et afin de pouvoir permettre ce XBee de recevoir des données transmis par FTDI via SPI nous avons collé les deux cartes arduino. nathan est ce que tu peux mettre ta partie de raspberry pi sur wiki?

Spi.jpg

Après nous pourrions voir que les deux XBee communiquent bien, un envoie des données en même temps l'autre reçoit des paquets en clignotant les LEDS.

Co.jpg

Sur le console, avec le minicom -os nous arrivions à visualiser que les données envoyées par l'émetteur sont bien reçues.

Co.png

Après nous avons essayé de détecter la présence d'un mouvement et d'envoyer ce signal à XBee. Pour réaliser cela nous avons écrit un petit programme.

void loop() {
 val = digitalRead(CAPTOR_PIN);  // read input value
 if (val == HIGH) {            // check if the input is HIGH
    digitalWrite(RED_PIN, HIGH);  // turn red LED ON
    digitalWrite(GREEN_PIN, LOW); // turn green LED off
    data = 'P';
    Serial.write(data); 
 }else  {
    digitalWrite(GREEN_PIN, HIGH); // turn green on
    digitalWrite(RED_PIN, LOW);
    data = 'N';
    Serial.write(data);
  }
  delay(100);
}

Quand il y a une présence, la LED devient rouge et sur le console nous recevons un P. Si c'est inverse, la LED est en vert et nous recevons un N. Voila le console et les photos de communication.

Dete.png

Pour encore aller plus loin, pendant cette séance nous avons essayé d'envoyer des paquets par un XBee(émetteur) avec une adresse spécifique à un autre XBee(récepteur) avec une adresse fixée. Finalement, ce que nous devrons réaliser est d'établir des connexions entre un récepteur et plusieurs émetteurs dans le même réseau. Et ce récepteur est censé de savoir l'adresse de l'émetteur ainsi que des données envoyées.

Say.png

Nous avons téléchargé un logiciel XTCU qui permet de configurer des paramètres basiques d'un XBee.

Cananl.png

D'un coté du récepteur XBee, nous pouvons lire des informations qu'il reçoit.

Xbee.png

Dans le message, nous pouvons lire le numéro de table et le nombre de capteur qui détecte. Nous avons programmé Arduino avec un capteur et un afficheur. L'objectif de cette séance est de réussir détecter la présence d'une personne et même temps l'afficheur peut montrer les places restantes. Nous avons d'abord commencé par un seul capteur. Voici quelques lignes de codes qui permettent cette réalisation.

void loop()
{  
if (counter > 0)
  {
  int aoccupe=occupe;
  val1 = digitalRead(CAPTOR_PIN_1);  // read input value
  val2 = digitalRead(CAPTOR_PIN_2);
  if ((val1 == HIGH) || (val2 == HIGH))
   {         
     digitalWrite(RED_PIN, HIGH);  // turn red LED ON
     digitalWrite(GREEN_PIN, LOW); // turn green LED off
     payload[1] = (payload[0] || 0b00000001);
     occupe = 1;
   } 
  else
   {
     digitalWrite(GREEN_PIN, HIGH);
     digitalWrite(RED_PIN, LOW);
     payload[1] = (payload[0] & 0b11111110);
     occupe = 0;
   }
  if (aoccupe = occupe)
    {
      if ((val1 && val2) == 1)
      {
        sprintf(tempString, "%4d", counter--);
        s7sSendStringSPI(tempString);
      }
      else
      {
        sprintf(tempString, "%4d", counter);
      s7sSendStringSPI(tempString);
      } 
    }
  else
   {
    sprintf(tempString, "%4d", 4);void loop()
{  
if (counter > 0)
  {
  int aoccupe=occupe;
  val1 = digitalRead(CAPTOR_PIN_1);  // read input value
  val2 = digitalRead(CAPTOR_PIN_2);
  if ((val1 == HIGH) || (val2 == HIGH))
   {         
     digitalWrite(RED_PIN, HIGH);  // turn red LED ON
     digitalWrite(GREEN_PIN, LOW); // turn green LED off
     payload[1] = (payload[0] || 0b00000001);
     occupe = 1;
   } 
  else
   {
     digitalWrite(GREEN_PIN, HIGH);
     digitalWrite(RED_PIN, LOW);
     payload[1] = (payload[0] & 0b11111110);
     occupe = 0;
   }
  if (aoccupe = occupe)
    {
      if ((val1 && val2) == 1)
      {
        sprintf(tempString, "%4d", counter--);
        s7sSendStringSPI(tempString);
      }
      else
      {
        sprintf(tempString, "%4d", counter);
      s7sSendStringSPI(tempString);
      } 
    }
  else
   {
    sprintf(tempString, "%4d", 4);
    s7sSendStringSPI(tempString);
   }
  xbee.send(tx); 
  delay(1000);
  }
  counter--;
}    s7sSendStringSPI(tempString);
   }
  xbee.send(tx); 
  delay(1000);
  }
  counter--;
}

Donce nous avons observé que quand la LED était en mode vert ( pas de présence ), l'afficheur a donné un chiffre 4 c'est à dire qu'il y a 4 places libres. Quand il y a une présence devant le capteur, la LED est devenue rouge et l'afficheur a changé le chiffre en 3.

4 places libres
3 places libres

Mise en place du serveur sur Raspberry Pi

Dans un premier temps, il a fallu configurer l'adresse IP de la Raspberry Pi afin d'y accéder par SSH.

Pour cela, on accède à la Raspberry Pi via connexion TTL (Série) à l'aide de Minicom.

La Raspberry Pi 3 possède deux UART : un UART pour le bluetooth et un mini UART pour la communication série.

De ce fait, il y a des problèmes pour accéder à la Raspberry Pi via Série du premier coup.


Nous avons eu besoin de modifier le fichier config de la Raspberry Pi pour réussir à avoir une communication série fonctionnelle.

Ajouter dans le fichier /boot/config.txt de la carte SD de la Raspberry :

core_freq=250
enable_uart=1


Nous pouvons ensuite accéder à la Raspberry via TTL.

Il faut maintenant configurer les paramètres réseaux de la Raspberry.

Pour cela, on commence par mettre ajouter l'adresse du serveur DNS de l'école pour résoudre les noms de domaines.

Ajouter dans le fichier /etc/resolv.conf :

nameserver 193.48.57.0


Ensuite on configure l'interface ethernet :

Dans le fichier /etc/network/interfaces :

auto eth0
iface eth0 inet static
  address 172.26.78.120
  netmask 255.255.240.0
  gateway 172.26.79.254


Et enfin on télécharge et installe le serveur apache avec interpréteur php :

apt-get install apache2 php5-common libapache2-mod-php5 php5-cli

Récupération des données et affichage sur le site

On récupère les valeurs de l'Arduino sur la Raspberry via un programme en Python et on écrit les valeurs dans un fichier :

//main.py
import XBee
from time import sleep

if __name__ == "__main__":
    xbee = XBee.XBee("/dev/ttyUSB0")  # Your serial port name her


while True:
    Msg = xbee.Receive()
    if Msg:
        content = Msg[7:-1]
        print("Msg: " + xbee.format(content))
        table_id = Msg[7:-3]
        print("Table ID: " + xbee.format(table_id))
        capteurs_values = Msg[8:-2]
        print("Capteurs: " + xbee.format(capteurs_values))
        data_file = open("/var/www/data/values.data","w")
        data_file.write("table:" + xbee.format(table_id)+"\n")
	data_file.write("pos:"+ xbee.format(table_id)+":" + xbee.format(capteurs_values)+"\n")        
        data_file.close()


Enfin, notre code PHP lit les valeurs de ce fichier et les affichent sur la page internet (/var/www/html/index.php) :

<html>

	<!--link rel="icon" type="image/png" href="images/Deadpool_ico.png" />
	<meta charset="utf-8" http-equiv="Refresh" content="2" url="172.26.78.120/index.php">
	<!--[if IE]><link rel="shortcut icon" type="image/x-icon" href="images/Deadpool_ico.png" /><![endif]-->

  <head>
    <title>Posto Libero</title>
  </head>
  <body bgcolor=#CEECF5>

	<center>

          <img src="images/table.png" height="25%" width="25%">

          <h1><FONT color="#0B0B61">Mappage des tables connectées</FONT></h1>


        <p><FONT color="#0B0B61">Par Cong CHEN, Michele NUZZOLESE et Nathan RICHEZ</FONT></p>
	<p><FONT color="#0B0B61">Lien vers <a href="http://projets-ima.plil.net/mediawiki/index.php?title=Posto_Libero_%28Table_connect%C3%A9e%29">notre Wiki</a></FONT></p>
	</center>

	<?php
        error_reporting(E_ALL);
        ini_set('display_errors', 1);
	$lines = file('/var/www/data/config.cfg');
	foreach ($lines as $lineNumber => $lineContent)
	{
		if( substr($lineContent,0,12) == 'table_count=' )
		{ 
			$table_count = (int)substr($lineContent,12);
			echo "Tables paramétrées : $table_count<br/><br/>";
		}
	}
        ?>

	<?php
	error_reporting(E_ALL);
	ini_set('display_errors',1);
	$lines = file ('/var/www/data/values.data');
	foreach ($lines as $lineNumber => $lineContent)
	{
		if( substr($lineContent,0,6) == 'table:')
		{
			$table_id = (int)substr($lineContent,6);
			$table_name = substr($lineContent,9);
			echo "Table ID : $table_id ($table_name)<br/>";
		}
		if( substr($lineContent,0,4) == 'pos:')
		{
			$table_id_2 = (int)substr($lineContent,4,6);
			$capteurs_values = substr($lineContent,7,8);
			echo "Capteurs de la table $table_id_2 : $capteurs_values<br/>";
		}
	}
	?>
  </body>
</html>


Pour terminer, on rajoute une ligne dans /etc/rc.local pour démarrer automatiquement notre script python :

python /home/pi/Documents/Posto_Libero/Python/main.py
Affichage des valeurs sur le site, personne non détectée
Affichage des valeurs sur le site, personne détectée

Conclusion

Nous avons ici un premier prototype fonctionnel.

Par la suite, il faudrait essayer avec 4 capteurs et 4 LEDs sur l'Arduino afin d'avoir un deuxième prototype plus complet.

Ensuite, modéliser et produire des supports pour les capteurs avec LEDs ainsi qu'un support pour fixer l'Arduino en dessous de la table.

Pour terminer, il faudrait faire une deuxième table connectée afin d'avoir un cas plus réaliste.

Livrables

Fichier:A3-poster-posto-libero.pdf