<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
		<id>https://projets-ima.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Rkrikori</id>
		<title>Wiki de Projets IMA - Contributions de l’utilisateur [fr]</title>
		<link rel="self" type="application/atom+xml" href="https://projets-ima.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Rkrikori"/>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php/Sp%C3%A9cial:Contributions/Rkrikori"/>
		<updated>2026-05-14T15:41:05Z</updated>
		<subtitle>Contributions de l’utilisateur</subtitle>
		<generator>MediaWiki 1.29.2</generator>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=21115</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=21115"/>
				<updated>2015-05-11T17:56:02Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Localisation - Extended Kalman Filter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Etablissement du cahier des charges====&lt;br /&gt;
&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
*Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
*Recherches de solutions pour la localisation (SLAM)&lt;br /&gt;
*Recherche de solution pour la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Recherche d'un algorithme de recherche de chemin====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de recherche de chemin, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous avons visualisé les différents algorithmes sur [http://qiao.github.io/PathFinding.js/visual/ PathFinding]&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | 400px | center]][[Image:Projet_S8_A_STAR_2.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | 400px | center]][[Image:Projet_S8_A_STAR_4.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
====Recherche d'une solution pour la localisation====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un '''''Algorithme de Localisation et Cartographie Simultanée''''' (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Découpage du travail à effectuer====&lt;br /&gt;
&lt;br /&gt;
Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
Chaque case du diagramme précédent correspond à un noeud ROS.&lt;br /&gt;
&lt;br /&gt;
Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
*'''Laser''' récupère les données brutes du laser.&lt;br /&gt;
*'''Filtrage''' permet, comme son nom l'indique, d'enlever les éventuels bruits qui affectent les données du laser.&lt;br /&gt;
*'''Reconnaissance des droites''' traite les données laser filtrées pour détecter les droites présentes (Transformée de Hough ou Ransac)&lt;br /&gt;
*'''Reconnaissance des formes''' extrapole les objets (machines) à partir des droites.&lt;br /&gt;
*'''Corrélation emplacements machines''' lie la position des machines détectées au laser et les positions envoyées par RefBoxCom pour éviter les incohérences.&lt;br /&gt;
*'''Odométrie''' récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
*'''Traitement de position''' corrige l'erreur sur le Twist avec les données du gyroscope (par dérivation).&lt;br /&gt;
*'''Fusion de Kalman''' est un algorithme qui va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
*'''Stockage machines + robot''' transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
*'''Grid Map''' renvoit une map utilisée ensuite pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
*'''RefBoxCom''' stocke et renvoie la position des machines.&lt;br /&gt;
*'''Position robot''' renvoie la position exacte du robot sur la grille.&lt;br /&gt;
*'''Manager''' Noeud qui envoie la position à atteindre.&lt;br /&gt;
*'''Pathfinder''' recherche le chemin demandé par le Manager sur une grille&lt;br /&gt;
*'''Parcoureur''' exécute le chemin trouvé en fournissant les vitesses au noeud Déplacement.&lt;br /&gt;
*'''Déplacement''' (noeud robotino_local_move_server), qui donne les commandes aux moteurs à partir de la vitesse linéaire et angulaire envoyée par le Parcoureur.&lt;br /&gt;
&lt;br /&gt;
====Recherche de documentation sur ROS et l'API du Robotino====&lt;br /&gt;
&lt;br /&gt;
Nous avons cherchés toutes les documentations techniques nécessaires pour la programmation de chaque noeud : [http://wiki.ros.org/fr Wiki_ROS] et [http://wiki.ros.org/robotino API_Robotino], nous permettant de mettre à jour le schéma global, notamment au niveau des types.&lt;br /&gt;
&lt;br /&gt;
====Etude de l'algorithme A-star précédent====&lt;br /&gt;
&lt;br /&gt;
Nous nous sommes ensuite concentrés sur le noeud GridMap qui contient ''Map.cpp'' :&lt;br /&gt;
&lt;br /&gt;
Dans le code de l'an dernier, ce noeud générait une grille en dur. Cependant, cette solution n'est pas possible cette année car nous ne connaissons pas toutes les informations sur la piste (on connaît à peu près la position mais pas l'orientation). Il va donc falloir générer une grille en fonction du noeud précédent qui nous renverra un type ''OccupancyGrid''. &lt;br /&gt;
&lt;br /&gt;
Etant donné que ce noeud tournera en permanence, si des informations changent pendant que le robot est sur la piste (détection des nouvelles machines par exemple), le noeud ''Map.cpp'' modifiera la grille en temps réel.&lt;br /&gt;
&lt;br /&gt;
La grille est décomposée en case pour le A-Star :&lt;br /&gt;
&lt;br /&gt;
Si c'est une case interdite (obstacle) ont associe a la case la valeur 1, si elle est autorisée, on associe la valeur 0. On illustre le principe précédent par un exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
Cependant, le noeud &amp;quot;Grid Map&amp;quot; va nous délivrer un vecteur et non une matrice par le biais de ''OccupancyGrid.Data''.Dans notre exemple précédent, on récupère le vecteur suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map_2.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
On choisit donc de transformer ce vecteur en matrice, car l'algorithme A-Star fonctionne sur un graphe, pas un vecteur. On connait la largeur (en case) de la grille grâce au type ''OccupancyGrid.info.width''.&lt;br /&gt;
&lt;br /&gt;
Le pseudo-code pour générer la matrice à partir de ce vecteur sera le suivant :&lt;br /&gt;
&lt;br /&gt;
 fonction create_grid (OccupancyGrid.Data vecteur[size]) : matrice[height].[width]&lt;br /&gt;
 {&lt;br /&gt;
   matrice[height].[width] ;		&lt;br /&gt;
      int t &amp;lt;- size;&lt;br /&gt;
          Pour (i de 0 à height)&lt;br /&gt;
          faire:&lt;br /&gt;
                {&lt;br /&gt;
                    Pour (j de 0 à width)&lt;br /&gt;
                    faire :&lt;br /&gt;
                            {&lt;br /&gt;
                               matrice[i].[j] &amp;lt;- vecteur[t] ;&lt;br /&gt;
                               t++;&lt;br /&gt;
                            }&lt;br /&gt;
                }&lt;br /&gt;
   return matrice;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction====&lt;br /&gt;
&lt;br /&gt;
Nous nous concentrons essentiellement sur la première partie, qui est la partie : &amp;quot;Landmarks Extraction&amp;quot; (extraction des points de repères). On travaille ici dans le repère du laser, qui est différent de celui du robot, et du global. La transposition dans le repère global se fera dans la partie &amp;quot;Data Association&amp;quot;. On doit ainsi, dans l'ordre :&lt;br /&gt;
&lt;br /&gt;
☑ récupérer des données lasers via le topic /scan&amp;lt;br&amp;gt;&lt;br /&gt;
☑ convertir les coordonnées polaires en coordonnées cartésiennes en filtrant les données aberrantes (&amp;gt; range_max et &amp;lt; range_min)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ implémenter l'algorithme [http://fr.wikipedia.org/wiki/RANSAC RANSAC] (Random SAmple Consensus) de détection de droites :&amp;lt;br&amp;gt;&lt;br /&gt;
☑ détecter la &amp;quot;meilleure&amp;quot; droite à partir des points en sélectionnant aléatoirement des combinaisons de points&amp;lt;br&amp;gt;&lt;br /&gt;
☑ stocker le meilleur modèle (angle + tableau de points)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ recommencer tant qu'il reste assez de points à traiter (5)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ extraire les segments à partir des modèles trouvés et des points&amp;lt;br&amp;gt;&lt;br /&gt;
☑ extraire les points extrèmes&amp;lt;br&amp;gt;&lt;br /&gt;
☑ calculer la taille du segment&amp;lt;br&amp;gt;&lt;br /&gt;
☑ chercher des angles droits, des segments de 35 ou 70 cm (largeur et longueur d'une machine)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ extrapoler les positions des machines dans le repère du laser&amp;lt;br&amp;gt;&lt;br /&gt;
☑ définir le barycentre de la machine ainsi que son angle&amp;lt;br&amp;gt;&lt;br /&gt;
☐ stocker ces positions&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Pathfinder====&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi pris du temps avec '''Valentin VERGEZ''', qui a développé, l'an dernier, les codes pour le déplacement du Robotino et le calcul de trajectoire&lt;br /&gt;
&lt;br /&gt;
Nous avons éclairci quelques points sur cette partie du projet :&lt;br /&gt;
*Les commentaires sur l'utilité de chaque fonction ont été rajoutés.&lt;br /&gt;
*Le &amp;quot;code mort&amp;quot; a été nettoyé ainsi que les parties inutiles.&lt;br /&gt;
*Nous devons trouver un moyen de tester cette partie du code seule. (A priori graphiquement).&lt;br /&gt;
&lt;br /&gt;
Etant donné l'arrivée d'un nouvel ordinateur au sein de l'équipe, nous en avons profités pour installer les logiciels qui nous permettrons de faire tourner les noeuds codés sur les Robotino :&lt;br /&gt;
&lt;br /&gt;
*Installation d'Ubuntu 12.04 ( c'est cette version qui permet de faire tourner ROS Hydro)&lt;br /&gt;
&lt;br /&gt;
*Installation de ROS Hydro (ensemble d'outils informatiques open source permettant de développer des logiciels pour la robotique.)&lt;br /&gt;
&lt;br /&gt;
*Installation des paquets nécessaires (catkin, Desktop Install, ROS-Base, Individual Package)&lt;br /&gt;
&lt;br /&gt;
*Installation de GIT (outil de bas niveau permettant de gérer l'évolution du contenu d'une arborescence)&lt;br /&gt;
&lt;br /&gt;
*Vérification que toutes les fonctionnalités de ROS Hydro étaient présentes ( [http://wiki.ros.org/ROS/Tutorials Tutoriel])&lt;br /&gt;
&lt;br /&gt;
La récupération du code complet de l'année dernière et une solution a été trouvée afin de tester le code de génération de trajectoire A-star:&lt;br /&gt;
&lt;br /&gt;
*Pour visualiser une Map ainsi qu'un Path (chemin), on peut utiliser l'outils [http://wiki.ros.org/rviz RVIZ].&lt;br /&gt;
*Dans RVIZ, on peut ajouter un Path (topic /path), ainsi qu'ajouter une Map (/grid): Ceci correspond exactement à ce que nous souhaitons visualiser pour la partie calcul de trajectoire.&lt;br /&gt;
*Pour publier une Map fictive, on executera le script fakeGrid.sh&lt;br /&gt;
*Pour générer un chemin, on lancera le pathfinder (rosruns rbqt_pathfinder server : notre code) et on effectuera une requête avec le script pathReq.sh.&lt;br /&gt;
&lt;br /&gt;
Si tout se passe correctement, le chemin devrait s'afficher en &amp;lt;span style=&amp;quot;color: #00FF00;&amp;quot;&amp;gt; vert &amp;lt;/span&amp;gt; sur la map.&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi du communiquer notre avancement aux autres parties de l'équipe. Le schéma général ainsi qu'un outil permettant d'expliquer les différents algorithmes de recherche de trajectoire optimale nous ont aidé à leur communiquer nos objectifs et les processus choisis.&lt;br /&gt;
&lt;br /&gt;
L'algorithme A-Star que nous allons utiliser donne le résultat final suivant (utilisation du site [http://qiao.github.io/PathFinding.js/visual/ PathFinding] ):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet S8 A STAR E.PNG | center | thumb ]]&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #FFFF00;&amp;quot;&amp;gt; le chemin optimal calculé par A-Star &amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #008000;&amp;quot;&amp;gt; le point de départ&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #FF0000;&amp;quot;&amp;gt; le point d'arrivée&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #808080;&amp;quot;&amp;gt; les points interdits (obstacle)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #00FFFF;&amp;quot;&amp;gt; les points que l'algorithme a déjà calculé&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #00FF00;&amp;quot;&amp;gt; les points que l'algorithme aurait calculé à la prochaine itération&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks extraction - filtrage====&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, nous avons commencé à définir une classe laserScan qui contient la fonction polarToCart, elle convertit les données laser (tableau de ranges) en liste de points (x,y) :&lt;br /&gt;
&lt;br /&gt;
 void laserScan::PolarToCart (){&lt;br /&gt;
  Point p;&lt;br /&gt;
  for (int i=0; i&amp;lt;m_ranges.size(); i++){&lt;br /&gt;
    if((m_ranges[i]&amp;gt;getRangeMin()) &amp;amp;&amp;amp; (m_ranges[i]&amp;lt;getRangeMax())){&lt;br /&gt;
      p.setX(m_ranges[i]*cos(getAngleMin() + i*getAngleInc()));&lt;br /&gt;
      p.setY(m_ranges[i]*sin(getAngleMin() + i*getAngleInc()));&lt;br /&gt;
      m_points.push_back(p);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks extraction - reconnaissance de droite====&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, nous avons déterminé quel algorithme nous allons utiliser : [http://fr.wikipedia.org/wiki/RANSAC#L.27algorithme RANSAC]. L'algorithme de RANSAC trouve la meilleure droite dans un nuage de points. On itère plusieurs fois cet algorithme afin de trouver l'ensemble de toutes les droites du scan laser. On a donc en sortie une liste des droites composants le nuage de points initial.&lt;br /&gt;
&lt;br /&gt;
 Entrée : listOfPoints    -&amp;gt; liste de points initiale &lt;br /&gt;
 Sortie : meilleur_modèle -&amp;gt; les paramètres de la droite qui correspondent le mieux aux points&lt;br /&gt;
                          -&amp;gt; tableau de points à partir desquels la droite a été estimée&lt;br /&gt;
                          -&amp;gt; erreur du modèle de droite par rapport aux points&lt;br /&gt;
&amp;lt;span style=&amp;quot;color: #000080;&amp;quot;&amp;gt;&lt;br /&gt;
 tant que la liste contient assez de points&lt;br /&gt;
  itérateur := 0&lt;br /&gt;
  meilleur_modèle := aucun&lt;br /&gt;
  tant que itérateur &amp;lt; k (fixé par une loi de probabilité)&lt;br /&gt;
   &amp;lt;span style=&amp;quot;color: #008000;&amp;quot;&amp;gt;on choisit deux points au hasard dans la liste&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span style=&amp;quot;color: #00FFFF;&amp;quot;&amp;gt;on fabrique un modèle_possible à partir de ces deux points&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span style=&amp;quot;color: #FF0000;&amp;quot;&amp;gt;Pour chaque point de la liste qui ne sont pas dans le modele_possible&lt;br /&gt;
    si le point s'ajuste au modele_possible avec une erreur inférieure à t&lt;br /&gt;
     Ajouter ce point au modele&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color: #00FF00;&amp;quot;&amp;gt;si le nombre de points dans le modele est suffisant pour valider l'existence du modele&lt;br /&gt;
     erreur := coefficient de corrélation de la régression linéaire de ensemble_points&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color: #808080;&amp;quot;&amp;gt;si erreur &amp;lt; erreur du meilleur_modele&lt;br /&gt;
     meilleur_modèle := modèle_possible&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  stocker meilleur_modèle dans liste de modèles&lt;br /&gt;
  retirer meilleur_ensemble_points de la liste des points initiale&lt;br /&gt;
  recommencer avec la liste modifiée&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - reconnaissance de droite====&lt;br /&gt;
&lt;br /&gt;
Nous avons adapté l'algorithme précédent afin de mieux correspondre aux structures que nous avons créées :&lt;br /&gt;
*Modele&lt;br /&gt;
**Liste de points&lt;br /&gt;
**Liste d'indices&lt;br /&gt;
**Corrélation&lt;br /&gt;
**Droite&lt;br /&gt;
***Point&lt;br /&gt;
***Angle&lt;br /&gt;
**Segment&lt;br /&gt;
***Point &amp;quot;min&amp;quot;&lt;br /&gt;
***Point &amp;quot;max&amp;quot;&lt;br /&gt;
***Angle&lt;br /&gt;
***Taille&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi codé toutes les fonctions nécessaires dans l'algorithme de Ransac, dont celle permettant la correction de l'approximation de droite par régression linéaire des points correspondants à un modèle trouvé (''linReg()'') qui nous a donné matière à réflexion. Aussi, notre première idée qui était de travailler avec des ''std::vector'' a du changer puisque l'aspect récursif de l'algorithme que nous allons utiliser nécessite de multiples suppressions sur les données à entrer dans l'algorithme de Ransac. On travaille donc maintenant avec des ''std::list''.&lt;br /&gt;
&lt;br /&gt;
Tous nos codes sont disponibles sur la branche [https://github.com/PyroTeam/robocup-pkg/tree/feature/navigation/SLAM/navigation/localisation/src feature/navigation/SLAM du GIT de l'équipe PyroTeam].&lt;br /&gt;
&lt;br /&gt;
===Semaine de vacances de février===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - reconnaissance de droite====&lt;br /&gt;
&lt;br /&gt;
Nous devons réaliser un noeud permettant de valider notre algorithme, c'est-à-dire implémenter sous ROS notre code C++ afin de tester, soit directement sur le robot, soit avec des [http://wiki.ros.org/Bags bagfiles]. Cette étape est très importante pour pouvoir passer à la suite : extrapoler les droites trouvées en segments puis en objets.&lt;br /&gt;
&lt;br /&gt;
Notre programme consistant à reconnaître les droites à partir du scan laser est fonctionnel et a été testé à partir du scan laser suivant :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ScanLaser.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Processus de validation :&lt;br /&gt;
&lt;br /&gt;
*Lancer le programme ''rosrun localisation test_polar_to_cart''&lt;br /&gt;
&lt;br /&gt;
résultat : on trouve 5 droites&lt;br /&gt;
&lt;br /&gt;
 m = -0.0229637 p = -0.24079&lt;br /&gt;
 nb de points dans la droite : 246&lt;br /&gt;
 coeff de correlation : 0.812376&lt;br /&gt;
&lt;br /&gt;
 m = -0.0315132 p = 3.7506&lt;br /&gt;
 nb de points dans la droite : 102&lt;br /&gt;
 coeff de correlation : 0.928089&lt;br /&gt;
&lt;br /&gt;
 m = 32.9243 p = -139.943&lt;br /&gt;
 nb de points dans la droite : 77&lt;br /&gt;
 coeff de correlation : 0.914475&lt;br /&gt;
&lt;br /&gt;
 m = 7.04634 p = -15.42&lt;br /&gt;
 nb de points dans la droite : 32&lt;br /&gt;
 coeff de correlation : 0.970724&lt;br /&gt;
&lt;br /&gt;
 m = 0.253029 p = 1.32235&lt;br /&gt;
 nb de points dans la droite : 28&lt;br /&gt;
 coeff de correlation : 0.979578&lt;br /&gt;
&lt;br /&gt;
ce qui correspond à l'image suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:DroitesTrouvées.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
On voit que la recherche de droite marche bien, mais peut être améliorée en ajoutant des conditions de proximité des points correspondants à une seule droite, pour éviter le phénomène que l'on voit au milieu. Le résultat après avoir ajouté cette condition et en ayant affiné au maximum les paramètres, au dépend d'un temps de calcul beaucoup plus élevé (9,416 secondes au lieu de 0,536 s)  :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:DroitesTrouvées2.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Les impératifs de la compétition nous imposant une certaine rapidité pour se localiser et détecter les machines, nous retiendrons la solution la plus rapide et nous séparerons les droites en segment après leur détection.&lt;br /&gt;
&lt;br /&gt;
Pour valider l'algorithme de régression linéaire nous avons :&lt;br /&gt;
*Récupéré tous les points correspondants à chaque droite&lt;br /&gt;
*Rentré ces points sur Excel&lt;br /&gt;
*Fait une courbe de tendance&lt;br /&gt;
*Affiché l'équation de droite et le coefficient de corrélation&lt;br /&gt;
*Comparé avec ce qu'a trouvé notre programme&lt;br /&gt;
*Conclu que notre programme était bon&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - reconnaissance de machines====&lt;br /&gt;
&lt;br /&gt;
Les objectifs de cette semaine :&lt;br /&gt;
&lt;br /&gt;
*à partir de la liste de droites, extraire les segments&lt;br /&gt;
*extrapoler les positions machines à partir d'un segment complet (35 ou 70 cm)&lt;br /&gt;
*réaliser une interface graphique pour visualiser les segments trouvés en temps réel&lt;br /&gt;
*regarder ce qu'on doit rentrer dans l' '''Extended Kalman Filter''' au niveau du format des positions machines et de l'odométrie pour pouvoir réaliser le '''Data Association''' de façon cohérente avec la suite.&lt;br /&gt;
&lt;br /&gt;
L'extraction de segment à partir des 5 droite précédemment trouvées nous donne 7 segments:&lt;br /&gt;
&lt;br /&gt;
 Segment 1&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(-1.04033e-08, -0.238)&lt;br /&gt;
 Max(4.24699, -0.26092)&lt;br /&gt;
 taille : 4.24705&lt;br /&gt;
 angle  : -0.309205&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 2&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(-1.64267e-07, 3.758)&lt;br /&gt;
 Max(3.4172, 3.63358)&lt;br /&gt;
 taille : 3.41946&lt;br /&gt;
 angle  : -2.08521&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 3&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(4.24452, -0.234635)&lt;br /&gt;
 Max(4.33124, 2.18017)&lt;br /&gt;
 taille : 2.41636&lt;br /&gt;
 angle  : 87.9432&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 4&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(2.30055, 0.871242)&lt;br /&gt;
 Max(2.32511, 0.736592)&lt;br /&gt;
 taille : 0.136872&lt;br /&gt;
 angle  : -79.6622&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 5&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(2.50359, 2.18655)&lt;br /&gt;
 Max(2.53413, 2.56542)&lt;br /&gt;
 taille : 0.380104&lt;br /&gt;
 angle  : 85.3914&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 6&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(2.73122, 2.05171)&lt;br /&gt;
 Max(3.049, 2.03728)&lt;br /&gt;
 taille : 0.318107&lt;br /&gt;
 angle  : -2.5999&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 7&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(1.14156, 1.64221)&lt;br /&gt;
 Max(1.39648, 1.61891)&lt;br /&gt;
 taille : 0.255984&lt;br /&gt;
 angle  : -5.22068&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SegmentsTrouvés.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Tout cela en 0,540s !&lt;br /&gt;
&lt;br /&gt;
A partir de la liste de segments précédente, on extrait une liste de machine à partir des segments de 35 ou 70 cm, qui sont les tailles des machines. Comme le scan que nous utilisons pour le moment n'est pas un scan avec une vraie machine, mais disposant quand même de 2 segments d'à peu près 35 cm, nous utilisons ces deux segments comme ''petit côté'' de la machine. On trouve ainsi deux machines :&lt;br /&gt;
&lt;br /&gt;
 Machine 1&lt;br /&gt;
   centre en (2.53292, 2.20155)&lt;br /&gt;
   orientation : 175.391°&lt;br /&gt;
&lt;br /&gt;
 Machine 2&lt;br /&gt;
   centre en (3.06493, 2.05243)&lt;br /&gt;
   orientation : 87.4001°&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une amélioration de l'algorithme a été faite pour la détection de machine. En effet, dans le cas où on détectait un petit et un grand côté de machine, on trouvait deux machines avec des centres à peu près au même endroit. Maintenant, on fusionne ces données en créant un point milieu entre les deux données, et on prend l'orientation du grand côté.&lt;br /&gt;
&lt;br /&gt;
On a commencé à faire des tests sur ROS directement avec un noeud factice qui publie un scan laser à une fréquence de 10Hz, ce qui est la fréquence réelle du laser Hokuyo. La détection se fait assez rapidement et de façon précise. Des tests sur le robot sont prévus en début de semaine 7 avec les vraies machines.&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Data Association====&lt;br /&gt;
&lt;br /&gt;
L'objectif principal de cette semaine est de coder le noeud '''Data Association''' qui liera la position donnée par l'odométrie (mesure relative de la position par rapport à un point de départ à peu près connu) avec les machines trouvées dans le champ du laser.&lt;br /&gt;
&lt;br /&gt;
Il faudra aussi corriger l'odométrie donné par le nœud ''robotino_odometry_node'', qui donne l'odométrie (mesure de la position et de la vitesse du robot). Le problème est que nous utilisons un gyroscope externe, car le gyroscope de base est de très basse qualité. Or, si le nœud corrige parfaitement la position, il ne corrige pas du tout la vitesse angulaire ! Nous devons donc réaliser un nœud qui le fera pour nous.&lt;br /&gt;
&lt;br /&gt;
D'après la dernière version du sujet 2015, l'aire de jeu de 6 x 12 m est séparée en zones de 1,5 x 2 m de large, dans lesquelles se situent une seule machine. Chaque équipe a 6 machines dont la zone est connue, donnée par la Referee Box. Le but du nœud ROS de ''Data Association'' sera de transposer les positions machines dans le repère global de la piste, ainsi le Manager pour savoir devant quelle machine le robot est, et connaître sa position et son orientation.&lt;br /&gt;
&lt;br /&gt;
La piste sera donc comme cela :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Piste.PNG | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
La correction d'odométrie a fait apparaître une erreur de mesure d'environ 1,7°/s sur la vitesse angulaire, à faible vitesse. Pour de la Localisation et Cartographie Simultanée, c'est assez important. Ça justifie donc la nécessité de faire cet ajustement.&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il a été décidé de fusionner les nœuds '''Data Association''' et '''Extended Kalman Filter''' puisque l'association de données n'étant au final qu'un changement de repère, la structure de nœud ROS n'est pas adaptée.&lt;br /&gt;
&lt;br /&gt;
Nous avons trouvé un [https://github.com/yangyimeng/machine-learning/blob/master/slam/EKF/SLAM%20course.pdf PDF] expliquant l'algorithme de SLAM. Grâce à celui ci nous avons déterminer les éléments à rentrer dans le noeud, ainsi que les différentes opérations incluses dans ce filtre. Pour les calculs matriciels, nous allons probablement utiliser la librairie EIGEN pour travailler sur des [http://eigen.tuxfamily.org/dox/classEigen_1_1Matrix.html matrices] de façon optimisée. La prochaine étape sera de &amp;quot;typer&amp;quot; nos informations (position robot + machine + murs) pour pouvoir les intégrer facilement au filtre. Nous avons aussi décidé d'inclure les murs comme ''landmark'' dans la matrice de covariance du vecteur d'état.&lt;br /&gt;
&lt;br /&gt;
Il a été décidé de faire une association de données avant la détection de machines, pour distinguer les pans de murs directement afin de stocker ces informations directement à la source. On pourra éventuellement détecter les coins intérieurs de la piste pour plus de précision dans le recalage. Pour le reste, rien ne change.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - vidéo====&lt;br /&gt;
&lt;br /&gt;
Pour visualiser les résultats de la détection des machines nous avons utiliser l'interface graphique disponible avec ROS, RVIZ. Nous visualisons alors le scan laser (points blancs), le résultat de la détection de segments (en rouge) et les positions des machines trouvées (en vert). Un premier test a été fait sur le scan originel, celui sur lequel nous avons travaillé depuis le début.&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/watch?v=XSn4s1y-XT0 Visualisation des machines]&lt;br /&gt;
&lt;br /&gt;
On rencontre un problème quand le robot est exactement parallèle ou perpendiculaire à un mur. Après vérification dans le programme, il s'avère que la détection ne fonctionne pas pour ces cas. Ce bug est maintenant corrigé :&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/watch?v=rKeqewpuLoQ Correction du bug]&lt;br /&gt;
====Localisation - Data Association====&lt;br /&gt;
&lt;br /&gt;
La première étape consiste juste à faire un changement de repère, d'abord du repère laser vers le repère robot, puisque le laser sera placé en avant du robot, puis du repère robot au repère global, comme ci dessous :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Chgt_Repère.png |center | thumb]]&lt;br /&gt;
&lt;br /&gt;
la matrice correspondant au changement (laser -&amp;gt; robot) est la suivante : &lt;br /&gt;
&lt;br /&gt;
 0   -1    0&lt;br /&gt;
 1    0  0.2&lt;br /&gt;
 0    0    1&lt;br /&gt;
&lt;br /&gt;
la matrice 2x2 en haut à gauche correspond à la rotation de 90°, et le vecteur (0, 0.2) correspond à la translation.&lt;br /&gt;
&lt;br /&gt;
Celle du changement (robot -&amp;gt; global) avec alpha angle mesuré par le gyroscope depuis la position initiale (angle 0) :&lt;br /&gt;
&lt;br /&gt;
 cos(alpha)   -sin(alpha)    posInit.x&lt;br /&gt;
 sin(alpha)    cos(alpha)    posInit.y&lt;br /&gt;
          0             0            1&lt;br /&gt;
&lt;br /&gt;
l'étape suivante est de vérifier si les machines vues par le laser sont bien des machines, c'est-à-dire si les positions mesurées à partir des données lasers correspond aux zones occupées par des machines envoyées par la Referee Box.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Grid Map====&lt;br /&gt;
&lt;br /&gt;
L'autre objectif de cette semaine a été de coder le noeud qui génère la map. La map est générée sous forme d'OccupancyGrid. Ce type est constitué d'un seul vecteur dont la première case correspond à la case en bas à gauche de la map. D'autres paramètres sont réglable comme l'origine et la taille.&lt;br /&gt;
&lt;br /&gt;
Pour la taille on choisit de diviser la map en case de 10 cm et l'origine choisie est le x du centre de la map et en y l'abscisse du premier mur (voir la map ci-dessous). Afin d'expliquer comment est constituée cette map, prenons le code et analysons les différentes fonctions ainsi que le main :&lt;br /&gt;
&lt;br /&gt;
Ce vecteur de Pose2D (x, y et theta (angle de la machine)) va permettre d'enregistrer la position des machines, c'est une variable global qui sera mise à jour avec le Callback :&lt;br /&gt;
&lt;br /&gt;
 std::vector&amp;lt;geometry_msgs::Pose2D&amp;gt; tab;&lt;br /&gt;
&lt;br /&gt;
*Récupération des machines envoyées par le noeud du SLAM (sur le topic /landmarks):&lt;br /&gt;
&lt;br /&gt;
 void Poses_Machine_Callback(const deplacement_msg::LandmarksConstPtr &amp;amp;machines)&lt;br /&gt;
 {&lt;br /&gt;
          tab=machines-&amp;gt;landmarks;&lt;br /&gt;
          for (int i=0; i&amp;lt;tab.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
     	     tab[i].x = tab[i].x*1000;&lt;br /&gt;
     	     tab[i].y = tab[i].y*1000;&lt;br /&gt;
 	  }&lt;br /&gt;
    &lt;br /&gt;
  }  &lt;br /&gt;
&lt;br /&gt;
*Création d'une map vide de taille 14m sur 8m. Chaque case est initialisée à une valeur nulle, on remplit également les autres paramètres de OccupancyGrid:&lt;br /&gt;
(On rappelle que la technique utilisée est un vecteur qui représente chaque case auxquelles il associe une probabilité 100 c'est un point interdit et 0 quand c'est un point sans danger pour le passage du robot)&lt;br /&gt;
&lt;br /&gt;
 void Create_Empty_Map(nav_msgs::OccupancyGrid &amp;amp;Map)&lt;br /&gt;
 {&lt;br /&gt;
      Map.info.origin.position.x=-7000;&lt;br /&gt;
      Map.info.origin.position.y=-1000;&lt;br /&gt;
      Map.info.origin.position.z=0;&lt;br /&gt;
      Map.info.origin.orientation.x=0;&lt;br /&gt;
      Map.info.origin.orientation.y=0;&lt;br /&gt;
      Map.info.origin.orientation.z=0;&lt;br /&gt;
      Map.info.origin.orientation.w=1;&lt;br /&gt;
      Map.info.map_load_time=ros::Time::now();&lt;br /&gt;
      Map.info.resolution=100;&lt;br /&gt;
      Map.info.width=140;&lt;br /&gt;
      Map.info.height=80;&lt;br /&gt;
      Map.data.assign(Map.info.width*Map.info.height, 0);                   //map vide&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
*Construction des points fixes de la map donc les murs (probabilité 100) et les zones à risques (probabilité 50):&lt;br /&gt;
&lt;br /&gt;
 void Set_Wall(nav_msgs::OccupancyGrid &amp;amp;Map)&lt;br /&gt;
 {&lt;br /&gt;
    for (int i=0;i&amp;lt;80;i++)&lt;br /&gt;
    {&lt;br /&gt;
       for (int j=0;j&amp;lt;140;j++)&lt;br /&gt;
       {&lt;br /&gt;
          if ((i&amp;lt;13)||(i&amp;gt;67))) Map.data[j+i*140]=100;&lt;br /&gt;
          if ((j&amp;lt;13)||(j&amp;gt;127)) Map.data[j+i*140]=100;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Nous ne mettons pas tout le code de cette fonction étant donné qu'il est long et répétitif puisque c'est le remplissage des données connues, donc en &amp;quot;dur&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*Calcul des positions machines: &lt;br /&gt;
&lt;br /&gt;
Lorsqu'on reçoit une position machine, c'est en fait son centre et son orientation par rapport à x que l'on reçoit. Etant donné que les machines doivent être des rectangles de 110cm sur 75cm (réellement 70 x 35 mais on compte la moitié du robot en plus par sécurité), on décide d'abord de déterminer un des coins du rectangle et plus précisément le coin en bas à droite de ce dernier:&lt;br /&gt;
&lt;br /&gt;
 void Get_One_Point_Of_The_Rectangle(float x, float &amp;amp;xA, float y, float &amp;amp;yA, float theta, float largeur, float longueur)&lt;br /&gt;
 {&lt;br /&gt;
      float x1,y1;&lt;br /&gt;
      x1 = x - cos(theta)*longueur;&lt;br /&gt;
      y1 = y - sin(theta)*longueur; &lt;br /&gt;
      xA = x1 + sin(M_PI_2-theta)*largeur;&lt;br /&gt;
      yA = y1 - cos(M_PI_2-theta)*largeur;&lt;br /&gt;
  &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Remplissage des positions sur la map :&lt;br /&gt;
&lt;br /&gt;
On met alors tous les points de ce rectangle à une probabilité 100 dans le vecteur Map. Pour les calculs on différencie le cas ou l'angle de la machine est entre 0 et pi/2 et le cas où il est entre pi/2 et pi. L'algorithme est le suivant : &lt;br /&gt;
&lt;br /&gt;
 A partir du coin, on incrémente x et y de sorte à longer le grand coté et de remplir chaque case (incrémentation de 5 cm).&lt;br /&gt;
 Une fois arrivé au bout, on incrémente x et y de 5cm sur la largeur à partir du coin et on recommence l'opération précédente.&lt;br /&gt;
 Ceci jusqu'à remplir le complètement le rectangle.&lt;br /&gt;
&lt;br /&gt;
Afin d'établir les probabilités correspondantes aux cases de ce rectangle, nous utilisons la fonctions floor() pour &amp;quot;convertir&amp;quot; nos flottants en entier et accéder à la case correspondante. On notera aussi que la case 1470 correspond à l'origine de notre map.&lt;br /&gt;
&lt;br /&gt;
 void Set_Machines_In_Map(float rank, float theta, float xA, float yA, nav_msgs::OccupancyGrid &amp;amp;Map)&lt;br /&gt;
 {&lt;br /&gt;
      float x=xA;&lt;br /&gt;
      float y=yA;&lt;br /&gt;
      if (theta&amp;lt;=M_PI_2)&lt;br /&gt;
      {&lt;br /&gt;
            for (int j=0;j&amp;lt;10;j++)&lt;br /&gt;
            {&lt;br /&gt;
                  for (int i=0;i&amp;lt;18;i++) &lt;br /&gt;
                  {&lt;br /&gt;
                      Map.data[1470+floor(x/rank)+floor(y/rank)*140]=100;&lt;br /&gt;
                      x = x + cos(theta)*50;&lt;br /&gt;
                      y = y + sin(theta)*50;&lt;br /&gt;
                  }&lt;br /&gt;
                  x = xA - j*cos(M_PI_2-theta)*50;&lt;br /&gt;
                  y = yA + j*sin(M_PI_2-theta)*50;&lt;br /&gt;
            }	&lt;br /&gt;
       }&lt;br /&gt;
       if (theta&amp;gt;M_PI_2)&lt;br /&gt;
       {&lt;br /&gt;
             for (int j=0;j&amp;lt;10;j++)&lt;br /&gt;
             {&lt;br /&gt;
                  for (int i=0;i&amp;lt;18;i++)&lt;br /&gt;
                  {&lt;br /&gt;
                        Map.data[1470+floor(x/rank)+floor(y/rank)*140]=100;&lt;br /&gt;
                        x = x - sin(theta-M_PI_2)*50;&lt;br /&gt;
                        y = y + cos(theta-M_PI_2)*50;&lt;br /&gt;
                  }&lt;br /&gt;
                  x = xA - j*cos(theta-M_PI_2)*50;&lt;br /&gt;
                  y = yA - j*sin(theta-M_PI_2)*50;&lt;br /&gt;
              }	&lt;br /&gt;
        }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Ci dessous on a les mains, avec les différentes fonctions appelées et la syntaxe particulière à ROS. &lt;br /&gt;
&lt;br /&gt;
*Noeud général pour le traitement et le remplissage de la map :   &lt;br /&gt;
                 &lt;br /&gt;
 /*==========  Main  ==========*/&lt;br /&gt;
 int main(int argc, char **argv)&lt;br /&gt;
 {&lt;br /&gt;
     ros::init(argc, argv, &amp;quot;server&amp;quot;);&lt;br /&gt;
     ros::NodeHandle n;&lt;br /&gt;
     ros::Subscriber sub_poses_machine    = n.subscribe(&amp;quot;/machines&amp;quot;, 1000, Poses_Machine_Callback);   // Récupération des machines&lt;br /&gt;
     ros::Publisher Map_Pub = n.advertise&amp;lt;nav_msgs::OccupancyGrid&amp;gt;(&amp;quot;/map&amp;quot;, 1000);                     // Préparation de la publication de la map&lt;br /&gt;
     ROS_INFO(&amp;quot;Ready to Generate the Map&amp;quot;);&lt;br /&gt;
     float xA,yA;&lt;br /&gt;
     ros::Rate loop_rate(1);&lt;br /&gt;
     while(ros::ok())&lt;br /&gt;
     {&lt;br /&gt;
        nav_msgs::OccupancyGrid Map;&lt;br /&gt;
        Create_Empty_Map(Map);&lt;br /&gt;
        Set_Wall(Map);&lt;br /&gt;
        for (int z=0;z&amp;lt;tab.size();z++)&lt;br /&gt;
        {&lt;br /&gt;
           Get_One_Point_Of_The_Rectangle(tab[z].x, xA, tab[z].y, yA, tab[z].theta, 275, 450);&lt;br /&gt;
 	   Set_Machines_In_Map(100, tab[z].theta, xA, yA, Map);&lt;br /&gt;
        }&lt;br /&gt;
        Map_Pub.publish(Map);                                                                   // publication de la map&lt;br /&gt;
        ros::spinOnce();&lt;br /&gt;
        loop_rate.sleep();&lt;br /&gt;
     }&lt;br /&gt;
     return 0;&lt;br /&gt;
  }  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Noeud test qui publie 2 positions de machines : &lt;br /&gt;
&lt;br /&gt;
 /*==========  Main  ==========*/&lt;br /&gt;
 int main(int argc, char **argv)&lt;br /&gt;
 {&lt;br /&gt;
    ros::init(argc, argv, &amp;quot;test&amp;quot;);&lt;br /&gt;
    ros::NodeHandle n;&lt;br /&gt;
    ros::Publisher Pose_Machines_Pub = n.advertise&amp;lt;deplacement_msg::Landmarks&amp;gt;(&amp;quot;/machines&amp;quot;, 1000);&lt;br /&gt;
    ROS_INFO(&amp;quot;Ready to send poses machines&amp;quot;);&lt;br /&gt;
    int xA,yA;&lt;br /&gt;
    ros::Rate loop_rate(1);&lt;br /&gt;
    while(ros::ok())&lt;br /&gt;
    {&lt;br /&gt;
       deplacement_msg::Landmarks machines_msgs;&lt;br /&gt;
       geometry_msgs::Pose2D tab;&lt;br /&gt;
       tab.x=-2;&lt;br /&gt;
       tab.y=2;&lt;br /&gt;
       tab.theta=0;&lt;br /&gt;
       machines_msgs.landmarks.push_back(tab);&lt;br /&gt;
       tab.x=5;&lt;br /&gt;
       tab.y=4;&lt;br /&gt;
       tab.theta=2.5;&lt;br /&gt;
       machines_msgs.landmarks.push_back(tab);&lt;br /&gt;
       Pose_Machines_Pub.publish(machines_msgs);&lt;br /&gt;
       ros::spinOnce();&lt;br /&gt;
       loop_rate.sleep();&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
On visualise le résultat grâce au logiciel RVIZ qui peut lire les topics publiés et donc le topic /map :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Mapcompet.PNG|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Extended Kalman Filter====&lt;br /&gt;
&lt;br /&gt;
l'objectif de cette semaine sera de coder toutes les fonctions nécessaires à l'implémentation finale du [http://fr.wikipedia.org/wiki/Filtre_de_Kalman#Filtre_de_Kalman_.C3.A9tendu filtre de Kalman étendu] :&lt;br /&gt;
&lt;br /&gt;
*initialisations des différents éléments&lt;br /&gt;
*étape de prédiction&lt;br /&gt;
*étape de mise à jour&lt;br /&gt;
*publication des positions machines et du robot dans le repère global via un topic ROS&lt;br /&gt;
&lt;br /&gt;
Le schéma ci-dessous nous montre les deux étapes du filtre de Kalman :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Kalman.png | center]]&lt;br /&gt;
&lt;br /&gt;
le code pour la partie ''prédiction'' :&lt;br /&gt;
&lt;br /&gt;
 //on ressort la position du robot pour l'état n+1&lt;br /&gt;
 //les paramètres sont le vecteurs où on a la position du robot à l'état n, la matrice P, les commandes en vitesses et le temps à l'état n&lt;br /&gt;
 Vector3d prediction(VectorXd xMean, MatrixXd &amp;amp;P, geometry_msgs::Pose2D cmdVel, ros::Time &amp;amp;temps){&lt;br /&gt;
   ros::Duration duree = ros::Time::now() - temps;&lt;br /&gt;
   double periode = duree.toSec();&amp;lt;br&amp;gt;&lt;br /&gt;
   Vector3d cmdVelVect = Pose2DToVector(cmdVel);&lt;br /&gt;
   //le xMean.topLeftCorner(3,1) correspond à la position du robot&lt;br /&gt;
   Vector3d xPredicted = xMean.topLeftCorner(3,1) + periode*cmdVelVect;&amp;lt;br&amp;gt;&lt;br /&gt;
   MatrixXd Fx;&lt;br /&gt;
   Fx = MatrixXd::Identity(P.rows(), P.cols());&lt;br /&gt;
   Fx(0,0) = xPredicted(0);&lt;br /&gt;
   Fx(1,1) = xPredicted(1);&lt;br /&gt;
   Fx(2,2) = xPredicted(2);&amp;lt;br&amp;gt;&lt;br /&gt;
   //mise à jour de P&lt;br /&gt;
   P = Fx*P*(Fx.transpose());&amp;lt;br&amp;gt;&lt;br /&gt;
   //mise à jour du temps&lt;br /&gt;
   temps = ros::Time::now();&amp;lt;br&amp;gt;&lt;br /&gt;
   return xPredicted;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
le code pour la partie ''correction'' :&lt;br /&gt;
&lt;br /&gt;
 void correction(VectorXd &amp;amp;xMean, MatrixXd &amp;amp;P, Vector3d xPredicted, geometry_msgs::Pose2D m){&lt;br /&gt;
   int taille = P.rows();&lt;br /&gt;
   //on vérifie si la machine est présente ou pas dans le vecteur d'état&lt;br /&gt;
   int i = checkStateVector(xMean, m);&amp;lt;br&amp;gt;&lt;br /&gt;
   if (i != 0){&lt;br /&gt;
     //calcul de H&lt;br /&gt;
     MatrixXd H(3, taille);&lt;br /&gt;
     H = buildH(taille, i);&amp;lt;br&amp;gt;&lt;br /&gt;
     //calcul de Pm&lt;br /&gt;
     MatrixXd Pm(taille, taille);&lt;br /&gt;
     Pm = buildPm(P, i);&amp;lt;br&amp;gt;&lt;br /&gt;
     //calcul de Z&lt;br /&gt;
     MatrixXd Z(taille, taille);&lt;br /&gt;
     Z = H*Pm*(H.transpose());	&amp;lt;br&amp;gt;&lt;br /&gt;
     //calcul du gain de Kalman&lt;br /&gt;
     MatrixXd K(taille, taille);&lt;br /&gt;
     K = P*(H.transpose())*(Z.inverse());&amp;lt;br&amp;gt;&lt;br /&gt;
     //mise à jour du vecteur xMean&lt;br /&gt;
     xMean = xMean + K*(xMean.block(xMean.rows()-3,0,3,1) - xPredicted);&amp;lt;br&amp;gt;&lt;br /&gt;
     //mise à jour de la matrice P&lt;br /&gt;
     P = P - K*Z*(K.transpose());&lt;br /&gt;
   }&lt;br /&gt;
   else {&lt;br /&gt;
     addMachine(m, xMean, P);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Pour notre cas, on doit ajouter des nouvelles machines, alors que pour un EKF classique on observe juste des machines déjà répertoriées. Il faut donc une fonction qui permet d'ajouter une machine dans le vecteur d'état. La voilà :&lt;br /&gt;
&lt;br /&gt;
 void addMachine(geometry_msgs::Pose2D machine, VectorXd &amp;amp;xMean, MatrixXd &amp;amp;P){&lt;br /&gt;
   //on redimensionne xMean et P pour accueillir la nouvelle machines&lt;br /&gt;
   xMean.conservativeResize(xMean.rows() + 3);&lt;br /&gt;
   P.conservativeResize(P.rows()+3,P.cols()+3);&amp;lt;br&amp;gt;&lt;br /&gt;
   //on remplit avec les coordonnées de la nouvelle machine&lt;br /&gt;
   xMean(xMean.rows()-3) = machine.x;&lt;br /&gt;
   xMean(xMean.rows()-2) = machine.y;&lt;br /&gt;
   xMean(xMean.rows()-1) = machine.theta;&amp;lt;br&amp;gt;&lt;br /&gt;
   //calcul de tous les PLi&lt;br /&gt;
   //initialisation des PLi à 0&lt;br /&gt;
   P.block(P.rows() - 3, 0, 3, P.cols()).setZero();&lt;br /&gt;
   P.block(0, P.cols() - 3, P.rows(), 3).setZero();&amp;lt;br&amp;gt;&lt;br /&gt;
   for (int j = 0; j &amp;lt; xMean.rows(); j = j + 3){&lt;br /&gt;
     //position de la nouvelle machines par rapport au robot et à toutes les autres&lt;br /&gt;
     double x 	 = xMean(xMean.rows()-3) - xMean(j  );&lt;br /&gt;
     double y 	 = xMean(xMean.rows()-2) - xMean(j+1);&lt;br /&gt;
     double theta = xMean(xMean.rows()-1) - xMean(j+2);&amp;lt;br&amp;gt;&lt;br /&gt;
     P(P.rows()-3, j  ) = x;&lt;br /&gt;
     P(P.rows()-2, j+1) = y;&lt;br /&gt;
     P(P.rows()-1, j+2) = theta;&amp;lt;br&amp;gt;&lt;br /&gt;
     P(j  , P.rows()-3) = x;&lt;br /&gt;
     P(j+1, P.rows()-2) = y;&lt;br /&gt;
     P(j+2, P.rows()-1) = theta;&amp;lt;br&amp;gt;&lt;br /&gt;
     P(j  , j  ) = xMean(j  ) - xMean(0);&lt;br /&gt;
     P(j+1, j+1) = xMean(j+1) - xMean(1);&lt;br /&gt;
     P(j+2, j+2) = xMean(j+2) - xMean(2);&amp;lt;br&amp;gt;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Extended Kalman Filter====&lt;br /&gt;
&lt;br /&gt;
La partie '''prédiction''' du filtre marche parfaitement, quelques corrections ont dues être faites au niveau de la commande vitesse. En effet, Nous avions oublié de la transposer dans le repère global. Pour la partie '''correction''', nous rencontrons un problème de divergence du filtre, qui est probablement due à une mauvaise initialisation. En effet, nous utilisons des enregistrements faits sur notre piste (1/4 de la vraie) avec des initialisations correspondant à la piste originale. Le filtre ne peut donc pas converger car la position de départ est fausse.&lt;br /&gt;
&lt;br /&gt;
===Semaine 11===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Extended Kalman Filter====&lt;br /&gt;
&lt;br /&gt;
Des corrections sont en cours de validation. Nous essayons de définir une initialisation avec les paramètres de notre piste, ce qui n'est pas évident. Les programmes permettant d'extraire les positions machines du filtres ont été réalisé, ainsi qu'un launch pour pouvoir lancer tous les noeuds de la localisation.&lt;br /&gt;
&lt;br /&gt;
===Semaine 12===&lt;br /&gt;
&lt;br /&gt;
====Compétition Open German - mise en place====&lt;br /&gt;
&lt;br /&gt;
Pendant les deux jours de mise en place, nous avons continué à travailler sur la localisation, qui est une partie critique et nécessaire à notre participation. Le filtre en lui même est fonctionnel et permet de corriger la position du robot, ainsi que celle des machines. Cependant, et ce n'est pas un petit &amp;quot;cependant&amp;quot;... Le fait que l'on ajoute des machines en cours de jeu perturbe fortement notre algorithme.&lt;br /&gt;
&lt;br /&gt;
En effet, le filtre de Kalman est optimal si la position des repères est connu, or, un ajout de machine crée un recalage forcé, et si l'on voit plusieurs machines... C'est la '''catastrophe'''. L'ajout de machines est une partie sensible qui nécessite des tests sur la position mesurée, avec un changement de repère à partir de la position du robot, si celle ci dérive, tout dérive. Chaque machine initialisée à la mauvaise position, ou chaque élément détecté comme machine mais n'en étant pas une (faux positif) perturbe le recalage.&lt;br /&gt;
&lt;br /&gt;
De nombreux tests ayant été fait sur la piste officiel avec différentes configurations nous ont permis de vérifier que l'odométrie mesurée ne dérivait que très peu. Il a donc été décidé de n'utiliser que l'odométrie et le scan laser pour la partie '''exploration'''. En effet, chaque machine mesurée est envoyée à un noeud ROS qui va créer une carte et la compléter au fur et à mesure de la partie. Le robot est donc repéré rien qu'avec son odométrie. Le fait que la phase d'exploration (découverte du terrain) ne dure que '''4 minutes''' nous a convaincu pour n'utiliser que cette mesure.&lt;br /&gt;
&lt;br /&gt;
De plus, la carte créée sera utilisée pour la phase suivante, la phase de '''production'''. Cette phase consiste, au niveau de la localisation, à se repérer sur la piste et atteindre la machine demandée par l'exécuteur de tâches. Pour cette phase qui dure '''15 minutes''', l'utilisation du filtre est nécessaire. Donc, avec les coordonnées des machines mesurées pendant la première phase, on peut créer le vecteur d'état et la matrice faisant le lien entre les machines. De là, la taille de ces deux éléments ne variant plus, on peut corriger uniquement la position du robot et le filtre sera efficace.&lt;br /&gt;
&lt;br /&gt;
====Compétition Open German - 1er jour====&lt;br /&gt;
&lt;br /&gt;
Durant ce premier jour, nous avons commencé à ''merger'' nos branches respectives pour pouvoir faire tourner tous nos programmes. Cette phase est laborieuse et nous a pris du temps. De toute façon, toutes les équipes ne sont pas prêtes, les organisateurs non plus. La '''Referee Box''' n'est pas fonctionnel pour la phase de production, ce qui veut dire que nous nous concentrons actuellement sur l'exploration. Les matchs joués aujourd'hui ne nous rapporte donc pas de points. Les tests nous ont permis de valider individuellement chacun des algos, il ne reste &amp;quot;plus qu'à&amp;quot; rejoindre le tout.&lt;br /&gt;
&lt;br /&gt;
====Compétition Open German - 2eme jour====&lt;br /&gt;
&lt;br /&gt;
Niveau '''localisation''', la navigation à l'odométrie et la détection de machine sont fonctionnelles. Cependant, le moyennage fait sur les positions machines (on moyenne toutes les positions trouvées appartenant à une même machine pour n'avoir qu'un seul point) fait que le point correspondant peut être perturbé par des mesures aberrantes. C'est le cas lorsque le robot se déplace à vitesse élevée.&lt;br /&gt;
&lt;br /&gt;
La détection de machine a été améliorée afin de ne rajouter QUE les machines, et pas les murs de la même taille. Nous allons donc retester le '''filtre de Kalman Etendu''' avec cette amélioration. Cependant, ce ne sera fait qu'après la compétition, puisque d'autres problèmes ont nécessité la présence de l'équipe sur certaines parties sensibles du déplacement.&lt;br /&gt;
&lt;br /&gt;
Sur la piste nous avons fait des mesures, qui nous donnent la carte suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PisteSamediSoir.PNG | center]]&lt;br /&gt;
&lt;br /&gt;
La visualisation du trajet pour découvrir ces machines est le suivant :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:DetectionSamediSoir.PNG | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Et les positions machines, ainsi que leur orientation sont les suivantes :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MachinesBagtestSamediSoir.PNG | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
====Compétition Open German - 3eme et dernier jour====&lt;br /&gt;
&lt;br /&gt;
L'architecture choisie pour la localisation est la suivante :&lt;br /&gt;
*Navigation à l'odométrie&lt;br /&gt;
*Détection de machines et moyennage&lt;br /&gt;
*Quand on a vu toutes nos machines, on utilise la symétrie pour compléter les machines restantes&lt;br /&gt;
*Navigation et Localisation avec l'EKF (correction des positions machines et du robot)&lt;br /&gt;
&lt;br /&gt;
====Localisation - Extended Kalman Filter====&lt;br /&gt;
&lt;br /&gt;
Après de longs tests et des corrections importantes au niveau de l'ajout des machines dans le filtre, ce qui était la partie critique... Le meilleur résultat que l'on ait pu avoir avec l'EKF est celui ci dessous. Les machines étant en &amp;lt;span style=&amp;quot;color:#9966CC&amp;quot;&amp;gt;violet&amp;lt;/span&amp;gt;, la trajectoire calculée par l'EKF en &amp;lt;span style=&amp;quot;color:#00FF00&amp;quot;&amp;gt;vert&amp;lt;/span&amp;gt; et la trajectoire mesurée par les codeurs en &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;rouge&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:BestResultWithEKF.PNG | center]]&lt;br /&gt;
&lt;br /&gt;
Nous rappelons que tous nos codes sont disponibles sur notre [https://github.com/PyroTeam/robocup-pkg/tree/navigation-devel/navigation/localisation GIT].&lt;br /&gt;
&lt;br /&gt;
====Video====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Enfin, afin d'illustrer nos résultats de manière ludique et attrayante, voici une vidéo qui vous donnera goût à la RoboCup !&lt;br /&gt;
&lt;br /&gt;
https://www.youtube.com/watch?v=PB6g2krvCFI&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=21032</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=21032"/>
				<updated>2015-05-11T06:40:40Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Grid Map */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Etablissement du cahier des charges====&lt;br /&gt;
&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
*Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
*Recherches de solutions pour la localisation (SLAM)&lt;br /&gt;
*Recherche de solution pour la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Recherche d'un algorithme de recherche de chemin====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de recherche de chemin, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous avons visualisé les différents algorithmes sur [http://qiao.github.io/PathFinding.js/visual/ PathFinding]&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | 400px | center]][[Image:Projet_S8_A_STAR_2.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | 400px | center]][[Image:Projet_S8_A_STAR_4.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
====Recherche d'une solution pour la localisation====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un '''''Algorithme de Localisation et Cartographie Simultanée''''' (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Découpage du travail à effectuer====&lt;br /&gt;
&lt;br /&gt;
Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
Chaque case du diagramme précédent correspond à un noeud ROS.&lt;br /&gt;
&lt;br /&gt;
Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
*'''Laser''' récupère les données brutes du laser.&lt;br /&gt;
*'''Filtrage''' permet, comme son nom l'indique, d'enlever les éventuels bruits qui affectent les données du laser.&lt;br /&gt;
*'''Reconnaissance des droites''' traite les données laser filtrées pour détecter les droites présentes (Transformée de Hough ou Ransac)&lt;br /&gt;
*'''Reconnaissance des formes''' extrapole les objets (machines) à partir des droites.&lt;br /&gt;
*'''Corrélation emplacements machines''' lie la position des machines détectées au laser et les positions envoyées par RefBoxCom pour éviter les incohérences.&lt;br /&gt;
*'''Odométrie''' récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
*'''Traitement de position''' corrige l'erreur sur le Twist avec les données du gyroscope (par dérivation).&lt;br /&gt;
*'''Fusion de Kalman''' est un algorithme qui va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
*'''Stockage machines + robot''' transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
*'''Grid Map''' renvoit une map utilisée ensuite pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
*'''RefBoxCom''' stocke et renvoie la position des machines.&lt;br /&gt;
*'''Position robot''' renvoie la position exacte du robot sur la grille.&lt;br /&gt;
*'''Manager''' Noeud qui envoie la position à atteindre.&lt;br /&gt;
*'''Pathfinder''' recherche le chemin demandé par le Manager sur une grille&lt;br /&gt;
*'''Parcoureur''' exécute le chemin trouvé en fournissant les vitesses au noeud Déplacement.&lt;br /&gt;
*'''Déplacement''' (noeud robotino_local_move_server), qui donne les commandes aux moteurs à partir de la vitesse linéaire et angulaire envoyée par le Parcoureur.&lt;br /&gt;
&lt;br /&gt;
====Recherche de documentation sur ROS et l'API du Robotino====&lt;br /&gt;
&lt;br /&gt;
Nous avons cherchés toutes les documentations techniques nécessaires pour la programmation de chaque noeud : [http://wiki.ros.org/fr Wiki_ROS] et [http://wiki.ros.org/robotino API_Robotino], nous permettant de mettre à jour le schéma global, notamment au niveau des types.&lt;br /&gt;
&lt;br /&gt;
====Etude de l'algorithme A-star précédent====&lt;br /&gt;
&lt;br /&gt;
Nous nous sommes ensuite concentrés sur le noeud GridMap qui contient ''Map.cpp'' :&lt;br /&gt;
&lt;br /&gt;
Dans le code de l'an dernier, ce noeud générait une grille en dur. Cependant, cette solution n'est pas possible cette année car nous ne connaissons pas toutes les informations sur la piste (on connaît à peu près la position mais pas l'orientation). Il va donc falloir générer une grille en fonction du noeud précédent qui nous renverra un type ''OccupancyGrid''. &lt;br /&gt;
&lt;br /&gt;
Etant donné que ce noeud tournera en permanence, si des informations changent pendant que le robot est sur la piste (détection des nouvelles machines par exemple), le noeud ''Map.cpp'' modifiera la grille en temps réel.&lt;br /&gt;
&lt;br /&gt;
La grille est décomposée en case pour le A-Star :&lt;br /&gt;
&lt;br /&gt;
Si c'est une case interdite (obstacle) ont associe a la case la valeur 1, si elle est autorisée, on associe la valeur 0. On illustre le principe précédent par un exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
Cependant, le noeud &amp;quot;Grid Map&amp;quot; va nous délivrer un vecteur et non une matrice par le biais de ''OccupancyGrid.Data''.Dans notre exemple précédent, on récupère le vecteur suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map_2.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
On choisit donc de transformer ce vecteur en matrice, car l'algorithme A-Star fonctionne sur un graphe, pas un vecteur. On connait la largeur (en case) de la grille grâce au type ''OccupancyGrid.info.width''.&lt;br /&gt;
&lt;br /&gt;
Le pseudo-code pour générer la matrice à partir de ce vecteur sera le suivant :&lt;br /&gt;
&lt;br /&gt;
 fonction create_grid (OccupancyGrid.Data vecteur[size]) : matrice[height].[width]&lt;br /&gt;
 {&lt;br /&gt;
   matrice[height].[width] ;		&lt;br /&gt;
      int t &amp;lt;- size;&lt;br /&gt;
          Pour (i de 0 à height)&lt;br /&gt;
          faire:&lt;br /&gt;
                {&lt;br /&gt;
                    Pour (j de 0 à width)&lt;br /&gt;
                    faire :&lt;br /&gt;
                            {&lt;br /&gt;
                               matrice[i].[j] &amp;lt;- vecteur[t] ;&lt;br /&gt;
                               t++;&lt;br /&gt;
                            }&lt;br /&gt;
                }&lt;br /&gt;
   return matrice;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction====&lt;br /&gt;
&lt;br /&gt;
Nous nous concentrons essentiellement sur la première partie, qui est la partie : &amp;quot;Landmarks Extraction&amp;quot; (extraction des points de repères). On travaille ici dans le repère du laser, qui est différent de celui du robot, et du global. La transposition dans le repère global se fera dans la partie &amp;quot;Data Association&amp;quot;. On doit ainsi, dans l'ordre :&lt;br /&gt;
&lt;br /&gt;
☑ récupérer des données lasers via le topic /scan&amp;lt;br&amp;gt;&lt;br /&gt;
☑ convertir les coordonnées polaires en coordonnées cartésiennes en filtrant les données aberrantes (&amp;gt; range_max et &amp;lt; range_min)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ implémenter l'algorithme [http://fr.wikipedia.org/wiki/RANSAC RANSAC] (Random SAmple Consensus) de détection de droites :&amp;lt;br&amp;gt;&lt;br /&gt;
☑ détecter la &amp;quot;meilleure&amp;quot; droite à partir des points en sélectionnant aléatoirement des combinaisons de points&amp;lt;br&amp;gt;&lt;br /&gt;
☑ stocker le meilleur modèle (angle + tableau de points)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ recommencer tant qu'il reste assez de points à traiter (5)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ extraire les segments à partir des modèles trouvés et des points&amp;lt;br&amp;gt;&lt;br /&gt;
☑ extraire les points extrèmes&amp;lt;br&amp;gt;&lt;br /&gt;
☑ calculer la taille du segment&amp;lt;br&amp;gt;&lt;br /&gt;
☑ chercher des angles droits, des segments de 35 ou 70 cm (largeur et longueur d'une machine)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ extrapoler les positions des machines dans le repère du laser&amp;lt;br&amp;gt;&lt;br /&gt;
☑ définir le barycentre de la machine ainsi que son angle&amp;lt;br&amp;gt;&lt;br /&gt;
☐ stocker ces positions&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Pathfinder====&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi pris du temps avec '''Valentin VERGEZ''', qui a développé, l'an dernier, les codes pour le déplacement du Robotino et le calcul de trajectoire&lt;br /&gt;
&lt;br /&gt;
Nous avons éclairci quelques points sur cette partie du projet :&lt;br /&gt;
*Les commentaires sur l'utilité de chaque fonction ont été rajoutés.&lt;br /&gt;
*Le &amp;quot;code mort&amp;quot; a été nettoyé ainsi que les parties inutiles.&lt;br /&gt;
*Nous devons trouver un moyen de tester cette partie du code seule. (A priori graphiquement).&lt;br /&gt;
&lt;br /&gt;
Etant donné l'arrivée d'un nouvel ordinateur au sein de l'équipe, nous en avons profités pour installer les logiciels qui nous permettrons de faire tourner les noeuds codés sur les Robotino :&lt;br /&gt;
&lt;br /&gt;
*Installation d'Ubuntu 12.04 ( c'est cette version qui permet de faire tourner ROS Hydro)&lt;br /&gt;
&lt;br /&gt;
*Installation de ROS Hydro (ensemble d'outils informatiques open source permettant de développer des logiciels pour la robotique.)&lt;br /&gt;
&lt;br /&gt;
*Installation des paquets nécessaires (catkin, Desktop Install, ROS-Base, Individual Package)&lt;br /&gt;
&lt;br /&gt;
*Installation de GIT (outil de bas niveau permettant de gérer l'évolution du contenu d'une arborescence)&lt;br /&gt;
&lt;br /&gt;
*Vérification que toutes les fonctionnalités de ROS Hydro étaient présentes ( [http://wiki.ros.org/ROS/Tutorials Tutoriel])&lt;br /&gt;
&lt;br /&gt;
La récupération du code complet de l'année dernière et une solution a été trouvée afin de tester le code de génération de trajectoire A-star:&lt;br /&gt;
&lt;br /&gt;
*Pour visualiser une Map ainsi qu'un Path (chemin), on peut utiliser l'outils [http://wiki.ros.org/rviz RVIZ].&lt;br /&gt;
*Dans RVIZ, on peut ajouter un Path (topic /path), ainsi qu'ajouter une Map (/grid): Ceci correspond exactement à ce que nous souhaitons visualiser pour la partie calcul de trajectoire.&lt;br /&gt;
*Pour publier une Map fictive, on executera le script fakeGrid.sh&lt;br /&gt;
*Pour générer un chemin, on lancera le pathfinder (rosruns rbqt_pathfinder server : notre code) et on effectuera une requête avec le script pathReq.sh.&lt;br /&gt;
&lt;br /&gt;
Si tout se passe correctement, le chemin devrait s'afficher en &amp;lt;span style=&amp;quot;color: #00FF00;&amp;quot;&amp;gt; vert &amp;lt;/span&amp;gt; sur la map.&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi du communiquer notre avancement aux autres parties de l'équipe. Le schéma général ainsi qu'un outil permettant d'expliquer les différents algorithmes de recherche de trajectoire optimale nous ont aidé à leur communiquer nos objectifs et les processus choisis.&lt;br /&gt;
&lt;br /&gt;
L'algorithme A-Star que nous allons utiliser donne le résultat final suivant (utilisation du site [http://qiao.github.io/PathFinding.js/visual/ PathFinding] ):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet S8 A STAR E.PNG | center | thumb ]]&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #FFFF00;&amp;quot;&amp;gt; le chemin optimal calculé par A-Star &amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #008000;&amp;quot;&amp;gt; le point de départ&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #FF0000;&amp;quot;&amp;gt; le point d'arrivée&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #808080;&amp;quot;&amp;gt; les points interdits (obstacle)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #00FFFF;&amp;quot;&amp;gt; les points que l'algorithme a déjà calculé&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #00FF00;&amp;quot;&amp;gt; les points que l'algorithme aurait calculé à la prochaine itération&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks extraction - filtrage====&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, nous avons commencé à définir une classe laserScan qui contient la fonction polarToCart, elle convertit les données laser (tableau de ranges) en liste de points (x,y) :&lt;br /&gt;
&lt;br /&gt;
 void laserScan::PolarToCart (){&lt;br /&gt;
  Point p;&lt;br /&gt;
  for (int i=0; i&amp;lt;m_ranges.size(); i++){&lt;br /&gt;
    if((m_ranges[i]&amp;gt;getRangeMin()) &amp;amp;&amp;amp; (m_ranges[i]&amp;lt;getRangeMax())){&lt;br /&gt;
      p.setX(m_ranges[i]*cos(getAngleMin() + i*getAngleInc()));&lt;br /&gt;
      p.setY(m_ranges[i]*sin(getAngleMin() + i*getAngleInc()));&lt;br /&gt;
      m_points.push_back(p);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks extraction - reconnaissance de droite====&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, nous avons déterminé quel algorithme nous allons utiliser : [http://fr.wikipedia.org/wiki/RANSAC#L.27algorithme RANSAC]. L'algorithme de RANSAC trouve la meilleure droite dans un nuage de points. On itère plusieurs fois cet algorithme afin de trouver l'ensemble de toutes les droites du scan laser. On a donc en sortie une liste des droites composants le nuage de points initial.&lt;br /&gt;
&lt;br /&gt;
 Entrée : listOfPoints    -&amp;gt; liste de points initiale &lt;br /&gt;
 Sortie : meilleur_modèle -&amp;gt; les paramètres de la droite qui correspondent le mieux aux points&lt;br /&gt;
                          -&amp;gt; tableau de points à partir desquels la droite a été estimée&lt;br /&gt;
                          -&amp;gt; erreur du modèle de droite par rapport aux points&lt;br /&gt;
&amp;lt;span style=&amp;quot;color: #000080;&amp;quot;&amp;gt;&lt;br /&gt;
 tant que la liste contient assez de points&lt;br /&gt;
  itérateur := 0&lt;br /&gt;
  meilleur_modèle := aucun&lt;br /&gt;
  tant que itérateur &amp;lt; k (fixé par une loi de probabilité)&lt;br /&gt;
   &amp;lt;span style=&amp;quot;color: #008000;&amp;quot;&amp;gt;on choisit deux points au hasard dans la liste&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span style=&amp;quot;color: #00FFFF;&amp;quot;&amp;gt;on fabrique un modèle_possible à partir de ces deux points&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span style=&amp;quot;color: #FF0000;&amp;quot;&amp;gt;Pour chaque point de la liste qui ne sont pas dans le modele_possible&lt;br /&gt;
    si le point s'ajuste au modele_possible avec une erreur inférieure à t&lt;br /&gt;
     Ajouter ce point au modele&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color: #00FF00;&amp;quot;&amp;gt;si le nombre de points dans le modele est suffisant pour valider l'existence du modele&lt;br /&gt;
     erreur := coefficient de corrélation de la régression linéaire de ensemble_points&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color: #808080;&amp;quot;&amp;gt;si erreur &amp;lt; erreur du meilleur_modele&lt;br /&gt;
     meilleur_modèle := modèle_possible&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  stocker meilleur_modèle dans liste de modèles&lt;br /&gt;
  retirer meilleur_ensemble_points de la liste des points initiale&lt;br /&gt;
  recommencer avec la liste modifiée&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - reconnaissance de droite====&lt;br /&gt;
&lt;br /&gt;
Nous avons adapté l'algorithme précédent afin de mieux correspondre aux structures que nous avons créées :&lt;br /&gt;
*Modele&lt;br /&gt;
**Liste de points&lt;br /&gt;
**Liste d'indices&lt;br /&gt;
**Corrélation&lt;br /&gt;
**Droite&lt;br /&gt;
***Point&lt;br /&gt;
***Angle&lt;br /&gt;
**Segment&lt;br /&gt;
***Point &amp;quot;min&amp;quot;&lt;br /&gt;
***Point &amp;quot;max&amp;quot;&lt;br /&gt;
***Angle&lt;br /&gt;
***Taille&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi codé toutes les fonctions nécessaires dans l'algorithme de Ransac, dont celle permettant la correction de l'approximation de droite par régression linéaire des points correspondants à un modèle trouvé (''linReg()'') qui nous a donné matière à réflexion. Aussi, notre première idée qui était de travailler avec des ''std::vector'' a du changer puisque l'aspect récursif de l'algorithme que nous allons utiliser nécessite de multiples suppressions sur les données à entrer dans l'algorithme de Ransac. On travaille donc maintenant avec des ''std::list''.&lt;br /&gt;
&lt;br /&gt;
Tous nos codes sont disponibles sur la branche [https://github.com/PyroTeam/robocup-pkg/tree/feature/navigation/SLAM/navigation/localisation/src feature/navigation/SLAM du GIT de l'équipe PyroTeam].&lt;br /&gt;
&lt;br /&gt;
===Semaine de vacances de février===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - reconnaissance de droite====&lt;br /&gt;
&lt;br /&gt;
Nous devons réaliser un noeud permettant de valider notre algorithme, c'est-à-dire implémenter sous ROS notre code C++ afin de tester, soit directement sur le robot, soit avec des [http://wiki.ros.org/Bags bagfiles]. Cette étape est très importante pour pouvoir passer à la suite : extrapoler les droites trouvées en segments puis en objets.&lt;br /&gt;
&lt;br /&gt;
Notre programme consistant à reconnaître les droites à partir du scan laser est fonctionnel et a été testé à partir du scan laser suivant :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ScanLaser.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Processus de validation :&lt;br /&gt;
&lt;br /&gt;
*Lancer le programme ''rosrun localisation test_polar_to_cart''&lt;br /&gt;
&lt;br /&gt;
résultat : on trouve 5 droites&lt;br /&gt;
&lt;br /&gt;
 m = -0.0229637 p = -0.24079&lt;br /&gt;
 nb de points dans la droite : 246&lt;br /&gt;
 coeff de correlation : 0.812376&lt;br /&gt;
&lt;br /&gt;
 m = -0.0315132 p = 3.7506&lt;br /&gt;
 nb de points dans la droite : 102&lt;br /&gt;
 coeff de correlation : 0.928089&lt;br /&gt;
&lt;br /&gt;
 m = 32.9243 p = -139.943&lt;br /&gt;
 nb de points dans la droite : 77&lt;br /&gt;
 coeff de correlation : 0.914475&lt;br /&gt;
&lt;br /&gt;
 m = 7.04634 p = -15.42&lt;br /&gt;
 nb de points dans la droite : 32&lt;br /&gt;
 coeff de correlation : 0.970724&lt;br /&gt;
&lt;br /&gt;
 m = 0.253029 p = 1.32235&lt;br /&gt;
 nb de points dans la droite : 28&lt;br /&gt;
 coeff de correlation : 0.979578&lt;br /&gt;
&lt;br /&gt;
ce qui correspond à l'image suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:DroitesTrouvées.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
On voit que la recherche de droite marche bien, mais peut être améliorée en ajoutant des conditions de proximité des points correspondants à une seule droite, pour éviter le phénomène que l'on voit au milieu. Le résultat après avoir ajouté cette condition et en ayant affiné au maximum les paramètres, au dépend d'un temps de calcul beaucoup plus élevé (9,416 secondes au lieu de 0,536 s)  :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:DroitesTrouvées2.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Les impératifs de la compétition nous imposant une certaine rapidité pour se localiser et détecter les machines, nous retiendrons la solution la plus rapide et nous séparerons les droites en segment après leur détection.&lt;br /&gt;
&lt;br /&gt;
Pour valider l'algorithme de régression linéaire nous avons :&lt;br /&gt;
*Récupéré tous les points correspondants à chaque droite&lt;br /&gt;
*Rentré ces points sur Excel&lt;br /&gt;
*Fait une courbe de tendance&lt;br /&gt;
*Affiché l'équation de droite et le coefficient de corrélation&lt;br /&gt;
*Comparé avec ce qu'a trouvé notre programme&lt;br /&gt;
*Conclu que notre programme était bon&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - reconnaissance de machines====&lt;br /&gt;
&lt;br /&gt;
Les objectifs de cette semaine :&lt;br /&gt;
&lt;br /&gt;
*à partir de la liste de droites, extraire les segments&lt;br /&gt;
*extrapoler les positions machines à partir d'un segment complet (35 ou 70 cm)&lt;br /&gt;
*réaliser une interface graphique pour visualiser les segments trouvés en temps réel&lt;br /&gt;
*regarder ce qu'on doit rentrer dans l' '''Extended Kalman Filter''' au niveau du format des positions machines et de l'odométrie pour pouvoir réaliser le '''Data Association''' de façon cohérente avec la suite.&lt;br /&gt;
&lt;br /&gt;
L'extraction de segment à partir des 5 droite précédemment trouvées nous donne 7 segments:&lt;br /&gt;
&lt;br /&gt;
 Segment 1&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(-1.04033e-08, -0.238)&lt;br /&gt;
 Max(4.24699, -0.26092)&lt;br /&gt;
 taille : 4.24705&lt;br /&gt;
 angle  : -0.309205&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 2&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(-1.64267e-07, 3.758)&lt;br /&gt;
 Max(3.4172, 3.63358)&lt;br /&gt;
 taille : 3.41946&lt;br /&gt;
 angle  : -2.08521&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 3&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(4.24452, -0.234635)&lt;br /&gt;
 Max(4.33124, 2.18017)&lt;br /&gt;
 taille : 2.41636&lt;br /&gt;
 angle  : 87.9432&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 4&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(2.30055, 0.871242)&lt;br /&gt;
 Max(2.32511, 0.736592)&lt;br /&gt;
 taille : 0.136872&lt;br /&gt;
 angle  : -79.6622&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 5&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(2.50359, 2.18655)&lt;br /&gt;
 Max(2.53413, 2.56542)&lt;br /&gt;
 taille : 0.380104&lt;br /&gt;
 angle  : 85.3914&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 6&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(2.73122, 2.05171)&lt;br /&gt;
 Max(3.049, 2.03728)&lt;br /&gt;
 taille : 0.318107&lt;br /&gt;
 angle  : -2.5999&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 7&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(1.14156, 1.64221)&lt;br /&gt;
 Max(1.39648, 1.61891)&lt;br /&gt;
 taille : 0.255984&lt;br /&gt;
 angle  : -5.22068&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SegmentsTrouvés.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Tout cela en 0,540s !&lt;br /&gt;
&lt;br /&gt;
A partir de la liste de segments précédente, on extrait une liste de machine à partir des segments de 35 ou 70 cm, qui sont les tailles des machines. Comme le scan que nous utilisons pour le moment n'est pas un scan avec une vraie machine, mais disposant quand même de 2 segments d'à peu près 35 cm, nous utilisons ces deux segments comme ''petit côté'' de la machine. On trouve ainsi deux machines :&lt;br /&gt;
&lt;br /&gt;
 Machine 1&lt;br /&gt;
   centre en (2.53292, 2.20155)&lt;br /&gt;
   orientation : 175.391°&lt;br /&gt;
&lt;br /&gt;
 Machine 2&lt;br /&gt;
   centre en (3.06493, 2.05243)&lt;br /&gt;
   orientation : 87.4001°&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une amélioration de l'algorithme a été faite pour la détection de machine. En effet, dans le cas où on détectait un petit et un grand côté de machine, on trouvait deux machines avec des centres à peu près au même endroit. Maintenant, on fusionne ces données en créant un point milieu entre les deux données, et on prend l'orientation du grand côté.&lt;br /&gt;
&lt;br /&gt;
On a commencé à faire des tests sur ROS directement avec un noeud factice qui publie un scan laser à une fréquence de 10Hz, ce qui est la fréquence réelle du laser Hokuyo. La détection se fait assez rapidement et de façon précise. Des tests sur le robot sont prévus en début de semaine 7 avec les vraies machines.&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Data Association====&lt;br /&gt;
&lt;br /&gt;
L'objectif principal de cette semaine est de coder le noeud '''Data Association''' qui liera la position donnée par l'odométrie (mesure relative de la position par rapport à un point de départ à peu près connu) avec les machines trouvées dans le champ du laser.&lt;br /&gt;
&lt;br /&gt;
Il faudra aussi corriger l'odométrie donné par le nœud ''robotino_odometry_node'', qui donne l'odométrie (mesure de la position et de la vitesse du robot). Le problème est que nous utilisons un gyroscope externe, car le gyroscope de base est de très basse qualité. Or, si le nœud corrige parfaitement la position, il ne corrige pas du tout la vitesse angulaire ! Nous devons donc réaliser un nœud qui le fera pour nous.&lt;br /&gt;
&lt;br /&gt;
D'après la dernière version du sujet 2015, l'aire de jeu de 6 x 12 m est séparée en zones de 1,5 x 2 m de large, dans lesquelles se situent une seule machine. Chaque équipe a 6 machines dont la zone est connue, donnée par la Referee Box. Le but du nœud ROS de ''Data Association'' sera de transposer les positions machines dans le repère global de la piste, ainsi le Manager pour savoir devant quelle machine le robot est, et connaître sa position et son orientation.&lt;br /&gt;
&lt;br /&gt;
La piste sera donc comme cela :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Piste.PNG | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
La correction d'odométrie a fait apparaître une erreur de mesure d'environ 1,7°/s sur la vitesse angulaire, à faible vitesse. Pour de la Localisation et Cartographie Simultanée, c'est assez important. Ça justifie donc la nécessité de faire cet ajustement.&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il a été décidé de fusionner les nœuds '''Data Association''' et '''Extended Kalman Filter''' puisque l'association de données n'étant au final qu'un changement de repère, la structure de nœud ROS n'est pas adaptée.&lt;br /&gt;
&lt;br /&gt;
Nous avons trouvé un [https://github.com/yangyimeng/machine-learning/blob/master/slam/EKF/SLAM%20course.pdf PDF] expliquant l'algorithme de SLAM. Grâce à celui ci nous avons déterminer les éléments à rentrer dans le noeud, ainsi que les différentes opérations incluses dans ce filtre. Pour les calculs matriciels, nous allons probablement utiliser la librairie EIGEN pour travailler sur des [http://eigen.tuxfamily.org/dox/classEigen_1_1Matrix.html matrices] de façon optimisée. La prochaine étape sera de &amp;quot;typer&amp;quot; nos informations (position robot + machine + murs) pour pouvoir les intégrer facilement au filtre. Nous avons aussi décidé d'inclure les murs comme ''landmark'' dans la matrice de covariance du vecteur d'état.&lt;br /&gt;
&lt;br /&gt;
Il a été décidé de faire une association de données avant la détection de machines, pour distinguer les pans de murs directement afin de stocker ces informations directement à la source. On pourra éventuellement détecter les coins intérieurs de la piste pour plus de précision dans le recalage. Pour le reste, rien ne change.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - vidéo====&lt;br /&gt;
&lt;br /&gt;
Pour visualiser les résultats de la détection des machines nous avons utiliser l'interface graphique disponible avec ROS, RVIZ. Nous visualisons alors le scan laser (points blancs), le résultat de la détection de segments (en rouge) et les positions des machines trouvées (en vert). Un premier test a été fait sur le scan originel, celui sur lequel nous avons travaillé depuis le début.&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/watch?v=XSn4s1y-XT0 Visualisation des machines]&lt;br /&gt;
&lt;br /&gt;
On rencontre un problème quand le robot est exactement parallèle ou perpendiculaire à un mur. Après vérification dans le programme, il s'avère que la détection ne fonctionne pas pour ces cas. Ce bug est maintenant corrigé :&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/watch?v=rKeqewpuLoQ Correction du bug]&lt;br /&gt;
====Localisation - Data Association====&lt;br /&gt;
&lt;br /&gt;
La première étape consiste juste à faire un changement de repère, d'abord du repère laser vers le repère robot, puisque le laser sera placé en avant du robot, puis du repère robot au repère global, comme ci dessous :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Chgt_Repère.png |center | thumb]]&lt;br /&gt;
&lt;br /&gt;
la matrice correspondant au changement (laser -&amp;gt; robot) est la suivante : &lt;br /&gt;
&lt;br /&gt;
 0   -1    0&lt;br /&gt;
 1    0  0.2&lt;br /&gt;
 0    0    1&lt;br /&gt;
&lt;br /&gt;
la matrice 2x2 en haut à gauche correspond à la rotation de 90°, et le vecteur (0, 0.2) correspond à la translation.&lt;br /&gt;
&lt;br /&gt;
Celle du changement (robot -&amp;gt; global) avec alpha angle mesuré par le gyroscope depuis la position initiale (angle 0) :&lt;br /&gt;
&lt;br /&gt;
 cos(alpha)   -sin(alpha)    posInit.x&lt;br /&gt;
 sin(alpha)    cos(alpha)    posInit.y&lt;br /&gt;
          0             0            1&lt;br /&gt;
&lt;br /&gt;
l'étape suivante est de vérifier si les machines vues par le laser sont bien des machines, c'est-à-dire si les positions mesurées à partir des données lasers correspond aux zones occupées par des machines envoyées par la Referee Box.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Grid Map====&lt;br /&gt;
&lt;br /&gt;
L'autre objectif de cette semaine a été de coder le noeud qui génère la map. La map est générée sous forme d'OccupancyGrid. Ce type est constitué d'un seul vecteur dont la première case correspond à la case en bas à gauche de la map. D'autres paramètres sont réglable comme l'origine et la taille.&lt;br /&gt;
&lt;br /&gt;
Pour la taille on choisit de diviser la map en case de 10 cm et l'origine choisie est le x du centre de la map et en y l'abscisse du premier mur (voir la map ci-dessous). Afin d'expliquer comment est constituée cette map, prenons le code et analysons les différentes fonctions ainsi que le main :&lt;br /&gt;
&lt;br /&gt;
Ce vecteur de Pose2D (x, y et theta (angle de la machine)) va permettre d'enregistrer la position des machines, c'est une variable global qui sera mise à jour avec le Callback :&lt;br /&gt;
&lt;br /&gt;
 std::vector&amp;lt;geometry_msgs::Pose2D&amp;gt; tab;&lt;br /&gt;
&lt;br /&gt;
*Récupération des machines envoyées par le noeud du SLAM (sur le topic /landmarks):&lt;br /&gt;
&lt;br /&gt;
 void Poses_Machine_Callback(const deplacement_msg::LandmarksConstPtr &amp;amp;machines)&lt;br /&gt;
 {&lt;br /&gt;
          tab=machines-&amp;gt;landmarks;&lt;br /&gt;
          for (int i=0; i&amp;lt;tab.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
     	     tab[i].x = tab[i].x*1000;&lt;br /&gt;
     	     tab[i].y = tab[i].y*1000;&lt;br /&gt;
 	  }&lt;br /&gt;
    &lt;br /&gt;
  }  &lt;br /&gt;
&lt;br /&gt;
*Création d'une map vide de taille 14m sur 8m. Chaque case est initialisée à une valeur nulle, on remplit également les autres paramètres de OccupancyGrid:&lt;br /&gt;
(On rappelle que la technique utilisée est un vecteur qui représente chaque case auxquelles il associe une probabilité 100 c'est un point interdit et 0 quand c'est un point sans danger pour le passage du robot)&lt;br /&gt;
&lt;br /&gt;
 void Create_Empty_Map(nav_msgs::OccupancyGrid &amp;amp;Map)&lt;br /&gt;
 {&lt;br /&gt;
      Map.info.origin.position.x=-7000;&lt;br /&gt;
      Map.info.origin.position.y=-1000;&lt;br /&gt;
      Map.info.origin.position.z=0;&lt;br /&gt;
      Map.info.origin.orientation.x=0;&lt;br /&gt;
      Map.info.origin.orientation.y=0;&lt;br /&gt;
      Map.info.origin.orientation.z=0;&lt;br /&gt;
      Map.info.origin.orientation.w=1;&lt;br /&gt;
      Map.info.map_load_time=ros::Time::now();&lt;br /&gt;
      Map.info.resolution=100;&lt;br /&gt;
      Map.info.width=140;&lt;br /&gt;
      Map.info.height=80;&lt;br /&gt;
      Map.data.assign(Map.info.width*Map.info.height, 0);                   //map vide&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
*Construction des points fixes de la map donc les murs (probabilité 100) et les zones à risques (probabilité 50):&lt;br /&gt;
&lt;br /&gt;
 void Set_Wall(nav_msgs::OccupancyGrid &amp;amp;Map)&lt;br /&gt;
 {&lt;br /&gt;
    for (int i=0;i&amp;lt;80;i++)&lt;br /&gt;
    {&lt;br /&gt;
       for (int j=0;j&amp;lt;140;j++)&lt;br /&gt;
       {&lt;br /&gt;
          if ((i&amp;lt;13)||(i&amp;gt;67))) Map.data[j+i*140]=100;&lt;br /&gt;
          if ((j&amp;lt;13)||(j&amp;gt;127)) Map.data[j+i*140]=100;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Nous ne mettons pas tout le code de cette fonction étant donné qu'il est long et répétitif puisque c'est le remplissage des données connues, donc en &amp;quot;dur&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*Calcul des positions machines: &lt;br /&gt;
&lt;br /&gt;
Lorsqu'on reçoit une position machine, c'est en fait son centre et son orientation par rapport à x que l'on reçoit. Etant donné que les machines doivent être des rectangles de 110cm sur 75cm (réellement 70 x 35 mais on compte la moitié du robot en plus par sécurité), on décide d'abord de déterminer un des coins du rectangle et plus précisément le coin en bas à droite de ce dernier:&lt;br /&gt;
&lt;br /&gt;
 void Get_One_Point_Of_The_Rectangle(float x, float &amp;amp;xA, float y, float &amp;amp;yA, float theta, float largeur, float longueur)&lt;br /&gt;
 {&lt;br /&gt;
      float x1,y1;&lt;br /&gt;
      x1 = x - cos(theta)*longueur;&lt;br /&gt;
      y1 = y - sin(theta)*longueur; &lt;br /&gt;
      xA = x1 + sin(M_PI_2-theta)*largeur;&lt;br /&gt;
      yA = y1 - cos(M_PI_2-theta)*largeur;&lt;br /&gt;
  &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Remplissage des positions sur la map :&lt;br /&gt;
&lt;br /&gt;
On met alors tous les points de ce rectangle à une probabilité 100 dans le vecteur Map. Pour les calculs on différencie le cas ou l'angle de la machine est entre 0 et pi/2 et le cas où il est entre pi/2 et pi. L'algorithme est le suivant : &lt;br /&gt;
&lt;br /&gt;
 A partir du coin, on incrémente x et y de sorte à longer le grand coté et de remplir chaque case (incrémentation de 5 cm).&lt;br /&gt;
 Une fois arrivé au bout, on incrémente x et y de 5cm sur la largeur à partir du coin et on recommence l'opération précédente.&lt;br /&gt;
 Ceci jusqu'à remplir le complètement le rectangle.&lt;br /&gt;
&lt;br /&gt;
Afin d'établir les probabilités correspondantes aux cases de ce rectangle, nous utilisons la fonctions floor() pour &amp;quot;convertir&amp;quot; nos flottants en entier et accéder à la case correspondante. On notera aussi que la case 1470 correspond à l'origine de notre map.&lt;br /&gt;
&lt;br /&gt;
 void Set_Machines_In_Map(float rank, float theta, float xA, float yA, nav_msgs::OccupancyGrid &amp;amp;Map)&lt;br /&gt;
 {&lt;br /&gt;
      float x=xA;&lt;br /&gt;
      float y=yA;&lt;br /&gt;
      if (theta&amp;lt;=M_PI_2)&lt;br /&gt;
      {&lt;br /&gt;
            for (int j=0;j&amp;lt;10;j++)&lt;br /&gt;
            {&lt;br /&gt;
                  for (int i=0;i&amp;lt;18;i++) &lt;br /&gt;
                  {&lt;br /&gt;
                      Map.data[1470+floor(x/rank)+floor(y/rank)*140]=100;&lt;br /&gt;
                      x = x + cos(theta)*50;&lt;br /&gt;
                      y = y + sin(theta)*50;&lt;br /&gt;
                  }&lt;br /&gt;
                  x = xA - j*cos(M_PI_2-theta)*50;&lt;br /&gt;
                  y = yA + j*sin(M_PI_2-theta)*50;&lt;br /&gt;
            }	&lt;br /&gt;
       }&lt;br /&gt;
       if (theta&amp;gt;M_PI_2)&lt;br /&gt;
       {&lt;br /&gt;
             for (int j=0;j&amp;lt;10;j++)&lt;br /&gt;
             {&lt;br /&gt;
                  for (int i=0;i&amp;lt;18;i++)&lt;br /&gt;
                  {&lt;br /&gt;
                        Map.data[1470+floor(x/rank)+floor(y/rank)*140]=100;&lt;br /&gt;
                        x = x - sin(theta-M_PI_2)*50;&lt;br /&gt;
                        y = y + cos(theta-M_PI_2)*50;&lt;br /&gt;
                  }&lt;br /&gt;
                  x = xA - j*cos(theta-M_PI_2)*50;&lt;br /&gt;
                  y = yA - j*sin(theta-M_PI_2)*50;&lt;br /&gt;
              }	&lt;br /&gt;
        }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Ci dessous on a les mains, avec les différentes fonctions appelées et la syntaxe particulière à ROS. &lt;br /&gt;
&lt;br /&gt;
*Noeud général pour le traitement et le remplissage de la map :   &lt;br /&gt;
                 &lt;br /&gt;
 /*==========  Main  ==========*/&lt;br /&gt;
 int main(int argc, char **argv)&lt;br /&gt;
 {&lt;br /&gt;
     ros::init(argc, argv, &amp;quot;server&amp;quot;);&lt;br /&gt;
     ros::NodeHandle n;&lt;br /&gt;
     ros::Subscriber sub_poses_machine    = n.subscribe(&amp;quot;/machines&amp;quot;, 1000, Poses_Machine_Callback);   // Récupération des machines&lt;br /&gt;
     ros::Publisher Map_Pub = n.advertise&amp;lt;nav_msgs::OccupancyGrid&amp;gt;(&amp;quot;/map&amp;quot;, 1000);                     // Préparation de la publication de la map&lt;br /&gt;
     ROS_INFO(&amp;quot;Ready to Generate the Map&amp;quot;);&lt;br /&gt;
     float xA,yA;&lt;br /&gt;
     ros::Rate loop_rate(1);&lt;br /&gt;
     while(ros::ok())&lt;br /&gt;
     {&lt;br /&gt;
        nav_msgs::OccupancyGrid Map;&lt;br /&gt;
        Create_Empty_Map(Map);&lt;br /&gt;
        Set_Wall(Map);&lt;br /&gt;
        for (int z=0;z&amp;lt;tab.size();z++)&lt;br /&gt;
        {&lt;br /&gt;
           Get_One_Point_Of_The_Rectangle(tab[z].x, xA, tab[z].y, yA, tab[z].theta, 275, 450);&lt;br /&gt;
 	   Set_Machines_In_Map(100, tab[z].theta, xA, yA, Map);&lt;br /&gt;
        }&lt;br /&gt;
        Map_Pub.publish(Map);                                                                   // publication de la map&lt;br /&gt;
        ros::spinOnce();&lt;br /&gt;
        loop_rate.sleep();&lt;br /&gt;
     }&lt;br /&gt;
     return 0;&lt;br /&gt;
  }  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Noeud test qui publie 2 positions de machines : &lt;br /&gt;
&lt;br /&gt;
 /*==========  Main  ==========*/&lt;br /&gt;
 int main(int argc, char **argv)&lt;br /&gt;
 {&lt;br /&gt;
    ros::init(argc, argv, &amp;quot;test&amp;quot;);&lt;br /&gt;
    ros::NodeHandle n;&lt;br /&gt;
    ros::Publisher Pose_Machines_Pub = n.advertise&amp;lt;deplacement_msg::Landmarks&amp;gt;(&amp;quot;/machines&amp;quot;, 1000);&lt;br /&gt;
    ROS_INFO(&amp;quot;Ready to send poses machines&amp;quot;);&lt;br /&gt;
    int xA,yA;&lt;br /&gt;
    ros::Rate loop_rate(1);&lt;br /&gt;
    while(ros::ok())&lt;br /&gt;
    {&lt;br /&gt;
       deplacement_msg::Landmarks machines_msgs;&lt;br /&gt;
       geometry_msgs::Pose2D tab;&lt;br /&gt;
       tab.x=-2;&lt;br /&gt;
       tab.y=2;&lt;br /&gt;
       tab.theta=0;&lt;br /&gt;
       machines_msgs.landmarks.push_back(tab);&lt;br /&gt;
       tab.x=5;&lt;br /&gt;
       tab.y=4;&lt;br /&gt;
       tab.theta=2.5;&lt;br /&gt;
       machines_msgs.landmarks.push_back(tab);&lt;br /&gt;
       Pose_Machines_Pub.publish(machines_msgs);&lt;br /&gt;
       ros::spinOnce();&lt;br /&gt;
       loop_rate.sleep();&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
On visualise le résultat grâce au logiciel RVIZ qui peut lire les topics publiés et donc le topic /map :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Mapcompet.PNG|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Extended Kalman Filter====&lt;br /&gt;
&lt;br /&gt;
l'objectif de cette semaine sera de coder toutes les fonctions nécessaires à l'implémentation finale du [http://fr.wikipedia.org/wiki/Filtre_de_Kalman#Filtre_de_Kalman_.C3.A9tendu filtre de Kalman étendu] :&lt;br /&gt;
&lt;br /&gt;
*initialisations des différents éléments&lt;br /&gt;
*étape de prédiction&lt;br /&gt;
*étape de mise à jour&lt;br /&gt;
*publication des positions machines et du robot dans le repère global via un topic ROS&lt;br /&gt;
&lt;br /&gt;
Le schéma ci-dessous nous montre les deux étapes du filtre de Kalman :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Kalman.png | center]]&lt;br /&gt;
&lt;br /&gt;
le code pour la partie ''prédiction'' :&lt;br /&gt;
&lt;br /&gt;
 //on ressort la position du robot pour l'état n+1&lt;br /&gt;
 //les paramètres sont le vecteurs où on a la position du robot à l'état n, la matrice P, les commandes en vitesses et le temps à l'état n&lt;br /&gt;
 Vector3d prediction(VectorXd xMean, MatrixXd &amp;amp;P, geometry_msgs::Pose2D cmdVel, ros::Time &amp;amp;temps){&lt;br /&gt;
   ros::Duration duree = ros::Time::now() - temps;&lt;br /&gt;
   double periode = duree.toSec();&amp;lt;br&amp;gt;&lt;br /&gt;
   Vector3d cmdVelVect = Pose2DToVector(cmdVel);&lt;br /&gt;
   //le xMean.topLeftCorner(3,1) correspond à la position du robot&lt;br /&gt;
   Vector3d xPredicted = xMean.topLeftCorner(3,1) + periode*cmdVelVect;&amp;lt;br&amp;gt;&lt;br /&gt;
   MatrixXd Fx;&lt;br /&gt;
   Fx = MatrixXd::Identity(P.rows(), P.cols());&lt;br /&gt;
   Fx(0,0) = xPredicted(0);&lt;br /&gt;
   Fx(1,1) = xPredicted(1);&lt;br /&gt;
   Fx(2,2) = xPredicted(2);&amp;lt;br&amp;gt;&lt;br /&gt;
   //mise à jour de P&lt;br /&gt;
   P = Fx*P*(Fx.transpose());&amp;lt;br&amp;gt;&lt;br /&gt;
   //mise à jour du temps&lt;br /&gt;
   temps = ros::Time::now();&amp;lt;br&amp;gt;&lt;br /&gt;
   return xPredicted;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
le code pour la partie ''correction'' :&lt;br /&gt;
&lt;br /&gt;
 void correction(VectorXd &amp;amp;xMean, MatrixXd &amp;amp;P, Vector3d xPredicted, geometry_msgs::Pose2D m){&lt;br /&gt;
   int taille = P.rows();&lt;br /&gt;
   //on vérifie si la machine est présente ou pas dans le vecteur d'état&lt;br /&gt;
   int i = checkStateVector(xMean, m);&amp;lt;br&amp;gt;&lt;br /&gt;
   if (i != 0){&lt;br /&gt;
     //calcul de H&lt;br /&gt;
     MatrixXd H(3, taille);&lt;br /&gt;
     H = buildH(taille, i);&amp;lt;br&amp;gt;&lt;br /&gt;
     //calcul de Pm&lt;br /&gt;
     MatrixXd Pm(taille, taille);&lt;br /&gt;
     Pm = buildPm(P, i);&amp;lt;br&amp;gt;&lt;br /&gt;
     //calcul de Z&lt;br /&gt;
     MatrixXd Z(taille, taille);&lt;br /&gt;
     Z = H*Pm*(H.transpose());	&amp;lt;br&amp;gt;&lt;br /&gt;
     //calcul du gain de Kalman&lt;br /&gt;
     MatrixXd K(taille, taille);&lt;br /&gt;
     K = P*(H.transpose())*(Z.inverse());&amp;lt;br&amp;gt;&lt;br /&gt;
     //mise à jour du vecteur xMean&lt;br /&gt;
     xMean = xMean + K*(xMean.block(xMean.rows()-3,0,3,1) - xPredicted);&amp;lt;br&amp;gt;&lt;br /&gt;
     //mise à jour de la matrice P&lt;br /&gt;
     P = P - K*Z*(K.transpose());&lt;br /&gt;
   }&lt;br /&gt;
   else {&lt;br /&gt;
     addMachine(m, xMean, P);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Pour notre cas, on doit ajouter des nouvelles machines, alors que pour un EKF classique on observe juste des machines déjà répertoriées. Il faut donc une fonction qui permet d'ajouter une machine dans le vecteur d'état. La voilà :&lt;br /&gt;
&lt;br /&gt;
 void addMachine(geometry_msgs::Pose2D machine, VectorXd &amp;amp;xMean, MatrixXd &amp;amp;P){&lt;br /&gt;
   //on redimensionne xMean et P pour accueillir la nouvelle machines&lt;br /&gt;
   xMean.conservativeResize(xMean.rows() + 3);&lt;br /&gt;
   P.conservativeResize(P.rows()+3,P.cols()+3);&amp;lt;br&amp;gt;&lt;br /&gt;
   //on remplit avec les coordonnées de la nouvelle machine&lt;br /&gt;
   xMean(xMean.rows()-3) = machine.x;&lt;br /&gt;
   xMean(xMean.rows()-2) = machine.y;&lt;br /&gt;
   xMean(xMean.rows()-1) = machine.theta;&amp;lt;br&amp;gt;&lt;br /&gt;
   //calcul de tous les PLi&lt;br /&gt;
   //initialisation des PLi à 0&lt;br /&gt;
   P.block(P.rows() - 3, 0, 3, P.cols()).setZero();&lt;br /&gt;
   P.block(0, P.cols() - 3, P.rows(), 3).setZero();&amp;lt;br&amp;gt;&lt;br /&gt;
   for (int j = 0; j &amp;lt; xMean.rows(); j = j + 3){&lt;br /&gt;
     //position de la nouvelle machines par rapport au robot et à toutes les autres&lt;br /&gt;
     double x 	 = xMean(xMean.rows()-3) - xMean(j  );&lt;br /&gt;
     double y 	 = xMean(xMean.rows()-2) - xMean(j+1);&lt;br /&gt;
     double theta = xMean(xMean.rows()-1) - xMean(j+2);&amp;lt;br&amp;gt;&lt;br /&gt;
     P(P.rows()-3, j  ) = x;&lt;br /&gt;
     P(P.rows()-2, j+1) = y;&lt;br /&gt;
     P(P.rows()-1, j+2) = theta;&amp;lt;br&amp;gt;&lt;br /&gt;
     P(j  , P.rows()-3) = x;&lt;br /&gt;
     P(j+1, P.rows()-2) = y;&lt;br /&gt;
     P(j+2, P.rows()-1) = theta;&amp;lt;br&amp;gt;&lt;br /&gt;
     P(j  , j  ) = xMean(j  ) - xMean(0);&lt;br /&gt;
     P(j+1, j+1) = xMean(j+1) - xMean(1);&lt;br /&gt;
     P(j+2, j+2) = xMean(j+2) - xMean(2);&amp;lt;br&amp;gt;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Extended Kalman Filter====&lt;br /&gt;
&lt;br /&gt;
La partie '''prédiction''' du filtre marche parfaitement, quelques corrections ont dues être faites au niveau de la commande vitesse. En effet, Nous avions oublié de la transposer dans le repère global. Pour la partie '''correction''', nous rencontrons un problème de divergence du filtre, qui est probablement due à une mauvaise initialisation. En effet, nous utilisons des enregistrements faits sur notre piste (1/4 de la vraie) avec des initialisations correspondant à la piste originale. Le filtre ne peut donc pas converger car la position de départ est fausse.&lt;br /&gt;
&lt;br /&gt;
===Semaine 11===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Extended Kalman Filter====&lt;br /&gt;
&lt;br /&gt;
Des corrections sont en cours de validation. Nous essayons de définir une initialisation avec les paramètres de notre piste, ce qui n'est pas évident. Les programmes permettant d'extraire les positions machines du filtres ont été réalisé, ainsi qu'un launch pour pouvoir lancer tous les noeuds de la localisation.&lt;br /&gt;
&lt;br /&gt;
===Semaine 12===&lt;br /&gt;
&lt;br /&gt;
====Compétition Open German - mise en place====&lt;br /&gt;
&lt;br /&gt;
Pendant les deux jours de mise en place, nous avons continué à travailler sur la localisation, qui est une partie critique et nécessaire à notre participation. Le filtre en lui même est fonctionnel et permet de corriger la position du robot, ainsi que celle des machines. Cependant, et ce n'est pas un petit &amp;quot;cependant&amp;quot;... Le fait que l'on ajoute des machines en cours de jeu perturbe fortement notre algorithme.&lt;br /&gt;
&lt;br /&gt;
En effet, le filtre de Kalman est optimal si la position des repères est connu, or, un ajout de machine crée un recalage forcé, et si l'on voit plusieurs machines... C'est la '''catastrophe'''. L'ajout de machines est une partie sensible qui nécessite des tests sur la position mesurée, avec un changement de repère à partir de la position du robot, si celle ci dérive, tout dérive. Chaque machine initialisée à la mauvaise position, ou chaque élément détecté comme machine mais n'en étant pas une (faux positif) perturbe le recalage.&lt;br /&gt;
&lt;br /&gt;
De nombreux tests ayant été fait sur la piste officiel avec différentes configurations nous ont permis de vérifier que l'odométrie mesurée ne dérivait que très peu. Il a donc été décidé de n'utiliser que l'odométrie et le scan laser pour la partie '''exploration'''. En effet, chaque machine mesurée est envoyée à un noeud ROS qui va créer une carte et la compléter au fur et à mesure de la partie. Le robot est donc repéré rien qu'avec son odométrie. Le fait que la phase d'exploration (découverte du terrain) ne dure que '''4 minutes''' nous a convaincu pour n'utiliser que cette mesure.&lt;br /&gt;
&lt;br /&gt;
De plus, la carte créée sera utilisée pour la phase suivante, la phase de '''production'''. Cette phase consiste, au niveau de la localisation, à se repérer sur la piste et atteindre la machine demandée par l'exécuteur de tâches. Pour cette phase qui dure '''15 minutes''', l'utilisation du filtre est nécessaire. Donc, avec les coordonnées des machines mesurées pendant la première phase, on peut créer le vecteur d'état et la matrice faisant le lien entre les machines. De là, la taille de ces deux éléments ne variant plus, on peut corriger uniquement la position du robot et le filtre sera efficace.&lt;br /&gt;
&lt;br /&gt;
====Compétition Open German - 1er jour====&lt;br /&gt;
&lt;br /&gt;
Durant ce premier jour, nous avons commencé à ''merger'' nos branches respectives pour pouvoir faire tourner tous nos programmes. Cette phase est laborieuse et nous a pris du temps. De toute façon, toutes les équipes ne sont pas prêtes, les organisateurs non plus. La '''Referee Box''' n'est pas fonctionnel pour la phase de production, ce qui veut dire que nous nous concentrons actuellement sur l'exploration. Les matchs joués aujourd'hui ne nous rapporte donc pas de points. Les tests nous ont permis de valider individuellement chacun des algos, il ne reste &amp;quot;plus qu'à&amp;quot; rejoindre le tout.&lt;br /&gt;
&lt;br /&gt;
====Compétition Open German - 2eme jour====&lt;br /&gt;
&lt;br /&gt;
Niveau '''localisation''', la navigation à l'odométrie et la détection de machine sont fonctionnelles. Cependant, le moyennage fait sur les positions machines (on moyenne toutes les positions trouvées appartenant à une même machine pour n'avoir qu'un seul point) fait que le point correspondant peut être perturbé par des mesures aberrantes. C'est le cas lorsque le robot se déplace à vitesse élevée.&lt;br /&gt;
&lt;br /&gt;
La détection de machine a été améliorée afin de ne rajouter QUE les machines, et pas les murs de la même taille. Nous allons donc retester le '''filtre de Kalman Etendu''' avec cette amélioration. Cependant, ce ne sera fait qu'après la compétition, puisque d'autres problèmes ont nécessité la présence de l'équipe sur certaines parties sensibles du déplacement.&lt;br /&gt;
&lt;br /&gt;
Sur la piste nous avons fait des mesures, qui nous donnent la carte suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PisteSamediSoir.PNG | center]]&lt;br /&gt;
&lt;br /&gt;
La visualisation du trajet pour découvrir ces machines est le suivant :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:DetectionSamediSoir.PNG | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Et les positions machines, ainsi que leur orientation sont les suivantes :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MachinesBagtestSamediSoir.PNG | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
====Compétition Open German - 3eme et dernier jour====&lt;br /&gt;
&lt;br /&gt;
L'architecture choisie pour la localisation est la suivante :&lt;br /&gt;
*Navigation à l'odométrie&lt;br /&gt;
*Détection de machines et moyennage&lt;br /&gt;
*Quand on a vu toutes nos machines, on utilise la symétrie pour compléter les machines restantes&lt;br /&gt;
*Navigation et Localisation avec l'EKF (correction des positions machines et du robot)&lt;br /&gt;
&lt;br /&gt;
====Localisation - Extended Kalman Filter====&lt;br /&gt;
&lt;br /&gt;
Après de longs tests et des corrections importantes au niveau de l'ajout des machines dans le filtre, ce qui était la partie critique... Le meilleur résultat que l'on ait pu avoir avec l'EKF est celui ci dessous. Les machines étant en &amp;lt;span style=&amp;quot;color:#9966CC&amp;quot;&amp;gt;violet&amp;lt;/span&amp;gt;, la trajectoire calculée par l'EKF en &amp;lt;span style=&amp;quot;color:#00FF00&amp;quot;&amp;gt;vert&amp;lt;/span&amp;gt; et la trajectoire mesurée par les codeurs en &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;rouge&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:BestResultWithEKF.PNG | center]]&lt;br /&gt;
&lt;br /&gt;
Nous rappelons que tous nos codes sont disponibles sur notre [https://github.com/PyroTeam/robocup-pkg/tree/navigation-devel/navigation/localisation GIT].&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Mapcompet.PNG&amp;diff=21031</id>
		<title>Fichier:Mapcompet.PNG</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Mapcompet.PNG&amp;diff=21031"/>
				<updated>2015-05-11T06:39:08Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=19509</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=19509"/>
				<updated>2015-03-30T06:54:03Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Génération du noeud Map= */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Etablissement du cahier des charges====&lt;br /&gt;
&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Recherche d'un algorithme de recherche de chemin====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de recherche de chemin, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous avons visualisé les différents algorithmes sur [http://qiao.github.io/PathFinding.js/visual/ PathFinding]&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | 400px | center]][[Image:Projet_S8_A_STAR_2.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | 400px | center]][[Image:Projet_S8_A_STAR_4.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
====Recherche d'une solution pour la localisation====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un '''''Algorithme de Localisation et Cartographie Simultanée''''' (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Découpage du travail à effectuer====&lt;br /&gt;
&lt;br /&gt;
Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
Chaque case du diagramme précédent correspond à un noeud ROS.&lt;br /&gt;
&lt;br /&gt;
Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
*'''Laser''' récupère les données brutes du laser.&lt;br /&gt;
*'''Filtrage''' permet, comme son nom l'indique, d'enlever les éventuels bruits qui affectent les données du laser.&lt;br /&gt;
*'''Reconnaissance des droites''' traite les données laser filtrées pour détecter les droites présentes (Transformée de Hough ou Ransac)&lt;br /&gt;
*'''Reconnaissance des formes''' extrapole les objets (machines) à partir des droites.&lt;br /&gt;
*'''Corrélation emplacements machines''' lie la position des machines détectées au laser et les positions envoyées par RefBoxCom pour éviter les incohérences.&lt;br /&gt;
*'''Odométrie''' récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
*'''Traitement de position''' corrige l'erreur sur le Twist avec les données du gyroscope (par dérivation).&lt;br /&gt;
*'''Fusion de Kalman''' est un algorithme qui va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
*'''Stockage machines + robot''' transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
*'''Grid Map''' renvoit une map utilisée ensuite pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
*'''RefBoxCom''' stocke et renvoie la position des machines.&lt;br /&gt;
*'''Position robot''' renvoie la position exacte du robot sur la grille.&lt;br /&gt;
*'''Manager''' Noeud qui envoie la position à atteindre.&lt;br /&gt;
*'''Pathfinder''' recherche le chemin demandé par le Manager sur une grille&lt;br /&gt;
*'''Parcoureur''' exécute le chemin trouvé en fournissant les vitesses au noeud Déplacement.&lt;br /&gt;
*'''Déplacement''' (noeud robotino_local_move_server), qui donne les commandes aux moteurs à partir de la vitesse linéaire et angulaire envoyée par le Parcoureur.&lt;br /&gt;
&lt;br /&gt;
====Recherche de documentation sur ROS et l'API du Robotino====&lt;br /&gt;
&lt;br /&gt;
Nous avons cherchés toutes les documentations techniques nécessaires pour la programmation de chaque noeud : [http://wiki.ros.org/fr Wiki_ROS] et [http://wiki.ros.org/robotino API_Robotino], nous permettant de mettre à jour le schéma global, notamment au niveau des types.&lt;br /&gt;
&lt;br /&gt;
====Etude de l'algorithme A-star précédent====&lt;br /&gt;
&lt;br /&gt;
Nous nous sommes ensuite concentrés sur le noeud GridMap qui contient ''Map.cpp'' :&lt;br /&gt;
&lt;br /&gt;
Dans le code de l'an dernier, ce noeud générait une grille en dur. Cependant, cette solution n'est pas possible cette année car nous ne connaissons pas toutes les informations sur la piste (on connaît à peu près la position mais pas l'orientation). Il va donc falloir générer une grille en fonction du noeud précédent qui nous renverra un type ''OccupancyGrid''. &lt;br /&gt;
&lt;br /&gt;
Etant donné que ce noeud tournera en permanence, si des informations changent pendant que le robot est sur la piste (détection des nouvelles machines par exemple), le noeud ''Map.cpp'' modifiera la grille en temps réel.&lt;br /&gt;
&lt;br /&gt;
La grille est décomposée en case pour le A-Star :&lt;br /&gt;
&lt;br /&gt;
Si c'est une case interdite (obstacle) ont associe a la case la valeur 1, si elle est autorisée, on associe la valeur 0. On illustre le principe précédent par un exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
Cependant, le noeud &amp;quot;Grid Map&amp;quot; va nous délivrer un vecteur et non une matrice par le biais de ''OccupancyGrid.Data''.Dans notre exemple précédent, on récupère le vecteur suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map_2.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
On choisit donc de transformer ce vecteur en matrice, car l'algorithme A-Star fonctionne sur un graphe, pas un vecteur. On connait la largeur (en case) de la grille grâce au type ''OccupancyGrid.info.width''.&lt;br /&gt;
&lt;br /&gt;
Le pseudo-code pour générer la matrice à partir de ce vecteur sera le suivant :&lt;br /&gt;
&lt;br /&gt;
 fonction create_grid (OccupancyGrid.Data vecteur[size]) : matrice[height].[width]&lt;br /&gt;
 {&lt;br /&gt;
   matrice[height].[width] ;		&lt;br /&gt;
      int t &amp;lt;- size;&lt;br /&gt;
          Pour (i de 0 à height)&lt;br /&gt;
          faire:&lt;br /&gt;
                {&lt;br /&gt;
                    Pour (j de 0 à width)&lt;br /&gt;
                    faire :&lt;br /&gt;
                            {&lt;br /&gt;
                               matrice[i].[j] &amp;lt;- vecteur[t] ;&lt;br /&gt;
                               t++;&lt;br /&gt;
                            }&lt;br /&gt;
                }&lt;br /&gt;
   return matrice;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction====&lt;br /&gt;
&lt;br /&gt;
Nous nous concentrons essentiellement sur la première partie, qui est la partie : &amp;quot;Landmarks Extraction&amp;quot; (extraction des points de repères). On travaille ici dans le repère du laser, qui est différent de celui du robot, et du global. La transposition dans le repère global se fera dans la partie &amp;quot;Data Association&amp;quot;. On doit ainsi, dans l'ordre :&lt;br /&gt;
&lt;br /&gt;
☑ récupérer des données lasers via le topic /scan&amp;lt;br&amp;gt;&lt;br /&gt;
☑ convertir les coordonnées polaires en coordonnées cartésiennes en filtrant les données aberrantes (&amp;gt; range_max et &amp;lt; range_min)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ implémenter l'algorithme [http://fr.wikipedia.org/wiki/RANSAC RANSAC] (Random SAmple Consensus) de détection de droites :&amp;lt;br&amp;gt;&lt;br /&gt;
☑ détecter la &amp;quot;meilleure&amp;quot; droite à partir des points en sélectionnant aléatoirement des combinaisons de points&amp;lt;br&amp;gt;&lt;br /&gt;
☑ stocker le meilleur modèle (angle + tableau de points)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ recommencer tant qu'il reste assez de points à traiter (5)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ extraire les segments à partir des modèles trouvés et des points&amp;lt;br&amp;gt;&lt;br /&gt;
☑ extraire les points extrèmes&amp;lt;br&amp;gt;&lt;br /&gt;
☑ calculer la taille du segment&amp;lt;br&amp;gt;&lt;br /&gt;
☑ chercher des angles droits, des segments de 35 ou 70 cm (largeur et longueur d'une machine)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ extrapoler les positions des machines dans le repère du laser&amp;lt;br&amp;gt;&lt;br /&gt;
☑ définir le barycentre de la machine ainsi que son angle&amp;lt;br&amp;gt;&lt;br /&gt;
☐ stocker ces positions&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Pathfinder====&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi pris du temps avec '''Valentin VERGEZ''', qui a développé, l'an dernier, les codes pour le déplacement du Robotino et le calcul de trajectoire&lt;br /&gt;
&lt;br /&gt;
Nous avons éclairci quelques points sur cette partie du projet :&lt;br /&gt;
*Les commentaires sur l'utilité de chaque fonction ont été rajoutés.&lt;br /&gt;
*Le &amp;quot;code mort&amp;quot; a été nettoyé ainsi que les parties inutiles.&lt;br /&gt;
*Nous devons trouver un moyen de tester cette partie du code seule. (A priori graphiquement).&lt;br /&gt;
&lt;br /&gt;
Etant donné l'arrivée d'un nouvel ordinateur au sein de l'équipe, nous en avons profités pour installer les logiciels qui nous permettrons de faire tourner les noeuds codés sur les Robotino :&lt;br /&gt;
&lt;br /&gt;
*Installation d'Ubuntu 12.04 ( c'est cette version qui permet de faire tourner ROS Hydro)&lt;br /&gt;
&lt;br /&gt;
*Installation de ROS Hydro (ensemble d'outils informatiques open source permettant de développer des logiciels pour la robotique.)&lt;br /&gt;
&lt;br /&gt;
*Installation des paquets nécessaires (catkin, Desktop Install, ROS-Base, Individual Package)&lt;br /&gt;
&lt;br /&gt;
*Installation de GIT (outil de bas niveau permettant de gérer l'évolution du contenu d'une arborescence)&lt;br /&gt;
&lt;br /&gt;
*Vérification que toutes les fonctionnalités de ROS Hydro étaient présentes ( [http://wiki.ros.org/ROS/Tutorials Tutoriel])&lt;br /&gt;
&lt;br /&gt;
La récupération du code complet de l'année dernière et une solution a été trouvée afin de tester le code de génération de trajectoire A-star:&lt;br /&gt;
&lt;br /&gt;
*Pour visualiser une Map ainsi qu'un Path (chemin), on peut utiliser l'outils [http://wiki.ros.org/rviz RVIZ].&lt;br /&gt;
*Dans RVIZ, on peut ajouter un Path (topic /path), ainsi qu'ajouter une Map (/grid): Ceci correspond exactement à ce que nous souhaitons visualiser pour la partie calcul de trajectoire.&lt;br /&gt;
*Pour publier une Map fictive, on executera le script fakeGrid.sh&lt;br /&gt;
*Pour générer un chemin, on lancera le pathfinder (rosruns rbqt_pathfinder server : notre code) et on effectuera une requête avec le script pathReq.sh.&lt;br /&gt;
&lt;br /&gt;
Si tout se passe correctement, le chemin devrait s'afficher en &amp;lt;span style=&amp;quot;color: #00FF00;&amp;quot;&amp;gt; vert &amp;lt;/span&amp;gt; sur la map.&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi du communiquer notre avancement aux autres parties de l'équipe. Le schéma général ainsi qu'un outil permettant d'expliquer les différents algorithmes de recherche de trajectoire optimale nous ont aidé à leur communiquer nos objectifs et les processus choisis.&lt;br /&gt;
&lt;br /&gt;
L'algorithme A-Star que nous allons utiliser donne le résultat final suivant (utilisation du site [http://qiao.github.io/PathFinding.js/visual/ PathFinding] ):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet S8 A STAR E.PNG | center | thumb ]]&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #FFFF00;&amp;quot;&amp;gt; le chemin optimal calculé par A-Star &amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #008000;&amp;quot;&amp;gt; le point de départ&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #FF0000;&amp;quot;&amp;gt; le point d'arrivée&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #808080;&amp;quot;&amp;gt; les points interdits (obstacle)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #00FFFF;&amp;quot;&amp;gt; les points que l'algorithme a déjà calculé&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #00FF00;&amp;quot;&amp;gt; les points que l'algorithme aurait calculé à la prochaine itération&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks extraction - filtrage====&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, nous avons commencé à définir une classe laserScan qui contient la fonction polarToCart, elle convertit les données laser (tableau de ranges) en liste de points (x,y) :&lt;br /&gt;
&lt;br /&gt;
 void laserScan::PolarToCart (){&lt;br /&gt;
  Point p;&lt;br /&gt;
  for (int i=0; i&amp;lt;m_ranges.size(); i++){&lt;br /&gt;
    if((m_ranges[i]&amp;gt;getRangeMin()) &amp;amp;&amp;amp; (m_ranges[i]&amp;lt;getRangeMax())){&lt;br /&gt;
      p.setX(m_ranges[i]*cos(getAngleMin() + i*getAngleInc()));&lt;br /&gt;
      p.setY(m_ranges[i]*sin(getAngleMin() + i*getAngleInc()));&lt;br /&gt;
      m_points.push_back(p);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks extraction - reconnaissance de droite====&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, nous avons déterminé quel algorithme nous allons utiliser : [http://fr.wikipedia.org/wiki/RANSAC#L.27algorithme RANSAC]. L'algorithme de RANSAC trouve la meilleure droite dans un nuage de points. On itère plusieurs fois cet algorithme afin de trouver l'ensemble de toutes les droites du scan laser. On a donc en sortie une liste des droites composants le nuage de points initial.&lt;br /&gt;
&lt;br /&gt;
 Entrée : listOfPoints    -&amp;gt; liste de points initiale &lt;br /&gt;
 Sortie : meilleur_modèle -&amp;gt; les paramètres de la droite qui correspondent le mieux aux points&lt;br /&gt;
                          -&amp;gt; tableau de points à partir desquels la droite a été estimée&lt;br /&gt;
                          -&amp;gt; erreur du modèle de droite par rapport aux points&lt;br /&gt;
&amp;lt;span style=&amp;quot;color: #000080;&amp;quot;&amp;gt;&lt;br /&gt;
 tant que la liste contient assez de points&lt;br /&gt;
  itérateur := 0&lt;br /&gt;
  meilleur_modèle := aucun&lt;br /&gt;
  tant que itérateur &amp;lt; k (fixé par une loi de probabilité)&lt;br /&gt;
   &amp;lt;span style=&amp;quot;color: #008000;&amp;quot;&amp;gt;on choisit deux points au hasard dans la liste&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span style=&amp;quot;color: #00FFFF;&amp;quot;&amp;gt;on fabrique un modèle_possible à partir de ces deux points&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span style=&amp;quot;color: #FF0000;&amp;quot;&amp;gt;Pour chaque point de la liste qui ne sont pas dans le modele_possible&lt;br /&gt;
    si le point s'ajuste au modele_possible avec une erreur inférieure à t&lt;br /&gt;
     Ajouter ce point au modele&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color: #00FF00;&amp;quot;&amp;gt;si le nombre de points dans le modele est suffisant pour valider l'existence du modele&lt;br /&gt;
     erreur := coefficient de corrélation de la régression linéaire de ensemble_points&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color: #808080;&amp;quot;&amp;gt;si erreur &amp;lt; erreur du meilleur_modele&lt;br /&gt;
     meilleur_modèle := modèle_possible&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  stocker meilleur_modèle dans liste de modèles&lt;br /&gt;
  retirer meilleur_ensemble_points de la liste des points initiale&lt;br /&gt;
  recommencer avec la liste modifiée&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - reconnaissance de droite====&lt;br /&gt;
&lt;br /&gt;
Nous avons adapté l'algorithme précédent afin de mieux correspondre aux structures que nous avons créées :&lt;br /&gt;
*Modele&lt;br /&gt;
**Liste de points&lt;br /&gt;
**Liste d'indices&lt;br /&gt;
**Corrélation&lt;br /&gt;
**Droite&lt;br /&gt;
***Point&lt;br /&gt;
***Angle&lt;br /&gt;
**Segment&lt;br /&gt;
***Point &amp;quot;min&amp;quot;&lt;br /&gt;
***Point &amp;quot;max&amp;quot;&lt;br /&gt;
***Angle&lt;br /&gt;
***Taille&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi codé toutes les fonctions nécessaires dans l'algorithme de Ransac, dont celle permettant la correction de l'approximation de droite par régression linéaire des points correspondants à un modèle trouvé (''linReg()'') qui nous a donné matière à réflexion. Aussi, notre première idée qui était de travailler avec des ''std::vector'' a du changer puisque l'aspect récursif de l'algorithme que nous allons utiliser nécessite de multiples suppressions sur les données à entrer dans l'algorithme de Ransac. On travaille donc maintenant avec des ''std::list''.&lt;br /&gt;
&lt;br /&gt;
Tous nos codes sont disponibles sur la branche [https://github.com/PyroTeam/robocup-pkg/tree/feature/navigation/SLAM/navigation/localisation/src feature/navigation/SLAM du GIT de l'équipe PyroTeam].&lt;br /&gt;
&lt;br /&gt;
===Semaine de vacances de février===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - reconnaissance de droite====&lt;br /&gt;
&lt;br /&gt;
Nous devons réaliser un noeud permettant de valider notre algorithme, c'est-à-dire implémenter sous ROS notre code C++ afin de tester, soit directement sur le robot, soit avec des [http://wiki.ros.org/Bags bagfiles]. Cette étape est très importante pour pouvoir passer à la suite : extrapoler les droites trouvées en segments puis en objets.&lt;br /&gt;
&lt;br /&gt;
Notre programme consistant à reconnaître les droites à partir du scan laser est fonctionnel et a été testé à partir du scan laser suivant :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ScanLaser.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Processus de validation :&lt;br /&gt;
&lt;br /&gt;
*Lancer le programme ''rosrun localisation test_polar_to_cart''&lt;br /&gt;
&lt;br /&gt;
résultat : on trouve 5 droites&lt;br /&gt;
&lt;br /&gt;
 m = -0.0229637 p = -0.24079&lt;br /&gt;
 nb de points dans la droite : 246&lt;br /&gt;
 coeff de correlation : 0.812376&lt;br /&gt;
&lt;br /&gt;
 m = -0.0315132 p = 3.7506&lt;br /&gt;
 nb de points dans la droite : 102&lt;br /&gt;
 coeff de correlation : 0.928089&lt;br /&gt;
&lt;br /&gt;
 m = 32.9243 p = -139.943&lt;br /&gt;
 nb de points dans la droite : 77&lt;br /&gt;
 coeff de correlation : 0.914475&lt;br /&gt;
&lt;br /&gt;
 m = 7.04634 p = -15.42&lt;br /&gt;
 nb de points dans la droite : 32&lt;br /&gt;
 coeff de correlation : 0.970724&lt;br /&gt;
&lt;br /&gt;
 m = 0.253029 p = 1.32235&lt;br /&gt;
 nb de points dans la droite : 28&lt;br /&gt;
 coeff de correlation : 0.979578&lt;br /&gt;
&lt;br /&gt;
ce qui correspond à l'image suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:DroitesTrouvées.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
On voit que la recherche de droite marche bien, mais peut être améliorée en ajoutant des conditions de proximité des points correspondants à une seule droite, pour éviter le phénomène que l'on voit au milieu. Le résultat après avoir ajouté cette condition et en ayant affiné au maximum les paramètres, au dépend d'un temps de calcul beaucoup plus élevé (9,416 secondes au lieu de 0,536 s)  :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:DroitesTrouvées2.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Les impératifs de la compétition nous imposant une certaine rapidité pour se localiser et détecter les machines, nous retiendrons la solution la plus rapide et nous séparerons les droites en segment après leur détection.&lt;br /&gt;
&lt;br /&gt;
Pour valider l'algorithme de régression linéaire nous avons :&lt;br /&gt;
*Récupéré tous les points correspondants à chaque droite&lt;br /&gt;
*Rentré ces points sur Excel&lt;br /&gt;
*Fait une courbe de tendance&lt;br /&gt;
*Affiché l'équation de droite et le coefficient de corrélation&lt;br /&gt;
*Comparé avec ce qu'a trouvé notre programme&lt;br /&gt;
*Conclu que notre programme était bon&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - reconnaissance de machines====&lt;br /&gt;
&lt;br /&gt;
Les objectifs de cette semaine :&lt;br /&gt;
&lt;br /&gt;
*à partir de la liste de droites, extraire les segments&lt;br /&gt;
*extrapoler les positions machines à partir d'un segment complet (35 ou 70 cm)&lt;br /&gt;
*réaliser une interface graphique pour visualiser les segments trouvés en temps réel&lt;br /&gt;
*regarder ce qu'on doit rentrer dans l' '''Extended Kalman Filter''' au niveau du format des positions machines et de l'odométrie pour pouvoir réaliser le '''Data Association''' de façon cohérente avec la suite.&lt;br /&gt;
&lt;br /&gt;
L'extraction de segment à partir des 5 droite précédemment trouvées nous donne 7 segments:&lt;br /&gt;
&lt;br /&gt;
 Segment 1&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(-1.04033e-08, -0.238)&lt;br /&gt;
 Max(4.24699, -0.26092)&lt;br /&gt;
 taille : 4.24705&lt;br /&gt;
 angle  : -0.309205&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 2&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(-1.64267e-07, 3.758)&lt;br /&gt;
 Max(3.4172, 3.63358)&lt;br /&gt;
 taille : 3.41946&lt;br /&gt;
 angle  : -2.08521&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 3&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(4.24452, -0.234635)&lt;br /&gt;
 Max(4.33124, 2.18017)&lt;br /&gt;
 taille : 2.41636&lt;br /&gt;
 angle  : 87.9432&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 4&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(2.30055, 0.871242)&lt;br /&gt;
 Max(2.32511, 0.736592)&lt;br /&gt;
 taille : 0.136872&lt;br /&gt;
 angle  : -79.6622&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 5&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(2.50359, 2.18655)&lt;br /&gt;
 Max(2.53413, 2.56542)&lt;br /&gt;
 taille : 0.380104&lt;br /&gt;
 angle  : 85.3914&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 6&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(2.73122, 2.05171)&lt;br /&gt;
 Max(3.049, 2.03728)&lt;br /&gt;
 taille : 0.318107&lt;br /&gt;
 angle  : -2.5999&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 7&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(1.14156, 1.64221)&lt;br /&gt;
 Max(1.39648, 1.61891)&lt;br /&gt;
 taille : 0.255984&lt;br /&gt;
 angle  : -5.22068&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SegmentsTrouvés.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Tout cela en 0,540s !&lt;br /&gt;
&lt;br /&gt;
A partir de la liste de segments précédente, on extrait une liste de machine à partir des segments de 35 ou 70 cm, qui sont les tailles des machines. Comme le scan que nous utilisons pour le moment n'est pas un scan avec une vraie machine, mais disposant quand même de 2 segments d'à peu près 35 cm, nous utilisons ces deux segments comme ''petit côté'' de la machine. On trouve ainsi deux machines :&lt;br /&gt;
&lt;br /&gt;
 Machine 1&lt;br /&gt;
   centre en (2.53292, 2.20155)&lt;br /&gt;
   orientation : 175.391°&lt;br /&gt;
&lt;br /&gt;
 Machine 2&lt;br /&gt;
   centre en (3.06493, 2.05243)&lt;br /&gt;
   orientation : 87.4001°&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une amélioration de l'algorithme a été faite pour la détection de machine. En effet, dans le cas où on détectait un petit et un grand côté de machine, on trouvait deux machines avec des centres à peu près au même endroit. Maintenant, on fusionne ces données en créant un point milieu entre les deux données, et on prend l'orientation du grand côté.&lt;br /&gt;
&lt;br /&gt;
On a commencé à faire des tests sur ROS directement avec un noeud factice qui publie un scan laser à une fréquence de 10Hz, ce qui est la fréquence réelle du laser Hokuyo. La détection se fait assez rapidement et de façon précise. Des tests sur le robot sont prévus en début de semaine 7 avec les vraies machines.&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Data Association====&lt;br /&gt;
&lt;br /&gt;
L'objectif principal de cette semaine est de coder le noeud '''Data Association''' qui liera la position donnée par l'odométrie (mesure relative de la position par rapport à un point de départ à peu près connu) avec les machines trouvées dans le champ du laser.&lt;br /&gt;
&lt;br /&gt;
Il faudra aussi corriger l'odométrie donné par le nœud ''robotino_odometry_node'', qui donne l'odométrie (mesure de la position et de la vitesse du robot). Le problème est que nous utilisons un gyroscope externe, car le gyroscope de base est de très basse qualité. Or, si le nœud corrige parfaitement la position, il ne corrige pas du tout la vitesse angulaire ! Nous devons donc réaliser un nœud qui le fera pour nous.&lt;br /&gt;
&lt;br /&gt;
D'après la dernière version du sujet 2015, l'aire de jeu de 6 x 12 m est séparée en zones de 1,5 x 2 m de large, dans lesquelles se situent une seule machine. Chaque équipe a 6 machines dont la zone est connue, donnée par la Referee Box. Le but du nœud ROS de ''Data Association'' sera de transposer les positions machines dans le repère global de la piste, ainsi le Manager pour savoir devant quelle machine le robot est, et connaître sa position et son orientation.&lt;br /&gt;
&lt;br /&gt;
La piste sera donc comme cela :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Piste.PNG | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
La correction d'odométrie a fait apparaître une erreur de mesure d'environ 1,7°/s sur la vitesse angulaire, à faible vitesse. Pour de la Localisation et Cartographie Simultanée, c'est assez important. Ça justifie donc la nécessité de faire cet ajustement.&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il a été décidé de fusionner les nœuds '''Data Association''' et '''Extended Kalman Filter''' puisque l'association de données n'étant au final qu'un changement de repère, la structure de nœud ROS n'est pas adaptée.&lt;br /&gt;
&lt;br /&gt;
Nous avons trouvé un [https://github.com/yangyimeng/machine-learning/blob/master/slam/EKF/SLAM%20course.pdf PDF] expliquant l'algorithme de SLAM. Grâce à celui ci nous avons déterminer les éléments à rentrer dans le noeud, ainsi que les différentes opérations incluses dans ce filtre. Pour les calculs matriciels, nous allons probablement utiliser la librairie EIGEN pour travailler sur des [http://eigen.tuxfamily.org/dox/classEigen_1_1Matrix.html matrices] de façon optimisée. La prochaine étape sera de &amp;quot;typer&amp;quot; nos informations (position robot + machine + murs) pour pouvoir les intégrer facilement au filtre. Nous avons aussi décidé d'inclure les murs comme ''landmark'' dans la matrice de covariance du vecteur d'état.&lt;br /&gt;
&lt;br /&gt;
Il a été décidé de faire une association de données avant la détection de machines, pour distinguer les pans de murs directement afin de stocker ces informations directement à la source. On pourra éventuellement détecter les coins intérieurs de la piste pour plus de précision dans le recalage. Pour le reste, rien ne change.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - vidéo====&lt;br /&gt;
&lt;br /&gt;
Pour visualiser les résultats de la détection des machines nous avons utiliser l'interface graphique disponible avec ROS, RVIZ. Nous visualisons alors le scan laser (points blancs), le résultat de la détection de segments (en rouge) et les positions des machines trouvées (en vert). Un premier test a été fait sur le scan originel, celui sur lequel nous avons travaillé depuis le début.&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/watch?v=XSn4s1y-XT0 Visualisation des machines]&lt;br /&gt;
&lt;br /&gt;
On rencontre un problème quand le robot est exactement parallèle ou perpendiculaire à un mur. Après vérification dans le programme, il s'avère que la détection ne fonctionne pas pour ces cas. Ce bug est maintenant corrigé :&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/watch?v=rKeqewpuLoQ Correction du bug]&lt;br /&gt;
====Localisation - Data Association====&lt;br /&gt;
&lt;br /&gt;
La première étape consiste juste à faire un changement de repère, d'abord du repère laser vers le repère robot, puisque le laser sera placé en avant du robot, puis du repère robot au repère global, comme ci dessous :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Chgt_Repère.png |center | thumb]]&lt;br /&gt;
&lt;br /&gt;
la matrice correspondant au changement (laser -&amp;gt; robot) est la suivante : &lt;br /&gt;
&lt;br /&gt;
 0   -1    0&lt;br /&gt;
 1    0  0.2&lt;br /&gt;
 0    0    1&lt;br /&gt;
&lt;br /&gt;
la matrice 2x2 en haut à gauche correspond à la rotation de 90°, et le vecteur (0, 0.2) correspond à la translation.&lt;br /&gt;
&lt;br /&gt;
Celle du changement (robot -&amp;gt; global) avec alpha angle mesuré par le gyroscope depuis la position initiale (angle 0) :&lt;br /&gt;
&lt;br /&gt;
 cos(alpha)   -sin(alpha)    posInit.x&lt;br /&gt;
 sin(alpha)    cos(alpha)    posInit.y&lt;br /&gt;
          0             0            1&lt;br /&gt;
&lt;br /&gt;
l'étape suivante est de vérifier si les machines vues par le laser sont bien des machines, c'est-à-dire si les positions mesurées à partir des données lasers correspond aux zones occupées par des machines envoyées par la Referee Box.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Génération du noeud Map===&lt;br /&gt;
&lt;br /&gt;
L'autre objectif de cette semaine a été de coder le noeud qui génère la map. La map est générée sous forme d'OccupancyGrid. Ce type est constitué d'un seul vecteur dont la première case correspond à la case en bas à gauche de la map. D'autres paramètres sont réglable comme l'origine, la taille etc.&lt;br /&gt;
&lt;br /&gt;
Pour la taille on choisi de diviser la map en case de 10 cm (100 mm) et l'origine choisi est le centre de la mep en x et en y le premier mur (voir la map ci-dessous)&lt;br /&gt;
&lt;br /&gt;
Afin d'expliquer comment est constituée cette map, prenons le code et analysons les différentes fonctions:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;Map.hpp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ce vecteur de Pose2D (x et y) va permettre d'enregistrer le vecteur qui contient la position des machines :&lt;br /&gt;
&lt;br /&gt;
 std::vector&amp;lt;geometry_msgs::Pose2D&amp;gt; tab;    &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                 &lt;br /&gt;
 /*==========  Main  ==========*/&lt;br /&gt;
 int main(int argc, char **argv)&lt;br /&gt;
 {&lt;br /&gt;
     ros::init(argc, argv, &amp;quot;server&amp;quot;);&lt;br /&gt;
     ros::NodeHandle n;&lt;br /&gt;
     ros::Subscriber sub_poses_machine    = n.subscribe(&amp;quot;/machines&amp;quot;, 1000, Poses_Machine_Callback);   // Récupération des machines&lt;br /&gt;
     ros::Publisher Map_Pub = n.advertise&amp;lt;nav_msgs::OccupancyGrid&amp;gt;(&amp;quot;/map&amp;quot;, 1000);                     // Préparation de la publication de la map&lt;br /&gt;
     ROS_INFO(&amp;quot;Ready to Generate the Map&amp;quot;);&lt;br /&gt;
     float xA,yA;&lt;br /&gt;
     ros::Rate loop_rate(1);&lt;br /&gt;
     while(ros::ok())&lt;br /&gt;
     {&lt;br /&gt;
     nav_msgs::OccupancyGrid Map;&lt;br /&gt;
     Create_Empty_Map(Map);&lt;br /&gt;
     Set_Wall(Map);&lt;br /&gt;
     for (int z=0;z&amp;lt;tab.size();z++)&lt;br /&gt;
         {&lt;br /&gt;
 		Get_One_Point_Of_The_Rectangle(tab[z].x, xA, tab[z].y, yA, tab[z].theta, 275, 450);&lt;br /&gt;
 		Set_Machines_In_Map(100, tab[z].theta, xA, yA, Map);&lt;br /&gt;
   	}&lt;br /&gt;
  	Map_Pub.publish(Map);                                                                   // publication de la map&lt;br /&gt;
  	ros::spinOnce();&lt;br /&gt;
 	loop_rate.sleep();&lt;br /&gt;
  	}&lt;br /&gt;
     return 0;&lt;br /&gt;
  }  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cette fonction va récupérer les machines envoyées par le noeud du slam (sur le message landmarks):&lt;br /&gt;
&lt;br /&gt;
 void Poses_Machine_Callback(const deplacement_msg::LandmarksConstPtr &amp;amp;machines)&lt;br /&gt;
 {&lt;br /&gt;
          tab=machines-&amp;gt;landmarks;&lt;br /&gt;
          for (int i=0; i&amp;lt;tab.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
     	     tab[i].x = tab[i].x*1000;&lt;br /&gt;
     	     tab[i].y = tab[i].y*1000;&lt;br /&gt;
 	  }&lt;br /&gt;
    &lt;br /&gt;
  }  &lt;br /&gt;
&lt;br /&gt;
Cette fonction va créer une map vide de taille 14m sur 8m. Chaque case à une valeur nulle, il remplit aussi les autres paramètres de OccupancyGrid:&lt;br /&gt;
(On rappelle que la technique utilisée est un vecteur qui représente chaque case auxquelles il associe une probabilité 100 étant un point interdit et 0 un point sans danger de passage pour le robot)&lt;br /&gt;
&lt;br /&gt;
 void Create_Empty_Map(nav_msgs::OccupancyGrid &amp;amp;Map)&lt;br /&gt;
 {&lt;br /&gt;
      Map.info.origin.position.x=-7000;&lt;br /&gt;
      Map.info.origin.position.y=-1000;&lt;br /&gt;
      Map.info.origin.position.z=0;&lt;br /&gt;
      Map.info.origin.orientation.x=0;&lt;br /&gt;
      Map.info.origin.orientation.y=0;&lt;br /&gt;
      Map.info.origin.orientation.z=0;&lt;br /&gt;
      Map.info.origin.orientation.w=1;&lt;br /&gt;
      Map.info.map_load_time=ros::Time::now();&lt;br /&gt;
      Map.info.resolution=100;&lt;br /&gt;
      Map.info.width=140;&lt;br /&gt;
      Map.info.height=80;&lt;br /&gt;
      Map.data.assign(Map.info.width*Map.info.height, 0);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Ce noeud va construire les points fixes de la map donc les murs (probabilité 100) et les zones à risques (probabilité 50):&lt;br /&gt;
&lt;br /&gt;
 void Set_Wall(nav_msgs::OccupancyGrid &amp;amp;Map)&lt;br /&gt;
 {&lt;br /&gt;
      for (int i=0;i&amp;lt;80;i++)&lt;br /&gt;
         {&lt;br /&gt;
           for (int j=0;j&amp;lt;140;j++)&lt;br /&gt;
		 {	&lt;br /&gt;
		 	 if ((i&amp;lt;13)||(i&amp;gt;67)) Map.data[j+i*140]=100;&lt;br /&gt;
                         if ((j&amp;lt;13)||(j&amp;gt;127)) Map.data[j+i*140]=100;&lt;br /&gt;
                 }&lt;br /&gt;
         }&lt;br /&gt;
      for (int i=0;i&amp;lt;80;i++)&lt;br /&gt;
         {&lt;br /&gt;
           for (int j=0;j&amp;lt;140;j++)&lt;br /&gt;
                {&lt;br /&gt;
                         if ((i&amp;lt;10)||(i&amp;gt;70)) Map.data[j+i*140]=50;&lt;br /&gt;
                         if ((j&amp;lt;10)||(j&amp;gt;130)) Map.data[j+i*140]=50;&lt;br /&gt;
                }  &lt;br /&gt;
&lt;br /&gt;
Nous ne mettons pas tout le code de cette fonction étant donné qu'il est long et répétitif afin de tout remplir&lt;br /&gt;
	&lt;br /&gt;
&lt;br /&gt;
Maintenant, nous passons aux positions machines: &lt;br /&gt;
&lt;br /&gt;
Lorsqu'on reçoit une position machine, c'est en fait son centre et son orientation par rapport à x que l'on reçoit.&lt;br /&gt;
Etant donné que les machines doivent être des rectangles de 90cm sur 55cm, on décide d'abord de déterminer un des coins du rectangle et plus précisément le coin en bas à droite de ce dernier:&lt;br /&gt;
&lt;br /&gt;
 void Get_One_Point_Of_The_Rectangle(float x, float &amp;amp;xA, float y, float &amp;amp;yA, float theta, float largeur, float longueur)&lt;br /&gt;
 {&lt;br /&gt;
      float x1,y1;&lt;br /&gt;
      x1 = x - cos(theta)*longueur;&lt;br /&gt;
      y1 = y - sin(theta)*longueur; &lt;br /&gt;
      xA = x1 + sin(M_PI_2-theta)*largeur;&lt;br /&gt;
      yA = y1 - cos(M_PI_2-theta)*largeur;&lt;br /&gt;
  &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Il reste ensuite à mettre tout les points de se rectangles à une probabilité 100 dans le vecteur Map.&lt;br /&gt;
Pour les calculs on différencie le cas ou l'angle de la machine est entre 0 et pi/2 et le cas où il est entre pi/2 et pi.&lt;br /&gt;
L'algorithme est le suivant : &lt;br /&gt;
&lt;br /&gt;
A partir du coin, on incrémente x et y de sorte à longer le grand coté et de remplir chaque case (incrémentation de 5 cm).&lt;br /&gt;
Une fois arrivé au bout, on incrémente x et y de 5cm sur la largeur à partir du coin et on recommence l'opération précédente.&lt;br /&gt;
Ceci jusqu'à remplir le complètement le rectangle.&lt;br /&gt;
&lt;br /&gt;
Afin d'établir les probabilités de ce rectangle, nous utilisons la fonctions floor pour convertir nos flottants en entier et accéder à la case correspondante.&lt;br /&gt;
On notera aussi que la case 1470 correspond à l'origine de notre map.&lt;br /&gt;
&lt;br /&gt;
 void Set_Machines_In_Map(float rank, float theta, float xA, float yA, nav_msgs::OccupancyGrid &amp;amp;Map)&lt;br /&gt;
 {&lt;br /&gt;
      float x=xA;&lt;br /&gt;
      float y=yA;&lt;br /&gt;
      if (theta&amp;lt;=M_PI_2)&lt;br /&gt;
      {&lt;br /&gt;
            for (int j=0;j&amp;lt;10;j++)&lt;br /&gt;
            {&lt;br /&gt;
                  for (int i=0;i&amp;lt;18;i++) &lt;br /&gt;
                  {&lt;br /&gt;
                      Map.data[1470+floor(x/rank)+floor(y/rank)*140]=100;&lt;br /&gt;
                      x = x + cos(theta)*50;&lt;br /&gt;
                      y = y + sin(theta)*50;&lt;br /&gt;
                  }&lt;br /&gt;
                  x = xA - j*cos(M_PI_2-theta)*50;&lt;br /&gt;
                  y = yA + j*sin(M_PI_2-theta)*50;&lt;br /&gt;
            }	&lt;br /&gt;
       }&lt;br /&gt;
       if (theta&amp;gt;M_PI_2)&lt;br /&gt;
       {&lt;br /&gt;
             for (int j=0;j&amp;lt;10;j++)&lt;br /&gt;
             {&lt;br /&gt;
                  for (int i=0;i&amp;lt;18;i++)&lt;br /&gt;
                  {&lt;br /&gt;
                        Map.data[1470+floor(x/rank)+floor(y/rank)*140]=100;&lt;br /&gt;
                        x = x - sin(theta-M_PI_2)*50;&lt;br /&gt;
                        y = y + cos(theta-M_PI_2)*50;&lt;br /&gt;
                  }&lt;br /&gt;
                  x = xA - j*cos(theta-M_PI_2)*50;&lt;br /&gt;
                  y = yA - j*sin(theta-M_PI_2)*50;&lt;br /&gt;
              }	&lt;br /&gt;
        }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
On crée un noeud test qui publie 2 positions de machines : &lt;br /&gt;
 #include &amp;quot;Test.hpp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /*==========  Main  ==========*/&lt;br /&gt;
 int main(int argc, char **argv)&lt;br /&gt;
 {&lt;br /&gt;
    ros::init(argc, argv, &amp;quot;test&amp;quot;);&lt;br /&gt;
    ros::NodeHandle n;&lt;br /&gt;
    ros::Publisher Pose_Machines_Pub = n.advertise&amp;lt;deplacement_msg::Landmarks&amp;gt;(&amp;quot;/machines&amp;quot;, 1000);&lt;br /&gt;
    ROS_INFO(&amp;quot;Ready to send poses machines&amp;quot;);&lt;br /&gt;
    int xA,yA;&lt;br /&gt;
    ros::Rate loop_rate(1);&lt;br /&gt;
    while(ros::ok())&lt;br /&gt;
    {&lt;br /&gt;
    deplacement_msg::Landmarks machines_msgs;&lt;br /&gt;
    geometry_msgs::Pose2D tab;&lt;br /&gt;
    tab.x=-2;&lt;br /&gt;
    tab.y=2;&lt;br /&gt;
    tab.theta=0;&lt;br /&gt;
    machines_msgs.landmarks.push_back(tab);&lt;br /&gt;
    tab.x=5;&lt;br /&gt;
    tab.y=4;&lt;br /&gt;
    tab.theta=2.5;&lt;br /&gt;
    machines_msgs.landmarks.push_back(tab);&lt;br /&gt;
 	Pose_Machines_Pub.publish(machines_msgs);&lt;br /&gt;
 	ros::spinOnce();&lt;br /&gt;
        loop_rate.sleep();&lt;br /&gt;
 	}&lt;br /&gt;
    return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
On visualise le résultat grâce au logiciel RVIZ qui peut lire les topics publiés et donc le topic /map !:&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Extended Kalman Filter====&lt;br /&gt;
&lt;br /&gt;
l'objectif de cette semaine sera de coder toutes les fonctions nécessaires à l'implémentation finale du [http://fr.wikipedia.org/wiki/Filtre_de_Kalman#Filtre_de_Kalman_.C3.A9tendu filtre de Kalman étendu] :&lt;br /&gt;
&lt;br /&gt;
*initialisations des différents éléments&lt;br /&gt;
*étape de prédiction&lt;br /&gt;
*étape de mise à jour&lt;br /&gt;
*publication des positions machines et du robot dans le repère global via un topic ROS&lt;br /&gt;
&lt;br /&gt;
Le schéma ci-dessous nous montre les deux étapes du filtre de Kalman :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Kalman.png | center]]&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=19508</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=19508"/>
				<updated>2015-03-30T06:20:44Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Semaine 8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Etablissement du cahier des charges====&lt;br /&gt;
&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Recherche d'un algorithme de recherche de chemin====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de recherche de chemin, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous avons visualisé les différents algorithmes sur [http://qiao.github.io/PathFinding.js/visual/ PathFinding]&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | 400px | center]][[Image:Projet_S8_A_STAR_2.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | 400px | center]][[Image:Projet_S8_A_STAR_4.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
====Recherche d'une solution pour la localisation====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un '''''Algorithme de Localisation et Cartographie Simultanée''''' (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Découpage du travail à effectuer====&lt;br /&gt;
&lt;br /&gt;
Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
Chaque case du diagramme précédent correspond à un noeud ROS.&lt;br /&gt;
&lt;br /&gt;
Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
*'''Laser''' récupère les données brutes du laser.&lt;br /&gt;
*'''Filtrage''' permet, comme son nom l'indique, d'enlever les éventuels bruits qui affectent les données du laser.&lt;br /&gt;
*'''Reconnaissance des droites''' traite les données laser filtrées pour détecter les droites présentes (Transformée de Hough ou Ransac)&lt;br /&gt;
*'''Reconnaissance des formes''' extrapole les objets (machines) à partir des droites.&lt;br /&gt;
*'''Corrélation emplacements machines''' lie la position des machines détectées au laser et les positions envoyées par RefBoxCom pour éviter les incohérences.&lt;br /&gt;
*'''Odométrie''' récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
*'''Traitement de position''' corrige l'erreur sur le Twist avec les données du gyroscope (par dérivation).&lt;br /&gt;
*'''Fusion de Kalman''' est un algorithme qui va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
*'''Stockage machines + robot''' transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
*'''Grid Map''' renvoit une map utilisée ensuite pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
*'''RefBoxCom''' stocke et renvoie la position des machines.&lt;br /&gt;
*'''Position robot''' renvoie la position exacte du robot sur la grille.&lt;br /&gt;
*'''Manager''' Noeud qui envoie la position à atteindre.&lt;br /&gt;
*'''Pathfinder''' recherche le chemin demandé par le Manager sur une grille&lt;br /&gt;
*'''Parcoureur''' exécute le chemin trouvé en fournissant les vitesses au noeud Déplacement.&lt;br /&gt;
*'''Déplacement''' (noeud robotino_local_move_server), qui donne les commandes aux moteurs à partir de la vitesse linéaire et angulaire envoyée par le Parcoureur.&lt;br /&gt;
&lt;br /&gt;
====Recherche de documentation sur ROS et l'API du Robotino====&lt;br /&gt;
&lt;br /&gt;
Nous avons cherchés toutes les documentations techniques nécessaires pour la programmation de chaque noeud : [http://wiki.ros.org/fr Wiki_ROS] et [http://wiki.ros.org/robotino API_Robotino], nous permettant de mettre à jour le schéma global, notamment au niveau des types.&lt;br /&gt;
&lt;br /&gt;
====Etude de l'algorithme A-star précédent====&lt;br /&gt;
&lt;br /&gt;
Nous nous sommes ensuite concentrés sur le noeud GridMap qui contient ''Map.cpp'' :&lt;br /&gt;
&lt;br /&gt;
Dans le code de l'an dernier, ce noeud générait une grille en dur. Cependant, cette solution n'est pas possible cette année car nous ne connaissons pas toutes les informations sur la piste (on connaît à peu près la position mais pas l'orientation). Il va donc falloir générer une grille en fonction du noeud précédent qui nous renverra un type ''OccupancyGrid''. &lt;br /&gt;
&lt;br /&gt;
Etant donné que ce noeud tournera en permanence, si des informations changent pendant que le robot est sur la piste (détection des nouvelles machines par exemple), le noeud ''Map.cpp'' modifiera la grille en temps réel.&lt;br /&gt;
&lt;br /&gt;
La grille est décomposée en case pour le A-Star :&lt;br /&gt;
&lt;br /&gt;
Si c'est une case interdite (obstacle) ont associe a la case la valeur 1, si elle est autorisée, on associe la valeur 0. On illustre le principe précédent par un exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
Cependant, le noeud &amp;quot;Grid Map&amp;quot; va nous délivrer un vecteur et non une matrice par le biais de ''OccupancyGrid.Data''.Dans notre exemple précédent, on récupère le vecteur suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map_2.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
On choisit donc de transformer ce vecteur en matrice, car l'algorithme A-Star fonctionne sur un graphe, pas un vecteur. On connait la largeur (en case) de la grille grâce au type ''OccupancyGrid.info.width''.&lt;br /&gt;
&lt;br /&gt;
Le pseudo-code pour générer la matrice à partir de ce vecteur sera le suivant :&lt;br /&gt;
&lt;br /&gt;
 fonction create_grid (OccupancyGrid.Data vecteur[size]) : matrice[height].[width]&lt;br /&gt;
 {&lt;br /&gt;
   matrice[height].[width] ;		&lt;br /&gt;
      int t &amp;lt;- size;&lt;br /&gt;
          Pour (i de 0 à height)&lt;br /&gt;
          faire:&lt;br /&gt;
                {&lt;br /&gt;
                    Pour (j de 0 à width)&lt;br /&gt;
                    faire :&lt;br /&gt;
                            {&lt;br /&gt;
                               matrice[i].[j] &amp;lt;- vecteur[t] ;&lt;br /&gt;
                               t++;&lt;br /&gt;
                            }&lt;br /&gt;
                }&lt;br /&gt;
   return matrice;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction====&lt;br /&gt;
&lt;br /&gt;
Nous nous concentrons essentiellement sur la première partie, qui est la partie : &amp;quot;Landmarks Extraction&amp;quot; (extraction des points de repères). On travaille ici dans le repère du laser, qui est différent de celui du robot, et du global. La transposition dans le repère global se fera dans la partie &amp;quot;Data Association&amp;quot;. On doit ainsi, dans l'ordre :&lt;br /&gt;
&lt;br /&gt;
☑ récupérer des données lasers via le topic /scan&amp;lt;br&amp;gt;&lt;br /&gt;
☑ convertir les coordonnées polaires en coordonnées cartésiennes en filtrant les données aberrantes (&amp;gt; range_max et &amp;lt; range_min)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ implémenter l'algorithme [http://fr.wikipedia.org/wiki/RANSAC RANSAC] (Random SAmple Consensus) de détection de droites :&amp;lt;br&amp;gt;&lt;br /&gt;
☑ détecter la &amp;quot;meilleure&amp;quot; droite à partir des points en sélectionnant aléatoirement des combinaisons de points&amp;lt;br&amp;gt;&lt;br /&gt;
☑ stocker le meilleur modèle (angle + tableau de points)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ recommencer tant qu'il reste assez de points à traiter (5)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ extraire les segments à partir des modèles trouvés et des points&amp;lt;br&amp;gt;&lt;br /&gt;
☑ extraire les points extrèmes&amp;lt;br&amp;gt;&lt;br /&gt;
☑ calculer la taille du segment&amp;lt;br&amp;gt;&lt;br /&gt;
☑ chercher des angles droits, des segments de 35 ou 70 cm (largeur et longueur d'une machine)&amp;lt;br&amp;gt;&lt;br /&gt;
☑ extrapoler les positions des machines dans le repère du laser&amp;lt;br&amp;gt;&lt;br /&gt;
☑ définir le barycentre de la machine ainsi que son angle&amp;lt;br&amp;gt;&lt;br /&gt;
☐ stocker ces positions&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Pathfinder====&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi pris du temps avec '''Valentin VERGEZ''', qui a développé, l'an dernier, les codes pour le déplacement du Robotino et le calcul de trajectoire&lt;br /&gt;
&lt;br /&gt;
Nous avons éclairci quelques points sur cette partie du projet :&lt;br /&gt;
*Les commentaires sur l'utilité de chaque fonction ont été rajoutés.&lt;br /&gt;
*Le &amp;quot;code mort&amp;quot; a été nettoyé ainsi que les parties inutiles.&lt;br /&gt;
*Nous devons trouver un moyen de tester cette partie du code seule. (A priori graphiquement).&lt;br /&gt;
&lt;br /&gt;
Etant donné l'arrivée d'un nouvel ordinateur au sein de l'équipe, nous en avons profités pour installer les logiciels qui nous permettrons de faire tourner les noeuds codés sur les Robotino :&lt;br /&gt;
&lt;br /&gt;
*Installation d'Ubuntu 12.04 ( c'est cette version qui permet de faire tourner ROS Hydro)&lt;br /&gt;
&lt;br /&gt;
*Installation de ROS Hydro (ensemble d'outils informatiques open source permettant de développer des logiciels pour la robotique.)&lt;br /&gt;
&lt;br /&gt;
*Installation des paquets nécessaires (catkin, Desktop Install, ROS-Base, Individual Package)&lt;br /&gt;
&lt;br /&gt;
*Installation de GIT (outil de bas niveau permettant de gérer l'évolution du contenu d'une arborescence)&lt;br /&gt;
&lt;br /&gt;
*Vérification que toutes les fonctionnalités de ROS Hydro étaient présentes ( [http://wiki.ros.org/ROS/Tutorials Tutoriel])&lt;br /&gt;
&lt;br /&gt;
La récupération du code complet de l'année dernière et une solution a été trouvée afin de tester le code de génération de trajectoire A-star:&lt;br /&gt;
&lt;br /&gt;
*Pour visualiser une Map ainsi qu'un Path (chemin), on peut utiliser l'outils [http://wiki.ros.org/rviz RVIZ].&lt;br /&gt;
*Dans RVIZ, on peut ajouter un Path (topic /path), ainsi qu'ajouter une Map (/grid): Ceci correspond exactement à ce que nous souhaitons visualiser pour la partie calcul de trajectoire.&lt;br /&gt;
*Pour publier une Map fictive, on executera le script fakeGrid.sh&lt;br /&gt;
*Pour générer un chemin, on lancera le pathfinder (rosruns rbqt_pathfinder server : notre code) et on effectuera une requête avec le script pathReq.sh.&lt;br /&gt;
&lt;br /&gt;
Si tout se passe correctement, le chemin devrait s'afficher en &amp;lt;span style=&amp;quot;color: #00FF00;&amp;quot;&amp;gt; vert &amp;lt;/span&amp;gt; sur la map.&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi du communiquer notre avancement aux autres parties de l'équipe. Le schéma général ainsi qu'un outil permettant d'expliquer les différents algorithmes de recherche de trajectoire optimale nous ont aidé à leur communiquer nos objectifs et les processus choisis.&lt;br /&gt;
&lt;br /&gt;
L'algorithme A-Star que nous allons utiliser donne le résultat final suivant (utilisation du site [http://qiao.github.io/PathFinding.js/visual/ PathFinding] ):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet S8 A STAR E.PNG | center | thumb ]]&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #FFFF00;&amp;quot;&amp;gt; le chemin optimal calculé par A-Star &amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #008000;&amp;quot;&amp;gt; le point de départ&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #FF0000;&amp;quot;&amp;gt; le point d'arrivée&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #808080;&amp;quot;&amp;gt; les points interdits (obstacle)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #00FFFF;&amp;quot;&amp;gt; les points que l'algorithme a déjà calculé&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color: #00FF00;&amp;quot;&amp;gt; les points que l'algorithme aurait calculé à la prochaine itération&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks extraction - filtrage====&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, nous avons commencé à définir une classe laserScan qui contient la fonction polarToCart, elle convertit les données laser (tableau de ranges) en liste de points (x,y) :&lt;br /&gt;
&lt;br /&gt;
 void laserScan::PolarToCart (){&lt;br /&gt;
  Point p;&lt;br /&gt;
  for (int i=0; i&amp;lt;m_ranges.size(); i++){&lt;br /&gt;
    if((m_ranges[i]&amp;gt;getRangeMin()) &amp;amp;&amp;amp; (m_ranges[i]&amp;lt;getRangeMax())){&lt;br /&gt;
      p.setX(m_ranges[i]*cos(getAngleMin() + i*getAngleInc()));&lt;br /&gt;
      p.setY(m_ranges[i]*sin(getAngleMin() + i*getAngleInc()));&lt;br /&gt;
      m_points.push_back(p);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks extraction - reconnaissance de droite====&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, nous avons déterminé quel algorithme nous allons utiliser : [http://fr.wikipedia.org/wiki/RANSAC#L.27algorithme RANSAC]. L'algorithme de RANSAC trouve la meilleure droite dans un nuage de points. On itère plusieurs fois cet algorithme afin de trouver l'ensemble de toutes les droites du scan laser. On a donc en sortie une liste des droites composants le nuage de points initial.&lt;br /&gt;
&lt;br /&gt;
 Entrée : listOfPoints    -&amp;gt; liste de points initiale &lt;br /&gt;
 Sortie : meilleur_modèle -&amp;gt; les paramètres de la droite qui correspondent le mieux aux points&lt;br /&gt;
                          -&amp;gt; tableau de points à partir desquels la droite a été estimée&lt;br /&gt;
                          -&amp;gt; erreur du modèle de droite par rapport aux points&lt;br /&gt;
&amp;lt;span style=&amp;quot;color: #000080;&amp;quot;&amp;gt;&lt;br /&gt;
 tant que la liste contient assez de points&lt;br /&gt;
  itérateur := 0&lt;br /&gt;
  meilleur_modèle := aucun&lt;br /&gt;
  tant que itérateur &amp;lt; k (fixé par une loi de probabilité)&lt;br /&gt;
   &amp;lt;span style=&amp;quot;color: #008000;&amp;quot;&amp;gt;on choisit deux points au hasard dans la liste&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span style=&amp;quot;color: #00FFFF;&amp;quot;&amp;gt;on fabrique un modèle_possible à partir de ces deux points&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span style=&amp;quot;color: #FF0000;&amp;quot;&amp;gt;Pour chaque point de la liste qui ne sont pas dans le modele_possible&lt;br /&gt;
    si le point s'ajuste au modele_possible avec une erreur inférieure à t&lt;br /&gt;
     Ajouter ce point au modele&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color: #00FF00;&amp;quot;&amp;gt;si le nombre de points dans le modele est suffisant pour valider l'existence du modele&lt;br /&gt;
     erreur := coefficient de corrélation de la régression linéaire de ensemble_points&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color: #808080;&amp;quot;&amp;gt;si erreur &amp;lt; erreur du meilleur_modele&lt;br /&gt;
     meilleur_modèle := modèle_possible&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  stocker meilleur_modèle dans liste de modèles&lt;br /&gt;
  retirer meilleur_ensemble_points de la liste des points initiale&lt;br /&gt;
  recommencer avec la liste modifiée&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - reconnaissance de droite====&lt;br /&gt;
&lt;br /&gt;
Nous avons adapté l'algorithme précédent afin de mieux correspondre aux structures que nous avons créées :&lt;br /&gt;
*Modele&lt;br /&gt;
**Liste de points&lt;br /&gt;
**Liste d'indices&lt;br /&gt;
**Corrélation&lt;br /&gt;
**Droite&lt;br /&gt;
***Point&lt;br /&gt;
***Angle&lt;br /&gt;
**Segment&lt;br /&gt;
***Point &amp;quot;min&amp;quot;&lt;br /&gt;
***Point &amp;quot;max&amp;quot;&lt;br /&gt;
***Angle&lt;br /&gt;
***Taille&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi codé toutes les fonctions nécessaires dans l'algorithme de Ransac, dont celle permettant la correction de l'approximation de droite par régression linéaire des points correspondants à un modèle trouvé (''linReg()'') qui nous a donné matière à réflexion. Aussi, notre première idée qui était de travailler avec des ''std::vector'' a du changer puisque l'aspect récursif de l'algorithme que nous allons utiliser nécessite de multiples suppressions sur les données à entrer dans l'algorithme de Ransac. On travaille donc maintenant avec des ''std::list''.&lt;br /&gt;
&lt;br /&gt;
Tous nos codes sont disponibles sur la branche [https://github.com/PyroTeam/robocup-pkg/tree/feature/navigation/SLAM/navigation/localisation/src feature/navigation/SLAM du GIT de l'équipe PyroTeam].&lt;br /&gt;
&lt;br /&gt;
===Semaine de vacances de février===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - reconnaissance de droite====&lt;br /&gt;
&lt;br /&gt;
Nous devons réaliser un noeud permettant de valider notre algorithme, c'est-à-dire implémenter sous ROS notre code C++ afin de tester, soit directement sur le robot, soit avec des [http://wiki.ros.org/Bags bagfiles]. Cette étape est très importante pour pouvoir passer à la suite : extrapoler les droites trouvées en segments puis en objets.&lt;br /&gt;
&lt;br /&gt;
Notre programme consistant à reconnaître les droites à partir du scan laser est fonctionnel et a été testé à partir du scan laser suivant :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ScanLaser.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Processus de validation :&lt;br /&gt;
&lt;br /&gt;
*Lancer le programme ''rosrun localisation test_polar_to_cart''&lt;br /&gt;
&lt;br /&gt;
résultat : on trouve 5 droites&lt;br /&gt;
&lt;br /&gt;
 m = -0.0229637 p = -0.24079&lt;br /&gt;
 nb de points dans la droite : 246&lt;br /&gt;
 coeff de correlation : 0.812376&lt;br /&gt;
&lt;br /&gt;
 m = -0.0315132 p = 3.7506&lt;br /&gt;
 nb de points dans la droite : 102&lt;br /&gt;
 coeff de correlation : 0.928089&lt;br /&gt;
&lt;br /&gt;
 m = 32.9243 p = -139.943&lt;br /&gt;
 nb de points dans la droite : 77&lt;br /&gt;
 coeff de correlation : 0.914475&lt;br /&gt;
&lt;br /&gt;
 m = 7.04634 p = -15.42&lt;br /&gt;
 nb de points dans la droite : 32&lt;br /&gt;
 coeff de correlation : 0.970724&lt;br /&gt;
&lt;br /&gt;
 m = 0.253029 p = 1.32235&lt;br /&gt;
 nb de points dans la droite : 28&lt;br /&gt;
 coeff de correlation : 0.979578&lt;br /&gt;
&lt;br /&gt;
ce qui correspond à l'image suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:DroitesTrouvées.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
On voit que la recherche de droite marche bien, mais peut être améliorée en ajoutant des conditions de proximité des points correspondants à une seule droite, pour éviter le phénomène que l'on voit au milieu. Le résultat après avoir ajouté cette condition et en ayant affiné au maximum les paramètres, au dépend d'un temps de calcul beaucoup plus élevé (9,416 secondes au lieu de 0,536 s)  :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:DroitesTrouvées2.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Les impératifs de la compétition nous imposant une certaine rapidité pour se localiser et détecter les machines, nous retiendrons la solution la plus rapide et nous séparerons les droites en segment après leur détection.&lt;br /&gt;
&lt;br /&gt;
Pour valider l'algorithme de régression linéaire nous avons :&lt;br /&gt;
*Récupéré tous les points correspondants à chaque droite&lt;br /&gt;
*Rentré ces points sur Excel&lt;br /&gt;
*Fait une courbe de tendance&lt;br /&gt;
*Affiché l'équation de droite et le coefficient de corrélation&lt;br /&gt;
*Comparé avec ce qu'a trouvé notre programme&lt;br /&gt;
*Conclu que notre programme était bon&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - reconnaissance de machines====&lt;br /&gt;
&lt;br /&gt;
Les objectifs de cette semaine :&lt;br /&gt;
&lt;br /&gt;
*à partir de la liste de droites, extraire les segments&lt;br /&gt;
*extrapoler les positions machines à partir d'un segment complet (35 ou 70 cm)&lt;br /&gt;
*réaliser une interface graphique pour visualiser les segments trouvés en temps réel&lt;br /&gt;
*regarder ce qu'on doit rentrer dans l' '''Extended Kalman Filter''' au niveau du format des positions machines et de l'odométrie pour pouvoir réaliser le '''Data Association''' de façon cohérente avec la suite.&lt;br /&gt;
&lt;br /&gt;
L'extraction de segment à partir des 5 droite précédemment trouvées nous donne 7 segments:&lt;br /&gt;
&lt;br /&gt;
 Segment 1&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(-1.04033e-08, -0.238)&lt;br /&gt;
 Max(4.24699, -0.26092)&lt;br /&gt;
 taille : 4.24705&lt;br /&gt;
 angle  : -0.309205&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 2&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(-1.64267e-07, 3.758)&lt;br /&gt;
 Max(3.4172, 3.63358)&lt;br /&gt;
 taille : 3.41946&lt;br /&gt;
 angle  : -2.08521&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 3&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(4.24452, -0.234635)&lt;br /&gt;
 Max(4.33124, 2.18017)&lt;br /&gt;
 taille : 2.41636&lt;br /&gt;
 angle  : 87.9432&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 4&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(2.30055, 0.871242)&lt;br /&gt;
 Max(2.32511, 0.736592)&lt;br /&gt;
 taille : 0.136872&lt;br /&gt;
 angle  : -79.6622&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 5&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(2.50359, 2.18655)&lt;br /&gt;
 Max(2.53413, 2.56542)&lt;br /&gt;
 taille : 0.380104&lt;br /&gt;
 angle  : 85.3914&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 6&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(2.73122, 2.05171)&lt;br /&gt;
 Max(3.049, 2.03728)&lt;br /&gt;
 taille : 0.318107&lt;br /&gt;
 angle  : -2.5999&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Segment 7&amp;lt;br&amp;gt;&lt;br /&gt;
 Min(1.14156, 1.64221)&lt;br /&gt;
 Max(1.39648, 1.61891)&lt;br /&gt;
 taille : 0.255984&lt;br /&gt;
 angle  : -5.22068&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SegmentsTrouvés.png | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
Tout cela en 0,540s !&lt;br /&gt;
&lt;br /&gt;
A partir de la liste de segments précédente, on extrait une liste de machine à partir des segments de 35 ou 70 cm, qui sont les tailles des machines. Comme le scan que nous utilisons pour le moment n'est pas un scan avec une vraie machine, mais disposant quand même de 2 segments d'à peu près 35 cm, nous utilisons ces deux segments comme ''petit côté'' de la machine. On trouve ainsi deux machines :&lt;br /&gt;
&lt;br /&gt;
 Machine 1&lt;br /&gt;
   centre en (2.53292, 2.20155)&lt;br /&gt;
   orientation : 175.391°&lt;br /&gt;
&lt;br /&gt;
 Machine 2&lt;br /&gt;
   centre en (3.06493, 2.05243)&lt;br /&gt;
   orientation : 87.4001°&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une amélioration de l'algorithme a été faite pour la détection de machine. En effet, dans le cas où on détectait un petit et un grand côté de machine, on trouvait deux machines avec des centres à peu près au même endroit. Maintenant, on fusionne ces données en créant un point milieu entre les deux données, et on prend l'orientation du grand côté.&lt;br /&gt;
&lt;br /&gt;
On a commencé à faire des tests sur ROS directement avec un noeud factice qui publie un scan laser à une fréquence de 10Hz, ce qui est la fréquence réelle du laser Hokuyo. La détection se fait assez rapidement et de façon précise. Des tests sur le robot sont prévus en début de semaine 7 avec les vraies machines.&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Data Association====&lt;br /&gt;
&lt;br /&gt;
L'objectif principal de cette semaine est de coder le noeud '''Data Association''' qui liera la position donnée par l'odométrie (mesure relative de la position par rapport à un point de départ à peu près connu) avec les machines trouvées dans le champ du laser.&lt;br /&gt;
&lt;br /&gt;
Il faudra aussi corriger l'odométrie donné par le nœud ''robotino_odometry_node'', qui donne l'odométrie (mesure de la position et de la vitesse du robot). Le problème est que nous utilisons un gyroscope externe, car le gyroscope de base est de très basse qualité. Or, si le nœud corrige parfaitement la position, il ne corrige pas du tout la vitesse angulaire ! Nous devons donc réaliser un nœud qui le fera pour nous.&lt;br /&gt;
&lt;br /&gt;
D'après la dernière version du sujet 2015, l'aire de jeu de 6 x 12 m est séparée en zones de 1,5 x 2 m de large, dans lesquelles se situent une seule machine. Chaque équipe a 6 machines dont la zone est connue, donnée par la Referee Box. Le but du nœud ROS de ''Data Association'' sera de transposer les positions machines dans le repère global de la piste, ainsi le Manager pour savoir devant quelle machine le robot est, et connaître sa position et son orientation.&lt;br /&gt;
&lt;br /&gt;
La piste sera donc comme cela :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Piste.PNG | center | thumb]]&lt;br /&gt;
&lt;br /&gt;
La correction d'odométrie a fait apparaître une erreur de mesure d'environ 1,7°/s sur la vitesse angulaire, à faible vitesse. Pour de la Localisation et Cartographie Simultanée, c'est assez important. Ça justifie donc la nécessité de faire cet ajustement.&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il a été décidé de fusionner les nœuds '''Data Association''' et '''Extended Kalman Filter''' puisque l'association de données n'étant au final qu'un changement de repère, la structure de nœud ROS n'est pas adaptée.&lt;br /&gt;
&lt;br /&gt;
Nous avons trouvé un [https://github.com/yangyimeng/machine-learning/blob/master/slam/EKF/SLAM%20course.pdf PDF] expliquant l'algorithme de SLAM. Grâce à celui ci nous avons déterminer les éléments à rentrer dans le noeud, ainsi que les différentes opérations incluses dans ce filtre. Pour les calculs matriciels, nous allons probablement utiliser la librairie EIGEN pour travailler sur des [http://eigen.tuxfamily.org/dox/classEigen_1_1Matrix.html matrices] de façon optimisée. La prochaine étape sera de &amp;quot;typer&amp;quot; nos informations (position robot + machine + murs) pour pouvoir les intégrer facilement au filtre. Nous avons aussi décidé d'inclure les murs comme ''landmark'' dans la matrice de covariance du vecteur d'état.&lt;br /&gt;
&lt;br /&gt;
Il a été décidé de faire une association de données avant la détection de machines, pour distinguer les pans de murs directement afin de stocker ces informations directement à la source. On pourra éventuellement détecter les coins intérieurs de la piste pour plus de précision dans le recalage. Pour le reste, rien ne change.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Landmarks Extraction - vidéo====&lt;br /&gt;
&lt;br /&gt;
Pour visualiser les résultats de la détection des machines nous avons utiliser l'interface graphique disponible avec ROS, RVIZ. Nous visualisons alors le scan laser (points blancs), le résultat de la détection de segments (en rouge) et les positions des machines trouvées (en vert). Un premier test a été fait sur le scan originel, celui sur lequel nous avons travaillé depuis le début.&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/watch?v=XSn4s1y-XT0 Visualisation des machines]&lt;br /&gt;
&lt;br /&gt;
On rencontre un problème quand le robot est exactement parallèle ou perpendiculaire à un mur. Après vérification dans le programme, il s'avère que la détection ne fonctionne pas pour ces cas. Ce bug est maintenant corrigé :&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/watch?v=rKeqewpuLoQ Correction du bug]&lt;br /&gt;
====Localisation - Data Association====&lt;br /&gt;
&lt;br /&gt;
La première étape consiste juste à faire un changement de repère, d'abord du repère laser vers le repère robot, puisque le laser sera placé en avant du robot, puis du repère robot au repère global, comme ci dessous :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Chgt_Repère.png |center | thumb]]&lt;br /&gt;
&lt;br /&gt;
la matrice correspondant au changement (laser -&amp;gt; robot) est la suivante : &lt;br /&gt;
&lt;br /&gt;
 0   -1    0&lt;br /&gt;
 1    0  0.2&lt;br /&gt;
 0    0    1&lt;br /&gt;
&lt;br /&gt;
la matrice 2x2 en haut à gauche correspond à la rotation de 90°, et le vecteur (0, 0.2) correspond à la translation.&lt;br /&gt;
&lt;br /&gt;
Celle du changement (robot -&amp;gt; global) avec alpha angle mesuré par le gyroscope depuis la position initiale (angle 0) :&lt;br /&gt;
&lt;br /&gt;
 cos(alpha)   -sin(alpha)    posInit.x&lt;br /&gt;
 sin(alpha)    cos(alpha)    posInit.y&lt;br /&gt;
          0             0            1&lt;br /&gt;
&lt;br /&gt;
l'étape suivante est de vérifier si les machines vues par le laser sont bien des machines, c'est-à-dire si les positions mesurées à partir des données lasers correspond aux zones occupées par des machines envoyées par la Referee Box.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Génération du noeud Map====&lt;br /&gt;
&lt;br /&gt;
L'autre objectif de cette semaine a été de coder le noeud qui génère la map. La map est générée sous forme d'OccupancyGrid. Ce type est constitué d'un seul vecteur dont la première case correspond à la case en bas à gauche de la map. D'autres paramètres sont réglable comme l'origine, la taille etc.&lt;br /&gt;
&lt;br /&gt;
Pour la taille on choisi de diviser la map en case de 10 cm (100 mm) et l'origine choisi est le centre de la mep en x et en y le premier mur (voir la map ci-dessous)&lt;br /&gt;
&lt;br /&gt;
Afin d'expliquer comment est constituée cette map, prenons le code et analysons les différentes fonctions:&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
====Localisation - Extended Kalman Filter====&lt;br /&gt;
&lt;br /&gt;
l'objectif de cette semaine sera de coder toutes les fonctions nécessaires à l'implémentation finale du [http://fr.wikipedia.org/wiki/Filtre_de_Kalman#Filtre_de_Kalman_.C3.A9tendu filtre de Kalman étendu] :&lt;br /&gt;
&lt;br /&gt;
*initialisations des différents éléments&lt;br /&gt;
*étape de prédiction&lt;br /&gt;
*étape de mise à jour&lt;br /&gt;
*publication des positions machines et du robot dans le repère global via un topic ROS&lt;br /&gt;
&lt;br /&gt;
Le schéma ci-dessous nous montre les deux étapes du filtre de Kalman :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Kalman.png | center]]&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=17140</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=17140"/>
				<updated>2015-02-18T14:17:48Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Jour 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2====&lt;br /&gt;
&lt;br /&gt;
'''''Génération de trajectoire :'''''&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous avons visualisé les différents algorithmes sur [http://qiao.github.io/PathFinding.js/visual/ PathFinding]&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | 400px | center]][[Image:Projet_S8_A_STAR_2.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | 400px | center]][[Image:Projet_S8_A_STAR_4.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
'''''Localisation :'''''&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1====&lt;br /&gt;
&lt;br /&gt;
Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
Chaque case du diagramme précédent correspond à un noeud ROS.&lt;br /&gt;
&lt;br /&gt;
Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
*'''Laser''' récupère les données brutes du laser.&lt;br /&gt;
*'''Filtrage''' permet, comme son nom l'indique, d'enlever les éventuels bruits qui affectent les données du laser.&lt;br /&gt;
*'''Reconnaissance des droites''' traite les données laser filtrées pour détecter les droites présentes (Transformée de Hough ou Ransac)&lt;br /&gt;
*'''Reconnaissance des formes''' extrapole les objets (machines) à partir des droites.&lt;br /&gt;
*'''Corrélation emplacements machines''' lie la position des machines détectées au laser et les positions envoyées par RefBoxCom pour éviter les incohérences.&lt;br /&gt;
*'''Odométrie''' récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
*'''Traitement de position''' corrige l'erreur sur le Twist avec les données du gyroscope (par dérivation).&lt;br /&gt;
*'''Fusion de Kalman''' est un algorithme qui va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
*'''Stockage machines + robot''' transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
*'''Grid Map''' renvoit une map utilisée ensuite pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
*'''RefBoxCom''' stocke et renvoie la position des machines.&lt;br /&gt;
*'''Position robot''' renvoie la position exacte du robot sur la grille.&lt;br /&gt;
*'''Manager''' Noeud qui envoie la position à atteindre.&lt;br /&gt;
*'''Pathfinder''' recherche le chemin demandé par le Manager sur une grille&lt;br /&gt;
*'''Parcoureur''' exécute le chemin trouvé en fournissant les vitesses au noeud Déplacement.&lt;br /&gt;
*'''Déplacement''' (noeud robotino_local_move_server), qui donne les commandes aux moteurs à partir de la vitesse linéaire et angulaire envoyée par le Parcoureur.&lt;br /&gt;
&lt;br /&gt;
====Jour 2====&lt;br /&gt;
&lt;br /&gt;
Nous avons cherchés toutes les documentations techniques nécessaires pour la programmation de chaque noeud : [http://wiki.ros.org/fr Wiki_ROS] et [http://wiki.ros.org/robotino API_Robotino], nous permettant de mettre à jour le schéma global (semaine 2 jour 2), notamment au niveau des types.&lt;br /&gt;
&lt;br /&gt;
Nous nous sommes ensuite concentrés sur le noeud GridMap qui contient ''Map.cpp'' :&lt;br /&gt;
&lt;br /&gt;
Dans le code de l'an dernier, ce noeud générait une grille en dur. Cependant, cette solution n'est pas possible cette année car nous ne connaissons pas toutes les informations sur la piste (on connaît à peu près la position mais pas l'orientation). Il va donc falloir générer une grille en fonction du noeud précédent qui nous renverra un type ''OccupancyGrid''. &lt;br /&gt;
&lt;br /&gt;
Etant donné que ce noeud tournera en permanence, si des informations changent pendant que le robot est sur la piste (détection des nouvelles machines par exemple), le noeud ''Map.cpp'' modifiera la grille en temps réel.&lt;br /&gt;
&lt;br /&gt;
La grille est décomposée en case pour le A-Star :&lt;br /&gt;
&lt;br /&gt;
Si c'est une case interdite (obstacle) ont associe a la case la valeur 1, si elle est autorisée, on associe la valeur 0. On illustre le principe précédent par un exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
Cependant, le noeud &amp;quot;Grid Map&amp;quot; va nous délivrer un vecteur et non une matrice par le biais de ''OccupancyGrid.Data''.Dans notre exemple précédent, on récupère le vecteur suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map_2.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
On choisit donc de transformer ce vecteur en matrice, car l'algorithme A-Star fonctionne sur un graphe, pas un vecteur. On connait la largeur (en case) de la grille grâce au type ''OccupancyGrid.info.width''.&lt;br /&gt;
&lt;br /&gt;
Le pseudo-code pour générer la matrice à partir de ce vecteur sera le suivant :&lt;br /&gt;
&lt;br /&gt;
 fonction create_grid (OccupancyGrid.Data vecteur[size]) : matrice[height].[width]&lt;br /&gt;
 {&lt;br /&gt;
   matrice[height].[width] ;		&lt;br /&gt;
      int t &amp;lt;- size;&lt;br /&gt;
          Pour (i de 0 à height)&lt;br /&gt;
          faire:&lt;br /&gt;
                {&lt;br /&gt;
                    Pour (j de 0 à width)&lt;br /&gt;
                    faire :&lt;br /&gt;
                            {&lt;br /&gt;
                               matrice[i].[j] &amp;lt;- vecteur[t] ;&lt;br /&gt;
                               t++;&lt;br /&gt;
                            }&lt;br /&gt;
                }&lt;br /&gt;
   return matrice;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
====Jour 1====&lt;br /&gt;
&lt;br /&gt;
'''''Localisation :'''''&lt;br /&gt;
&lt;br /&gt;
Nous nous concentrons essentiellement sur la première partie, qui est la partie : &amp;quot;Landmarks Extraction&amp;quot; (extraction des points de repères). On travaille ici dans le repère du laser, qui est différent de celui du robot, et du global. La transposition dans le repère global se fera dans la partie &amp;quot;Data Association&amp;quot;. On doit ainsi, dans l'ordre :&lt;br /&gt;
*récupérer des données lasers via le topic /scan&lt;br /&gt;
*convertir les coordonnées polaires en coordonnées cartésiennes en filtrant les données aberrantes (&amp;gt; range_max et &amp;lt; range_min)&lt;br /&gt;
*concevoir l'algorithme [http://fr.wikipedia.org/wiki/RANSAC RANSAC] (Random SAmple Consensus) de détection de droites :&lt;br /&gt;
**détecter la &amp;quot;meilleure&amp;quot; droite à partir des points en sélectionnant aléatoirement des combinaisons de points&lt;br /&gt;
**stocker le meilleur modèle (angle + tableau de points)&lt;br /&gt;
**recommencer tant qu'il reste assez de points à traiter (5)&lt;br /&gt;
*extraire les segments à partir des modèles trouvés et des points&lt;br /&gt;
**projeter tous les point appartenant à un modèle de droite sur cette même droite&lt;br /&gt;
**extraire les points extrèmes&lt;br /&gt;
**calculer la taille du segment&lt;br /&gt;
**calculer le vecteur normal de la droite&lt;br /&gt;
**grouper les segments qui appartiennent potentiellement à une même machine&lt;br /&gt;
***chercher des angles droits, des segments de 35 ou 70 cm (largeur et longueur d'une machine)&lt;br /&gt;
**extrapoler les positions des machines dans le repère du laser&lt;br /&gt;
***définir le barycentre de la machine ainsi que son angle&lt;br /&gt;
**stocker ces positions&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi pris du temps avec '''Valentin VERGEZ''', qui a développé, l'an dernier, les codes pour le déplacement du Robotino et le calcul de trajectoire&lt;br /&gt;
&lt;br /&gt;
Nous avons éclairci quelques points sur cette partie du projet :&lt;br /&gt;
&lt;br /&gt;
*Les commentaires sur l'utilité de chaque fonction ont été rajoutés.&lt;br /&gt;
&lt;br /&gt;
*Le &amp;quot;code mort&amp;quot; a été nettoyé ainsi que les parties inutiles.&lt;br /&gt;
&lt;br /&gt;
*Nous devons trouver un moyen de tester cette partie du code seule. (A priori graphiquement).&lt;br /&gt;
&lt;br /&gt;
====Jour 2====&lt;br /&gt;
&lt;br /&gt;
Etant donné l'arrivée d'un nouvel ordinateur au sein de l'équipe, nous en avons profités pour installer les logiciels qui nous permettrons de faire tourner les noeuds codés sur les Robotino :&lt;br /&gt;
&lt;br /&gt;
*Installation d'Ubuntu 12.04 ( c'est cette version qui permet de faire tourner ROS Hydro)&lt;br /&gt;
&lt;br /&gt;
*Installation de ROS Hydro (ensemble d'outils informatiques open source permettant de développer des logiciels pour la robotique.)&lt;br /&gt;
&lt;br /&gt;
*Installation des paquets nécessaires (catkin, Desktop Install, ROS-Base, Individual Package)&lt;br /&gt;
&lt;br /&gt;
*Installation de GIT (outil de bas niveau permettant de gérer l'évolution du contenu d'une arborescence)&lt;br /&gt;
&lt;br /&gt;
*Vérification que toutes les fonctionnalités de ROS Hydro étaient présentes ( [http://wiki.ros.org/ROS/Tutorials Tutoriel])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La récupération du code complet de l'année dernière et une solution a été trouvée afin de tester le code de génération de trajectoire A-star:&lt;br /&gt;
&lt;br /&gt;
*Pour visualiser une Map ainsi qu'un Path (chemin), on peut utiliser l'outils rviz.&lt;br /&gt;
*Dans RVIZ, on peut ajouter un Path et lire le topic &amp;quot;path&amp;quot;, ainsi qu'ajouter une Map et lire le topic &amp;quot;grid&amp;quot;: Ceci correspond exactement à ce que nous souhaitons visualiser pour la partie calcul de trajectoire.&lt;br /&gt;
*Pour publier une Map fictive, on éxecutera le script fakeGrid.sh&lt;br /&gt;
*Pour générer un chemin, on lancera le pathfinder (rosruns rbqt_pathfinder server : notre code) et on effectuera une requête avec le script pathReq.sh.&lt;br /&gt;
'''Si tout se passe correctement, le chemin devrait s'afficher en vert sur la map.'''&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi du communiquer notre avancement aux autres parties de l'équipe. Le schéma général ainsi qu'un outil permettant d'expliquer les différents algorithmes de recherche de trajectoire optimale nous ont aidé à leur communiquer nos objectifs et les processus choisis.&lt;br /&gt;
&lt;br /&gt;
Le scripts est le suivant : [http://qiao.github.io/PathFinding.js/visual/ Pathfinder]&lt;br /&gt;
&lt;br /&gt;
L'algorithme A-Star que nous allons utiliser donne le résultat final suivant :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet S8 A STAR E.PNG | center ]]&lt;br /&gt;
&lt;br /&gt;
* '''en jaune :''' le chemin choisi par A-Star&lt;br /&gt;
* '''en vert foncé :''' le point de départ&lt;br /&gt;
* '''en rouge :''' le point d'arrivée&lt;br /&gt;
* '''en gris :''' points interdits (obstacle)&lt;br /&gt;
* '''en bleu ciel :''' les points que l'algorithme à calculé&lt;br /&gt;
* '''en vert clair:''' les points qui ont permis de savoir que le chemin n'était pas optimal&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_A_STAR_E.PNG&amp;diff=17139</id>
		<title>Fichier:Projet S8 A STAR E.PNG</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_A_STAR_E.PNG&amp;diff=17139"/>
				<updated>2015-02-18T14:16:19Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=17128</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=17128"/>
				<updated>2015-02-18T13:23:54Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Jour 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2====&lt;br /&gt;
&lt;br /&gt;
'''''Génération de trajectoire :'''''&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous avons visualisé les différents algorithmes sur [http://qiao.github.io/PathFinding.js/visual/ PathFinding]&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | 400px | center]][[Image:Projet_S8_A_STAR_2.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | 400px | center]][[Image:Projet_S8_A_STAR_4.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
'''''Localisation :'''''&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1====&lt;br /&gt;
&lt;br /&gt;
Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
Chaque case du diagramme précédent correspond à un noeud ROS.&lt;br /&gt;
&lt;br /&gt;
Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
*'''Laser''' récupère les données brutes du laser.&lt;br /&gt;
*'''Filtrage''' permet, comme son nom l'indique, d'enlever les éventuels bruits qui affectent les données du laser.&lt;br /&gt;
*'''Reconnaissance des droites''' traite les données laser filtrées pour détecter les droites présentes (Transformée de Hough ou Ransac)&lt;br /&gt;
*'''Reconnaissance des formes''' extrapole les objets (machines) à partir des droites.&lt;br /&gt;
*'''Corrélation emplacements machines''' lie la position des machines détectées au laser et les positions envoyées par RefBoxCom pour éviter les incohérences.&lt;br /&gt;
*'''Odométrie''' récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
*'''Traitement de position''' corrige l'erreur sur le Twist avec les données du gyroscope (par dérivation).&lt;br /&gt;
*'''Fusion de Kalman''' est un algorithme qui va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
*'''Stockage machines + robot''' transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
*'''Grid Map''' renvoit une map utilisée ensuite pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
*'''RefBoxCom''' stocke et renvoie la position des machines.&lt;br /&gt;
*'''Position robot''' renvoie la position exacte du robot sur la grille.&lt;br /&gt;
*'''Manager''' Noeud qui envoie la position à atteindre.&lt;br /&gt;
*'''Pathfinder''' recherche le chemin demandé par le Manager sur une grille&lt;br /&gt;
*'''Parcoureur''' exécute le chemin trouvé en fournissant les vitesses au noeud Déplacement.&lt;br /&gt;
*'''Déplacement''' (noeud robotino_local_move_server), qui donne les commandes aux moteurs à partir de la vitesse linéaire et angulaire envoyée par le Parcoureur.&lt;br /&gt;
&lt;br /&gt;
====Jour 2====&lt;br /&gt;
&lt;br /&gt;
Nous avons cherchés toutes les documentations techniques nécessaires pour la programmation de chaque noeud : [http://wiki.ros.org/fr Wiki_ROS] et [http://wiki.ros.org/robotino API_Robotino], nous permettant de mettre à jour le schéma global (semaine 2 jour 2), notamment au niveau des types.&lt;br /&gt;
&lt;br /&gt;
Nous nous sommes ensuite concentrés sur le noeud GridMap qui contient ''Map.cpp'' :&lt;br /&gt;
&lt;br /&gt;
Dans le code de l'an dernier, ce noeud générait une grille en dur. Cependant, cette solution n'est pas possible cette année car nous ne connaissons pas toutes les informations sur la piste (on connaît à peu près la position mais pas l'orientation). Il va donc falloir générer une grille en fonction du noeud précédent qui nous renverra un type ''OccupancyGrid''. &lt;br /&gt;
&lt;br /&gt;
Etant donné que ce noeud tournera en permanence, si des informations changent pendant que le robot est sur la piste (détection des nouvelles machines par exemple), le noeud ''Map.cpp'' modifiera la grille en temps réel.&lt;br /&gt;
&lt;br /&gt;
La grille est décomposée en case pour le A-Star :&lt;br /&gt;
&lt;br /&gt;
Si c'est une case interdite (obstacle) ont associe a la case la valeur 1, si elle est autorisée, on associe la valeur 0. On illustre le principe précédent par un exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
Cependant, le noeud &amp;quot;Grid Map&amp;quot; va nous délivrer un vecteur et non une matrice par le biais de ''OccupancyGrid.Data''.Dans notre exemple précédent, on récupère le vecteur suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map_2.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
On choisit donc de transformer ce vecteur en matrice, car l'algorithme A-Star fonctionne sur un graphe, pas un vecteur. On connait la largeur (en case) de la grille grâce au type ''OccupancyGrid.info.width''.&lt;br /&gt;
&lt;br /&gt;
Le pseudo-code pour générer la matrice à partir de ce vecteur sera le suivant :&lt;br /&gt;
&lt;br /&gt;
 fonction create_grid (OccupancyGrid.Data vecteur[size]) : matrice[height].[width]&lt;br /&gt;
 {&lt;br /&gt;
   matrice[height].[width] ;		&lt;br /&gt;
      int t &amp;lt;- size;&lt;br /&gt;
          Pour (i de 0 à height)&lt;br /&gt;
          faire:&lt;br /&gt;
                {&lt;br /&gt;
                    Pour (j de 0 à width)&lt;br /&gt;
                    faire :&lt;br /&gt;
                            {&lt;br /&gt;
                               matrice[i].[j] &amp;lt;- vecteur[t] ;&lt;br /&gt;
                               t++;&lt;br /&gt;
                            }&lt;br /&gt;
                }&lt;br /&gt;
   return matrice;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
====Jour 1====&lt;br /&gt;
&lt;br /&gt;
'''''Localisation :'''''&lt;br /&gt;
&lt;br /&gt;
Nous nous concentrons essentiellement sur la première partie, qui est la partie : &amp;quot;Landmarks Extraction&amp;quot; (extraction des points de repères). On travaille ici dans le repère du laser, qui est différent de celui du robot, et du global. La transposition dans le repère global se fera dans la partie &amp;quot;Data Association&amp;quot;. On doit ainsi, dans l'ordre :&lt;br /&gt;
*récupérer des données lasers via le topic /scan&lt;br /&gt;
*convertir les coordonnées polaires en coordonnées cartésiennes en filtrant les données aberrantes (&amp;gt; range_max et &amp;lt; range_min)&lt;br /&gt;
*concevoir l'algorithme [http://fr.wikipedia.org/wiki/RANSAC RANSAC] (Random SAmple Consensus) de détection de droites :&lt;br /&gt;
**détecter la &amp;quot;meilleure&amp;quot; droite à partir des points en sélectionnant aléatoirement des combinaisons de points&lt;br /&gt;
**stocker le meilleur modèle (angle + tableau de points)&lt;br /&gt;
**recommencer tant qu'il reste assez de points à traiter (5)&lt;br /&gt;
*extraire les segments à partir des modèles trouvés et des points&lt;br /&gt;
**projeter tous les point appartenant à un modèle de droite sur cette même droite&lt;br /&gt;
**extraire les points extrèmes&lt;br /&gt;
**calculer la taille du segment&lt;br /&gt;
**calculer le vecteur normal de la droite&lt;br /&gt;
**grouper les segments qui appartiennent potentiellement à une même machine&lt;br /&gt;
***chercher des angles droits, des segments de 35 ou 70 cm (largeur et longueur d'une machine)&lt;br /&gt;
**extrapoler les positions des machines dans le repère du laser&lt;br /&gt;
***définir le barycentre de la machine ainsi que son angle&lt;br /&gt;
**stocker ces positions&lt;br /&gt;
&lt;br /&gt;
Nous avons aussi pris du temps avec '''Valentin VERGEZ''', qui a développé, l'an dernier, les codes pour le déplacement du Robotino et le calcul de trajectoire&lt;br /&gt;
&lt;br /&gt;
Nous avons éclairci quelques points sur cette partie du projet :&lt;br /&gt;
&lt;br /&gt;
*Les commentaires sur l'utilité de chaque fonction ont été rajoutés.&lt;br /&gt;
&lt;br /&gt;
*Le &amp;quot;code mort&amp;quot; a été nettoyé ainsi que les parties inutiles.&lt;br /&gt;
&lt;br /&gt;
*Nous devons trouver un moyen de tester cette partie du code seule. (A priori graphiquement).&lt;br /&gt;
&lt;br /&gt;
====Jour 2====&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16815</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16815"/>
				<updated>2015-02-12T07:53:09Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Jour 2 : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
'''''Génération de trajectoire :'''''&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | 400px | center]][[Image:Projet_S8_A_STAR_2.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | 400px | center]][[Image:Projet_S8_A_STAR_4.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
'''''Localisation :'''''&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
*Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
*Chaque case du diagramme précédent correspond à un noeud ROS.&lt;br /&gt;
&lt;br /&gt;
*Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
**'''Laser''' récupère les données brutes du laser.&lt;br /&gt;
**'''Filtrage''' permet, comme son nom l'indique, d'enlever les éventuels bruits qui affectent les données du laser.&lt;br /&gt;
**'''Reconnaissance des droites''' traite les données laser filtrées pour détecter les droites présentes (Transformée de Hough ou Ransac)&lt;br /&gt;
**'''Reconnaissance des formes''' extrapole les objets (machines) à partir des droites.&lt;br /&gt;
**'''Corrélation emplacements machines''' lie la position des machines détectées au laser et les positions envoyées par RefBoxCom pour éviter les incohérences.&lt;br /&gt;
**'''Odométrie''' récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
**'''Traitement de position''' corrige l'erreur sur le Twist avec les données du gyroscope (par dérivation).&lt;br /&gt;
**'''Fusion de Kalman''' est un algorithme qui va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
**'''Stockage machines + robot''' transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
**'''Grid Map''' renvoit une map utilisée ensuite pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
**'''RefBoxCom''' stocke et renvoie la position des machines.&lt;br /&gt;
**'''Position robot''' renvoie la position exacte du robot sur la grille.&lt;br /&gt;
**'''Manager''' Noeud qui envoie la position à atteindre.&lt;br /&gt;
**'''Pathfinder''' recherche le chemin demandé par le Manager sur une grille&lt;br /&gt;
**'''Parcoureur''' exécute le chemin trouvé en fournissant les vitesses au noeud Déplacement.&lt;br /&gt;
**'''Déplacement''' (noeud robotino_local_move_server), qui donne les commandes aux moteurs à partir de la vitesse linéaire et angulaire envoyée par le Parcoureur.&lt;br /&gt;
&lt;br /&gt;
====Jour 2 :====&lt;br /&gt;
&lt;br /&gt;
Nous avons cherchés toutes les documentations techniques nécessaires pour la programmation de chaque noeud.&lt;br /&gt;
&lt;br /&gt;
[http://wiki.ros.org/fr Wiki_ROS]&lt;br /&gt;
&lt;br /&gt;
[http://wiki.ros.org/robotino API_Robotino]&lt;br /&gt;
&lt;br /&gt;
Certaines informations nous ont permis de mettre à jour le schéma global (semaine 2 jour 2) notamment au niveau des types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous nous sommes ensuite concentrés sur le noeud GridMap qui contient ''Map.cpp'' :&lt;br /&gt;
&lt;br /&gt;
Dans le code de l'an dernier, ce noeud générer une grille en dur.&lt;br /&gt;
Cette année cette solution n'est pas possible car nous ne connaissons pas les informations sur la piste. Il va donc falloir générer une grille en fonction du noeud précédent qui nous renverra un type ''OccupancyGrid''. &lt;br /&gt;
&lt;br /&gt;
Etant donné que ce noeud tournera en permanence, si des informations changent pendant que le robot est sur la piste (détection des nouvelles machines par exemple), le noeud ''Map.cpp'' modifiera la grille en temps réel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La grille est décomposée en case pour le A-Star :&lt;br /&gt;
&lt;br /&gt;
Si c'est une case interdite (obstacle) ont associe a la case la valeur 1, si elle est autorisée, on associe la valeur 0.&lt;br /&gt;
&lt;br /&gt;
On illustre le principe précédent par un exemple :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cependant, le noeud &amp;quot;Grid Map&amp;quot; va nous délivrer un vecteur et non une matrice par le biais de ''OccupancyGrid.Data'' .&lt;br /&gt;
&lt;br /&gt;
Dans notre exemple précédent, on récupère le vecteur suivant : &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map_2.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On choisit donc de transformer ce vecteur en matrice. On connait la largeur (en case) de la grille grâce au type ''OccupancyGrid.info.width''.&lt;br /&gt;
&lt;br /&gt;
Le pseudo-code pour générer la matrice à partir de ce vecteur sera le suivant :&lt;br /&gt;
&lt;br /&gt;
 fonction create_grid (OccupancyGrid.Data vecteur[size]) : matrice[height].[width]&lt;br /&gt;
 {&lt;br /&gt;
   matrice[height].[width] ;		&lt;br /&gt;
      int t &amp;lt;- size;&lt;br /&gt;
          Pour (i de 0 à height)&lt;br /&gt;
          faire:&lt;br /&gt;
                {&lt;br /&gt;
                    Pour (j de 0 à width)&lt;br /&gt;
                    faire :&lt;br /&gt;
                            {&lt;br /&gt;
                               matrice[i].[j] &amp;lt;- vecteur[t] ;&lt;br /&gt;
                               t++;&lt;br /&gt;
                            }&lt;br /&gt;
                }&lt;br /&gt;
   return matrice;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16794</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16794"/>
				<updated>2015-02-11T16:43:19Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Jour 2 : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
=====Génération de trajectoire :=====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | 400px | center]][[Image:Projet_S8_A_STAR_2.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | 400px | center]][[Image:Projet_S8_A_STAR_4.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
=====Localisation : =====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
*Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
*Chaque case du diagramme précédent correspond à un noeud ROS. '''Les cases vertes sont des entrées, les bleus sont des sorties et les données rouges sont les types qui seront utilisés'''&lt;br /&gt;
&lt;br /&gt;
*Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
**'''Laser :''' Ce noeud récupère les données du laser, il permet de détecter les objets qui entoure le robot.&lt;br /&gt;
**'''Filtrage :''' Ce bloc permettra d'enlever les éventuels bruits qui affectent les données du laser car la précision de ce dernier diminue avec la distance. A 5m, la précision est de + ou - 5 cm.&lt;br /&gt;
**'''Reconnaissance des droites :''' Algorithme de traitement des données pour repérer les droites  (Transformée de Hough / Ransac, point + orientation)&lt;br /&gt;
**'''Reconnaissance des formes :''' Algorithme qui permettra de reconnaître des objets à partir des droites.&lt;br /&gt;
**'''Odométrie :''' Ce noeud récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
**'''Traitement de position :''' Etant donné que nous avons besoin du Twist pour la fusion de Kalman, nous corrigeons l'erreur par une dérivation. Celle-ci se fait dans ce noeud.&lt;br /&gt;
**'''Fusion de Kalman :''' Cet algorithme va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
**'''Emplacements des machines :''' ce noeud issu du traitement des données du laser permettra de connaître l'emplacement des machines sur la piste.&lt;br /&gt;
**'''Stockage/Position orientation :''' Ce noeud transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
**'''Map Fixe :''' Ce noeud est une sortie. Il renverra une map utilisée pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
**'''RefBoxCom :''' Stock et renvoie la position des machines.&lt;br /&gt;
**'''Position :''' Sortie qui renvoie la position exacte du robot sur la grille.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Jour 2 :====&lt;br /&gt;
&lt;br /&gt;
Nous avons cherchés toutes les documentations techniques nécessaires pour la programmation de chaque noeud.&lt;br /&gt;
&lt;br /&gt;
[http://wiki.ros.org/fr Wiki_ROS]&lt;br /&gt;
&lt;br /&gt;
[http://wiki.ros.org/robotino API_Robotino]&lt;br /&gt;
&lt;br /&gt;
Certaines informations nous ont permis de mettre à jour le schéma global (semaine 2 jour 2) notamment au niveau des types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous nous sommes ensuite concentrés sur le noeud GridMap qui contient ''Map.cpp'' :&lt;br /&gt;
&lt;br /&gt;
Dans le code de l'an dernier, ce noeud générer une grille en dur.&lt;br /&gt;
Cette année cette solution n'est pas possible car nous ne connaissons pas les informations sur la piste. Il va donc falloir générer une grille en fonction du noeud précédent qui nous renverra un type ''OccupancyGrid''. &lt;br /&gt;
&lt;br /&gt;
Etant donné que ce noeud tournera en permanence, si des informations changent pendant que le robot est sur la piste (détection des nouvelles machines par exemple), le noeud ''Map.cpp'' modifiera la grille en temps réel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La grille est décomposée en case pour le A-Star :&lt;br /&gt;
&lt;br /&gt;
Si c'est une case interdite (obstacle) ont associe a la case la valeur 1, si elle est autorisée, on associe la valeur 0.&lt;br /&gt;
&lt;br /&gt;
On illustre le principe précédent par un exemple :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cependant, le noeud &amp;quot;Grid Map&amp;quot; va nous délivrer un vecteur et non une matrice par le biais de ''OccupancyGrid.Data'' .&lt;br /&gt;
&lt;br /&gt;
Dans notre exemple précédent, on récupère le vecteur suivant : &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map_2.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On choisit donc de transformer ce vecteur en matrice. On connait la largeur (en case) de la grille grâce au type ''OccupancyGrid.info.width''.&lt;br /&gt;
&lt;br /&gt;
Le pseudo-code pour générer la matrice à partir de ce vecteur sera le suivant :&lt;br /&gt;
&lt;br /&gt;
 fonction create_grid (OccupancyGrid.Data vecteur[size]) : matrice[height].[width]&lt;br /&gt;
 {&lt;br /&gt;
   matrice[height].[width] ;		&lt;br /&gt;
      int t &amp;lt;- size;&lt;br /&gt;
          Pour (i de 0 à height)&lt;br /&gt;
          faire:&lt;br /&gt;
                {&lt;br /&gt;
                    Pour (j de 0 à width)&lt;br /&gt;
                    faire :&lt;br /&gt;
                            {&lt;br /&gt;
                               matrice[i].[j] &amp;lt;- vecteur[t] ;&lt;br /&gt;
                               t++;&lt;br /&gt;
                            }&lt;br /&gt;
                }&lt;br /&gt;
   return matrice;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16793</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16793"/>
				<updated>2015-02-11T16:42:22Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Jour 2 : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
=====Génération de trajectoire :=====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | 400px | center]][[Image:Projet_S8_A_STAR_2.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | 400px | center]][[Image:Projet_S8_A_STAR_4.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
=====Localisation : =====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
*Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
*Chaque case du diagramme précédent correspond à un noeud ROS. '''Les cases vertes sont des entrées, les bleus sont des sorties et les données rouges sont les types qui seront utilisés'''&lt;br /&gt;
&lt;br /&gt;
*Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
**'''Laser :''' Ce noeud récupère les données du laser, il permet de détecter les objets qui entoure le robot.&lt;br /&gt;
**'''Filtrage :''' Ce bloc permettra d'enlever les éventuels bruits qui affectent les données du laser car la précision de ce dernier diminue avec la distance. A 5m, la précision est de + ou - 5 cm.&lt;br /&gt;
**'''Reconnaissance des droites :''' Algorithme de traitement des données pour repérer les droites  (Transformée de Hough / Ransac, point + orientation)&lt;br /&gt;
**'''Reconnaissance des formes :''' Algorithme qui permettra de reconnaître des objets à partir des droites.&lt;br /&gt;
**'''Odométrie :''' Ce noeud récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
**'''Traitement de position :''' Etant donné que nous avons besoin du Twist pour la fusion de Kalman, nous corrigeons l'erreur par une dérivation. Celle-ci se fait dans ce noeud.&lt;br /&gt;
**'''Fusion de Kalman :''' Cet algorithme va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
**'''Emplacements des machines :''' ce noeud issu du traitement des données du laser permettra de connaître l'emplacement des machines sur la piste.&lt;br /&gt;
**'''Stockage/Position orientation :''' Ce noeud transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
**'''Map Fixe :''' Ce noeud est une sortie. Il renverra une map utilisée pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
**'''RefBoxCom :''' Stock et renvoie la position des machines.&lt;br /&gt;
**'''Position :''' Sortie qui renvoie la position exacte du robot sur la grille.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Jour 2 :====&lt;br /&gt;
&lt;br /&gt;
Nous avons cherchés toutes les documentations techniques nécessaires pour la programmation de chaque noeud.&lt;br /&gt;
&lt;br /&gt;
[http://wiki.ros.org/fr Wiki_ROS]&lt;br /&gt;
&lt;br /&gt;
[http://wiki.ros.org/robotino API_Robotino]&lt;br /&gt;
&lt;br /&gt;
Certaines informations nous ont permis de mettre à jour le schéma global (semaine 2 jour 2) notamment au niveau des types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous nous sommes ensuite concentrés sur le noeud GridMap qui contient ''Map.cpp'' :&lt;br /&gt;
&lt;br /&gt;
Dans le code de l'an dernier, ce noeud générer une grille en dur.&lt;br /&gt;
Cette année cette solution n'est pas possible car nous ne connaissons pas les informations sur la piste. Il va donc falloir générer une grille en fonction du noeud précédent qui nous renverra un type ''OccupancyGrid''. &lt;br /&gt;
&lt;br /&gt;
Etant donné que ce noeud tournera en permanence, si des informations changent pendant que le robot est sur la piste (détection des nouvelles machines par exemple), le noeud ''Map.cpp'' modifiera la grille en temps réel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La grille est décomposée en case pour le A-Star :&lt;br /&gt;
&lt;br /&gt;
Si c'est une case interdite (obstacle) ont associe a la case la valeur 1, si elle est autorisée, on associe la valeur 0.&lt;br /&gt;
&lt;br /&gt;
On illustre le principe précédent par un exemple :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cependant, le noeud &amp;quot;Grid Map&amp;quot; va nous délivrer un vecteur et non une matrice par le biais de ''OccupancyGrid.Data'' .&lt;br /&gt;
&lt;br /&gt;
Dans notre exemple précédent, on récupère le vecteur suivant : &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map_2.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On choisit donc de transformer ce vecteur en matrice. On connait la largeur (en case) de la grille grâce au type ''OccupancyGrid.info.width''.&lt;br /&gt;
&lt;br /&gt;
Le pseudo-code pour générer la matrice à partir de ce vecteur sera le suivant :&lt;br /&gt;
&lt;br /&gt;
 fonction create_grid (OccupancyGrid.Data vecteur[size]) : matrice[height].[width]&lt;br /&gt;
 {&lt;br /&gt;
   matrice[height].[width] ;		&lt;br /&gt;
      int t &amp;lt;- size;&lt;br /&gt;
          Pour (i de 0 à height)&lt;br /&gt;
          faire:&lt;br /&gt;
                {&lt;br /&gt;
                    Pour (j de 0 à width)&lt;br /&gt;
                    faire :&lt;br /&gt;
                            {&lt;br /&gt;
                               matrice[i].[j] &amp;lt;- vecteur[t] ;&lt;br /&gt;
                               t++;&lt;br /&gt;
                            }&lt;br /&gt;
                }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16792</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16792"/>
				<updated>2015-02-11T16:40:22Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Jour 2 : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
=====Génération de trajectoire :=====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | 400px | center]][[Image:Projet_S8_A_STAR_2.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | 400px | center]][[Image:Projet_S8_A_STAR_4.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
=====Localisation : =====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
*Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
*Chaque case du diagramme précédent correspond à un noeud ROS. '''Les cases vertes sont des entrées, les bleus sont des sorties et les données rouges sont les types qui seront utilisés'''&lt;br /&gt;
&lt;br /&gt;
*Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
**'''Laser :''' Ce noeud récupère les données du laser, il permet de détecter les objets qui entoure le robot.&lt;br /&gt;
**'''Filtrage :''' Ce bloc permettra d'enlever les éventuels bruits qui affectent les données du laser car la précision de ce dernier diminue avec la distance. A 5m, la précision est de + ou - 5 cm.&lt;br /&gt;
**'''Reconnaissance des droites :''' Algorithme de traitement des données pour repérer les droites  (Transformée de Hough / Ransac, point + orientation)&lt;br /&gt;
**'''Reconnaissance des formes :''' Algorithme qui permettra de reconnaître des objets à partir des droites.&lt;br /&gt;
**'''Odométrie :''' Ce noeud récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
**'''Traitement de position :''' Etant donné que nous avons besoin du Twist pour la fusion de Kalman, nous corrigeons l'erreur par une dérivation. Celle-ci se fait dans ce noeud.&lt;br /&gt;
**'''Fusion de Kalman :''' Cet algorithme va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
**'''Emplacements des machines :''' ce noeud issu du traitement des données du laser permettra de connaître l'emplacement des machines sur la piste.&lt;br /&gt;
**'''Stockage/Position orientation :''' Ce noeud transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
**'''Map Fixe :''' Ce noeud est une sortie. Il renverra une map utilisée pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
**'''RefBoxCom :''' Stock et renvoie la position des machines.&lt;br /&gt;
**'''Position :''' Sortie qui renvoie la position exacte du robot sur la grille.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Jour 2 :====&lt;br /&gt;
&lt;br /&gt;
Nous avons cherchés toutes les documentations techniques nécessaires pour la programmation de chaque noeud.&lt;br /&gt;
&lt;br /&gt;
[http://wiki.ros.org/fr Wiki_ROS]&lt;br /&gt;
&lt;br /&gt;
[http://wiki.ros.org/robotino API_Robotino]&lt;br /&gt;
&lt;br /&gt;
Certaines informations nous ont permis de mettre à jour le schéma global (semaine 2 jour 2) notamment au niveau des types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous nous sommes ensuite concentrés sur le noeud ''Map.cpp'' :&lt;br /&gt;
&lt;br /&gt;
Dans le code de l'an dernier, ce noeud générer une grille en dur.&lt;br /&gt;
Cette année cette solution n'est pas possible car nous ne connaissons pas les informations sur la piste. Il va donc falloir générer une grille en fonction du noeud précédent qui nous renverra un type ''OccupancyGrid''. &lt;br /&gt;
&lt;br /&gt;
Etant donné que ce noeud tournera en permanence, si des informations changent pendant que le robot est sur la piste (détection des nouvelles machines par exemple), le noeud ''Map.cpp'' modifiera la grille en temps réel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La grille est décomposée en case pour le A-Star :&lt;br /&gt;
&lt;br /&gt;
Si c'est une case interdite (obstacle) ont associe a la case la valeur 1, si elle est autorisée, on associe la valeur 0.&lt;br /&gt;
&lt;br /&gt;
On illustre le principe précédent par un exemple :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cependant, le noeud &amp;quot;Grid Map&amp;quot; va nous délivrer un vecteur et non une matrice par le biais de ''OccupancyGrid.Data'' .&lt;br /&gt;
&lt;br /&gt;
Dans notre exemple précédent, on récupère le vecteur suivant : &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Creation_Map_2.PNG | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On choisit donc de transformer ce vecteur en matrice. On connait la largeur (en case) de la grille grâce au type ''OccupancyGrid.info.width''.&lt;br /&gt;
&lt;br /&gt;
Le pseudo-code pour générer la matrice à partir de ce vecteur sera le suivant :&lt;br /&gt;
&lt;br /&gt;
 fonction create_grid (OccupancyGrid.Data vecteur[size]) : matrice[height].[width]&lt;br /&gt;
 {&lt;br /&gt;
   matrice[height].[width] ;		&lt;br /&gt;
      int t &amp;lt;- size;&lt;br /&gt;
          Pour (i de 0 à height)&lt;br /&gt;
          faire:&lt;br /&gt;
                {&lt;br /&gt;
                    Pour (j de 0 à width)&lt;br /&gt;
                    faire :&lt;br /&gt;
                            {&lt;br /&gt;
                               matrice[i].[j] &amp;lt;- vecteur[t] ;&lt;br /&gt;
                               t++;&lt;br /&gt;
                            }&lt;br /&gt;
                }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_Creation_Map_2.PNG&amp;diff=16789</id>
		<title>Fichier:Projet S8 Creation Map 2.PNG</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_Creation_Map_2.PNG&amp;diff=16789"/>
				<updated>2015-02-11T16:36:21Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_Creation_Map.PNG&amp;diff=16788</id>
		<title>Fichier:Projet S8 Creation Map.PNG</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_Creation_Map.PNG&amp;diff=16788"/>
				<updated>2015-02-11T16:35:31Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16787</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16787"/>
				<updated>2015-02-11T16:24:15Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Semaine 3 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
=====Génération de trajectoire :=====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | 400px | center]][[Image:Projet_S8_A_STAR_2.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | 400px | center]][[Image:Projet_S8_A_STAR_4.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
=====Localisation : =====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
*Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
*Chaque case du diagramme précédent correspond à un noeud ROS. '''Les cases vertes sont des entrées, les bleus sont des sorties et les données rouges sont les types qui seront utilisés'''&lt;br /&gt;
&lt;br /&gt;
*Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
**'''Laser :''' Ce noeud récupère les données du laser, il permet de détecter les objets qui entoure le robot.&lt;br /&gt;
**'''Filtrage :''' Ce bloc permettra d'enlever les éventuels bruits qui affectent les données du laser car la précision de ce dernier diminue avec la distance. A 5m, la précision est de + ou - 5 cm.&lt;br /&gt;
**'''Reconnaissance des droites :''' Algorithme de traitement des données pour repérer les droites  (Transformée de Hough / Ransac, point + orientation)&lt;br /&gt;
**'''Reconnaissance des formes :''' Algorithme qui permettra de reconnaître des objets à partir des droites.&lt;br /&gt;
**'''Odométrie :''' Ce noeud récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
**'''Traitement de position :''' Etant donné que nous avons besoin du Twist pour la fusion de Kalman, nous corrigeons l'erreur par une dérivation. Celle-ci se fait dans ce noeud.&lt;br /&gt;
**'''Fusion de Kalman :''' Cet algorithme va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
**'''Emplacements des machines :''' ce noeud issu du traitement des données du laser permettra de connaître l'emplacement des machines sur la piste.&lt;br /&gt;
**'''Stockage/Position orientation :''' Ce noeud transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
**'''Map Fixe :''' Ce noeud est une sortie. Il renverra une map utilisée pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
**'''RefBoxCom :''' Stock et renvoie la position des machines.&lt;br /&gt;
**'''Position :''' Sortie qui renvoie la position exacte du robot sur la grille.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Jour 2 :====&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16786</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16786"/>
				<updated>2015-02-11T16:23:29Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Génération de trajectoire : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
=====Génération de trajectoire :=====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | 400px | center]][[Image:Projet_S8_A_STAR_2.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | 400px | center]][[Image:Projet_S8_A_STAR_4.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | 400px | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
=====Localisation : =====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
*Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
*Chaque case du diagramme précédent correspond à un noeud ROS. '''Les cases vertes sont des entrées, les bleus sont des sorties et les données rouges sont les types qui seront utilisés'''&lt;br /&gt;
&lt;br /&gt;
*Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
**'''Laser :''' Ce noeud récupère les données du laser, il permet de détecter les objets qui entoure le robot.&lt;br /&gt;
**'''Filtrage :''' Ce bloc permettra d'enlever les éventuels bruits qui affectent les données du laser car la précision de ce dernier diminue avec la distance. A 5m, la précision est de + ou - 5 cm.&lt;br /&gt;
**'''Reconnaissance des droites :''' Algorithme de traitement des données pour repérer les droites  (Transformée de Hough / Ransac, point + orientation)&lt;br /&gt;
**'''Reconnaissance des formes :''' Algorithme qui permettra de reconnaître des objets à partir des droites.&lt;br /&gt;
**'''Odométrie :''' Ce noeud récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
**'''Traitement de position :''' Etant donné que nous avons besoin du Twist pour la fusion de Kalman, nous corrigeons l'erreur par une dérivation. Celle-ci se fait dans ce noeud.&lt;br /&gt;
**'''Fusion de Kalman :''' Cet algorithme va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
**'''Emplacements des machines :''' ce noeud issu du traitement des données du laser permettra de connaître l'emplacement des machines sur la piste.&lt;br /&gt;
**'''Stockage/Position orientation :''' Ce noeud transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
**'''Map Fixe :''' Ce noeud est une sortie. Il renverra une map utilisée pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
**'''RefBoxCom :''' Stock et renvoie la position des machines.&lt;br /&gt;
**'''Position :''' Sortie qui renvoie la position exacte du robot sur la grille.&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16785</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16785"/>
				<updated>2015-02-11T16:21:50Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Jour 1 : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
=====Génération de trajectoire :=====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | thumb | center]][[Image:Projet_S8_A_STAR_2.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | thumb | center]][[Image:Projet_S8_A_STAR_4.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
=====Localisation : =====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
*Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | 800px | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
*Chaque case du diagramme précédent correspond à un noeud ROS. '''Les cases vertes sont des entrées, les bleus sont des sorties et les données rouges sont les types qui seront utilisés'''&lt;br /&gt;
&lt;br /&gt;
*Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
**'''Laser :''' Ce noeud récupère les données du laser, il permet de détecter les objets qui entoure le robot.&lt;br /&gt;
**'''Filtrage :''' Ce bloc permettra d'enlever les éventuels bruits qui affectent les données du laser car la précision de ce dernier diminue avec la distance. A 5m, la précision est de + ou - 5 cm.&lt;br /&gt;
**'''Reconnaissance des droites :''' Algorithme de traitement des données pour repérer les droites  (Transformée de Hough / Ransac, point + orientation)&lt;br /&gt;
**'''Reconnaissance des formes :''' Algorithme qui permettra de reconnaître des objets à partir des droites.&lt;br /&gt;
**'''Odométrie :''' Ce noeud récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
**'''Traitement de position :''' Etant donné que nous avons besoin du Twist pour la fusion de Kalman, nous corrigeons l'erreur par une dérivation. Celle-ci se fait dans ce noeud.&lt;br /&gt;
**'''Fusion de Kalman :''' Cet algorithme va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
**'''Emplacements des machines :''' ce noeud issu du traitement des données du laser permettra de connaître l'emplacement des machines sur la piste.&lt;br /&gt;
**'''Stockage/Position orientation :''' Ce noeud transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
**'''Map Fixe :''' Ce noeud est une sortie. Il renverra une map utilisée pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
**'''RefBoxCom :''' Stock et renvoie la position des machines.&lt;br /&gt;
**'''Position :''' Sortie qui renvoie la position exacte du robot sur la grille.&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16783</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16783"/>
				<updated>2015-02-11T16:20:19Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Jour 1 : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
=====Génération de trajectoire :=====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | thumb | center]][[Image:Projet_S8_A_STAR_2.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | thumb | center]][[Image:Projet_S8_A_STAR_4.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
=====Localisation : =====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
*Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png | upright=0.4 | center]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
*Chaque case du diagramme précédent correspond à un noeud ROS. '''Les cases vertes sont des entrées, les bleus sont des sorties et les données rouges sont les types qui seront utilisés'''&lt;br /&gt;
&lt;br /&gt;
*Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
**'''Laser :''' Ce noeud récupère les données du laser, il permet de détecter les objets qui entoure le robot.&lt;br /&gt;
**'''Filtrage :''' Ce bloc permettra d'enlever les éventuels bruits qui affectent les données du laser car la précision de ce dernier diminue avec la distance. A 5m, la précision est de + ou - 5 cm.&lt;br /&gt;
**'''Reconnaissance des droites :''' Algorithme de traitement des données pour repérer les droites  (Transformée de Hough / Ransac, point + orientation)&lt;br /&gt;
**'''Reconnaissance des formes :''' Algorithme qui permettra de reconnaître des objets à partir des droites.&lt;br /&gt;
**'''Odométrie :''' Ce noeud récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
**'''Traitement de position :''' Etant donné que nous avons besoin du Twist pour la fusion de Kalman, nous corrigeons l'erreur par une dérivation. Celle-ci se fait dans ce noeud.&lt;br /&gt;
**'''Fusion de Kalman :''' Cet algorithme va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
**'''Emplacements des machines :''' ce noeud issu du traitement des données du laser permettra de connaître l'emplacement des machines sur la piste.&lt;br /&gt;
**'''Stockage/Position orientation :''' Ce noeud transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
**'''Map Fixe :''' Ce noeud est une sortie. Il renverra une map utilisée pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
**'''RefBoxCom :''' Stock et renvoie la position des machines.&lt;br /&gt;
**'''Position :''' Sortie qui renvoie la position exacte du robot sur la grille.&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16706</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16706"/>
				<updated>2015-02-11T14:21:30Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Génération de trajectoire : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
=====Génération de trajectoire :=====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | thumb | center]][[Image:Projet_S8_A_STAR_2.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | thumb | center]][[Image:Projet_S8_A_STAR_4.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
=====Localisation : =====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
*Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
*Chaque case du diagramme précédent correspond à un noeud ROS. '''Les cases vertes sont des entrées, les bleus sont des sorties et les données rouges sont les types qui seront utilisés'''&lt;br /&gt;
&lt;br /&gt;
*Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
**'''Laser :''' Ce noeud récupère les données du laser, il permet de détecter les objets qui entoure le robot.&lt;br /&gt;
**'''Filtrage :''' Ce bloc permettra d'enlever les éventuels bruits qui affectent les données du laser car la précision de ce dernier diminue avec la distance. A 5m, la précision est de + ou - 5 cm.&lt;br /&gt;
**'''Reconnaissance des droites :''' Algorithme de traitement des données pour repérer les droites  (Transformée de Hough / Ransac, point + orientation)&lt;br /&gt;
**'''Reconnaissance des formes :''' Algorithme qui permettra de reconnaître des objets à partir des droites.&lt;br /&gt;
**'''Odométrie :''' Ce noeud récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
**'''Traitement de position :''' Etant donné que nous avons besoin du Twist pour la fusion de Kalman, nous corrigeons l'erreur par une dérivation. Celle-ci se fait dans ce noeud.&lt;br /&gt;
**'''Fusion de Kalman :''' Cet algorithme va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
**'''Emplacements des machines :''' ce noeud issu du traitement des données du laser permettra de connaître l'emplacement des machines sur la piste.&lt;br /&gt;
**'''Stockage/Position orientation :''' Ce noeud transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
**'''Map Fixe :''' Ce noeud est une sortie. Il renverra une map utilisée pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
**'''RefBoxCom :''' Stock et renvoie la position des machines.&lt;br /&gt;
**'''Position :''' Sortie qui renvoie la position exacte du robot sur la grille.&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16705</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16705"/>
				<updated>2015-02-11T14:20:58Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Localisation : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
=====Génération de trajectoire :=====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | thumb | center]][[Image:Projet_S8_A_STAR_2.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | thumb | center]][[Image:Projet_S8_A_STAR_4.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
=====Localisation : =====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
*Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
*Chaque case du diagramme précédent correspond à un noeud ROS. '''Les cases vertes sont des entrées, les bleus sont des sorties et les données rouges sont les types qui seront utilisés'''&lt;br /&gt;
&lt;br /&gt;
*Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
**'''Laser :''' Ce noeud récupère les données du laser, il permet de détecter les objets qui entoure le robot.&lt;br /&gt;
**'''Filtrage :''' Ce bloc permettra d'enlever les éventuels bruits qui affectent les données du laser car la précision de ce dernier diminue avec la distance. A 5m, la précision est de + ou - 5 cm.&lt;br /&gt;
**'''Reconnaissance des droites :''' Algorithme de traitement des données pour repérer les droites  (Transformée de Hough / Ransac, point + orientation)&lt;br /&gt;
**'''Reconnaissance des formes :''' Algorithme qui permettra de reconnaître des objets à partir des droites.&lt;br /&gt;
**'''Odométrie :''' Ce noeud récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
**'''Traitement de position :''' Etant donné que nous avons besoin du Twist pour la fusion de Kalman, nous corrigeons l'erreur par une dérivation. Celle-ci se fait dans ce noeud.&lt;br /&gt;
**'''Fusion de Kalman :''' Cet algorithme va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
**'''Emplacements des machines :''' ce noeud issu du traitement des données du laser permettra de connaître l'emplacement des machines sur la piste.&lt;br /&gt;
**'''Stockage/Position orientation :''' Ce noeud transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
**'''Map Fixe :''' Ce noeud est une sortie. Il renverra une map utilisée pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
**'''RefBoxCom :''' Stock et renvoie la position des machines.&lt;br /&gt;
**'''Position :''' Sortie qui renvoie la position exacte du robot sur la grille.&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16704</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16704"/>
				<updated>2015-02-11T14:20:12Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Cahier des charges */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
====Vocabulaire====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos comptes rendus peuvent contenir des expressions que nous employons régulièrement mais qui ne sont parfois pas évidentes. Nous proposons alors cette partie vocabulaire afin d'aider le lecteur à comprendre ces expressions.&lt;br /&gt;
&lt;br /&gt;
* '''Noeud :''' C'est un programme qui tourne de manière indépendante et qui réalise une tâche spécifique.&lt;br /&gt;
&lt;br /&gt;
* '''Type :''' C'est un format spécifique de message. Il définit les valeurs que peut prendre une donnée, ainsi que les opérateurs qui peuvent lui être appliqués.&lt;br /&gt;
&lt;br /&gt;
* '''Odométrie :''' L’odométrie est une technique permettant d'estimer la position d'un véhicule en mouvement. Cette mesure de bas niveau est présente sur quasiment tous les robots mobiles, grâce à des capteurs embarqués permettant de mesurer le déplacement du robot (de ses roues).&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
=====Génération de trajectoire :=====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | thumb | center]][[Image:Projet_S8_A_STAR_2.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | thumb | center]][[Image:Projet_S8_A_STAR_4.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
=====Localisation : =====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
*Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SchémaProjetS8-1.png]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
*Chaque case du diagramme précédent correspond à un noeud ROS. '''Les cases vertes sont des entrées, les bleus sont des sorties et les données rouges sont les types qui seront utilisés'''&lt;br /&gt;
&lt;br /&gt;
*Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
**'''Laser :''' Ce noeud récupère les données du laser, il permet de détecter les objets qui entoure le robot.&lt;br /&gt;
**'''Filtrage :''' Ce bloc permettra d'enlever les éventuels bruits qui affectent les données du laser car la précision de ce dernier diminue avec la distance. A 5m, la précision est de + ou - 5 cm.&lt;br /&gt;
**'''Reconnaissance des droites :''' Algorithme de traitement des données pour repérer les droites  (Transformée de Hough / Ransac, point + orientation)&lt;br /&gt;
**'''Reconnaissance des formes :''' Algorithme qui permettra de reconnaître des objets à partir des droites.&lt;br /&gt;
**'''Odométrie :''' Ce noeud récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
**'''Traitement de position :''' Etant donné que nous avons besoin du Twist pour la fusion de Kalman, nous corrigeons l'erreur par une dérivation. Celle-ci se fait dans ce noeud.&lt;br /&gt;
**'''Fusion de Kalman :''' Cet algorithme va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
**'''Emplacements des machines :''' ce noeud issu du traitement des données du laser permettra de connaître l'emplacement des machines sur la piste.&lt;br /&gt;
**'''Stockage/Position orientation :''' Ce noeud transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
**'''Map Fixe :''' Ce noeud est une sortie. Il renverra une map utilisée pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
**'''RefBoxCom :''' Stock et renvoie la position des machines.&lt;br /&gt;
**'''Position :''' Sortie qui renvoie la position exacte du robot sur la grille.&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16652</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16652"/>
				<updated>2015-02-09T17:14:24Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Jour 1 : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
*Conception du schéma global des différentes parties :&lt;br /&gt;
**Localisation avec le SLAM&lt;br /&gt;
**Création de la carte avec le SLAM&lt;br /&gt;
**Génération de trajectoire avec A-Star&lt;br /&gt;
**Execution de trajectoire avec le noeud ROS pour Robotino robotino_local_move&lt;br /&gt;
&lt;br /&gt;
*Codage des différents noeuds ROS&lt;br /&gt;
&lt;br /&gt;
*Tests de précision et de robustesse sur robot&lt;br /&gt;
&lt;br /&gt;
*Validation du modèle&lt;br /&gt;
&lt;br /&gt;
*Améliorations possibles :&lt;br /&gt;
**Fusionner les maps des 3 robots&lt;br /&gt;
**D-Star Lite au lieu de A-Star&lt;br /&gt;
**Filtrage des données laser&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
=====Génération de trajectoire :=====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | thumb | center]][[Image:Projet_S8_A_STAR_2.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | thumb | center]][[Image:Projet_S8_A_STAR_4.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
=====Localisation : =====&lt;br /&gt;
&lt;br /&gt;
Pour la localisation nous allons utilisé un algorithme de Localisation et Cartographie Simultanée (SLAM en anglais):&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
Ce schéma sera explicité à la séance prochaine.&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
*Nous avons découper le travail de génération de map et de la correction de position de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_Schematic.PNG]]&lt;br /&gt;
&lt;br /&gt;
( Nous recommandons au lecteur de se référer à la partie vocabulaire pour comprendre les termes techniques )&lt;br /&gt;
&lt;br /&gt;
*Chaque case du diagramme précédent correspond à un noeud ROS. '''Les cases vertes sont des entrées, les bleus sont des sorties et les données rouges sont les types qui seront utilisés'''&lt;br /&gt;
&lt;br /&gt;
*Décrivons précisément le rôle de chaque noeud :&lt;br /&gt;
**'''Laser :''' Ce noeud récupère les données du laser, il permet de détecter les objets qui entoure le robot.&lt;br /&gt;
**'''Filtrage :''' Ce bloc permettra d'enlever les éventuels bruits qui affectent les données du laser car la précision de ce dernier diminue avec la distance. A 5m, la précision est de + ou - 5 cm.&lt;br /&gt;
**'''Reconnaissance des droites :''' Algorithme de traitement des données pour repérer les droites  (Transformée de Hough / Ransac, point + orientation)&lt;br /&gt;
**'''Reconnaissance des formes :''' Algorithme qui permettra de reconnaître des objets à partir des droites.&lt;br /&gt;
**'''Odométrie :''' Ce noeud récupère la position du robot par rapport au point de départ. Il renvoie une position corrigée grâce au gyroscope(Pose) et une position non corrigée par le gyroscope (Twist) &lt;br /&gt;
**'''Traitement de position :''' Etant donné que nous avons besoin du Twist pour la fusion de Kalman, nous corrigeons l'erreur par une dérivation. Celle-ci se fait dans ce noeud.&lt;br /&gt;
**'''Fusion de Kalman :''' Cet algorithme va coupler les données de position et les données du laser afin de fournir un modèle et une position précise. C'est le noeud central du SLAM.&lt;br /&gt;
**'''Emplacements des machines :''' ce noeud issu du traitement des données du laser permettra de connaître l'emplacement des machines sur la piste.&lt;br /&gt;
**'''Stockage/Position orientation :''' Ce noeud transforme les positions des machines et du robot en grille. Il sera couplé aux détections d'obstacles.&lt;br /&gt;
**'''Map Fixe :''' Ce noeud est une sortie. Il renverra une map utilisée pour les déplacements et les calculs de trajectoires (A_Star)&lt;br /&gt;
**'''RefBoxCom :''' Stock et renvoie la position des machines.&lt;br /&gt;
**'''Position :''' Sortie qui renvoie la position exacte du robot sur la grille.&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_Schematic.PNG&amp;diff=16651</id>
		<title>Fichier:Projet S8 Schematic.PNG</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_Schematic.PNG&amp;diff=16651"/>
				<updated>2015-02-09T17:10:44Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16643</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16643"/>
				<updated>2015-02-09T16:27:07Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Avancement du Projet */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Avec plusieurs IMAs, nous avons créer une équipe pour participer à la [http://www.robocup-logistics.org/ Logistic League] de la RoboCup. Lors de la compétition de l'Open German, version européenne de la RoboCup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux) afin de réaliser des produits en fonction des demandes de l'arbitre du jeu : la Referee Box. Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu permettant de définir des zones de passage entre les machines. Dans la phase de production, la navigation permettra de se déplacer à partir de la carte créée au préalable (avec les obstacles fixes) et des robots (obstacles mobiles) se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
Schéma du concept de la Localisation et Cartographie Simultanée :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:SLAM.png | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
Explicitation des différentes parties :&lt;br /&gt;
&lt;br /&gt;
*Odometry change     : changement de position&lt;br /&gt;
*Odometry update     : mise à jour de l'odométrie&lt;br /&gt;
*Re-observation      : vérification des changements à partir de toutes les données disponibles&lt;br /&gt;
*New observations    : mise à jours de la matrice d'état&lt;br /&gt;
&lt;br /&gt;
*Laser scan          : scan laser brut&lt;br /&gt;
*Landmark Extraction : extraction des objets caractéristiques&lt;br /&gt;
*Data Association    : association entre objets scannés et objets en mémoire&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
Etablissement du cahier des charges :&lt;br /&gt;
*Prise de connaissance des contraintes d'environnement&lt;br /&gt;
*Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
====Jour 2 : ====&lt;br /&gt;
&lt;br /&gt;
Nous avons fait nos recherches en nous orientant sur le déplacement du Robotino afin de trouver un algorithme de trajectoire, capable de trouver le chemin le plus court, puisqu'un des buts de la compétition étant la rapidité.&amp;lt;br&amp;gt;&lt;br /&gt;
Plusieurs algorithmes sont donc ressortis :&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme Dijkstra (On part du point de départ et on cherche le chemin le plus court vers le point d'arrivée en cherchant dans TOUTES les directions)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme A-Star (Basé sur Dijkstra, cet algo s'oriente directement vers le point d'arrivée en minimisant la distance avec celui-ci)&amp;lt;br&amp;gt;&lt;br /&gt;
*L'algorithme D-Star Lite (Amélioration du A-Star avec bufferisation des précédents calculs pour éviter les calculs inutiles en cas d'arrivée d'un obstacle mobile sur la trajectoire)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fonctionnement de l'algorithme A-Star :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on définit les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_1.PNG | thumb | center]][[Image:Projet_S8_A_STAR_2.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_3.PNG | thumb | center]][[Image:Projet_S8_A_STAR_4.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Projet_S8_A_STAR_5.PNG | thumb | center]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
====Jour 1 :====&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16497</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16497"/>
				<updated>2015-02-05T10:21:22Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Avancement du Projet */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Lors de la compétition de l'Open German, prélude de la Robocup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux). Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu afin de définir des zones de passage entre les machines et dans la phase de production afin de permettre le déplacement à partir de la carte créée au préalable et des robots adverses ou non se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
Jour 1 :&lt;br /&gt;
&lt;br /&gt;
*Etablissement du cahier des charges :&lt;br /&gt;
**Prise de connaissance des contraintes d'environnement&lt;br /&gt;
**Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
*Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
*Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
Jour 2 : &lt;br /&gt;
&lt;br /&gt;
*Tout d'abord nous avons voulu orientés nos recherches sur le déplacement du Robotino, pour cela il a fallu chercher un algorithme de trajectoire.&lt;br /&gt;
*Un des buts de la compétition étant la rapidité, nous avons orientés nos recherches vers des algorithmes qui offraient la possibilité de parcourir une *distance minimale.&lt;br /&gt;
*Deux algorithmes sont donc ressortis : &lt;br /&gt;
&lt;br /&gt;
**- L'algorithme A-Star (ou A*)&lt;br /&gt;
&lt;br /&gt;
**- L'algorithme Dikjstra &lt;br /&gt;
&lt;br /&gt;
*L'algorithme A-Star est un algorithme dérivé de celui de Dikjstra mais qui permet au robot de faire moins de calcul. &lt;br /&gt;
*L'algorithme de Dikjstra est utile si les obstacles créent un vrai labyrinthe pour le robot, mais ce n'est pas le cas de notre compétition.&lt;br /&gt;
&lt;br /&gt;
*Nous avons donc choisi l'algorithme A-Star, voici son fonctionnement :&lt;br /&gt;
&lt;br /&gt;
*Tout d'abord, on calcule la distance qui sépare le robot du point d'arrivée, et on défini les points interdits par les obstacles. (la zone bleue correspond&lt;br /&gt;
*à l'obstacle et la zone verte est une zone ou le robot touche l'obstacle. Ces deux zones constituent la zone interdite).&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_A_STAR_1.PNG]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-------------------------------------------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_A_STAR_2.PNG]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Ensuite le Robot trouve un premier noeud sur la grille qu'on lui a attribué. Si le noeud n'est pas dans une zone interdite, il sauvegarde ce noeud.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_A_STAR_3.PNG]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-------------------------------------------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_A_STAR_4.PNG]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Il répète l'opération jusqu'à trouver le chemin qui le mènera à l'arrivée&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Projet_S8_A_STAR_5.PNG]]&lt;br /&gt;
&lt;br /&gt;
*Attention : c'est seulement lorsqu'il aura trouvé le chemin complet que le robot va se déplacer !&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_A_STAR_5.PNG&amp;diff=16496</id>
		<title>Fichier:Projet S8 A STAR 5.PNG</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_A_STAR_5.PNG&amp;diff=16496"/>
				<updated>2015-02-05T10:18:50Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_A_STAR_4.PNG&amp;diff=16495</id>
		<title>Fichier:Projet S8 A STAR 4.PNG</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_A_STAR_4.PNG&amp;diff=16495"/>
				<updated>2015-02-05T10:18:35Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_A_STAR_3.PNG&amp;diff=16494</id>
		<title>Fichier:Projet S8 A STAR 3.PNG</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_A_STAR_3.PNG&amp;diff=16494"/>
				<updated>2015-02-05T10:18:23Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_A_STAR_2.PNG&amp;diff=16493</id>
		<title>Fichier:Projet S8 A STAR 2.PNG</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_A_STAR_2.PNG&amp;diff=16493"/>
				<updated>2015-02-05T10:18:09Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_A_STAR_1.PNG&amp;diff=16492</id>
		<title>Fichier:Projet S8 A STAR 1.PNG</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Projet_S8_A_STAR_1.PNG&amp;diff=16492"/>
				<updated>2015-02-05T10:16:57Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16491</id>
		<title>RoboCup 2015 - Pyro Team</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=RoboCup_2015_-_Pyro_Team&amp;diff=16491"/>
				<updated>2015-02-05T10:01:35Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:logoPyro_icone.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
Lors de la compétition de l'Open German, prélude de la Robocup, il faudra mettre en place un système autonome de production à l'aide de Robotinos (robots mobiles de Festo ayant un système d'exploitation Linux). Nous traiterons dans ce projet de l'aspect navigation des robots, composé d'une partie localisation et d'une partie déplacement.&lt;br /&gt;
&lt;br /&gt;
====Contexte====&lt;br /&gt;
&lt;br /&gt;
La compétition de l'Open German se déroule en quatre phases spécifiques : phase de début-de-jeu, phase d'exploration, phase de production, phase de fin-de-jeu. La navigation sera utilisée dans la phase d'exploration afin de réaliser une carte de la zone de jeu afin de définir des zones de passage entre les machines et dans la phase de production afin de permettre le déplacement à partir de la carte créée au préalable et des robots adverses ou non se déplaçant en même temps.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
Fournir aux Robotinos un système capable de se localiser et de parcourir des trajectoires calculées à partir de coordonnées envoyées par le [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]. &lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
[[Fichier:ProjetS8.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
*Localiser correctement le robot (à 5 cm près)&lt;br /&gt;
*Localiser les éléments fixes :&lt;br /&gt;
**Murs&lt;br /&gt;
**Machines&lt;br /&gt;
*Générer une trajectoire selon :&lt;br /&gt;
**les demandes du &amp;quot;[http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&amp;quot;&lt;br /&gt;
**la détection d'obstacles dynamiques (robots)&lt;br /&gt;
*Assurer le suivi de la trajectoire&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
&lt;br /&gt;
*Utilisation de 3 Robotinos équipés chacun de :&lt;br /&gt;
**1 détecteur laser pouvant réaliser des mesures à 240°&lt;br /&gt;
**1 gyroscope&lt;br /&gt;
**9 capteurs SHARP (télémètres infrarouges)&lt;br /&gt;
**3 codeurs incrémentaux présents en sortie de chaque moteur du Robotino&lt;br /&gt;
*Utilisation de [http://wiki.ros.org/hydro ROS Hydro]&lt;br /&gt;
*Utilisation de différents langages : C++ ou Python&lt;br /&gt;
*Utilisation de Linux Ubuntu 12.04&lt;br /&gt;
&lt;br /&gt;
===Etapes du projet===&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Participation aux Finales Nationales des Olympiades des Métiers en robotique mobile (4ème)&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Etablissement du cahier des charges :&lt;br /&gt;
**Prise de connaissance des contraintes d'environnement&lt;br /&gt;
**Dialogue avec l'équipe responsable de la partie [http://projets-imasc.plil.net/mediawiki/index.php?title=RoboCup_2015 Manager]&lt;br /&gt;
*Familiarisation avec l'environnement logiciel ROS&lt;br /&gt;
*Recherches de solutions pour la localisation (SLAM) et la génération de trajectoire (algorithme A-star)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13706</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13706"/>
				<updated>2014-06-14T10:15:08Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* Conclusion : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Beaucoup de notions ont été comprises et travaillées.&lt;br /&gt;
Ces projets sont un bon moyens pour nous confronter aux problèmes que nous rencontrerons lors de nos futurs projets professionnels&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13705</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13705"/>
				<updated>2014-06-14T10:12:59Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* 1.	Gérer la liaison série */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13704</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13704"/>
				<updated>2014-06-14T10:12:50Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* 1.	Gérer la liaison série */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13703</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13703"/>
				<updated>2014-06-14T10:12:39Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* 1.	Gérer la liaison série */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13702</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13702"/>
				<updated>2014-06-14T10:12:28Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* 1.	Gérer la liaison série */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13701</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13701"/>
				<updated>2014-06-14T10:12:13Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* 1.	Gérer la liaison série */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13700</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13700"/>
				<updated>2014-06-14T10:11:21Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* 3. Fox....Board to be alive !  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13699</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13699"/>
				<updated>2014-06-14T10:11:10Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* 3. Fox....Board to be alive !  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13698</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13698"/>
				<updated>2014-06-14T10:10:56Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* A. Le produit fini */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13697</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13697"/>
				<updated>2014-06-14T10:10:12Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* D.	Faut que ça bouge ! */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|thumb|liaison série avec FoxBoard]]&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13696</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13696"/>
				<updated>2014-06-14T10:09:55Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* D.	Faut que ça bouge ! */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|thumb|liaison série avec FoxBoard]]&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13695</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13695"/>
				<updated>2014-06-14T10:09:36Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* D.	Faut que ça bouge ! */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|thumb|liaison série avec FoxBoard]]&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13694</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13694"/>
				<updated>2014-06-14T10:09:19Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* D.	Faut que ça bouge ! */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|thumb|liaison série avec FoxBoard]]&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13693</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13693"/>
				<updated>2014-06-14T10:08:49Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* D.	Faut que ça bouge ! */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|thumb|liaison série avec FoxBoard]]&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13692</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13692"/>
				<updated>2014-06-14T10:08:14Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* 2. Mise en place de l'application sur ordinateur  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|thumb|message défilant sur les afficheurs]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|thumb|message défilant sur les afficheurs]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|thumb|liaison série avec FoxBoard]]&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13691</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13691"/>
				<updated>2014-06-14T10:08:03Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* 2. Mise en place de l'application sur ordinateur  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|thumb|message défilant sur les afficheurs]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|thumb|message défilant sur les afficheurs]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|thumb|liaison série avec FoxBoard]]&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13690</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13690"/>
				<updated>2014-06-14T10:07:43Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* B.	L'alphabet latin, un bonheur ! */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|left|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|thumb|message défilant sur les afficheurs]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|thumb|message défilant sur les afficheurs]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|thumb|liaison série avec FoxBoard]]&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13689</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13689"/>
				<updated>2014-06-14T10:07:17Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* C.  Lire un fichier, c'est la base ! */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|thumb|message défilant sur les afficheurs]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|thumb|message défilant sur les afficheurs]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|thumb|liaison série avec FoxBoard]]&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13688</id>
		<title>Gestion afficheurs, 2013/2014, TD1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Gestion_afficheurs,_2013/2014,_TD1&amp;diff=13688"/>
				<updated>2014-06-14T10:06:49Z</updated>
		
		<summary type="html">&lt;p&gt;Rkrikori : /* 1.	Gérer la liaison série */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt; [[Fichier:Gestion_afficheurs_compressé.mp4|200px|thumb|right|vidéo]] &amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt; Vidéo : http://projets-imasc.plil.net/mediawiki/images/d/df/Gestion_afficheurs_compress%C3%A9.mp4 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projet SC : ==&lt;br /&gt;
 &lt;br /&gt;
'''Gestion d'afficheurs 16 segments'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==''Partie programmation''==&lt;br /&gt;
	&lt;br /&gt;
Cette partie sera décomposée en X parties correspondant aux X difficultés rencontrées lors de ce projet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''1.	Gérer la liaison série''''' ===&lt;br /&gt;
&lt;br /&gt;
Pour transmettre notre programme au banc d'essai, il faut tout d'abord initialiser ce banc d'essai et dire à notre contrôleur (ici l'ordinateur) où il se trouve.&lt;br /&gt;
&lt;br /&gt;
Ceci ne constituais pas une grande difficulté étant donné que de nombreux travaux avaient déjà étaient fait sur la liaison série et que le code permettant de l'initialiser était sur le wiki :&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
[[File:seriel.JPG|800px|thumb|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il fallait rajouter une sécurité à cette initialisation pour éviter de perdre des données :&lt;br /&gt;
&lt;br /&gt;
   sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
source : http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/systeme018.html&lt;br /&gt;
&lt;br /&gt;
Ces données seront réutilisées lors du passage à la FoxBoard.&lt;br /&gt;
Notre Port série est maintenant configuré, on peut envoyer notre code !&lt;br /&gt;
&lt;br /&gt;
==='''''2. Mise en place de l'application sur ordinateur ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A.Un afficheur : un caractère !'''====&lt;br /&gt;
&lt;br /&gt;
Nous avons vite compris que l'afficheur 16 segments était codé sur 16 bits.&lt;br /&gt;
&lt;br /&gt;
Nous avons dans un premier temps affiché un code 16 bits (le 0x0001 par exemple) sur les 8 segments pour comprendre comment on pouvait gérer les 8  afficheurs.&lt;br /&gt;
&lt;br /&gt;
	Après plusieurs essais, nous avons opté pour la création d'un tableau qui contiendrai le message à afficher. &lt;br /&gt;
&lt;br /&gt;
Dans le premier code nous avions un compteur d'afficheur qui recevait les cases du tableau.&lt;br /&gt;
A chaque incrémentation compteur correspondait une incrémentation tableau, ce qui nous 	permettait  d'afficher des caractères différents sur les afficheurs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''B.	L'alphabet latin, un bonheur !'''====&lt;br /&gt;
Maintenant que nous savons afficher, il faut maîtriser le contenu de l'affichage.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc mis chaque bit à 1 séparément (ex : 0x0001 puis 0x0002 puis 0x0004 ..) et reportés sur papier quel segment s'allumait pour ce bit.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite nommé chaque segment pour pouvoir créer nos caractères !&lt;br /&gt;
&lt;br /&gt;
Cette technique nous permet de modéliser un afficheur :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Afficheur16seg.JPG|thumb|afficheur 16 segments]]&lt;br /&gt;
&lt;br /&gt;
===='''C.  Lire un fichier, c'est la base !'''====&lt;br /&gt;
&lt;br /&gt;
Notre application doit permettre de modifier le message affiché. Pour ce faire, notre page html modifiera un fichier et notre code C lira ce&lt;br /&gt;
fichier pour créer le message.&lt;br /&gt;
On présente maintenant le code de l'action &amp;quot;creer_message&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
   void cree_message(FILE* fp)&lt;br /&gt;
   {&lt;br /&gt;
     int i=0,j=0;&lt;br /&gt;
     char car;&lt;br /&gt;
     while(j&amp;lt;8) { x[j]=0x0000; j++;}                 //Cette boule sert à initialiser les 8 afficheurs au caractère NULL (0x0000)&lt;br /&gt;
     while (!feof(fp))&lt;br /&gt;
       {&lt;br /&gt;
         fscanf(fp,&amp;quot;%c&amp;quot;,&amp;amp;car);&lt;br /&gt;
         while((car!=carac[i])){i++;}               //Cette boucle stocke dans x le message du fichier en paramètre &lt;br /&gt;
         x[j]=correspondance[i];                    //lit le premier caractere, on le cherche dans le tableau carc[]&lt;br /&gt;
         j++;                                       //on stocke dans x le code 16bits correspondant puis on incrémente la case j du message x&lt;br /&gt;
         i=0;                                       //on met i à 0 pour la recherche du caractère suivant&lt;br /&gt;
       }&lt;br /&gt;
     x[j--]=0x0000;                                 //Avec cette methode le dernier caractère est doublé car le fscanf n'est pas fait avant la boucle&lt;br /&gt;
     while (j&amp;lt;MAX_SIZE)                             //Ainsi on remet le dernier caractère du message x à NULL puis on met 8 caractère NULL qui serviront &lt;br /&gt;
       {                                            //au défilement&lt;br /&gt;
         x[j]=0x0000;&lt;br /&gt;
         j++;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''D.	Faut que ça bouge !'''====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans un afficheur publicitaire, les messages défilent de droite à gauche.&lt;br /&gt;
	&lt;br /&gt;
Pour reproduire cet effet, nous procédons en 3 étapes!&lt;br /&gt;
&lt;br /&gt;
'''Étape 1 :'''  ''Créer le message et afficher les 8 premiers caractères''&lt;br /&gt;
→ Cette étape est décrite dans la partie précédente&lt;br /&gt;
'''Étape 2 :''' ''Afficher la suite du message pas à pas'' &lt;br /&gt;
→ Pour ce faire, on utilise deux boucles, dont une qui commence quand les 8 premiers caractères du tableau ont été affichés&lt;br /&gt;
→ On parcours le tableau au complet en incrémentant à chaque période le code que l'afficheur reçoit de 1 dans le tableau&lt;br /&gt;
&lt;br /&gt;
'''Étape 3 :''' ''Une boucle infinie''&lt;br /&gt;
→ On utilise un «  while 1 » sur tout le main pour pouvoir revenir au début de notre tableau contenant le message et ainsi afficher le message en continu !&lt;br /&gt;
&lt;br /&gt;
Cette action est l'action principale de notre application, c'est-à-dire que nous avons choisi de la mettre dans le main étant donné qu'elle boucle sur 1&lt;br /&gt;
&lt;br /&gt;
Voici donc la partie du main qui gère le défilement:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     unsigned char low[MAX_SIZE];                            // correspondance est codé sur 16 bits, mais on ne peut envoyer que 8bits à la fois&lt;br /&gt;
     unsigned char high[MAX_SIZE];                           // on découpe donc le tableau message en 2 tableaux low et high&lt;br /&gt;
     int sd=serialOpen(SERIAL_DEVICE,SERIAL_BOTH);           // ouverture du port série&lt;br /&gt;
     int i=0,z=0,a=0,tot=0;&lt;br /&gt;
     while(1)&lt;br /&gt;
     {&lt;br /&gt;
        FILE*fp=fopen(argv[1],&amp;quot;r&amp;quot;);&lt;br /&gt;
        if(fp==NULL){ perror(&amp;quot;fopen(message)&amp;quot;); exit(-1); }  // vérification du bon déroulement de l'ouverture du fichier passé en argument&lt;br /&gt;
        cree_message(fp);                                    // on crée le message x&lt;br /&gt;
        for(i=0;i&amp;lt;MAX_SIZE;i++)                              // i va servir à lire dans le message x &lt;br /&gt;
         {&lt;br /&gt;
           if (i&amp;gt;8) a++;                                     // cette ligne permet d'initialiser rapidement sans devoir décaler les 8 premiers caractères&lt;br /&gt;
           tot=i+a;                                          //NULL, puis on stocke l'endroit où on va lire dans tot (i + le nombre de fois ou on a été   &lt;br /&gt;
           for(z=0;z&amp;lt;8;z++)                                  // au dessus de i&lt;br /&gt;
                {&lt;br /&gt;
                  low[z] = x[tot] &amp;amp; 0x00ff;                  // La correspondance est en 16 bits, or l'envoi sur z se fait en 8bits, ces fonctions nous &lt;br /&gt;
                  high[z]= x[tot]&amp;gt;&amp;gt;8;                        // permettent de stocker correctement sur z, z représentant le numéro de l'afficheur &lt;br /&gt;
                  if(write(sd,&amp;amp;high[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;); exit(-1); }  //Écriture sur l'afficheur&lt;br /&gt;
                  if(write(sd,&amp;amp;low[z],sizeof(char))!=1){ perror(&amp;quot;main.write&amp;quot;);  exit(-1); }&lt;br /&gt;
                  usleep(delai);&lt;br /&gt;
                  tot++;&lt;br /&gt;
                }&lt;br /&gt;
           if (tot&amp;gt;MAX_SIZE) i=MAX_SIZE;&lt;br /&gt;
         }                                                  // Cette ligne nous permet de sortir un peu plus rapidement de la&lt;br /&gt;
          tot=0;                                            //boucle lorsque le message a été affiché &lt;br /&gt;
          i=0;                                              // on réinitialise les variables pour le message suivant, on ferme fp&lt;br /&gt;
          a=0;&lt;br /&gt;
          z=0;&lt;br /&gt;
          fclose(fp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement1.jpg|thumb|message défilant sur les afficheurs]]&lt;br /&gt;
&lt;br /&gt;
[[File:Defilement2.jpg|thumb|message défilant sur les afficheurs]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On sait désormais lire notre message et le faire défiler, mais nous sommes loin d'avoir répondu au cahier des charges !&lt;br /&gt;
&lt;br /&gt;
===='''E. Le cahier des charges'''====&lt;br /&gt;
&lt;br /&gt;
Les deux grands axes du cahier des charges concernant la programmation sont les suivants :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''1)''' Par le biais d'une page php (que nous verrons plus tard), nous modifierons un fichier.txt contenant le message à afficher. Ce message peut être modifié pendant l’exécution et dois défiler en continu.&lt;br /&gt;
&lt;br /&gt;
'''2)''' Par le biais d'une page php, la vitesse de défilement peut être modifiée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
======'''1) Le fichier texte !'''======&lt;br /&gt;
&lt;br /&gt;
La modification du fichier texte se fait dans une fonction écrire.php, voici son code :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;?php&lt;br /&gt;
     $message=$_REQUEST['message'];                //on récupère le message de la page html&lt;br /&gt;
     file_put_contents(&amp;quot;note.txt&amp;quot;,$message);       //on écrit ce message dans note.txt&lt;br /&gt;
     echo &amp;quot;message=$message&amp;quot;;&lt;br /&gt;
     ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La question que l'on se pose maintenant est &amp;quot;Comment faire appel à cette fonction?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Grâce aux commande ajax, on peut récupérer une message sur la page html et appeler le fichier ercire.php&lt;br /&gt;
&lt;br /&gt;
Voici les lignes du code html qui vont permettre de récupérer le message dans une case texte prévue à cet effet:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;message&amp;quot; value=&amp;quot;message&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Envoyer&amp;quot; onclick=&amp;quot;javascript:envoyer();&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici le code ajax qui va permettre d'appeler ecrire.php avec comme paramètre le message:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
     function envoyer(){&lt;br /&gt;
     var m=$('#message').val();&lt;br /&gt;
     $.ajax({url: 'ecrire.php', type: 'post', data: {message: m}});&lt;br /&gt;
     &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====='''2) La vitesse de défilement'''=====&lt;br /&gt;
&lt;br /&gt;
La vitesse de défilement doit pouvoir se gérer grâce à deux boutons sur la page html.&lt;br /&gt;
&lt;br /&gt;
Un bouton fast qui va appeler la fonction rapide.php et un bouton slow qui va appeler la fonction lent.php&lt;br /&gt;
&lt;br /&gt;
En cliquant sur ces boutons, l'utilisateur va envoyer un signe (SIGUSR1 pour Fast et SIGUSR2 pour slow)&lt;br /&gt;
&lt;br /&gt;
Grâce aux fonctionx lent.php et rapide.php ainsi qu'au pid, le code c (corresp.c) va récupérer le signal envoyé ou non par l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Voici le code des boutons Fast et Slow ainsi que le code ajax qui renvoie aux fonction lent.php et rapide.php :&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Fast&amp;quot; onclick=&amp;quot;javascript:rapide();&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Slow&amp;quot; onclick=&amp;quot;javascript:lent();&amp;quot;&amp;gt;&lt;br /&gt;
     function rapide(){&lt;br /&gt;
     $.ajax({url: 'rapide.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
     function lent(){&lt;br /&gt;
     $.ajax({url: 'lent.php', type:'post'});&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Passons maintenant à la fonction rapide.php :&lt;br /&gt;
&lt;br /&gt;
     define('SIGUSR1',10);                          // Ici les valeur des signaux SIGUSR1 et SIGUSR2&lt;br /&gt;
     define('SIGUSR2',12);&lt;br /&gt;
&lt;br /&gt;
     $pid=trim(file_get_contents(&amp;quot;pid.txt&amp;quot;));       // On récupère le pid (envoyé par le code c dans pid.txt) pour pouvoir communiquer avec le .c&lt;br /&gt;
     if(is_numeric($pid)){&lt;br /&gt;
     posix_kill($pid,SIGUSR1);                      // On envoie SIGUSR1 au code c&lt;br /&gt;
     $erreur=posix_get_last_error();                // Vérification que l'envoi s'est bien fait&lt;br /&gt;
     if($erreur!=0) echo 'Erreur : '.posix_strerror($erreur).&amp;quot;&amp;lt;br&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Pour la fonction lent.php, il suffit de remplacer SIGUSR1 par SIGUSR2 !&lt;br /&gt;
&lt;br /&gt;
Comment le code exploite ces signaux?&lt;br /&gt;
&lt;br /&gt;
Dans le code qui gère le défilement, nous avons vu qu'a chaque fois que les 8 afficheurs étaient remplis, une pause usleep(delai) était effectuée&lt;br /&gt;
&lt;br /&gt;
Ce &amp;quot;delai&amp;quot; est en fait une variable globale. Lorsque le code va recevoir un signal SIGUSR1 ou SIGUSR2, il va appeler respectivement les fonction &amp;quot;rapide&amp;quot;&lt;br /&gt;
et &amp;quot;lent&amp;quot; et ainsi modifier la valeur de &amp;quot;delai&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Les fonction rapide et lent sont les suivant :&lt;br /&gt;
&lt;br /&gt;
    void rapide(int sig){             // le paramètre est un entier qui représente le signal reçu, c'est le 10 et 12 que nous avions défini dans les .php&lt;br /&gt;
    delai=delai/2;}&lt;br /&gt;
&lt;br /&gt;
    void lent(int sig){&lt;br /&gt;
    delai=delai*2;}&lt;br /&gt;
&lt;br /&gt;
Ces fonction sont simples, la complexité réside dans la réception et l'appel à ces fonctions.&lt;br /&gt;
&lt;br /&gt;
Ceci se fait dans le main grâce au code suivant:&lt;br /&gt;
&lt;br /&gt;
    FILE*fd=fopen(&amp;quot;pid.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    if(fd==NULL){perror(&amp;quot;open(pid)&amp;quot;); exit(-1);}           //on écrit le pid dans le fichier pid.txt, pour pouvoir communiquer avec le php&lt;br /&gt;
    fprintf(fd,&amp;quot;%d&amp;quot;,getpid());&lt;br /&gt;
    fclose(fd);&lt;br /&gt;
&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));                  //on ecrase l'adresse de action pour ne pas mélanger les fonctions rapide et lent&lt;br /&gt;
    action.sa_handler=rapide;                             // on stocke la fonction rapide dans action&lt;br /&gt;
    if(sigaction(SIGUSR1,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}  // on appelle action si on reçoit SIGUSR1&lt;br /&gt;
    memset(&amp;amp;action,'\0',sizeof(action));&lt;br /&gt;
    action.sa_handler=lent;                                                  // pareil pour SIGUSR2 et lent&lt;br /&gt;
    if(sigaction(SIGUSR2,&amp;amp;action,NULL)&amp;lt;0){perror(&amp;quot;sigaction()&amp;quot;); exit(-1);}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout notre code est prêt et fonctionne, il reste maintenant à tout embarquer sur la foxBoard !&lt;br /&gt;
&lt;br /&gt;
==='''''3. Fox....Board to be alive ! ''''' ===&lt;br /&gt;
&lt;br /&gt;
===='''A. Le produit fini'''====&lt;br /&gt;
&lt;br /&gt;
Le produit fini de notre projet est un système embarqué (la foxBoard) qui contiendra notre application et qui, dès que la foXboard sera branchée aux afficheurs, exécutera l'application.&lt;br /&gt;
&lt;br /&gt;
Il fallait toutefois configurer la foxBoard avec minicom pour pouvoir ensuite accéder au ssh et ainsi finaliser ntore projet&lt;br /&gt;
&lt;br /&gt;
[[File:Liaisonserie.JPG|thumb|liaison série avec FoxBoard]]&lt;br /&gt;
&lt;br /&gt;
===='''B. Les autorisations pour l'exécution'''====&lt;br /&gt;
&lt;br /&gt;
Sur la foxBoard, comme sur l'ordinateur, le code html ne peut pas modifier notre fichier &amp;quot;note.txt&amp;quot; si celui-ci n'est pas autorisé www-data&lt;br /&gt;
Par un raisonnement similaire, le code html ne peut pas récupérer la valeur dans &amp;quot;pid.txt&amp;quot; si ce fichier n'est pas autorisé sur www-data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois que ces autorisations sont faites, que les fichiers sont placés au bon endroit (var/www/html) et que l'application est compilée, il faut créer un script permettant de l'exécuter au démarrage&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===='''C. Le script rc.local'''====&lt;br /&gt;
&lt;br /&gt;
La foxBoard contient (comme tout système unix) un fichier rc.local se lançant au démarrage.&lt;br /&gt;
Par défaut celui ci est vide mais si vous voulez lancer une application au démarrage, il faut entrer dans ce fichier les lignes de commandes que vous entreriez dans le terminal pour lancer l'application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Voici notre scipt qui finalise donc le projet:&lt;br /&gt;
&lt;br /&gt;
   stty -F /dev/ttyACM0 9600 cs8 \                        //initialisation du port série (vu au premier paragraphe)&lt;br /&gt;
  -hupcl -icrnl -ixon -opost -onlcr -isig -icanon \&lt;br /&gt;
  -iexten -echo -echoe -echok -echoctl -echoke ignbrk&lt;br /&gt;
  sleep 9999d 3&amp;lt;/dev/ttyACM0 &amp;amp;                            //Cette tache est une tache de fond, elle met un certain temps à s'exécuter                     &lt;br /&gt;
  sleep 5                                                 //on ajoute donc une temporisation avant de passer à l'exécution de l'application&lt;br /&gt;
  ( cd /var/www/html ; su www-data -c &amp;quot;./test note.txt&amp;quot; ) &amp;amp; //Exécution&lt;br /&gt;
  exit 0&lt;br /&gt;
&lt;br /&gt;
===='''''4. Les problèmes nous font avancer  ! ''''' ====&lt;br /&gt;
&lt;br /&gt;
On a trouvé judicieux de recenser les problèmes rencontrés lors de ce projet, nous remercions également Mr Xavier REDON pour l'aide et les explications &lt;br /&gt;
apportées durant ce projet.&lt;br /&gt;
&lt;br /&gt;
1 --&amp;gt; trouver à quel bit correspond quel segment (difficulté faible, mais nous avons tout de même du réfléchir pour trouver une solution rapide)&lt;br /&gt;
&lt;br /&gt;
2 --&amp;gt; La gestion des signaux était quelque chose de nouveau et a engendré la difficulté 3. &lt;br /&gt;
&lt;br /&gt;
3 --&amp;gt; Comprendre et maîtriser les autorisations.&lt;br /&gt;
&lt;br /&gt;
4 --&amp;gt; Bloquage lors de la réception du signal. En effet notre code fonctionnait mais nous avions oubliés les sécurités, on créait donc une boucle infinie.&lt;br /&gt;
Suite à une intervention de M. REDON, les vérifications ont été codés et le programme fonctionnait parfaitement. &lt;br /&gt;
&lt;br /&gt;
5 --&amp;gt; le minicom pour configurer la foxBoard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sur ces difficultés, nous retiendrons particulièrement les sécurités sur les vérifications de la bon ouverture des fichiers&lt;br /&gt;
&lt;br /&gt;
Le projet est terminé, le cahier des charges comblé, nous vous laissons avec une vidéo du travail final!&lt;br /&gt;
&lt;br /&gt;
==''Partie électronique :''==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Première séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Découverte du projet et du cahier des charges.&lt;br /&gt;
&lt;br /&gt;
Prise en main du logiciel altium et suivi partiel du tutoriel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Deuxième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Fin du tutoriel proposé. Compréhension du schéma.&lt;br /&gt;
&lt;br /&gt;
Définition du cahier des charges de notre projet et proposition de schéma électronique.&lt;br /&gt;
&lt;br /&gt;
Découverte d'un possible problème sur nos afficheurs à anode commune (contrôle par la masse)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Troisième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Mise en place du schéma électronique établi à la séance précédente sur altium.&lt;br /&gt;
&lt;br /&gt;
Correction des quelques problèmes rencontrés puis simulation (réussie) du schéma.&lt;br /&gt;
&lt;br /&gt;
Problème des afficheurs confirmé (courant et tension admissibles), étude avec les deux professeurs des solutions possibles.&lt;br /&gt;
&lt;br /&gt;
Câblage d'une solution retenue (driver de leds + 2 demi afficheurs) -&amp;gt; la solution résolve partiellement le problème (on peut fournir une tension et un courant correct).&lt;br /&gt;
&lt;br /&gt;
Commande de 4 transistors pouvant résoudre le dernier problème électronique (contrôle des afficheurs).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Quatrième séance :'''''===&lt;br /&gt;
&lt;br /&gt;
Câblage de l’autre moitié du premier afficheur. Le reste ne sera pas câblé car trop long et inutile pour résoudre le problème des transistors.&lt;br /&gt;
&lt;br /&gt;
Les transistors n’ont pas permis de contrôler séparément chacun des afficheurs, car leur tension de seuil de déclenchement est trop élevée par rapport à la tension que l’on récupère déjà à côté pour les drivers de leds et afficheurs.&lt;br /&gt;
&lt;br /&gt;
On a cependant une petite simulation de 3 caractères (IMA) pour montrer que notre montage fonctionne (on peut afficher les caractères désirés, mais le défilement ne s'effectue pas. Il faudrait trouver quatre transistors capables de se déclencher avec les 3,3V max que la nanoboard peut fournir, sachant que les leds s'allument avec une tension minimale de 3,8V).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==='''''Explications détaillées :'''''===&lt;br /&gt;
&lt;br /&gt;
Après avoir pris en main la NanoBoard grâce au tutoriel proposé (http://rex.plil.fr/Enseignement/Systeme/Projet.IMA3/tutoriel_nanoboard.pdf), nous avons établi un cahier des charges pour notre projet. &amp;lt;br&amp;gt;&lt;br /&gt;
Voici l’idée globale retenue pour le circuit :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_1.jpg|vignette|upright=5|centre|Schéma théorique]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Explications :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On récupère les informations du port série, ainsi que son signal d’horloge. On mémorise ces informations grâce aux bascules, elles même gérées par un démultiplexeur relié à l’horloge du port série. On cadence ainsi les informations afin que le multiplexeur les reçoivent une par une. Le décodeur va ensuite choisir tour à tour un afficheur grâce au signal d’horloge, et le multiplexeur envoie ainsi une information sur tous les afficheurs, mais seulement un sera allumé à ce moment grâce au décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Il nous est possible d’envoyer qu’un seul bus de 16 bits sur les afficheurs reliés en dérivation, car la fréquence de sélection du décodeur est bien plus rapide que la fréquence rétinienne de l’homme. On a donc l’impression que le message est fixe avec un caractère affiché sur chaque afficheur, alors qu’en réalité il a toujours qu’un seul afficheur d’allumé.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après plusieurs essais, voici notre circuit définitif sur Altium :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Julian_2.jpg|vignette|upright=5|centre|Circuit sur Altium]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nous avons dissocié les deux compteurs afin de pouvoir contrôler la fréquence d’affichage des caractères.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=====Simulation :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
[[Fichier:Julian_3.jpg|vignette|upright=5|centre|Simulation]]&lt;br /&gt;
&lt;br /&gt;
Dans le rectangle du haut nous pouvons envoyer le code binaire d’un caractère à afficher. Le rectangle du dessous permet d’envoyer ce code en mettant l’horloge à 1. Au milieu nous gérons la fréquence d’affichage (ici 2Hz afin d’avoir le temps de prendre une photo). Puis dans l’avant dernier rectangle on peut voir que notre code binaire se déplace correctement. Et dans le dernier un voit quel afficheur est sélectionné par le décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_4.jpg|vignette|upright=2|centre|Tests sur l'oscilloscope]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
On voit ici de D7 à D4 les 4 bascules, et de D0 à D3 les 4 codes binaires envoyés.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Câblage :=====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Après cette simulation concluante, nous avons commencé le câblage. Celui-ci s’est avéré fastidieux dès le départ, car le simple fait d’avoir 4 afficheurs pour lesquels il fallait 16 fils chacun nous promettait de nous y faire consacrer une bonne partie de la séance.&amp;lt;br&amp;gt;&lt;br /&gt;
En regardant la datasheet  de la NanoBoard sur internet nous avons constaté que les sorties de la carte pouvaient fournir au maximum 3,3V chacune (dont une à 5V), et notre encadrant nous a dit qu’il valait mieux ne pas tirer plus de 20mA par sortie. &amp;lt;br&amp;gt;&lt;br /&gt;
Le problème alors rencontré est que nos afficheurs ont une led par petits segments, et deux par grands segments. Après quelques tests avec l’encadrant, nous avons constaté qu’il fallait minimum 3,8V pour un grand segment si on voulait l’allumer avec 20mA. La NanoBoard ne permettait donc pas d’allumer tous les segments (ce sont des afficheurs à anode commune).&amp;lt;br&amp;gt;&lt;br /&gt;
              &lt;br /&gt;
[[Fichier:Julian_5.jpg|vignette|gauche|Datasheet des afficheurs]]  &lt;br /&gt;
[[Fichier:Julian_6.jpg|vignette|upright=1.5|droite|Câblage]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul nous a permis de déterminer la valeur des résistances à mettre avant chaque afficheur : une résistance de 50Ω (47Ω) pour un petit segment, une de 300Ω pour un grand (270Ω).&amp;lt;br&amp;gt;&lt;br /&gt;
La solution retenue après discussion avec les deux encadrants a été d’utiliser deux amplificateurs (drivers ULN2803) pour avoir une bonne tension sur nos afficheurs. Le problème créé avec cette solution est que nous ne pouvions plus contrôler séparément nos afficheurs. Nous avons donc eu l’idée d’utiliser un transistor par afficheur, qui recevrait l’ordre de commande des sorties de la carte correspondants à celles du décodeur.&amp;lt;br&amp;gt;&lt;br /&gt;
Après plusieurs tests, nous avons compris que ceux utilisés (des TMOS) ne pourraient fonctionner car leur tension de seuil VGS est plus élevée que les 3,3V que peut fournir notre carte.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Fichier:Julian_7.jpg|upright=2|centre]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conclusion :==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ce projet nous a permis de mettre en pratique nos connaissances informatiques et électroniques acquises au cours de l'année.&amp;lt;br&amp;gt;&lt;br /&gt;
Nous aurions aimé pouvoir relier directement la partie informatique à la partie électronique afin de pouvoir tester la totalité du projet.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rkrikori</name></author>	</entry>

	</feed>