ELECINF344/381

Partie interactive du site pédagogique ELECINF344/ELECINF381 de Télécom ParisTech (occurrence 2011).

Catégories

TSV Safe Express: DCC Signals and Ethernet

Our journey has continued from CAN to LAN passing through DCC in its way. During the last two days, we tried to write the dcc encoder for our card which will act as the central station. In brief, I will try to explain DCC for all those who are not already aware of it. DCC (Digital Command Control) is a standard which permits us to operate model railways by sending modulated pulse wave(amplified with the help of a booster) to the rail tracks. Thereby, we can control any locomotive or accessory (like Traffic lights) if they have the dcc decoder. DCC is standard provided by NMRA.
We have done the following encodings for bit 0 and 1 as per NMRA DCC Standard.
(i) bit ’0′ – 232 microseconds (half high and half low)
(ii) bit ’1′ – 116 microseconds (half cycle is low)
On the implementation part, to generate such type of signal on the STM32 GPIO port, we use PWM module(using Internal Timer of STM32) with 50% duty cycle. This was setup in Output Compare Mode. Through the help of oscilloscope, we verified that we got the expected results. We created a dcc packet simulator(coded as a task of FreeRTOS) and we tried sending Messages to the port as per DCC Communication Packet format.

On the Ethernet part, we have chosen LwIP Stack as the TCP/IP Stack. We have chosen LwIP primarily as it has features like DHCP, UDP, IPv6 which we may need as the project matures further. So, we integrated the LwIP stack with STM32F107(which has in-built MAC Controller) and DP83848P Phy Controller taking help of a similar example provided by ST on their website. We were able to make a telnet connection to our Central Station and correponding exchange messages through telnet.

On the stabilisation of NMRA CAN protocol, we added a watchdog module within all the nodes including the central station. This was required because if the software hangs in one of the nodes, it should have the ability to re-join the network. The timeout of the watchdog module has been kept to 3 seconds(Typically because we want our nodes to rejoin the network as soon as possible and at the same time give Central Station enough time to remove this node from the node table and event table). Also, the command to reset the nodes sent by the network manager at the start of his execution as a broadcast message to all the nodes will have a deeper impact. Instead of doing a cache reset at the nodes, we are now doing an actual software reset to the node. This is just to simulate an actual reset. All these changes done to stabilisation are open for discussions and all remarks/critics/ideas are heartily welcomed.

[CASPER] Prototype fonctionnel

Hier, nous avons finalisé le prototype mécanique.

Nous avons installé les trois servomoteurs sous le plan du socle. Nous les contrôlons grâce à un signal PWM de la carte de TP STM32.

Nous avons changé nos anciens câbles de carbone par des câbles en plastique. Il est apparu que bien que leurs propriétés mécaniques en poussée/traction étaient bonnes, celles-ci ne sont pas assez flexible pour supporter les mouvements au niveau des bras motorisés.

Nous avons implémenté un programme de commandes qui fait effectuer un 360° à Casper que nous contrôlons par le potentiomètre (relié à l’ADC) de la carte de TP.

Nous allons maintenant travailler sur des fonctions qui permettent un contrôle précis de la direction et de l’inclinaison de Casper et en parallèle peaufiner le prototype afin qu’il soit plus robuste.

Voilà la vidéo du programme de démonstration (360° contrôlé par ADC) :

 

Parallèlement, l’UART sur le PCB est fonctionnel et on peut pour l’instant afficher les chaînes de caractères reçues sur l’écran LCD.

RoseWheel : préambules de propulsion

Pour contrôler nos moteurs correctement, nous avons dû estimer la fréquence minimale de la PWM qu’on leur fournira.

En effet, les hautes fréquences sont à éviter pour des raisons de consommation mais une trop basse fréquence provoquerait une rotation saccadée des moteurs.

Nous avons donc utilisé la relation suivante pour notre estimation :

Fmin = R / [ -2 . L . ln (1 - P / 100) ] (source : cliquer ici)

 

Nous avions déjà une estimation de la résistance interne R ≈ 0,6 Ω mais nous n’avons pas été en mesure de trouver de datasheet spécifiant L, l’inductance propre de notre moteur.

Nous avons donc décidé de mesurer L de façon expérimentale en utilisant le matériel des salles de TP d’électronique analogique (merci Chadi!) :

Mesure de l'inductance de notre moteur

Mesure de l'inductance de notre moteur

 

Le principe est assez simple, si on modélise un moteur comme une bobine et une résistance en série, on a l’égalité suivante :

tan(φ) = ω . L / R

=> Avec un déphasage de φ = 45°:

L = R / ω (avec ω = 2 . π . f)

 

Nous avons effectués plusieurs mesures car nous étions à des fréquences assez élevées et le bruit était assez important donc il était difficile d’obtenir précisément 45°.

Voici ce que l’on obtient avec la dernière mesure :

f = 14,3 MHz (fréquence avec un déphasage de 45°)

R = 10 kΩ (résistance utilisée pour observer le courant, on néglige la résistance interne)

 

=> Nous obtenons donc une inductance de:

L = 10 000 / ( 2 * π * 14 300 000) ≈ 0,1 mH

 

Il nous reste donc à estimer en précision le pourcentage de stabilité P, qui parait avoisiner raisonnablement les 5% d’après le site évoquée précédemment.

Ça implique une PWM à une fréquence en dessous de 10 KHz, donc audible mais ça ne pose pas de problème à priori.

Nous ferons de vrai tests sur notre carte très bientôt puisque quelques composants sont encore en cours de route mais ils devraient arriver dans la semaine si tout va bien.

…à suivre…

RoseWheel : à pleine vitesse

Voici un compte rendu des avancées que nous avons fait pour la démonstration de vendredi et pendant le weekend :

Carte capteurs

Côté accéléromètre, nous avons réussi à communiquer proprement avec accéléromètre en utilisant une interruption externe liée au signal RDY ; cela nous a permis plusieurs démonstrations intéressantes : contrôle d’une LED suivant l’angle, envoi des valeurs mesurées par le port série, affichage de l’angle mesurée avec Matlab.

Pour le gyroscope, nous avons eu plus de difficultés, notamment pour bien gérer l’implémentation du protocole I2C dans le STM32. Après quelques heures de debug, nous sommes arrivés à une implémentation minimale du driver pour la démonstration, les données lues étant transmises par le port série et affichées dans le même graphique que celles en provenance de l’accéléromètre ; cependant, le capteur parfois s’arrêtait sans explication.

Dans un premier temps, nous avions attribué ce problème à des micro-coupures d’alimentation. Néanmoins, nous ne sommes toujours pas satisfaits de cette explication, puisque une telle fragilité n’est pas désirable pour une partie si vitale de notre projet ; alors, nous avons travaillé sur le code pendant le weekend pour essayer de trouver la source des instabilités, mais nous n’avons pas encore trouvé la réponse. À suivre donc…

Filtre de Kalman

Nous avons implémenté en C notre filtre de Kalman dans la journée du vendredi. Afin de procéder aux tests « définitifs », nous attendons d’avoir des drivers plus fiables pour le gyroscope et la partie mécanique monté, étant donné qu’il est indispensable de tester le filtre dans les conditions prévues sur le système pour lequel il a été conçu.

Entre-temps, nous envisageons d’utiliser une version un peu modifié qui ne traquerait que la dérive du gyroscope sur notre banc de test. Pendant la démonstration, nous avons montré nos performances en simulation, dont nous avions parlé dans notre dernier post.

Banc de test

Nous avons également montré au jury le fonctionnement de notre banc de test, notamment le graphique de variation d’angle et de vitesse angulaire, que nous avons détaillé dans des posts précédents.

CAN

Nous avons aussi avancé sur le bus CAN, et nous pensons à le tester demain avec les drivers que nous avons écrit ce week-end.

Moteurs

Nous commençons à implémenter les des moteurs et l’utilisation de PWM pour contrôler les ponts en H.
Sur notre PCB, nous utilisons des « pilotes de demi ponts en H » (IRS2184SPBF) qui permettent (entre autres) d’éviter les court circuits.
Dans le schéma suivant, ces composants se brancheraient à droite et à gauche de façon à ne jamais avoir A et B à la même valeur :


Pour pouvoir changer le sens de rotation, on pense utiliser la broche enable disponible sur le « pilote » (IRS2184SPBF).
Le chronogramme suivant illustre ce que l’on croit nécessaire au moment de la transition d’un sens de rotation à l’autre :

 

De façon à éviter d’entendre le signal de contrôle, on pense utiliser une fréquence de l’ordre de 20KHz mais on ne sait pas encore si cela ne sera pas trop élevé pour « limiter les pertes lors de la commutation des transistors du pont en H ».
Un certain nombre d’incertitudes persistent donc toute suggestion serait la bienvenue !

Planning pour la semaine – « micro-tâches »

Envisageant pouvoir asservir correctement le segway avant dimanche prochain, nous nous sommes attribués les « micro-tâches » suivantes pour la suite :

Drivers carte capteurs

- I2C / Gyroscope -> João 12/04
- SPI / Accéléromètre -> Clément 11/04

Drivers carte principale

- Drivers Ponts en H -> Cédric 13/04
- Contrôle moteurs -> Cédric 14/04
- Drivers CAN -> Florian 11/04
- Tests Drivers CAN -> Florian 11/04
- Protocole CAN -> João 13/04
- Tests protocole CAN -> João 14/04
- Drivers encodeurs -> Clément 14/04

Tests filtre de Kalman

- Intégration filtre TestBench -> Florian 13/04
- Réglage filtre -> Florian 17/04

Intégration logicielle carte capteurs

- Implémentation asservissement en C -> Clément 12/04
- Réglage de l’asservissement -> Clément 17/04
- Réglage direction -> João 17/04

Divers

- Montage RoseWheel -> Cédric 12/04
- Montage encodeurs RoseWheel -> Cédric 13/04

[CASPER] Avancées du projet côté mécanique…

Du côté de la mécanique, nous avons mis en pause le développement des drivers linux qui doivent à terme contrôler les moteurs. En effet, nous avons jugé que commander les moteurs au plus tôt et avec précision était plus prioritaire. Nous nous sommes donc penchés sur le contrôle des servos par PWM en utilisant la carte de TP STM32.

Jusque ici nous avons écrit un programme qui prend en charge les trois servos, qui est capable de prendre en entrée un angle comprit entre 0 et 180° et d’amener un servo à cette position. La prochaine étape est d’implémenter le modèle mécanique que nous avons conçu afin de donner au programme la direction de casper (sur 360°) et son inclinaison (sur 90°). Le programme interprétera ces données en terme de commandes moteurs.

[CASPER] Beagleboard, pilotes et pwm

Voici un petit compte rendu de ce que Thomas et moi-même avons réalisé hier et aujourd’hui.

 

Bootstrap

Partant de ce que Thomas avait réalisé précédemment, nous avons automatisé l’installation de la carte SD pour la beagleboard. En effet, celle-ci doit contenir dans une première partition FAT les fichiers du noyau nécessaires au démarrage, et sur une deuxième partition du format de notre choix la racine du système de fichiers.

Afin de pouvoir choisir plus finement quel noyau et quel paquets nous souhaitons installer sur notre beagleboard, et pour pouvoir la placer rapidement dans une configuration « prête à utiliser » lors d’une éventuelle réinitialisation, nous avons choisi de ne pas utiliser les images de rootfs proposées sur internet par la communauté de développeurs beagleboard.

Nous avons donc construit notre propre image rootfs à l’aide de l’outil debootstrap couplé à l’émulateur qemu, ce qui permet de créer sur un ordinateur portable classique une distribution pour une architecture arm, par exemple. Nous avons inclus de nombreux paquets tels que la bibliothèque opencv qui nous sert pour le traitement de l’image, et SVOX pico, qui nous sert pour la synthèse vocale.

Nous avons ensuite configuré la distribution afin d’obtenir une console sur le port série et paramétré la distribution afin de la rendre directement utilisable.

Ces étapes ont été totalement automatisées dans un script, ce qui nous permettrait éventuellement de regénérer tout ceci très rapidement, tout en faisant évoluer nos paramètres.

Nous avons ensuite généré les fichiers de boot à partir du noyau de sorte qu’il supporte le système de fichiers nilfs2¹ (Le garbage collector du nilfs2 sera lancé automatiquement, dès lors que les paquets nilfs-tools et nilfs2-tools sont installés sur le système. Il faut donc les ajouter dans le script debootstrap_init.sh).

 

Le système de fichiers nilfs2 offre en résumé deux avantages : sa structure garantit l’intégrité des fichiers écrits ce qui évite la corruption de la carte en cas de coupure de courant ou de plantage et il offre d’excellentes performances sur la carte SD en comparaison avec l’ext2 par exemple.

Cela est certainement dû à sa structure circulaire, et à son mode de fonctionnement avec garbage collector. En effet, les fichiers supprimés ne sont pas effacés immédiatement, ce qui aurait pour effet de ralentir les opérations. Ces effacements ne sont réalisés que beaucoup plus tard, à la fin d’un compte à rebours ou lorsque les segments propres sont en nombre insuffisant. Ainsi, l’écriture est rapide puisque sans effacement, et l’effacement est retardé ce qui à nouveau permet de gagner beaucoup en vitesse de fonctionnement. (L’installation de paquets logiciels est aussi rapide que sur un ordinateur moderne avec nilfs2, ce qui était loin d’être le cas avec ext2 puisqu’en fonction des dépendances, il fallait entre 15 et 60 min)

 

Ensuite, un autre script que nous avons réalisé automatise la génération d’une archive tarball rootfs.

Une version adaptée du script setup_sdcard.sh (http://github.com/RobertCNelson/omap-image-builder/blob/master/tools/setup_sdcard.sh) nous permet ensuite, là encore de manière automatisée, de formater la carte mémoire et de créer les partitions, de générer les fichiers uImage et uBoot, et enfin de copier les fichiers de boot et d’extraire le tarball rootfs sur les partitions correspondantes.

Nous avons de plus écrit une notice détaillant l’utilisation de ces scripts en vue de générer rapidement une installation pleinement fonctionnelle et incluant tous les paquets logiciels nécessaires sur la carte SD.

 

¹ Merci PHH pour les conseils !

 

 

Pilotes et PWM

Thomas continue de se pencher sur la question des pilotes. Il a réalisé un helloworld que nous ne pouvions malheureusement tester sur la beagleboard, du fait que celle-ci était immobilisée par les opérations de préparation de la carte SD. Maintenant que celle-ci est prête, nous allons pouvoir tester la compilation et l’installation dynamique de ce module de communication helloworld dans le noyau.

Étant donné que la beagleboard n’était pas prête, et outre sa participation à la création de la nouvelle distribution au travers de son expérience précédente avec la première installation que nous avions réalisée avec le script setup_sdcard.sh, Thomas a continué de se documenter sur la réalisation de pilotes et sur l’utilisation des modules PWM sur la beagleboard.

MB Led: Depuis la soutenance intermédiaire…

Notre dernier article datant de mardi dernier. Je vais faire un résumé de mes avancées des derniers jours:

Mercredi et jeudi:

J’ai terminé de coder les fonctions de communications avec le driver de LED. J’ai désormais un exécutable censé afficher une image décrite pour l’instant en dur (pixels écrit un par un à la main dans un tableau). Je ne peux pas avancer plus de ce côté sans nos blocs, une fois ceux-là soudés,  je pourrais passer au debugage

Voici comment fonctionne cet affichage dans les grandes lignes:

Initialisation:

  1. On initialise la communication SPI: messages de 16 bit, fréquence d’envoi de 18MHz, LSB transmis en premier.
  2. On initialise le DMA.
  3. On initialise l’horloge qui servira de référence pour le PWM du driver.
  4. On configure les différentes luminosités pour les trois groupes de couleur (rouge, vert et  bleu)
  5. On configure la fréquence de l’interruption qui rafraichira l’affichage de l’image. Cette fréquence n’est pas définitive, elle dépendra de la puissance des LED qui influe sur la persistance rétinienne. Plus cette puissance sera grande plus on pourra réduire la fréquence de rafraîchissement. Cette fréquence ne peut donc être réglée qu’empiriquement. Pour l’instant 80KHz en se basant sur le code des GLiP.

Routine d’affichage:

Les 8 lignes sont affichées les unes après les autres. Une seule ligne est allumée à un instant donné.

L’affichage d’une ligne se fait de la façon suivante:

  1. On récupère la ligne dans l’image courante.
  2. On extrait, des pixels de cette ligne, les valeurs des 24 LED.
  3. Ces valeurs sont pour l’instant sur 4 bit, une fonction est chargée « d’étirer » ces valeurs sur 12 bits pour correspondre aux attentes du driver. C’est cette fonction qu’il faudra modifier lorsque nous déciderons d’élargir le champ de couleur disponible (pour l’instant on garde le format GLiP).
  4. On construit finalement, sous forme de 18 messages de 16 bit, le vecteur de 288 bit attendu par le driver pour piloter ses 24 sorties (24*12bit).
  5. Ces 18 messages sont envoyés en SPI par accès direct à la mémoire au driver de LED qui va afficher la ligne courante.

Vendredi et samedi:

Depuis vendredi je réfléchi à une façon de faire des mises à jour de firmware via l’IrDA. En effet si nous avons 36 blocs, dès qu’il s’agira de flasher une nouvelle version de notre code, cela s’avérera être une opération fastidieuse. Petit calcul: 30 secondes (au moins) pour flasher un bloc et 36 blocs. Soit un peu moins de 20 minutes à chaque fois!

Une organisation possible de la mémoire flash, pour la mise en place d’un système de mise à jour que je détaille plus bas, serait la suivante:



Les premières instructions du bloc Flash programmer font « sauter » en _firmware_begin.

Puis, le firmware pourrait être mis à jour de la façon suivante:

  1. Notre firmware courant s’exécute normalement sur un bloc B : affichage d’animations, jeux, etc…
  2. Nous souhaitons faire une mise à jour du firmware depuis la carte microSD d’un bloc A par exemple.
  3. En se reposant sur notre système de transmission de donné par IrDA que je ne détaille pas ici, le bloc A va d’abord envoyer une commande indiquant l’arrivé d’une mise à jour (broadcastée ou non)
  4. Un des blocs, B, recevant cette commande décide de l’accepter ou non.
  5. Si il accepte il va placer les différentes parties du firmware  envoyé par le bloc A (là encore en se reposant sur notre système de transmission IrDA gérant les problèmes de communication, les paquets corrompus, perdus etc.) en flash à partir de l’adresse _new_firmware_begin à la bonne position: _new_firmware_begin + (taille d’un paquet * position du paquet).
  6. Lorsque tous les paquets ont été reçu correctement (on peut redemander une confirmation à ce moment-là), le programme saute à l’adresse  dans le bloc Flash programmer de début de traitement de la copie.
  7. Le nouveau firmware est alors entièrement copié à la place de l’ancien.
  8. Une fois la copie terminée on retourne à l’adresse _firmware_beginn.

La mise à jour est terminée!

Je m’intéresse maintenant à l’implémentation de ce système de mise à jour ainsi qu’au fonctionnement du debugage via le port série prévu pour ça.

Référence :

Pour le flashage « in-application » : AN2557

 

RoseWheel : Test bench & Kalman

Aujourd’hui nous avons continué l’amélioration de notre test bench d’un coté et recommencé la modélisation physique de l’autre.

 

Le document de Rich Chi Ooi a été complètement abandonné, il y aurait apparemment des erreurs de calcul (au moins intermédiaire) et son implémentation complexe n’était vraiment pas pratique.

Les équations de BoRam seraient de loin bien plus simple à implémenter et les résultats sont beaucoup plus satisfaisants.

Il reste néanmoins un facteur 4 dans le sens où on obtient des commandes en tension au dessous de 100V au lieu de 24V (alors qu’on avait une erreur de l’ordre de 10 000V avec Rich Chi Ooi).

 

Les améliorations sur le test bench sont moins conséquentes puisqu’il ne s’agissait que d’optimisations.

Tout d’abord avons rendu le test asynchrone de façon à pouvoir changer d’inclinaison cible en cours de route sans avoir à attendre la fin de l’exécution d’une commande (ce qui peut être long si la vitesse demandée est faible). Pour ce faire, nous utilisons des queues que nous remplissons d’objets composés de commandes angulaire et de leur délai associé pour aller à la vitesse demandée.

Enfin, nous avons doublé la précision de calibration de la commande du moteur en mesurant de nombreuses fois chaque PWM associé à un angle et ce tous les 10°.

A l’origine, nous utilisions un tableau de valeurs à interpoler pour calculer les PWM à mettre dans le registre TIM1->CCR3 :

const static uint16_t PWM_list[] =
{
59840, 60130, 60400, 60700, 61010, 61310 // -60° -> -10
61580, // 0°
61900, 62190, 62500, 62780, 63050, 63430, // +10° -> +60°
};

Cette mesure expérimentale présentait une irrégularité non négligeable mais en considérant la linéarité du moteur nous avons fait une régression linéaire pour diminuer l’imprécision.

Voici l’approximation graphique obtenue avec open office (courbe de tendance) :

 

On peut voir en haut à gauche de l’image la fonction à utiliser dans notre code C.

Et pour finir, pour interpréter les données obtenues par l’ADC de façon à connaitre plus précisément notre inclinaison nous avions un tableau similaire :

const static uint16_t ADC_list[] =
{
663, 845, 1018, 1169, 1324, 1485, // -60° -> -10
1644, // 0°
1764, 1975, 2127, 2284, 2455, 2611, // +10° -> +60°
};

…et voici l’approximation graphique ainsi que la fonction linéaire associée que nous en avons extrait :

 

On peut voir que R², le coefficient de détermination, est très proche de 1 dans les 2 cas, donc notre linéarisation peut être considérée comme fiable.

RoseWheel : PCB, banc de tests

Après deux jours de travail, nous avons fini les schémas de nos PCB et, à l’heure où cet article est écrit, nous parachevons le routage de la carte capteurs (autrefois appelée « carte logique »). Parmi les changements clé que nous avons faits, nous pouvons citer notamment l’inclusion d’une alimentation exclusive pour les références des convertisseurs analogique-numériques à l’intérieur du gyroscope et de l’accéléromètre – cela permet d’avoir des conversions plus fiables et donc de réduire le bruit des mesures.

Pour la carte principale (ancienne « carte de puissance »), les plans ont été un peu modifiés : finalement, le circuit de puissance, responsable du contrôle des moteurs en courant, sera intégré par Alexis à la carte, principalement à cause de problèmes d’intégrité du signal (utiliser le bus CAN en entrée permet d’être plus robuste face aux bruits induits par les moteurs à courant continu) et économiques (l’intégration élimine la nécessité de fabriquer une troisième carte qui ne ferait qu’accepter un PWM en entrée et le transmettre aux moteurs).

Côté banc de test, nous avons réussi à contrôler le servomoteur en angle avec la carte de TP, en utilisant les broches originalement assignées au bus SPI pour sortir du PWM. Nous avons commencé alors à le calibrer, puisque la position horizontale (à 0°) ne se trouve pas forcement au milieu de l’échelle du PWM ; pour faire cela, nous avons utilisé une application Android qui nous indiquait l’angle d’inclinaison du téléphone portable. Voici notre dispositif expérimental :

Après cela, nous avons  fini la partie mécanique en fixant une planche de balsa pour tenir la carte dans sa place pendant que nous faisons les tests. Le montage final est celui-ci :

Par rapport à la simulation physique, nous hésitons encore entre continuer à la développer en Octave ou passer à Matlab, étant donné que certaines bibliothèques utiles pour l’implémentation du filtre de Kalman ne sont pas disponibles dans le logiciel libre.

MB Led et PCB

Aujourd’hui, fin du STM32 et continuation du projet. J’ai donc continuer à faire le PCB que Benjamin avait repris en l’adaptant à l’évolution des composants.
Il a donc fallu lire les Datasheets des composants qui avaient changé lors de la commande ce qui permet ce soir et après le TP une meilleur vision de leur utilisation.
Après les suggestions d’Alexis, nous avons cherché un nouveau driver de LED car l’ancien proposait une sortie en PWM ce qui aurait posé des problèmes avec le système d’affichage ligne par ligne. Nous resterons donc chez TI mais prendrons le TLC5951 dont les sorties sont à courant continu. L’avantage de ce driver est qu’il possède 24 sorties réparties en 3 groupes permettant de gérer ensemble des paramètres comme l’intensité maximale. Il prendra 5 pin pour le contrôler 2 timers et 3 des quatre fils du SPI (MISO,MOSI,SCK).

Pour le module bluetooth, nous aurons également besoin de 5 pin (2GPIO, 1UART, un reset) afin de pouvoir configurer le module.

Tout cela m’a permis de finaliser le brochage et demain je commencerai le routage.