IMA4 2017/2018 P22
Sommaire
- 1 Présentation générale
- 2 Analyse du projet
- 3 Préparation du projet
- 4 Réalisation du Projet
- 5 Documents Rendus
Présentation générale
Notre projet consiste à étudier le fonctionnement d'une horloge connectée réalisée par des élèves de seconde du lycée Fénélon de Lille, en vue de l'améliorer ou d'y ajouter des fonctionnalités. Cette horloge de forme carrée possède divers éléments électronique orchestrés par une carte Raspberry Pi 3B elle-même fonctionnant sous Raspbian Jessie Lite. L'affichage se fait grâce à 2 panneaux de 16x32 LEDs. L'alimentation est composée d'un régulateur 230V-5.2V relié à un shield "Adafruit RGB Matrix Hat". Ce shield permet d'alimenter les 2 panneaux de LEDs ainsi que la Raspberry Pi.
Description
L'horloge sur laquelle nous travaillerons possède plusieurs fonctionnalités actuellement:
- Elle affiche l'heure du système Raspbian sur une matrice de LED.
- Elle affiche un message sur la matrice de LEDs supérieure.
Le but de notre projet est de lui ajouter des fonctionnalités supplémentaires en vue de la rendre plus interactive avec l'utilisateur.
L'horloge est principalement constituée d'une Rasperry Pi, de son système Raspbian et de 2 matrices de LED. La Raspberry nous permettra de rajouter la plupart des fonctionnalités en les programmant en langage C/C++.
Objectifs
- Installer un serveur de temps NTP.
- Améliorer la réception DCF77.
- Protéger le système contre les coupures de courant ou les débranchements inopinés.
- Trouver une application à la 2e matrice de LED.
- Faire interagir l'utilisateur avec l'horloge (personnalisation de l'affichage, jeu-vidéo).
- Gérer les fuseaux horaires.
Analyse du projet
Positionnement par rapport à l'existant
Le marché des objets connectés est en plein essor. Il est donc naturel que beaucoup de produits soient très semblables au notre, en effet il n'en manque pas :
- Montre connectée : se porte au poignet, accès aux réseaux sociaux, aux sms, aux appels téléphonique, etc.
- Réveil connecté : fonction principale de réveil, affiche la météo, affiche des rappels.
- Horloge connectée : affiche des rappels, la météo, les grands titres de l'actualité.
Analyse du premier concurrent
LaMetric
Caractéristique :
- matrice de led 37x8
- connectée au smartphone en wifi
- ajout de fonctionnalités via un marché d’applications.
- électriquement dépendant à la prise murale
- orientée réseau sociaux
- synchronise son heure via serveur LaMetric
Exemple de fonctionnalité :
Météo, compteur de “j’aime / abonnée”, Domotique, ...
Analyse du second concurrent
Glance Clock
- Affichage de l’heure
- Réveil et chronomètre
- Sonorisations
- Rappels
- Appels téléphoniques entrants et sortants
- Afficheur météo
- Calendrier compatible Google, Microsoft, etc.
- Affiche diverses informations dans le cas d’une maison connectée
Scénario d'usage du produit ou du concept envisagé
L’utilisateur entre dans la salle où se trouve l’horloge, elle est accrochée à un mur. Si elle n’est pas allumée, il la branche et l'horloge s'allume. L’heure s’affiche automatiquement.
Cas “ludique” :
L’utilisateur a quelques minutes à perdre. Il lance le jeu depuis son smartphone Android. Le jeu se lance sur la deuxième matrice de LEDs. Son téléphone fait office de manette. Il joue et essaie de battre le score des personnes ayant joué précédemment.
Cas “informations” :
L’utilisateur souhaite suivre les nouvelles en temps réel. Il configure la deuxième matrice de LEDs en se rendant sur une application Android. Sur l’application Android il indique l’adresse d’un ou plusieurs site d’actualités ou disposant d’un flux (RSS par exemple). La deuxième matrice de LED fait défiler les titres de l’actualité. Quand il veut éteindre l’horloge il la débranche, celle-ci s'éteint correctement. En cas de coupure de courant l’horloge s’éteint aussi correctement grâce à l’appui énergétique d’un accumulateur.
Réponse à la question difficile
Question: Comment gérer les différents fuseaux horaires ainsi que les décalages horaires de l'heure d'été/heure d'hiver ?
Solution envisagée : Choix du fuseau horaire à l'initialisation de l'horloge (choix par pays), questionnement d'une base de données qui fait correspondre le pays au fuseau horaire.
Solution réalisée : Sélection manuelle du fuseau horaire via l'application Android.
Préparation du projet
Cahier des charges
- Réception de l'heure par ondes radios DCF77 (77.5 kHz)
- Ajout d'un jeu sur la 2e matrice de LEDs
- Ajout d'un bandeau d'information sur la 2e matrice de LEDs
- Ajout d'une batterie à la Raspberry Pi pour effectuer une extinction propre en cas de coupure de l'alimentation
- Mise en place d'un serveur NTP sur l'horloge
Choix techniques : matériel et logiciel
- Application mobile Android, programmée en Java avec Android Studio
- Liaison application/horloge : technologie Bluetooth.
Extinction propre :
- Batterie rechargeable.
- Contrôleur de batterie.
Réception DCF77 :
- Module BN 641138
Programmation côté serveur en C/C++
Liste des tâches à effectuer
- Récupérer l'heure via DCF77
- Créer l'application mobile
- Créer le jeu et l'afficher sur la 2e matrice de LEDs
- Mettre en place l'extinction propre (batterie)
- Mettre en place le serveur NTP
- Mettre en place le bandeau d'information sur la 2e matrice de LEDs
Calendrier prévisionnel
Réalisation du Projet
Matériels nécessaire
Cette liste constitue le matériel pour réaliser le PCB de contrôle d'extinction :
- Une batterie 4,8 v | 500mAh http://fr.farnell.com/varta/55750404014/pack-de-batterie-nimh-510mah-4/dp/1903286
- LT1512 - contrôleur batterie https://fr.rs-online.com/web/p/controleurs-de-charge-de-batterie/5456852/
- Transistor T1 2N2222
- condensateur c1 22µf capacité parallèle à la batterie, recommandée Tantale
- condensateur c2 0.22 µf ( CERAMIC 1E225ZY5U-C203-F)
- condensateur c3 22 µf capacité d'entrée, recommandée Tantale avec faible ESR
- condensateur c4 0.22 µf
- condensateur c5 0.1 µf
- résistances :
- r1 : 1kΩ
- r2: 12,4 kΩ
- r3 : 0.2 Ω
- r4 : 24 Ω
- r5 : 1 kΩ
- r6 : 1.2 kΩ
- r7 : 2.2 kΩ
- r8 : 2.2 kΩ
- r9 : 1 kΩ
- inductances ctx33-3
- diode schottky D1 D4 10TQ035
- diode D3 1N4001
Feuille d'heures
Tâche | Prélude | Heures S1 | Heures S2 | Heures S3 | Heures S4 | Heures S5 | Heures S6 | Heures S7 | Heures S8 | Heures S9 | Heures S10 | Total |
---|---|---|---|---|---|---|---|---|---|---|---|---|
DCF77 | 4 | 4 | 4 | |||||||||
Analyse du projet | 15 | |||||||||||
Panneau de Led : Texte défilant | 12 | |||||||||||
Serveur Bluetooth | 2 | |||||||||||
Application Bluetooth | 8 | 12 | ||||||||||
Carte électronique batterie | 4 |
Prologue
- Recherche sur les systèmes existant.
- Analyse du fonctionnement de l'antenne DCF 77
- Réponse à la question "difficile" .
Semaine 1
Analyse du matériel nécessaire
Batterie permettant à la Raspberry d'être alimentée le temps de son extinction, en cas de coupure électrique. Calcul de la puissance instantanée consommée par l'horloge.
Raspberry Pi 3B | Panneau LED | Antenne | Total | |
---|---|---|---|---|
Consommation | 4 W | 2 x 10 W | 0,015 W | 24,015 W |
Sachant que la Raspberry Pi s'éteint en moins d'une minute, on choisit une batterie avec 5 minutes d'autonomie, par précaution, soit environ 2Wh d'énergie. la raspberry s'alimente entre 4,5 et 5,7V , nous avons choisi une batterie de 4,8 V et 500 mAh. La charge de la batterie est gérée par un contrôleur, nous avons choisi le LT1512.
Décision sur l'interaction entre l'utilisateur et l'horloge.
Après avoir comparé les avantages et les inconvénients de l'application web et de l'application mobile, notre choix s'est porté sur la réalisation d'une application mobile. Celle-ci communiquera par bluetooth avec l'horloge. Il est inutile qu'elle communique par internet étant donné que les interactions se feront à proximités de l'horloge. L'application mobile sera sur Android et sera développée en Java avec Android studio.
Information sur la configuration de la Raspberry:
Wifi :
nom : HorlogeICN mdp : fenelonlille
Wlan0 :
address : 192.168.100.1
Eth0:
address : 192.168.0.42 gateway : 192.168.0.1
Semaine 2
Le horloge n'affiche pas l'heure correcte. Le problème peut venir d'une mauvaise réception, d'une perturbation ou du programme qui récupère l'heure.
On commence par l'analyse du programme de récupération de l'heure.
Le message de la 2e matrice de LED est modifiable via le fichier /var/www/html/index.php. Celui-ci écrit le message dans le fichier "message". On suppose ensuite que "message" est ouvert par le programme "horloge" qui se charge d'envoyer les 2 lignes sur la matrice de LED.
Semaine 3
Le récepteur intégré à l'horloge est trouvable sur le site du revendeur "Conrad". Sur ce site nous avons trouvé une doc sur la connexion des fils au module mais pas de datasheet sur le module électronique nommé BN 641138 qui se charge de transformer le signal en bits.
Le signal DCF77 est envoyé depuis une antenne en Allemagne à Mainflingen (près de Francfort-sur-le-Main) par le Physikalisch-Technische Bundesanstalt (PTB). Le signal de fréquence 77.5 kHz est envoyé à une puissance environnant les 30 kW. L'information est numérique et modulée de manière semblable à une modulation OOK. Une trame dure 60 secondes, chaque secondes correspond à un bit :
L'information est codée sur un abaissement de l'amplitude pendant une durée donnée. Pour signifier un 1 ou un 0, l'amplitude est de 15% sa taille maximale. Un bit 0 correspond à un changement d'amplitude pendant 100ms, pour un bit 1 c'est 200 ms.
Décodage de la trame :
Une trame de 60 secondes est constituée des informations suivantes :
Bit0 : Début de trame (bit à 1). Bit1 à 14 : Réservé pour une utilisation future. Bit 15 : Bit d'antenne (0 = antenne normal 1 = antenne de réserve) Bit 16 : Changement heure d'hiver/heure d'été (1= passage heure été/hiver) Bit 17 : 0: inactif / 1: heure d'été (GMT+2) Bit 18 : 0: inactif / 1: heure d'hiver (GMT+1) Bit 19 : 1 quand une minute de 61 secondes est insérée Bit 20 : Bit de début (start) (Toujours à 1) Bit 21..27 : Valeur des Minutes ( Bit: 21 = 1, 22 = 2, 23 = 4 , 24 = 8 , 25 = 10 , 26 = 20, 27 = 40) Bit 28 : Parité pour tous les bits de minutes (Bits de parité paire) Bit 29..34 Valeur des heures ( Bit: 29 = 1, 30 = 2, 31 = 4 , 32 = 8 , 33 = 10 , 34 = 20) Bit 35 : Parité pour tous les bits d'heures transmis (Bits de parité paire) Bit 36..41 : Valeur du jour ( Bit: 36 = 1, 37 = 2, 38 = 4 , 39 = 8 , 40 = 10 , 41 = 20) Bit 42..-44 : Valeur du jour dans la semaine ( Bit: 42 = 1, 43 = 2, 44 = 4) Bit 45..49 : Valeur du mois ( Bit: 45 = 1, 46 = 2, 47 = 4 , 48 = 8 , 49 = 10) Bit 50..57 : Valeur de l'année ( Bit: 50 = 1, 51 = 2, 52 = 4 , 53 = 8 , 54 = 10 , 55 = 20, 56 = 40, 57 = 80) Bit 58 : Parité pour tous les bits de date transmis (Bits de parité paire) Source : http://s159401799.onlinehome.fr/600HorlogeAtomiqueDCF77.html
Nous avons installé RaspBian Jessie sur une seconde Raspberry Pi pour pouvoir faire nos test de réception et coder les programmes nécessaire au projet. Ces programmes pourront ensuite être transférés sur la Raspberry Pi du projet.
Raspberry PI n°2
IP salle E304 :"172.26.145.114"
Pour récupérer les bits du module BN 641138, nous allons utiliser la bibliothèque C, wiringPI. Elle permet de faciliter l'accès aux GPIOs des RaspberryPi.
Le module, demandant très peu de courant, il peut-être alimenté par la Raspberry Pi directement. Nous branchons son alimentation sur la pin 3.3 Volts et la pin non inverseuse sur le GPIO 17.
Nous avons installé Python pour pouvoir rapidement observer un signal à l'aide d'un petit programme trouvé sur internet. Celui-ci n'a pas voulu fonctionner.
- Test GPIOs python : https://pythonhosted.org/RPIO/#documentation
- Comment utiliser le GPIOs http://s159401799.onlinehome.fr/600HorlogeAtomiqueDCF77.html
Semaine 4
Lundi : Test du récepteur BN 641138 (récepteur DCF77). Nous nous sommes documentés sur la manière de recevoir correctement le signal DCF77. Globalement les utilisateurs de ce modules n'ont pas eu de problème pour recevoir les signaux, ce qui n'a pas été notre cas. Nous avons effectué les premiers test dans la salle E306, nous n'avons pour l'instant eu aucun signal.
Mercredi :
Prise en main de l'outil de développement Android Studio avec "formation" sur open classroom.
Analyse de la trame du récepteur BN 641138
Face aux multiples échecs de réception en salle E306 nous avons testé l'antenne en salle C201. Pour cela nous avons utilisé un oscilloscope. Nous avons effectués les test sur la pin inverseuse et la pin non inverseuse du module DCF77. Nous avons pu enfin obtenir un signal pendant quelques instants.
La réception du signal est très sensible, une variation de l'orientation de l'antenne de quelque degrés empêche une bonne réception. Nous pensons que les alimentations à découpage des ordinateurs polluent le spectre électromagnétique local et qu'elle peuvent donc générer des signaux parasites sur la bande de 77.5 kHz.
Une autre hypothèse plus probable est que la composition du bâtiment de Polytech atténue le signal déjà très faible, envoyé depuis Mainflingen.
Lorsque nous avons pu capter le signal nous l'avions récupéré sur une durée dépassant les 120 secondes. Nous avons pu ainsi décoder une trame de 60 secondes et récupéré l'heure. Pour récupérer cette trame nous avons simplement noté la valeur affichée à l'oscilloscope. La trame suivante est extraite de notre échantillons, après correction sur 4-5 bits nous avons pu décoder l'horaire diffusé par le système DCF77.
Doc, réception DCF77 :
https://www.compuphase.com/mp3/h0420_timecode.htm
https://blog.blinkenlight.net/experiments/dcf77/dcf77-receiver-modules/
Semaine 5
Étude visant à améliorer la réception du signal DCF77
- Dans le but de placer (éventuellement redimensionner) l'antenne au mieux dans l'horloge, nous nous sommes aidé de l'analyseur de spectre présent en C203.
- Après avoir demandé conseil auprès de Mme Baranowski notre professeur de "Support de Transmission" nous avons appris que la réception pouvait être améliorée en augmentant la tension du signal reçu par l'antenne. En effet le circuit électronique post-antenne ne détecte pas nécessairement la composante de 77,5 khz qui a trop peu d'amplitude. Pour augmenter la tension du signal on s'appuie sur la formule de réception d'une antenne boucle.
Les 3 paramètres qui nous permettent d'avoir une meilleure réception sont : la surface délimitée par une spire et le nombre de spires, c'est ce dernier paramètre qui est le plus facilement modifiable et que nous allons exploiter.
Prise en main de l'environnement de développement Android Studio
- Suivi d'une formation sur open-classroom pour découvrir les différentes bibliothèque, les outils graphique, le language XML.
- Développement du classique jeux du nombre aléatoire pour ce familiariser avec l'IDE, les bibliothèques et l'outil graphique.
Le jeu final sera basé sur un concept différent. L'affichage ce fera sur le panneau de LED de l'horloge.
Semaine 6
Design de l'application
Nous avons commencé à développer l'application Android, nous avons choisi de découper l’application en 5 parties :
- Jeu : nous aurons la commande du jeux qui sera affiché sur l'horloge.
- Bluetooth : nous aurons les démarches à suivre pour se connecter en Bluetooth à l'Horloge, ainsi que la listes des appareils Bluetooth présents à proximitée.
- Capteur : nous aurons les informations des capteurs présents dans la Raspberry.
- Polytech Lille : nous aurons un accès aux différents médias de Polytech Lille (Facebook, wiki de projets, ...)
- Support : nous aurons les informations pour envoyer un mail au développeurs.
- à propos : nous aurons une page d'informations sur le projet.
Pour faciliter la navigation, nous avons développé une barre latéral de navigation qui permet d'avoir accès à n'importe quelle page depuis n'importe quel endroit.
Pour mettre en place ce type de barre de navigation, il faut créer un "objet" NavigationView dans le fichier Xml de l'activité concerné. Une "activité" étant le terme employé par l'IDE pour désigner ce qui s'apparente plus communément à une page.
Ensuite il faut créer deux fichier XML. D'abord Nav_header_activity qui comprendra les données graphiques de l'entête de la barre de navigation pour le premier(si on se réfère à la photo ci-dessus c'est la partie verte comprenant une adresse mail et un logo). Le deuxième fichier XML à créer est le fichier activity_activity_drawer qui comprend les informations graphiques pour la partie de sélection des activités du menu : Jeu, Bluetooth, etc.
Préparation Bluetooth
La communication bluetooth est basée sur un protocole maître-esclave (ou serveur-client). Dans notre cas l'horloge est maître et l'esclave sera le smartphone.
Nous utiliserons une communication par sockets Bluetooth (vue en cours de PSR, pour les sockets IP). La norme Bluetooth propose de transférer des données en mode connecté grâce à la couche RFCOMM. Le système en couche de Bluetooth fonctionne de la même manière que pour TCP/IP, c'est pourquoi il est possible de l'utiliser via les sockets. La connexion se fait de la sorte : Si le smartphone n'a jamais été connecté à l'horloge, alors il y a appairage avec l'horloge. Cette opération n'est pas une connexion à proprement parlé, mais une façon pour l'horloge de connaître l’existence du smartphone. Ensuite le smartphone se connecte avec l'horloge. L'utilisateur communique via une application Android faisant office d'interface user-friendly avec l'horloge.
Paramétrage bluetooth
Le côté horloge de la communication est réalisé en C a l'aide des fonctions utilisant les sockets et celles offerte par le noyau BlueZ, l'implantation Linux officielle de Bluetooth.
Récepteur DCF77
Nous n'avons toujours pas réussi à obtenir à nouveau une trame depuis les essais sur oscilloscope en semaine 4. Des tests vont être réalisés sur Arduino pour vérifier que le problème ne vient pas des modules DCF77 ou de la Raspberry Pi sur laquelle les tentatives sont habituellement effectuées. Nous allons aussi essayer d'améliorer la réception en augmentant la taille de l'antenne en ferrite. La raison de la présence d'une ferrite au milieu de l'antenne spiral reste pour nous plutôt inconnu mais nous avons pu voir qu'il existait un bâtonnet de ferrite en vente sur internet permettant d'améliorer la synchronisation des montres utilisant le DCF77 juste en le plaçant à proximité de la montre.
Pour chercher l'origine du problème nous nous sommes rendu dans une salle de transmission de signal de Lille 1 du bâtiment P5. Avec l'aide de M Wichmann nous avons pu tester l'efficacité de l'antenne en ferrite pour la réception du signal. Dans la salle nous obtenions une puissance de -83dbm à 77.5 kHz. Nous avons testé si l'antenne était défectueuse. En utilisant 2 antennes, une en émission, une réception. Nous avons pu mesurer un signal, donc l'antenne n'est pas défectueuse.
Semaine 7
Communication Bluetooth Horloge
1. Paramétrage
Après beaucoup de documentation sur internet, nous avons été en mesure d'établir une connexion Bluetooth, avec un appareil Android et permettre un transfert de trame dans le sens Smartphone -> Horloge. Le message a été émis à l'aide de l'application "Bluetooth Terminal". Cette application permet d'envoyer des trames de données brut sur la couche RFCOMM.
1.
Pour établir cette connexion il a d'abord fallu paramétrer la Raspberry Pi pour que son équipement Bluetooth soit activé dès l'allumage. Ceci se fait en ajoutant le service Bluetooth dans la liste des services à lancer au démarrage via la commande :
systemctl enable bluetooth.service
2.
Ensuite il faut que l'horloge soit visible par les autres appareils, dans notre cas les smartphones. Quelque soit l'appareil, il faut qu'elle soit "discoverable". On en profite pour changer l'alias par défaut du terminal Bluetooth, pour un nom plus proche de notre projet. Les modifications sont effectuées dans le fichier /var/lib/bluetooth/<adresse du contrôleur Bluetooth>/settings
[General] Discoverable=true DiscoverableTimeout=0 Alias=Horloge DCF77
L'option DiscoverableTimout permet de définir une échéance sur la durée de visibilité de l'horloge par les autres appareils, définie à 0 il n'y a aucune échéance.
3.
Il faut ensuite indiquer à l'appareil distant, quels services (protocole de communication) Bluetooth offre l'appareil auquel il se connecte. Pour cela on cré un service "SP" pour "serial profile" (la couche RFCOMM étant utilisable pour une communication série) via la commande "sdptool" au lancement du service Bluetooth. Ceci l'ajoute ainsi au "Service Discovery Protocole", interrogé par un appareil distant.
Dans le fichier /etc/systemd/system/dbus-org.bluez.service il faut donc modifier la ligne :
ExecStart=/usr/lib/bluetooth/bluetoothd -C
Et ajouter la ligne :
ExecStartPost=/usr/bin/sdptool add SP
La connexion est réalisée avec le smartphone uniquement si ils sont appairés. Habituellement l'appairage requiert l'échange d'un code PIN entre les 2 appareils. Une personne constate l'appairage des deux appareils en vérifiant que le code PIN affiché par les terminaux est le même. Nous ne voulons pas utiliser ce code PIN puisque tout le monde doit pouvoir se connecter à l'horloge facilement et puis car l'horloge ne possède "normalement" aucune sortie graphique (exceptée les panneaux de LEDs) pour vérifier le code PIN. Heureusement BlueZ désactive le code PIN, par défaut.
2. Mise en place du serveur socket
Il y a très peu de documentation sur internet pour utiliser la librairie libbluetooth de BlueZ. Le peu d'information sur certaines fonctions qu'elle offre provient du site internet https://people.csail.mit.edu/albert/bluez-intro/c404.html . Un tutoriel permet d'expliquer comment utiliser les sockets pour communiquer avec la couche RFCOMM. Pour notre projet, l'horloge se comporte comme un "serveur bluetooth". Ce serveur possède une file d'attente de taille 1 puisque seul un utilisateur à la fois peut interagir avec l'horloge. La source (commentée) /horloge/Bluetooth/server/rfcomm.c est visible sur le dépôt Git https://archives.plil.fr/aknockae/projetS8_HorlogeDCF77
Semaine 8
Test des perturbations sur le lieu d'installation de l'antenne
Les alimentations à découpage émettent du bruit dans une bande passante contenant la fréquence de notre antenne, nous avons analysé l'impact de celles-ci sur notre antenne actuelle. Nous avons monté un oscilloscope en E306 pour pouvoir observer ces perturbations. Nous avons relié l'entrée de l'oscilloscope à l'antenne du module DCF et placée à proximité d'une installation informatique. Sans surprise la FFT indiquait un fort rayonnement des alimentations sur la fréquence de 77.5 kHz. Nous avons pu relever une puissance allant jusqu'à 40 db de différences lorsque l'antenne est collée à l'alimentation. Toutefois il semble que cette perturbation s'affaiblisse énormément à mesure que l'on s'en éloigne. A environ 2m d'une alimentation il reste encore un bruit, mais nous ne savons pas encore à l'heure actuelle, s'il est responsable de nos échecs de réceptions en E306.
Texte défilant personnel et information
Cette semaine nous nous sommes attelés au panneau de LEDs. Lundi nous avons étudié le fonctionnement de la librairie rpi-rgb-led-matrix/ déjà utilisée par les précédents créateur de l'horloge et qui permet une personnalisation complète de l'affichage des LEDs. Le programme qui gère l'affichage de l'heure sur les LEDs est déjà présent dans le dossier /var/www/html et est lancé au démarrage. Ce programme provient d'un exemple déjà présent sur le dépôt git de la bibliothèque. La bibliothèque est écrite en C++ pour permettre de considérer un panneau de LED comme un objet. Les classes fournie sont :
- Canvas : représente une surface de taille 16x32 ou 32x32 pixels. Canvas possède plusieurs méthodes permettant de modifier la couleur d'un seul pixel, ou de la surface entière
- RGBMatrix : hérite de Canvas, transpose la surface fictive de Canvas et la gère sur le panneau de LEDs
- Font : permet de charger une police au format bdf et d'afficher un texte sur le Canvas facilement.
Le format BDF est un format simple permettant de stocker la forme du caractère dans un fichier, sans compression. Le caractère est dessinée dans le fichier.
Un des objectif avec le panneau de LED et de faire défiler, soit un message personnel, soit une suite de titres issues d'un flux RSS/ATOM quelconque. Les flux RSS (ou ATOM) sont des fichiers XML ayant une syntaxe normée, présent sur beaucoup de sites internet. Souvent présent sur les sites d'actualité en tout genre ils permettent d'accéder facilement aux dernière nouvelles, tel des billets de blog ou des articles. Notre horloge pourra ainsi afficher soit les titres de l'actualité d'un site d'information ou alors les titres d'un nouveau billet de blog, d'un site que l'utilisateur fréquente. Il pourra personnaliser cet affichage en renseignant l'adresse URL du site internet en question dans un champ de texte dans le menu Information de l'application Android.
Mercredi et Jeudi nous nous sommes attelés à la programmation du texte défilant. Le programme affichant un message défilant sur le panneau de LED s'appelle bandeau.cpp et se trouve dans le dossier /horloge/ledPanel du projet. Au sein de ce dossier ledPanel se trouve la librairie statique librgbmatrix.a ainsi que les "includes" nécessaires.
Le programme bandeau.cpp se charge d'afficher les titres qui seront stockés dans un fichier, et récupèrera directement le message depuis le serveur Bluetooth. Nous avons codé la fonction strHorizontalScroll prenant en paramètres le canvas, la police, la couleur, la chaîne de caractères et le délai de maintient du message sur les même pixels (la vitesse de déplacement, en soit). Pour l'instant cette fonction affiche directement un texte défilant sur les 2 matrices de LEDs. Cependant nous souhaitons afficher le texte sur les LEDs du haut et l'heure sur les LEDs du bas.
En fin de semaine nous avons aussi codé le programme qui extrait les premiers titres d'un flux RSS ou ATOM. Pour l'instant nous avons réussi à extraire les titres, il reste à les enregistrer dans un fichier texte pour qu'ils puissent être lu par le programme bandeau.cpp. Pour l'extraction, étant donné que les fichiers RSS/ATOM sont écrits en XML, nous avons utilisé la librairie tinyXML2, écrite en C++. Cette librairie a l'avantage d'être légère et possède les fonctionnalités minimales d'un analyseur de syntaxe XML. Comme nos actions sur le fichier de flux se résument surtout à accéder aux différents nœuds, nom donné à tout élément dans un fichier xml, alors elle est adéquate. De plus comme pour librgbmatrix, libtinyxml fonctionne sous forme de classe, ainsi on peut aisément représenter chaque nœuds par un objet XMLNode ou XMLElement.
Typiquement les fichiers RSS ont pour syntaxe (source wikipedia) :
<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0"> <channel> <title>W3Schools Home Page</title> <link>https://www.w3schools.com</link> <description>Free web building tutorials</description> <item> <title>RSS Tutorial</title> <link>https://www.w3schools.com/xml/xml_rss.asp</link> <description>New RSS tutorial on W3Schools</description> </item>...
Et les fichiers ATOM (source wikipédia) :
<?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <title>Fil d'exemple</title> <subtitle>Un titre secondaire.</subtitle> <link href="http://example.org/"/> <updated>2010-05-13T18:30:02Z</updated> <author> <name>Paul Martin</name> <email>paulmartin@example.com</email> </author> <id>urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af6</id> <entry> <title>Des robots propulsés par Atom deviennent fous</title> <link href="http://example.org/2003/12/13/atom03"/> <updated>2010-04-01T18:30:02Z</updated> <summary>Poisson d'avril !</summary> </entry> </feed>
Notre programme récupère le contenu des balises <title> présentes dans les balises <item> pour les flux RSS et <entry> pour les flux ATOM. Chacune des item et entry étant un billet ou un article différent.
Le débogage du programme a pris du temps puisqu'une fuite mémoire est apparue une fois le programme finie. Les seuls allocations réalisées sont celles qui permettent de créer la liste des chaînes de caractères contenant les titres. L'usage de Valgrind nous a bien aidé et a permis de voir que la liste était correctement désallouée. De fil en aiguille nous avons conclu que la fuite de mémoire venait de la déclaration de l'objet XMLDocument, représentant le document XML dans le programme et permettant de le charger. Nous ne négligeons pas cette fuite de mémoire. Nous continuerons de trouver une alternative pour l'éviter plus tard.
Modification du serveur Bluetooth
En fin de semaine toujours, nous avons tenté de mettre en place une file de messages Unix. La file de message permet de faire communiquer le programme serveur avec les autres programmes bandeau et jeu notamment. Le programme server gravite autour de la file de messages. Il effectue le transfert des commandes reçues depuis Bluetooth vers les programmes et inversement; programmes animant les diverses fonctionnalités de notre horloge. Beaucoup de temps à été passé sur la file de message. Une mauvaise configuration nous a longtemps empêché de recevoir les messages émis.
Nous avons aussi décomposé le code du serveur en fonctions pour une meilleur clarté du "main".
Application
- Partie Jeu :
La partie "Jeu" de notre application est la partie principale de notre application, d'un point de vue graphique et fonctionnalité elle est assez simple. Elle se compose de trois éléments : un décors , une zone de texte au milieu permettant d'informer l'utilisateur de l'état du jeu(non démarré, démarré ,scoretemps réel, perdu) et d'un bouton de commande (la flèche).
Le jeu fonctionne de la manière suivante : l'utilisateur sera connecté à l'horloge via Bluetooth, il appuiera sur le bouton JUMP pour démarrer et l'horloge démarrera une animation (sur la matrice de LED du haut) comme celle de la page de chargement de Google chrome, c'est à dire un "dinosaure" qui devras sauter au dessus de différent obstacle, le dinosaure reste mobile ce sont les obstacles qui se déplace.
D'un point de vue logiciel, l'activité "Jeu" se connecte en Bluetooth à l'horloge, nous avons mis en place des sécurités permettant premièrement que le Bluetooth soit activé, deuxièmement qu'un appareil de type "horloge" soit associé à notre téléphone.
Si le Bluetooth n'est pas activé on renvoie l'utilisateur vers l'activité Bluetooth qui gère les connexions. L'activitée Bluetooth va demander à l'utilisateur d'activer le Bluetooth de son téléphone.
L'autre vérification mise en place est l'association du téléphone avec une horloge (nous ne fermons pas l'application à une seule horloge au cas ou dans le future, plusieurs horloges seraient installées). Nous parcourons la liste des appareils Bluetooth associés avec le téléphone et vérifions si ce sont des équipement nommé Horloge, nous avons pas fait de vérification par adresse mac car nous sommes pas capables de connaitre les futures adresses mac d'éventuelles future horloge. Dans l'éventualité ou un autre équipement Bluetooth comporterait le même nom, la partie traitement de la socket en provenance de l'horloge s'occupera de gérer ce cas.
Avec la méthode getBondedDevices() nous avons pu récupérer la liste des équipements associés à ce téléphone, nous effectuons une recherche(via la méthode de la classe String : Indexof) parmi la liste d'équipement d'un équipement nommé "Horloge" qui serait connecté au téléphone (via un thread que je détails après). Si l'appareil n'a pas d'équipement horloge ou d'équipement quelconque associé, on renvoie l'utilisateur vers l'activité Bluetooth qui va gérer l'association avec une Horloge.
- Partie Bluetooth :
La partie Bluetooth de notre application sert à gérer la connexion entre l'horloge et le téléphone. Elle est appelé depuis la bar de navigation mais aussi depuis les autres pages lorsque la communication Bluetooth n'est pas fonctionnelle.
La page comprend un objet de type spinners qui est une liste déroulantes qui référence tous les objets "horloge" bluetooth déjà associés, elle sert à sélectionner l'horloge. Une deuxième liste déroulante comprenant les horloge accessible mais non associé est en développement. Comme on peut le voir sur la photo de droite lorsque que le Bluetooth n'est pas activé, il est demandé à l'utilisateur de le faire.
Si le Bluetooth n'est pas activé on démarre une activité par dessus la page qui s'affiche tant que l'on pas sélectionné une option.
- Partie connexion :
Pour cette partie nous sommes beaucoup aidé de la documentation en ligne Android Pour avoir une connexion avec un appareil, il faut créer un thread qui gère la connexion en arrière plan. On passe en paramètre du constructeur du thread un objet BluetoothDevice qui correspond à un appareil Bluetooth. Il y a une méthode "Run" pour démarrer une socket Bluetooth et une méthode "Cancel" à appeler lors de ça déconnexion. Nous avons mis des méthodes "read" et "write" qui permettent la lecture et l'écriture sur la socket.
Semaine 9
Cette semaine nous avons enfin réussi à capter un signal correct provenant de l'antenne de Mainflingen. Suite à cela nous nous sommes attaqués à la programmation du programme décodeur.
Réception du signal
Nouveaux tests réalisés
Après les nombreux essais infructueux de réception DCF77, nous avons enfin pu obtenir un résultat plutôt convaincant. Le gros problème en travaillant sur une fréquence de 77.5 kHz, est qu'elle se situe sur la large bande passante des ondes émises par les alimentations à découpage des appareils électriques. Ces ondes sont donc très présentes en salle de projet. Après en avoir discuté avec les tuteurs de projet, nous avons décidé de tester le programme de réception en extérieur. Jusqu'à présent la réception a été testée en intérieur. Nous avons donc mis en place un programme python, simple, permettant d'accéder rapidement aux valeurs retournées par l'antenne :
import time from RPi import GPIO b1=17 print b1 GPIO.setmode(GPIO.BCM) GPIO.setup(b1, GPIO.IN, pull_up_down=GPIO.PUD_UP) fichier = open("fichier22.txt","a"); i=0 while i<=600: inputVal = GPIO.input(b1) fichier.write(str(inputVal)) print inputVal time.sleep(0.1) i=i+1 fichier.close()
Finalement il n'a pas été testé en extérieur, seulement en collant l'antenne à une fenêtre au fond de la salle E304. Avec surprise, parce que nous étions quand même à moins de 2 mètres des ordinateurs, nous avons reçu périodiquement une suite de bits correspondant à ce qu'envoie l'antenne de Mainflingen.
100000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000001101111100000000000000000000000000000000 000000000000000000000000000000000000100000000011000000001000000000100000000010000 000000100000000011000000001100000000110000000010000000001100000000110000000010000 000000100000000010000000001000000000100000000010000000001100000000110000000010000 000000100000000010000000001000000000000000000010000000001000000000110000000010000 000000100000001011000000001000000000100000000010000000001000000000110000000011000 00000011000000001100010000110000000010000
On remarque que lors de cette mesure, le module n'a étonnement pas renvoyé beaucoup de signaux parasites. Contrairement à toutes nos mesure effectué jusque là.
Une trame DCF77 envoie un bit toutes les secondes. Quand il n'y a pas de bit, si on effectue les relevés sur la sortie non inverseuse du DCF77, le module retourne 0 Volt. Un bit de valeur 0 correspond à la sortie à l'état haut, pour nous 3.3V, pendant 100 ms. Un bit de valeur 1 correspond à la sortie à l'état haut sur une durée de 200 ms. Nous lisons donc l'état de la pin GPIO de la Raspberry Pi toutes les 100 ms. Les relevés sont enregistré dans un tableau. Si 2 case adjacentes ont pour valeur 1 alors le bit correspondant vaut 1. Si une case est à 1 et la suivante à 0, alors cela correspond à un état 0 envoyé par l'antenne. En effectuant les mesures toutes les 100 ms, on garantie qu'aucun bit n'est pas oublié lors de la mesure. Nous aurions pu effectuer la mesure aussi sur 50ms, sauf qu'un bit à l'état haut aurait été symbolisé par 4 cases valant 1, et 2 cases valant 1 pour un état bas. Le schéma (qui n'est pas à l'échelle pour l'intervalle entre 2 bits) montre l'instant de prélèvement des bits (les barres verticales):
Accès aux GPIOs en C
Après avoir trouvé cette méthode de prélèvement, nous sommes passés à la création du programme de décryptage de l'heure. Pour cela il fallait accéder du point de vue logiciel, aux GPIOs. Nous ne savions pas du tout comment faire en C. Beaucoup d'exemple sur internet proposait via Python, mais il n'était pas question pour nous de programmer dans ce langage. Ça syntaxe est certes facile, mais d'un autre côté, le langage est interprété donc son exécution est plus lourde et pas forcément plus rapide que pour un programme écrit en C. Nous avions aussi découvert, au début du projet, l’existence de la bibliothèque wiringPI, permettant d'accéder aux GPIO de la même manière qu'aux pin d'une arduino. Cependant cette bibliothèque possède un niveau d’abstraction trop haut pour notre utilisation des GPIOs. En fin de compte nous devions juste lire sur une pin. Après beaucoup de recherche nous avons finalement trouvé que les GPIOs pouvaient être accessible facilement, même depuis le shell [1].
Le système de gestion des pins se trouve à l'adresse /sys/class/gpio et existe sur la plupart des distributions Linux, même sur les systèmes n'en possédant pas. Ce dossier contient ce qui semble être des fichiers accessibles uniquement en écriture par l'utilisateur root : export et unexport. Par défaut les GPIOs ne sont pas activées, pour les activer il suffit d'écrire le numéro du GPIO dans le fichier export. Par la suite un dossier gpio*numero* est créé contenant les fichiers :
- active_low : permettant d'indiquer la valeur binaire correspondant à un état bas.
- value : en lecture, permet de lire l'état de la pin GPIO
- direction : configure la pin en entrée ou en sortie
- edge : spécifie si la valeur haute correspond à un front montant, un état haut complet ou un front descendant
Lorsqu'on ne souhaite plus utiliser la GPIO, il suffit d'écrire son numéro dans le fichier unexport. En partant de cela, il est facile d'accéder aux GPIOs en C à l'aide des fonctions de gestion des descripteurs de fichiers. Nous avons trouvé un exemple de code sur le site eLinux et l'avons repris pour l'adapter à notre utilisation en ajoutant la fonction paramétrant la valeur de retour sur un état bas. (Fichier GPIOaccess.c sur le dépôt Git). Les autres fonctions permettent d'activer un GPIO, de lire son état et d'établir sa direction. Les fonctions sont disponibles sous forme d'une bibliothèque statique nommée libGPIOaccess.
Suite à la programmation de ces fonctions de gestions des ports GPIO, nous avons codé le programme de décryptage de l'heure. Ce programme est désormais fonctionnel.
Décryptage de l'heure
Le programme de décryptage fonctionne en 3 temps :
- Écoute du port GPIO pendant au moins 2 trames (fonctionnel)
- Extraction d'une trame correct de l’échantillon de l'écoute (fonctionnel)
- Modification de l'horloge interne du système Linux (à faire)
Dans un premier temps on récupère toutes les 100 ms, la valeur de la pin 17 du GPIO reliée à la sortie non inverseuse du module BN641138 et cela pendant une durée de 1300 ms ce qui correspond à une écoute sur 130 secondes. Sachant qu'une trame complète dure 60 secondes nous sommes sûr d'en obtenir au moins une complète.
Par la suite une fonction decodeSample va se charger d'extraire une trame de l'échantillon. Pour cela, il existe certains bits particuliers :
- Le bit 0 est toujours à 0
- Le bit 20 est toujours à 1
- Il n'y aucun bit sur la 59e seconde hormis lors de l'ajout d'une seconde intercalaire, phénomène rare donc non pris en compte pour l'instant par notre programme
Les premiers test ne donnait jamais la bonne heure, même si les échantillons était très peu affectés par les bits parasites. Il a donc fallu renforcer la vérification en y incluant les bits de parité paire et en recalculant cette parité :
- Le bit 28, pour la parité des minutes
- Le bit 35, pour la parité des heures
- Le bit 58, pour la parité de la date
Ainsi si la parité n'est pas correct on cherche une nouvelle trame. Une fois la trame correct récupérée, on calcul les heures et les minutes et on les enregistrent dans une structure.
Résultats
Les test de ce programme ont été effectués dans un endroit dépourvue d'appareils électriques dans un rayon d'au moins 5 mètres, hormis d'un ordinateur et son alimentation. Plusieurs tests ont été effectués et il semble que si l'antenne est surélevée par rapport au bloc d'alimentation, le programme récupère l'heure plus facilement.
Notre plus grosse erreur au cours de ce projet a été de penser qu'il était impossible d'obtenir l'heure depuis un signal pollué par des bits parasites.
Or il est tout à fait possible de le faire, ce que démontre notre méthode de détection de trames. On remarque aussi que plus le signal est pollué, plus il faut mettre en œuvre des méthodes de vérifications d'intégrité. Ce qui est de plus en plus difficile puisque, hormis les bits fixe quelque soit la trame ou les bits de parité, il n'est pas possible de vérifier directement la conformité de la trame.
Semaine 10
PCB de la batterie de secours
Nous avons commencé cette semaine à étudier la gestion des arrêts brusques de l'horloge. Lorsque quelqu'un débranche sans précaution l'horloge, il faut que la Raspberry et son système Linux s'éteignent correctement. Pour cela, elle est alimentée par une batterie. Cette batterie permet d'alimenter la Raspberry, au minimum, pendant la durée de l'extinction de Raspbian. A l'instant où la batterie prend le relai sur l'alimentation, les LEDs s'éteignent. Les 2 panneaux de LEDs peuvent consommer jusqu'à 2 Ampères, il nous faudrait alors une batterie beaucoup plus robuste et inutilement grosse pour supporter un courant aussi fort.
Pour gérer les arrêts brusque, il nous faut basculer sur la batterie dès que l'alimentation principale n'est plus reliée au secteur. Il faut aussi envoyer l'information à la Raspberry, via un GPIO, sur laquelle tourne un programme qui exécute la commande halt, éteignant le système proprement.
La première solution choisi pour réaliser ces deux fonctions est la suivante :
Ce schéma représente la partie qui gère le changement entre l'alimentation secteur et alimentation par batterie. Un comparateur, qui comparera la tension adaptateur secteur et la tension de la batterie, enverra vers une pin GPIO un niveau logique 1 pour indiquer à la Raspberry que l'alimentation électrique murale est absente.
La batterie est reliée à une diode puis à la Raspberry. Lorsque la tension de l'adaptateur secteur diminue suite à la coupure la diode est passante et la batterie alimente la Raspberry.
Une diode supplémentaire, située à proximité de la batterie permet d’empêcher que la batterie alimente l'adaptateur secteur.
Le contrôleur que nous utilisons est un LT1512, le montage de chargement de batterie correspond à l'application typique réalisée avec ce boîtier.
Retour sur la détection de l'heure
Suite à la réussite de la détection de l'heure dans un environnement à proximité de l'air libre. Nous avons effectués d'autres tests dans un environnement confiné, comme un appartement étudiant. Le programme semble avoir beaucoup plus de mal a récupérer l'heure.
Nous sommes toujours à la recherche de moyens de vérification de conformité de la trame. A ce propos en faisant des récupérations de l'heure, le programme se trompe et renvoie des heures supérieurs à 24 et des minutes supérieurs à 60. Il est donc possible d'ajouter un moyen de vérification supplémentaire pour détecter les dépassements de valeurs. Nous allons aussi mettre en place cette vérification sur la date. Les jours ne dépasseront jamais 31 et les mois 12.
Pour aller plus loin, il est peut-être aussi possible de corriger les bits ayant des valeurs incorrects.
Serveur bluetooth
Suite à la découverte et de la prise en main du Bluetooth sous Linux. Nous avons commencé la réalisation du serveur Bluetooth. Lancé en arrière plan dans un thread parallèle, il est chargé d'écouter les données venant de l'application mobile tout en étant capable d'en envoyer. Le serveur se trouve en arrière plan pour laisser les future tâche d'affichage du bandeau et du jeu s’exécuter, tout en étant à l'écoute des consignes envoyées par l’utilisateur.
Semaine 11
Dessin du PCB sur Altium
Nous avons réalisé sur Altium un schematic regroupant toutes les parties de la carte :
Comme on peut le voir il manque une diode par rapport au schéma précédent. C'est normal puisque nous utilisons celle présente sur le shield "adafruit led matrix hat" qui sépare l'alimentation des LEDS est celle de la Raspberry.
Dans la partie qui compare la tension de l'alimentation est celle de la batterie, nous avons utilisé un TL081 comme comparateur. Le reste des composant a été choisi en fonction des indications du constructeur du contrôleur de batterie LT1512.
Il faut calculer les valeurs de R1 et R2 , pour R2 la datasheet conseil de prendre 12.4kΩ. Les inductances L1A et L1B sont en réalité 2 bobinage présent autour d'un même cœur, le modèle conseillé est le CTX33-3. Parmi les autres informations disponible sur les composants à utiliser nous connaissons le courant maximale d’ondulation pour la capacité de découplage Icoups = 0.561A, ainsi que le courant d’alimentation du LT1512 : I1N = 0.016A
Les composants présents sur la carte qui sont nécessaires à la gestion de la batterie sont :
- LT1512 - contrôleur batterie
- TL081 - AOP pour comparateur
- condensateur c1 22µF
- condensateur c2 0.22 µF
- condensateur c3 0.22 µF
- condensateur c4 0.22 µF
- condensateur c5 0.1 µF
- résistances
- r1 : 1kΩ
- r2: 12,4kΩ
- r3 : 0.2 Ω
- r4 : 24 Ω
- inductance CTX33-3
- diode Schottky D1 D4 10TQ035
- diode D3 1N4001
Nous avons également réalisé une première version du PCB :
Finalisation PCB
Après réflexion et retour sur le PCB nous avons réalisé plusieurs modifications. Dans un premier temps nous avons pris en compte le rallumage de la Raspberry automatiquement lorsqu'on rebranche l'horloge à la prise électrique 230V. Lorsque l'OS d'une Raspberry s'éteint, celle-ci reste "en veille". Pour démarrer à nouveau l'OS il faut retirer et remettre l'alimentation. Nous avons étudié deux solutions la première : gérer l'allumage via une pin du GPIO à la manière des boutons ON/OFF. La deuxième solution, plus "automatique", consiste à arrêter d'alimenter la Raspberry une fois l'extinction correct de l'OS Linux. Nous détectons l'extinction de l'OS à l'aide d'une pin GPIO qui passe à 0V lorsque l'OS s’éteint. Cette solution est moins gourmande en composant.
Pour mettre en œuvre cette fonctionnalité nous avons simplement utilisé un transistor (NPN) "commandé" par la pin. Lorsque celle-ci est à l'état haut, le transistor laisse passer le courant qui va de la batterie, vers la Raspberry (en cas de coupure, bien sûr). Lorsque la pin passe à 0, la batterie cesse d'alimenter l'ensemble de l'horloge. Il suffit alors de rebrancher la prise secteur pour rallumer la Raspberry Pi.
Nous avons aussi enlevé le comparateur qui n'était pas nécessaire et nous avons simplement branché l'adaptateur sur la pin GPIO dédiée(nous adaptons bien sûr la tension à 3.3V, tension nominale pour les pins GPIOs).
La liste des composants, mise à jour :
- LT1512 - contrôleur batterie
- Transistor T1 2N2222
- condensateur c1 22µf capacité parallèle à la batterie, recommandée Tantale
- condensateur c2 0.22 µf ( CERAMIC 1E225ZY5U-C203-F
- condensateur c3 22 µf capacité d'entrée, recommandée Tantale avec faible ESR
- condensateur c4 0.22 µf
- condensateur c5 0.1 µf
- résistances :
- r1 : 1 kΩ
- r2: 12,4 kΩ
- r3 : 0.2 Ω
- r4 : 24 Ω
- r5 : 1 kΩ
- r6 : 1.2 kΩ
- r7 : 2.2kΩ
- r8 : 2.2kΩ
- r9 1 kΩ
- inductances ctx33-3
- diode Schottky D1 D4 10TQ035
- diode D3 1N4001
Ci-contre à droite, le PCB incluant l'ensemble : contrôleur de batterie et gestion d'allumage et d'extinction de la Raspberry Pi:
Serveur Bluetooth terminé
La partie serveur Bluetooth est terminée et intégrée dans une librairie statique. A plusieurs moment nous avons été confronté aux problèmes de tâches parallèles avec les threads. Le programme est de cette forme : 1. Une fonction "communication" lance une socket d'écoute ayant une file d'attente de taille 1. 2. Un client arrive, on lance une boucle de réception. 3. Un client arrive, en parallèle de la boucle d'écoute, un thread est lancé. Il se charge d'envoyer les données écrite par l'utilisateur 4. Lors de la fin d'une communication, la boucle de réception attend la fin du thread d'envoi. 5. Une nouvelle socket d'écoute est créée.
On remarque qu'une socket d'écoute est créée à chaque fois qu'un utilisateur arrête de communiquer. En effet nous avons fait en sorte de détruire la socket d'écoute lorsqu'un client est en communication. Nous avons dû faire ceci pour éviter que d'autres utilisateurs ne soient en attente. Bien que notre file d'attente soit de taille 1, lorsqu'un client est présent et qu'un deuxième arrive, le système accepte ça présence et stock les échanges de données. Celles-ci se retrouvent dans la partie "réception" et "envoie" lorsque le client n°1) se déconnecte. Par exemple, si l'utilisateur 2 envoie plusieurs trames de données, celles-ci sont reçu immédiatement par le programme de réception, ce qui peut poser des problèmes lorsque par exemple un utilisateur perd sur le jeu et quitte la communication. Du coup nous devons arrêter cette socket d'écoute à chaque arrivée d'utilisateur.
Pour que les fonctions utilisant la communication Bluetooth puisse communiquer avec l'application Android simplement et rapidement, nous avons créé 2 structure :
- La première chargée de stocker ce qu'envoie l'application :
struct bt_msg_recv { uint8_t client; //est à 1 si un client est présent, sinon 0 char *msg; //contenu du message Bluetooth reçu };
- La deuxième chargée de stocker ce que va envoyer l'horloge :
struct bt_msg_send { uint8_t client; //est à 1 si un client est présent, sinon 0 uint8_t write; //si il vaut 1, alors la donnée est à écrire, si il vaut 0 elle a été écrite char *msg; //contenu du message Bluetooth à envoyer };
Intelligemment accessible, sans oublier de les encapsuler avec les fonctions pthread_mutex_lock() et pthread_mutex_unlock(), elles permettent un accès depuis différents thread, à la communication Bluetooth.
Semaine 12
Erreur sur le PCB
Notre PCB imprimé, nous avons remarqué que des erreurs étaient présentes. Bien que nous avions vérifié plusieurs fois le PCB sur ordinateur, une erreur sur le "schematic" nous a forcé à devoir couper sur quelques pistes et effectuer d'autres straps en plus de celui déjà présent (mais irremplaçable) sur le PCB physique.
Lors de cette séance nous avons soudé les composants. Nous avons du nous y reprendre plusieurs fois notamment parce qu'il n'étaient pas toujours couché sur la plaque, ce qui fut le cas pour plusieurs résistance.
Bandeau d'information et jeu
Nous avons mis à jour la librairie "rgb-led-matrix". La version déjà présente sur la Raspberry Pi possédait quelques fonctionnalités en moins. Que ce soit pour l'ancienne version ou la nouvelle, la librairie fonctionne majoritairement avec des objets. Cependant la partie serveur Bluetooth est codée en C et compilée avec gcc, et non g++. Nous allons sûrement devoir faire face à des modifications.
La partie qui affiche un bandeau de texte est terminée. Il suffit juste d'indiquer la chaîne de caractère en paramètres d'une fonction et celle-ci se charge de faire défiler le texte.
Le jeu est en cours de codage. Comme prévu il s'agira d'un dinosaure qui saute au dessus de cactus comme on peut le voir dans le navigateur internet google chrome.
Mise en place de l'application
Afin que la application communique, nous avons mis en place différentes requête que l'application doit envoyer et recevoir, vers et depuis le serveur.
Pour le jeu :
start_jeu => 70 //envoyé à chaque démarrage de nouveau jeu. Jump => 71 //envoyé à chaque saut end_jeu => 72 //reçu lorsqu'on perd
Pour le FLUX RSS:
code_flux => 65 //envoyé à chaque envoi d'un flux ou message, suivi du contenu de la textbox fin_flux => 69 //envoyé avant l'envoi d'une nouveau flux et au début d'une autre activité (exemple jeu).
Pour les fuseaux horaires:
code_fuseau => 76 //envoyé lors du changement de fuseaux horaire, suivi du nouveau fuseau horaire
Voici les activités pour les fuseaux horaires et les flux RSS/ATOM:
Voici des captures des autres activités présentes dans l'application :
Pour réaliser la vue Site web / réseaux sociaux qui renvoie lors d'un clique sur un bouton, vers le site de Polytech, de notre wiki, la page Facebook Polytech et le compte instagram Polytech; nous avons utilisé la Class Intent qui permet de lancer une nouvelle activité indépendante de l'application.
public void btn_wiki(View view) { Intent wikiIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://projets-ima.plil.fr/mediawiki/index.php/IMA4_2017/2018_P22")); startActivity(wikiIntent); }
On cré un Intent de type ACTION_VIEW qui ouvre le lien de wiki.
Semaine 13 et interruption pédagogique
Nouvelle erreur sur le PCB
Nous sommes de nouveau confrontés à un nouveau problème avec notre PCB. Sur la partie qui concerne la coupure de l'alimentation de la batterie lorsque Raspbian est arrêté. Lors de nos test, nous avons réalisé que nous avions effectué un mauvais montage. Lorsque la pin du GPIO est à l'état haut, l'entrée de l'alimentation de la Raspberry Pi est à 0V.
Ceci est dû à la mauvaise position du fil d'alimentation de la Raspberry Pi par rapport au transistor. Comme on peut le voir sur la capture d’écran ci-contre, le fil "alimrasp" devrait se trouver sur l’émetteur du transistor et non le collecteur. De cette manière lorsque la base est à 0V le circuit collecteur-émetteur est ouvert et il est à 5V lorsque la base est à 3.3V. Nous avons réalisé un inverseur plutôt qu'un amplificateur. Pour corriger cette erreur nous avons ajouté un deuxième inverseur pour annuler l'inversion sur breadboard. Nous n'avons pas eu le temps d'usiner un nouveau PCB, la correction n'a donc pas pu être réalisée.
Hormis cette erreur, le reste du circuit fonctionne parfaitement. Les test effectués en mettant une commande inversé nous ont permis d'avoir une tension de 5V délivrée vers la Raspberry pi depuis la batterie lorsque l'alimentation secteur était absente.
Avec l'ajout du deuxième inverseur via breadboard nous avons pu obtenir le résultat souhaité.
Jeu du Dinosaure
Nous avons effectué de multiple tests sur papier et matrice de LED afin de trouver un jeu de type arcade comme Snake, Pong ou Space invaders qui serait adaptable et jouable sur la matrice de Led 16*32.La plupart des jeux n'étaient pas adaptables car la résolution de la matrice était trop faible, ou encore le format rectangulaire ne permettait pas une bonne expérience du jeu (par exemple pour snake).
Le jeu que nous avons sélectionné a été le jeu T-REX de Google Chrome, facilement jouable sur la matrice de LED 16*32. Auparavant nous avions dimensionné les cactus et le dinosaure, de cette manière :
Du côté code le jeu fonctionne de la manière suivante : une matrice (16*32+5*3) est déclarée. 5 case sont ajoutée, elles correspondent à l'emplacement du nouveau cactus créé en dehors des LED. La matrice possède aussi une profondeur de 3 car c'est une matrice RGB (Red Green Blue).
Le jeu comporte plusieurs fonction :
- Déplacement des cactus :
On déplace tous les pixels vert en direction de la gauche.
- Ajout d'un cactus de manière aléatoire :
À chaque fois qu'un cactus est généré on attend 16 déplacements vers la gauche, on a 10% de chance d'avoir un cactus (utilisation de la fonction srand pour générer un nombre pseudo aléatoire). Si le cactus n'est pas généré on augmente la chance de 1% à chaque déplacement.
- Saut d'un dinosaure
Lorsque l'horloge reçoit une demande de saut de l'application, le dinosaure saute en diagonale de 5 pixel de haut, reste en l'air 4 pixels puis redescend en diagonale. Lorsque l'ensemble avance, le saut du dinosaure est vu comme un saut linéaire sur la verticale.
- Vérification de collision
Après chaque déplacements, on vérifie si un pixel vert(les cactus sont en vert) possède aussi une composante rouge (le T-REX) si c'est le cas le jeu s'arrête et envoi à l'application le code correspondant à un échec au jeu.
Assemblage des différentes parties du code
Nous avons assemblé les différentes pièces du programme. Sachant que la communication Bluetooth, le bandeau et le jeu fonctionnent dans le même programme et que le décodeur DCF77 ainsi que l'affichage de l'heure forment 2 processus supplémentaires. Ci-contre se trouve l'arborescence des programmes et leurs dépendances sur la Raspberry pi.
Le travail d'assemblage des différentes parties a surtout consisté à créer un programme exécutable "Horloge". Au préalable les fonctions du jeu et du bandeau ont été rassemblé dans une librairie statique nommée "libLedPanel.a". Dans ce programme on lance dans un thread, la fonction de gestion de la communication Bluetooth (qui elle-même lance un thread qui gère la réception). On effectue ensuite dans une boucle infinie, les différentes actions : 1. Attente d'une communication 2. Lorsqu'une liaison est présente on boucle sur le contenu de la structure de réception et on écoute une commande 3. En fonction de la commande reçu on exécute la fonction qui gère le bandeau d'information ou celle qui gère le jeu
Les commandes sont en faite représentées par un unique octet à l'indice 0 du buffer de communication. Par exemple pour afficher les titres RSS d'un site web il suffit de renseigner le lien hypertexte dans le champs de texte de l'application. Le lien est ensuite envoyé à la Raspberry, tout en ayant la commande qui correspond à une mise en place du bandeau, en début de trame. L'horloge s'occupe d'extraire les titres du flux RSS/ATOM, à condition qu'elle soit reliée à internet. De plus l'horloge est programmée pour continuer à diffuser le bandeau d'information même si personne n'est connecté à l'horloge.
Finalisation DCF77
Pour que l'antenne DFC77 capte le signal, il faut qu'elle soit correctement installée(perpendiculaire à la ligne imaginaire Lille-Francfort). Pour faciliter son installation, nous avons imprimé une boîte (fichiers .stl disponible dans la prochaine partie) sur lequel est installé un compas de manière à pouvoir orienter l'antenne correctement. Si l'utilisateur se trouve à Lille, il a juste à pointer la direction Nord du compas, vers le Nord.
Dans les salles de Polytech où se trouvent beaucoup d'ordinateurs, la réception pourra se faire si le récepteur se trouve en hauteur. De cette manière il sera éloigné des interférences. Si en plus il se trouve près de la fenêtre, alors la réception n'en sera que meilleure.
Documents Rendus
Rapport de projet Fichier:Rapport de projet.pdf
Archives Git : https://archives.plil.fr/aknockae/projetS8_HorlogeDCF77
Fichier STL boite DCF77 Fichier:Boite dcf77.zip
Dans l'archive git se trouvent :
- Les fichiers de l'horloge
- Les fichiers de l'application
- Le PCB
- Les fichiers de paramétrage de l'horloge et du NTP