Projet IMA3 P5, 2015/2016, TD1
Sommaire
Projet IMA3-SC 2015/2016 : Sonde Thermique
Cahier des charges
L'objectif de notre projet SC est de réaliser un objet connecté qui permettra de relever la température dans un lieu donné. Une LED s'allumera en fonction de la température et de l'encadrement saisi par l'utilisateur sur l'application. Un affichage tricolore sera utilisé pour indiquer l'état thermique actuel selon le code couleur : ROUGE pour un dépassement de la plus grande des valeurs saisies, VERT pour une température respectant l'encadrement et BLEU sinon.
L'interface WEB permettra à l'utilisateur de saisir les valeurs supérieure et inférieure de température avant le déploiement de l'objet, puis affichera celles-ci ainsi que la température mesurée.
Le matériel
- la nanoBoard FPGA
- la RaspBerry PI
- une Arduino
- 3 LEDs de couleur unique (Rouge, Vert et Bleu) ou une LED RGB
- un capteur de température
- PCs et logiciels nécessaires au développement du projet
Optionnel
Ajouter des afficheurs sept segments pour que la valeur exacte de la température apparaisse sur l'objet connecté.
Séance 1
Partie électronique
Schéma électronique
Nous avons du concevoir le circuit reliant nos LEDs, notre capteur et le FPGA/arduino.
Conversion Analogique-Numérique
Dans le circuit électronique, nous allons utiliser un capteur de température de type analogique. Ce capteur sera connecté à la carte arduino dans un premier temps puis à une carte FPGA dans un second temps. L'arduino possède des ports capables de recevoir des données analogiques et effectue donc la conversion automatiquement, mais pas la FPGA. On aura donc besoin de rajouter un convertisseur analogique-numérique (CAN ou ADC en anglais).
Deux possibilités se sont présentées à nous :
- Réaliser le convertisseur sur la carte FPGA. Il faudrait pour cela utiliser un comparateur auquel on envoie deux tensions : une tension analogique de référence, la sortie du capteur, et une autre que l'on augmente petit à petit à l'aide d'un compteur. Lorsque celle-ci atteint la tension de référence, la conversion s'arrête et la valeur du compteur est l'équivalent numérique de la tension de référence.
- Connecter la sortie du capteur à un composant conçu pour réaliser la conversion et récupérer sa sortie numérique.
Nous avons fait le choix d'utiliser un composant, que nous avons commandé auprès du magasin électronique de Polytech'Lille. Le ADC0820BCNA+ correspondait à ce que nous recherchions.
Nous avons également récupéré sa datasheet qui nous permettra de déterminer comment le connecter au circuit.
En étudiant celle-ci, nous avons déduit le fonctionnement du composant :
Envoyer 0 à RD si on souhaite commencer la conversion. La conversion s'effectue. Lorsqu'elle est terminée, le composant envoie 0 sur INT. On peut lire les bits de sortie (DB0, ... DB7). On envoie 1 à RD lorsqu'on a terminé. Quand RD est mis à 1, INT aussi est mis à 1 automatiquement. On peut de nouveau effectuer une conversion.
On connectera donc le composant comme sur le schéma ci-dessous.
Partie informatique
Nous avons commencé par installer la bibliothèque Web 2.0 JQuery puis une bibliothèque C de Websocket sur le poste qui nous a été attribué en salle info. JQuery nous permettra de lancer des requêtes HTTP asynchrones et de faciliter la programmation JavaScript, tandis que Websocket servira à créer un serveur embarqué sur la Raspberry avec lequel nous communiquerons depuis la page web.
Simulation sur ARDUINO
- Dans un premier temps, un schéma général du fonctionnement de notre système a été réalisé sur le logiciel logisim. Nous considérons dans ce modèle que l'entrée (capteur de température) arrivait convertie en binaire. Nous avons ainsi simulé l'allumage des LEDs en fonction de la valeur d'entrée et des températures de seuil. Ici, nous avons imposé les valeurs de 5 et 20, soient 0x05 et 0x14 en hexadécimal. Voici un petit gif de la simulation :
Il est à noter que dans cette simulation, les résistances du montage ne sont pas représentées. Par la suite, n'ayant pas à notre disposition de LED de couleur BLEUE, nous utiliserons pour les montages une LED de couleur JAUNE en compensation.
- Dans un deuxième temps, le câblage a été réalisé sur l'arduino RedBoard. Cette fois-ci, les résistances ont été incluses ainsi que le capteur de température. Le capteur de température est connecté au pin analogique 0 : le pin central va sur A0. Les autres pins sont reliés à 5V et à la masse. La première LED1 est connectée au pin 9 et à la masse, la LED2 au pin 10 et à la masse et la LED3 au pin 11 et à la masse. Voici une photographie du montage :
Le code Arduino suivant a ensuite été réalisé :
const int analogInPin = A0; //capteur de température const int LED1 = 9; const int LED2 = 10; const int LED3 = 11; //On impose des valeurs de seuil pour réaliser les tests const int inferieur = 10; const int superieur = 60; int sensorValue = 0; //valeur lue par le capteur de température int outputValue = 0; //valeur de sortie (LED) void setup() { // initialisation pinMode(LED1,OUTPUT); pinMode(LED2,OUTPUT); pinMode(LED3,OUTPUT); } void loop() { // lecture de la valeur analogique sensorValue = analogRead(analogInPin); //restriction de l'intervalle outputValue = map(sensorValue,0, 1023, 0, 255); //ligne à rajouter afin de simuler une variation de la valeur convertie du capteur //outputValue = 80; if(outputValue < inferieur) { digitalWrite(LED1,HIGH); } if(outputValue > superieur) { digitalWrite(LED3,HIGH); } if((outputValue <= superieur) && (outputValue >= inferieur)) { digitalWrite(LED2,HIGH); } delay(100); }
La fonction map s'utilise de la manière suivante : map(valeur, limite_basse_source, limite_haute_source, limite_basse_destination, limite_haute_destination). Or ici, nous passons d'une valeur allant de 0 à 1023 à une valeur allant de 0 à 255.
Les LEDs s'allument bien en fonction des valeurs prises par le capteur de température.
Protocoles de communication
Nous nous sommes aussi intéressés aux protocoles de communication entre les différentes entités de notre projet (ordinateur et momentanément arduino). Nous avons donc réalisé le protocole de communication de l'arduino vers le PC et étudié la communication du PC vers l'arduino. C'est-à-dire la transmission plus que la réception. Pour cela nous avons dû définir les données à transmettre et leur sens.
L'arduino calcule elle-même la position de la température vis-à-vis des bornes que l'utilisateur donne, il suffit donc de renvoyer la température afin de l'afficher sur l'interface utilisateur.
Le PC doit lui envoyer l'encadrement de température désiré (Temp_min et Temp_Max) ainsi que la décision de faire fonctionner le système de détection (Depart_Arret).
Le code ARDUINO est simple mais peut être complété pour envoyer une information seulement lorsque le programme fonctionne ou que la température change :
void setup() { Serial.begin(9600) } void loop() { Serial.write(temp); // envoi de la température }
Séance 2
Partie électronique
Programmation de la FPGA nanoboard
- Dans un premier temps, nous avons créé un circuit sous altium avec des valeurs simulées pour la température ainsi que pour les valeurs de seuil. Nous avons pour cet essai allumé des LEDs déjà présentes sur la nanoboard. La LED0 faisant office de LED jaune, la LED1 de LED verte et la LED2 de LED Rouge. Le schéma logique suivant a ainsi été construit :
La simulation du circuit a montré les résultats attendus. Les LEDs correspondantes s'allument bien en fonction des valeurs entrées. Voici un gif de la simulation :
- Dans une deuxième temps, nous avons réalisé un montage et schéma logique (sous altium) en tenant compte de notre circuit physique avec les LEDs colorées, le capteur de température et le convertisseur CAN.
La valeur convertie du capteur de température est envoyée sur 8 bits, en numérique, aux pins 2 à 9. La LED bleue est connectée au pin 18. La LED verte est connectée au pin 19. La LED rouge est connectée au pin 15. RD du CAN est connectée au pin 16. INT du CAN est connectée au pin 14. Le câblage suivant a ainsi été réalisé :
Au niveau des bits de contrôle du CAN, il faut complexifier un peu le circuit logique sous altium. Déjà, le bit RD sera contrôlé par une Clock. Nous devons renvoyer la valeur 1 au bit RD du CAN une fois la conversion finie pour le réinitialiser, en attente d'une prochaine conversion. La Clock, à son deuxième top d'horloge, fait cette mise à 1.
De plus, quand INT = 0, cela signifie que la donnée analogique du capteur a bien été convertie en numérique. Dès que INT passe à 0, il faut donc autoriser la comparaison avec les valeurs seuils et allumer la LED correspondante. Pour cela, on a rajouté au schéma précédent, des multiplexeurs qui contrôlent l'allumage des LEDs. Si le bit de sélection du multiplexeur vaut 0, la valeur en sortie du comparateur est envoyé via YA sur la LED correspondante et l'allumera en conséquence. Si le bit de sélection du multiplexeur vaut 1, nous relions l'entrée du démultiplexeur à YB qui est relié à la masse. Dans ce cas, la LED restera dans son état précédent sans tenir compte de la dernière comparaison effectuée. Le schéma sous altium suivant a été réalisé :
Ce dernier schéma contient encore des erreurs que nous allons corriger lors de la prochaine séance. Les démultiplexeurs pourraient notamment être remplacés par des portes « OR », pour pallier à certaines sources d'erreurs.
Partie informatique
Communication Port Serie
Sur cette séance, nous avons terminé la programmation des protocoles de connexion entre le pc et la carte ARDUINO. Nous avons ainsi modifié le programme ".ino" principalement en rajoutant les méthodes de type Serial :
void setup() { // initialisation pinMode(LED1,OUTPUT); pinMode(LED2,OUTPUT); pinMode(LED3,OUTPUT); Serial.begin(9600); // début de la communication } void loop() { if(Serial.available()>0) // si il y'a une donnée en attente de lecture sur le bus { inferieur =Serial.read(); // on lit la première donnée en attente correspondant à la borne inférieure de température. superieur = Serial.read(); // on lit la seconde donnée en attente correspondant à la borne supérieure de température. } // lecture de la valeur analogique sensorValue = analogRead(analogInPin); digitalWrite(LED1,LOW); digitalWrite(LED2,LOW); digitalWrite(LED3,LOW); //restriction de l'intervalle outputValue = map(sensorValue,0, 1023, 0, 255); Serial.write(outputValue); // On met sur le bus de données la valeur de sortie du //capteur ne correspondant pas a la température mais a une valeur de tension //Serial.write(inferieur); //Serial.write(superieur); if(outputValue < inferieur) { digitalWrite(LED1,HIGH); digitalWrite(LED2,LOW); digitalWrite(LED3,LOW); } else if(outputValue > superieur) { digitalWrite(LED1,LOW); digitalWrite(LED2,LOW); digitalWrite(LED3,HIGH); } else if((outputValue <= superieur) && (outputValue >= inferieur)) { digitalWrite(LED1,LOW); digitalWrite(LED3,LOW); digitalWrite(LED2,HIGH); } delay(1000); }
Nous avons aussi forcé les LEDs à l'état haut ou bas selon les conditions réalisées ce qui rend le programme interactif avec de nouvelles données envoyées par l'ordinateur. Chaque fois que le PC enverra des données et une fois par seconde maximum la carte ARDUINO enregistre les données pour les bornes de température. Toutes les secondes l'arduino vérifie la température, la compare aux bornes et l'envoie au PC.
Pour la communication du point de vue PC, nous avons adapté le programme exemple selon nos besoins. La carte ARDUINO est en fonctionnement donc l'utilisateur peut exécuter le programme. Il rentre la borne inférieure puis la borne supérieure de l'encadrement de température. Alors le programme en C met l'encadrement sur le bus de données à destination de l'ARDUINO. Puis tant que l'on n’arrête ni le programme ni l'ARDUINO, le programme relève la donnée de température sur le bus et l'affiche.
int main(void){ unsigned char temp_min=0,temp_max=0,temp =0; int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH); serialConfig(sd,B9600); printf("Rentrez la température inferieure :"); scanf("%hhd", &temp_min); printf("Rentrez la température superieure :"); scanf("%hhd", &temp_max); //envoyer la température min if(write(sd,&temp_min,sizeof(char))!=1){ perror("main.write"); exit(-1); } //envoyer la température max if(write(sd,&temp_max,sizeof(char))!=1){ perror("main.write"); exit(-1); } // Lecture des données envoyées while(1) { if(read(sd,&temp,sizeof(char))!=1){ perror("main.read"); exit(-1); } printf("%d\n",temp); usleep(10000); // attendre } serialClose(sd); exit(0); }
Séance 3
Partie électronique
Nous avons commencé par rajouter le composant du port RS232 qui permettra d'envoyer et recevoir des données par liaison série. Nous avons également ajouté deux modules récupérés auprès des encadrants, un d'émission et un de réception. Une erreur liée à l'horloge de l'un de ces modules revient assez fréquemment, mais une fois tue n'empêche pas le fonctionnement normal du programme. Pour la transformer en avertissement et permettre la compilation, nous nous sommes servi du descriptif de l'erreur : il suffit d'ajouter manuellement une ligne de code (NET "RS_RX" CLOCK_DEDICATED_ROUTE = FALSE;) dans les fichiers .ucf du projet et de recompiler à partir de là où il y avait eu l'erreur. Malheureusement cette étape est à refaire à chaque nouvelle compilation du projet.
Sur le schéma ci-dessous, "horloger" est le nom que nous avons donné à notre horloge.
La valeur à transmettre par liaison série est directement prise en sortie de la mémoire qui la stockait après réception du capteur de température.
Nous nous sommes ensuite occupés de la réception. Les deux températures sont reçues l'une après l'autre avec une seconde de décalage et nous avons fait le choix de les stocker dans deux mémoires, une pour chaque valeur. Nous nous sommes servi d'un démultiplexeur qui prend en entrée le bus de réception et en sortie mène aux deux mémoires. Le choix de la mémoire est ensuite effectué par un compteur : Après une réception, un bit "data_ok" est à 1. Nous récupérons celui-ci et l'envoyons au compteur qui prendra alors successivement les valeurs 0 et 1 et déterminera à quelle mémoire envoyer la donnée reçue.
Les bits reçues et envoyés sur le port série ont été visualisés sur un analyseur logique. Il est à noter que nous envoyons la valeur de la température en continue. Voici une photographie de ce que l'on apercevait à l'écran.
Nous effectuons ensuite une comparaison entre les valeurs des deux mémoires et les renvoyons dans deux autres mémoires correspondant aux températures minimum et maximum. Nous utilisons pour cela deux démultiplexeurs et un comparateur. Cela permettra d'empêcher des problèmes éventuels suite à la réception du maximum avant le minimum, par exemple. Il nous reste à gérer le cas où les deux températures reçues sont égales.
Les valeurs des minimum et maximum sont ensuite passées aux comparateurs chargés d'allumer les LEDS en fonction de la valeur relevée par le capteur de température.
Voici le schéma final, complet, réalisé sur Altium Designer.
Avec ce schéma, nous avons rencontré un problème lors de la réception : le démultiplexeur envoie la valeur reçue dans une mémoire en fonction de la valeur du compteur, mais envoie également 0 sur l'autre sortie. Nous souhaiterions que le démultiplexeur ne renvoie rien sur l'autre mémoire lorsqu'elle n'est pas concernée.
Après avoir réétudié le schéma, nous en avons déduit que le problème devait venir du bit de contrôle des premières mémoires : en effet, il prend la même valeur pour les deux mémoires, data_ok, ce qui signifie qu'à chaque nouvelle donnée reçue les valeurs des deux mémoires sont modifiées. Il suffirait ainsi de rajouter un inverseur sur le bit de contrôle d'une des mémoires. Il faudrait également tenir compte de la valeur de data_ok, pour que les valeurs des mémoires restent identiques lorsque les conversions sont terminées et que le compteur est revenu à 0.
Partie informatique
WEBSOCKET
L'objectif de cette séance était d'adapter le websocket aux données transmises ainsi que créer une page html permettant les actions propres à l'utilisateur. Tout d'abord il a fallu convertir les données envoyées par l'utilisateur pour que le FPGA puisse les lire et inversement. Nous avons 3 unités différentes le degré, la tension envoyée par le capteur et l'octet lu et écrit par le FPGA. Nous les nommerons respectivement y,x et z. Cependant nous ne communiquons que entre l'utilisateur et le FPGA; le FPGA transformant lui même la tension donnée par le capteur en octet.
La fiche technique nous a indiqué que le capteur faisait une relation linéaire entre la tension qu'il fournit et la température. Nous en avons déduit cette fonction affine :
y= 100x-50
Ensuite nous devions donc transformer le courant en octet (valeur entière de 0 à 255) pour communiquer de y vers z. x va de 0 à 5V et z de 0 à 255. La température évoluant de manière affine de manière conjointe avec la tension, nous en avons conclus une relation de proportionnalité entre x et z avec k le coefficient.
x = k*z donc ici k = 5/255 On en déduit la relation entre y et z Soit y= 100x - 50 y= 100*k*z -50 y= 100*(5/255)*z -50 ==> y = (5/2.55)*z -50 Mais nous en avons aussi besoin dans le sens inverse ce qui donne : z =(2.55/5)(y+50)
Séance Supplémentaire
Informatique
Après avoir programmé le websocket il a fallu le transférer sur la raspberry afin de s'en servir de serveur. Notre tuteur en informatique a installé Apache et la libraire c propre au websocket. Nous avons programmé son type de connexion ainsi que son adresse sur le réseau local. L'adresse est la suivante :
172.26.79.05
Après avoir compilé le programme directement sur la raspberry dans le dossier du serveur, nous y avons ajouté la page web uWebsocket.html que nous avons programmé en html avec quelques lignes de javascript.
Notre application se connecte au port 8000 de la carte. Le programme se lance désormais au démarrage donc sans affichage dans la console des actions du programme. Nous avons donc déboguer le programme de websocket en se connectant à la FPGA en le lançant manuellement. Il nous a permis ensuite de tenter de déboguer le FPGA et d'observer les interactions entre la FPGA et la RASPBERRY.
Démonstration
Conclusion
Ce projet fût l'opportunité de nous familiariser avec la filière IMA SC et de concevoir un objet faisant autant appel à l'informatique qu'à l'électronique. Nous nous sommes vus confrontés à la difficulté de réunir deux parties initialement indépendantes ainsi qu'à celle de trouver un cahier des charges répondant aux exigences du sujet, de temps ou encore de matériel.
En ce qui concerne la partie informatique, la difficulté majeure fût de travailler avec des technologies pas encore abordées en cours (Javascript, Websocket) et de créer le lien notamment entre le code en html et celui en Javascript.
Pour ce qui est de l'électronique, l'utilisation du CAN a rendu cette partie plus complexe à réaliser mais également plus intéressante.
Finalement, nous avons réussi à réunir les deux parties, électronique et informatique. Bien que le stockage des valeurs en mémoire ne se fasse pas correctement au niveau du schéma sur Altium Designer, les données souhaitées sont correctement envoyées sur le port série, autant en réception qu'en envoie depuis la FPGA. Les deux parties fonctionnant indépendamment correctement.
Avec plus de temps, nous aurions pu corriger les défauts persistants et afficher la valeur de la température directement sur l'objet à l'aide d'un afficheur 16 segments. Ce projet a également un grand potentiel en matière d'amélioration et pourrait être implanté dans un système plus complexe. Par exemple, lorsque la température est en dessous du premier seuil, une résistance pourrait se mettre à chauffer ou encore si elle est au dessus du deuxième seuil, un ventilateur pourrait se déclencher, ou une alarme pourrait sonner.
Nous remercions les professeurs, M. REDON, M. BOÉ et M. WICHMANN pour leur aide apportée au cours de ce projet.