Smart Sensor WiFi

De Wiki de Projets IMA
Révision datée du 12 avril 2014 à 08:37 par Tmaurice (discussion | contributions) (Point sur la partie capteur à la mi mars)

Informations générales

Page de wiki du projet Smart Sensor WiFi

Étudiants Thomas Maurice et Benoit Maliar

Tuteurs Alexandre Boé et Thomas Vantroys

Les fichiers sources du projet sont disponibles via Git.

Liste du matériel nécessaire

Liste non exhaustive, pourra être modifiée !

Désignation Quantité Référence Prix Disponible en salle de projet
Shield WiFi TEL 0047 1 GoTronic 83€ Nope nope nope Alexandre : il doit y avoir un équivalent, voir Thomas T.M: Yep mais c'est celui là qu'il faut
Module WiFi WizFi210 1 Lextronic 30€ Nope
Quartz 32.768kHz 2 Lextronic 1.15€ Nope
Capteur de présence infrarouge 1 Lextronic 7.92€ Nope
Photorésistance ~2-3 - quelques € Nope - je verrai au magasin de l'école
ATMega328p 1 pour le proto Magasin de l'école quelques € Nope - je verrai au magasin de l'école
Cristal 16MHz 1 pour le proto Lextronic 1.40€ Nope
Capa 22pF pour le quartz 2 Magasin de l'école quelques € Nope - je verrai au magasin de l'école
Des résistances  ? Magasin de l'école quelques m€ Yep

Énoncé initial du projet

L'objectif du projet consiste en la conception et la réalisation de capteurs autonomes communiquant en WiFi afin de pouvoir remonter régulièrement des informations sur l'état des salles de cours. Les capteurs seront par exemple des détecteurs de lumières, de pression, de qualité de l'air, ...

La communication sera obligatoirement réalisée en WiFi sur le réseau de l'université en respectant les contraintes de sécurité (WPA2, ...).

Deux options sont possibles :

  • Refaire complètement une carte avec un microcontroleur et une puce wifi (comme par exemple les spark)
  • Réaliser un shield pour raspberry pi contenant les différents capteurs.

Analyse du sujet

On a ici affaire à un réseau de capteurs reliés à une base de donnée centrale accessible depuis un navigateur Internet qui est chargée de recevoir les données des différents capteurs de manière à pouvoir présenter à un utilisateur un état des différentes pièces dans lesquelles on aura disposé les capteurs. Cela peut notamment impliquer :

  • Un accès à ces données via une interface web
  • Un accès à ces données via une application mobile

On identifie donc deux parties au projet :

  • La partie capteur
  • La partie serveur

Cahier des charges

Spécifications des capteurs

Les caractéristiques souhaitées pour les capteurs sont :

  • Être capable de mesurer l'environnement dans lequel évolue le capteur (Pression, température, lumière, présence, ouverture de porte...)
  • Contacter le serveur via le WiFi pour actualiser la base. Alexandre : ce qui implique la prise en compte de la sécurité type WPA2
  • Éventuellement, être reconfigurable à distance (via un serveur web embarqué dans le microcontrôleur)
  • Être capable de gérer sa consommation d'énergie.
  • Agir en temps que datalogger si le réseau n'est pas accessible.

Spécifications du serveur

Les caractéristiques souhaitées pour le serveur sont :

  • Être capable de contacter ou d'être contacté par les capteurs via le réseau.
  • Respecter les contraintes de sécurité (WPA2)
  • Être capable d'authentifier les clients
  • Stocker les données reçues dans une base de données et éventuellement faire des calculs et des statistiques sur ces données.
  • Présenter sous format compréhensibles les données au client (web ou appli)
  • Vérifier l'état des capteurs et notifier un responsable en cas d'anomalie (déconnexion du réseau, valeur anormale d'un capteur...)

Propositions de solutions technologiques

Les capteurs

Nous proposons de réaliser une carte basée sur un ATmega328 dans lequel on pourra flasher du code Arduino. Pour gérer le WiFi, nous proposons une solution utilisant le shield TEL 0047 de Wiznet utilisant la puce WiFi WizFi210.

Cette puce gère le WPA2-PEAP mais malheureusement pas dans son firmware natif. Il va donc falloir s'arranger avec Wiznet pour obtenir le firmware qui nous permettra de faire de l'EAP.

Dans un premier temps, on se concentrera sur la mise en place d'un prototype fonctionnel a base d'un simple capteur de température. On étendra ensuite les capacités de la chose à des capteurs peut être plus complexes style I2C ou SPI.

Pour la reconfiguration du capteur, on le fera via un serveur web embarqué dans le microcontrôleur.

Le serveur

On propose une solution à base d'une machine sous Linux hébergeant un serveur MySQL et PHP.

Le SGBD utilisé sera MySQL.

La partie web du serveur destinée à présenter à l'utilisateur une vue des données serait développée en PHP/HTML5/CSS3. Les capteurs enverront les données sous forme JSON au serveur web qui se chargera du traitement.

Travail à effectuer dans un premier temps

Pour la partie BDD/Web

  • Structurer les tables dans un diagramme UML qui va bien
  • Déterminer une architecture de site (MVC)
  • Traiter les données envoyées par les capteurs au format JSON
  • Incorporer une interface admin
  • Faire un design swag

Pour les capteurs

Avant la réception du matos WiFi:

  • Réaliser la lecture d'une température et la formater en JSON Quasiment fait, on peut lire sur les ADC, le formattage n'est qu'une formalité
  • L'envoyer sur un port série à interval régulier Pareil mes routines d'envoi de strings sont écrites
  • Parser et répondre à des requêtes HTTP sur le port série Fait, mais en série, pas encore adapté au wifi
  • Faire fonctionner une RTC pour agir en tant que datalogger En cours mais il manque l'interface avec la carte SD

Après réception du matos WiFi:

  • Envoyer les requêtes JSON directement en POST au serveur Web
  • Traiter les requêtes client
  • Adapter une nouvelle carte avec juste la puce WiFi

Partie capteurs

Principe

Le principe est de réaliser des capteurs qui s'interfaceront avec l'application web de Benoit. Pour celà deux solutions ont été explorées durant le projet

  • Une solution a base d'Arduino
  • Une solution à base de RaspberryPi

Finalement la solution la plus avancée a été celle à base d'Arduino. Notons que je ne me suis pas penchés sur tout ce qui est considération d'intégration et de contraintes énérgétiques. Le but premier que je me sommes fixé était de fournir un prototype qui marche et qui peut facilement être alélioré par quiconque en aurait envie.

Organisation pratique et documentation

Tout le travail que nous avons fourni est disponible dans le dépôt git que nous avons mis en place dès les premières semaines du projet et dont le lien est le suivant : celui là, là. Pour effectuer un clone :

   git clone git://svartbergtroll.fr/smartsensor.git

La documentation a été un travail très important pour moi dans la mesure ou TOUT le code de la partie Arduino du projet a été richement documentée via Doxygen. Ainsi il est très facile de comprendre comment le capteur interragit avec ses ADC/ports série/spi ou autre simplement en lisant la doc mise à disposition.

Les documentations suivantes sont disponibles :

Point sur la partie capteurs au 28 février 2014

Shield Arduino avec la RTC et photo-résistance

Ce qui a été fait

  • L'appareil peut lire l'ADC câblé sur une photodiode et un capteur de température et convertir ça en chaine pour l'envoyer.
  • Stocker des infos de config en EEPROM et y accéder sur demande.
  • Il peut envoyer des choses au monde extérieur sur le port série et en lire.
  • Il gère quasiment parfaitement l'horloge temps réelle DS1302 (aux burst-modes près, mais c'est pas indispensable pour le moment).
  • L'intégralité du code est documenté, fonction par fonction et une doc au format Doxygen est générable.
  • Le PCB est en cours de création sous Eagle.

Ce qui ne sera pas fait

  • L'interface avec une carte SD, puisque on a opté pour une mémoire Flash.

Ce qui est en train d'être repensé mais qui doit être discuté avec les enseignants

  • Implanter un serveur Web dans l'atmega328p. Je doute que ça soit pertinent d'un point de vue énergétique, dans la mesure ou l'appareil devra être up H24 si on veut faire ça. Je pense qu'il est plus malin d'enregister les changements de config à faire dans la BDD et de les comitter au senseur dans la page de réponse qui suivra sa mise à jour des données de température/lumière. L'avantage est double, on a des écolomies d'énergies, et un cout de traitement moindre dans la mesure ou on peut déterminer le format de la chaine de màj et de le faire simple, au lieu de parser l'intégralité d'une requête HTTP.
  • Je pense qu'il est intéressant d'implanter un mode de "config initiale" par le port série pour qu'on puisse mettre manuellement les infos du capteur avant le permier déploiement (de toutes façons il faut bien entrer une conf initiale) quitte à le vérouiller logiciellement (via un bit en EEPROM par exemple) lorsqu'on en a fini avec lui. De cette manière il ne sera plus reprogrammable que par le serveur de BDD ou par un re-flashage de l'EEPROM.

Point sur la partie capteur à la mi mars

Schematic Réalisé pour la Raspberry Pi
PCB Réalisé pour la Raspberry Pi

Développement d'une solution alternative à base de RaspberryPi

Comme la carte WizFi tardait à arriver, j'ai pensé opter pour une solution alternative pour réaliser le capteur, à base d'une RaspberryPi. Certes la solution était un peu overkill pour ce que l'on voulait en faire, mais comme cela on aurait eu quelque chose de fonctionnel à montrer lors de la soutenance. L'idée était d'utiliser les GPIO de la Raspberry pour l'interfacer avec le monde exterieur.

Malheureusement la RaspberryPi est un appareil qui ne dispose pas d'entrées analogique, ce qui est assez peu pratique pour lire une température ou une luminosité de la même manière que sur un ATmega. Nous avons donc du recourir à un ADC externe fonctionnant suivant le protocole SPI, ce qui tombait plutôt bien puisque la Raspberry est équipée d'une inetrface SPI lui permettant de contrôler jusqu'à deux esclaves. Pour notre problème nous avons opté pour l'ADC MCP3208 de MicroChip. Pourquoi celui là ? Tout simplement parce qu'il dispose de huit canaux analogiques ce qui permet une grande variété de capteurs, mais également parce qu'il peut fonctionner en 3v3, tension à laquelle fonctionne également la Raspberry, comme ça on évite de la griller.

J'ai donc réalisé une carte et un PCB pour réaliser cette alternative, mais également la couche logicielle qui va avec. J'ai en effet développé une classe en C++ qui encapsule tout les appels systèmes permettant d'écrire et de lire sur le port SPI de la raspberry, en full duplex. J'ai en réalité réalisé deux classes, une classe SPI qui est la classe mère, comprenant seulement les routines d'initialisation et d'écriture du port SPI, et une SPI_MCP3208 qui comprend les commandes spécifiées dans la datasheet du composant.

Pour info, cette classe et le programme d'exemple sont disponibles sur GitHub et la documentation est disponible

Le problème parce qu'évidemment il y en a eu un, était que les données renvoyées par l'ADC étaient totalement hors sujet. Le fait est qu'à luminosité égale, si je lançais 10 acquisitions je pouvais obtenir des écarts de plus de 3000 (sur 4095 d'amplitude) entre deux valeurs, quand bien même la luminosité ne variait pas. Le plus déroutant dans tout ça c'est que le problème n'avait pas l'air de venir de mon logiciel, dans la mesure ou j'étais parfaitement capable, avec la même couche logicielle, de piloter d'autre appareils SPI fonctionnant en esclave (comme un afficheur 4x7 segments de chez SparkFun par exemple). La seconde chose la plus dérourante était que les données étaient cohérentes du point de vue du fonctionnement du composant tel que décris dans la datasheet. Je m'explique, une trame classique de communication avec l'ADC se compose comme il suit (schématiquement) :

   4 bits de commande | deux bits de sample | 12 bits de résultat MSB first

Le fait est que d'après la datasheet en continuant à envoyer des coups d'horloge au composant après le dernier bit de donnée, le composant va nous renvoyer le resultat de la conversion mais LSB first. On récupère donc le symétrique des données par rapport au LSB. Après avoir analysé plusieurs séquences j'ai pu constater que l'erreur ne venait pas de comment je récupérais mes données puisqu'elles étaient correctes du point de vue de la datasheet mais totalement abérantes d'un point de vue physique.

L'erreur ne venait pas non plus du hardware puisqu'un rapide coup d'oeuil à l'oscilloscope m'a permis de constater que ma tension sur la patte de l'ADC évoluait bien comme elle le devait. Le mystère est resté entier puisqu'après nous avons reçus la carte WizFi et nous avons pu commencer à travailler dessus, cette solution a donc été abandonnée. Cela dit, j'avais déjà commencé à réfléchir aux technologies aue j'aurais pu mettre en place pour réaliser la solution, qui auraient été :

  • Un programme de lecture des données appelé par cron à intervalle régulier (un bête script bash qui lit le port SPI et conditionne les données en POST par exemple pour les envoyer au site de Benoît)
  • Une application Web similaire à celle de Benoît mais ne concernant que les données locales de l'appareil, qui aurait permis de modifier les paramètres de mises à jour/sécurité tout simplement depuis un navigateur. J'avais penser à la réaliser en Python avec CherryPy un excellent framework python très léger, et évidemment [http:/int.sapo.pt Ink] pour le design.

Partie Arduino

La partie Arduino n'a pas beaucoup évolué entre temps, dans la mesure ou le gros du travail avait déjà été fait en amont. Le driver de la RTC a cependant été enrichi de quelques fonctions supplémentaires de manière à pouvoir lire/écrire l'heure plus facilement dans la puce.

Un choix important a également été fait, il a été choisi d'abandonner l'envoi des données en JSON à l'appli web de benoit au profit de données POST, bien plus faciles à envoyer et à mettre en forme.

Partie Web/BDD

Langages et méthodes utilisées

  • HTML 5, CSS3, PHP 5, Javascript
  • PDO (interface d'accès aux bases de données) [1]
  • INK (CSS framework)
  • Chart.js (script javascript de création de graphique)

Point sur la partie BDD/Web au 28 février 2014

  • Prise en main d'INK (framework css : [2] ). Justification d'utilisation :
    • Design visuellement beau (subjectif)
    • Simple d'utilisation une fois assimilé
  • La base de données est constituée de 2 tables : une pour gérer les utilisateurs qui se connecteront à la plateforme de monitoring et l'autre pour stocker les données des capteurs.
  • Le site se compose à cette date de 2 onglets : l'un est l'index où l'on peut voir les dernières mises à jour des capteurs et l'autre permet de chercher un capteur en particulier et d'en afficher les informations.

Point sur la partie BDD/Web mi-mars

  • La base de données contient désormais 3 tables :
    • L'une contient toujours les utilisateurs de la plateforme
    • La seconde contient désormais la liste des capteurs déclarés
    • La dernières contient les données des capteurs.
  • Le site a été amélioré :
    • Au niveau de la recherche, on affiche toujours les informations du capteur sélectionné mais on projette d'implanter un graphique des données (Utilisation de Chart.js)
    • On peut désormais déclarer et supprimer un capteur de la base. Seul les capteurs déclarés peuvent stocker leurs données dans la BDD.
    • Panel d'administration : Ajout et suppression d'utilisateur de la plateforme. Vidage de la table des données possible.
  • Modification des mises à jour dans la base de données : précédemment, on récupérait les données envoyées par l'Arduino sous format JSON. On a décidé finalement d'envoyer les données en POST (simple optimisation mémoire de l'arduino, le JSON prenait un tout petit peu plus de place)

Point sur la partie BDD/Web début avril

  • La base de données n'a pas changé depuis la dernière fois.
  • La plateforme Web a été améliorée :
    • Deux graphiques ont été incorporés suite à la recherche d'information sur un capteur. On peut désormais voir l'évolution des 10 dernières mesures de température et de luminosité du capteur sélectionné.
    • La partie d'administration permet désormais d'obtenir un suivi des mises à jour des capteurs. On y voit désormais un résumé des capteurs (ratio et liste) n'ayant pas communiqué leurs informations à H+1 (ou plus).

Requêtes sur la base

  • Requêtes de création :
    • Table 'captors' :
 CREATE TABLE IF NOT EXISTS `captors` (
   `id` int(255) NOT NULL,
   `temp` float NOT NULL,
   `lum` int(255) NOT NULL,
   `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
    • Table 'data' :
 CREATE TABLE IF NOT EXISTS `data` (
   `id` int(255) NOT NULL auto_increment,
   `password` text character set utf8 NOT NULL,
   `name` varchar(255) character set utf8 NOT NULL,
   `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
   PRIMARY KEY  (`id`)
 ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=0;
    • Table 'users' :
 CREATE TABLE IF NOT EXISTS `users` (
   `login` varchar(255) character set utf8 NOT NULL,
   `password` varchar(255) character set utf8 NOT NULL,
   UNIQUE KEY `name` (`login`)
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
  • Requêtes d'insertion (préparées avec PDO)

Exemple

  INSERT INTO captors(temp,lum,timestamp,id) VALUES(?,?,?,?)

Les '?' sont à remplacer par les variables PHP contenant les valeurs à mettre à jour

  • Requêtes d'update (préparées avec PDO)

Exemple

 UPDATE data SET timestamp=? WHERE id=?
  • Requêtes de suppression (préparées avec PDO)

Exemple

 DELETE  captors FROM captors WHERE timestamp  <  ?


Visuel de la plateforme