Projet 5A 2020 2021/Tuto utilisation et modification

De Polybot Grenoble
Sauter à la navigation Sauter à la recherche

Afin de vous aider à mieux comprendre la façon dont nous avons réalisé notre projet, nous avons rédigé ce document tutoriel. Cela devrait vous permettre de réussir à reprendre les différentes étapes du projet si nécessaire.

Projet 1 : Carte d'alimentation

Soudure de la carte du robot 2

Projet 2 : Écran de contrôle

Procédure générale

Pour pouvoir utiliser notre application vous devez :

  • Télécharger les applis et docs nécessaires + l'application Polybot (voir section "Télécharger l'application")
  • Câbler le module sur la STM32 (voir section "Cablâge des modules")
  • Connecter le téléphone/tablette au module Bluetooth dans les paramètres généraux
  • Lancer l'application (le robot doit être allumé)
  • Choisir les données qu'on souhaite afficher, si on souhaite stocker les données ou pas et valider
  • Cliquer sur "choisir périphérique" et sélectionner le module correspondant puis l'affichage devrait se lancer
  • Si on a choisit de stocker les données et qu'on veut aller les regarder on va dans l'application Cx Explorateur de Fichier, on clique sur AppInventor/asset et on ouvre le fichier stockage_data_robot. On peut aussi brancher le téléphone/tablette sur un ordinateur pour aller ouvrir le fichier directement sur l'ordinateur et traiter les données ensuite par exemple. (voir section ci-dessous)

A NOTER : il s'agit d'une application uniquement disponible pour les téléphones et tablettes Android.


Au niveau des performances, pour le moment, une donnée est actualisée toute les 0,8 secondes environ. Après discussion avec les professeurs, nous avons conclu que ce temps était largement acceptable étant donné la non-priorité de cette tâche par rapport aux autres tâches du robot. Donc il ne faut pas forcément chercher à améliorer le temps d'actualisation.

Application Polybot

Télécharger l'application

Voici la procédure pour télécharger l'application que nous avons crééé sur App Inventor. ATTENTION il s'agit d'une application uniquement disponible pour périphériques Android.

  • Installer de "Cx Explorateur de fichier"
  • Brancher votre mobile sur un ordinateur
  • Télécharger le dossier AppInventor à ce lien : Dossier AppInventor
  • Dézippez puis copier/coller ce dossier AppInventor dans votre téléphone (dans le stockage général)
  • Depuis votre téléphone, téléchargez l'application au format .apk au lien suivant : Application Polybot
  • Puis suivez les consignes jusque l'installation de l'application
  • Lancez l'application puis continuez de suivre les étapes de la section : Procédure Générale

Comprendre et/ou modifier le code de l'application

Si vous souhaitez modifier l'application, vous devez :

  • Télécharger le fichier .aia au lien suivant : Application .aia
  • Ouvrir la page web MIT App inventor et y charger le fichier .aia
  • Vous aurez ainsi accès à toutes les composantes de l'application Polybot

ATTENTION vous ne pouvez pas modifier le code de la STM32 sans modifier le code Scratch de l'application (dans certains cas) !



Rappels des différents Screen crées :

  • Screen 1 : Page de lancement avec logo Polybot
  • Screen 2 : Choix des valeurs à afficher et choix de stocker ou non les données affichées
  • Screen 3 : Affichage des données souhaitées
Screen 1 de l'application
Screen 2 de l'application
Screen 3 de l'application


Étant donné que nous avons utilisé App Inventor pour réaliser notre application, nous avons uniquement pu utiliser du Scratch pour coder le fonctionnement de l'appli. Malheureusement ce langage de programmation sous forme de blocs entraine souvent de grosses suites de blocs pas toujours très lisibles. Nous allons donc essayer de vous expliquer clairement et simplement ce que nous avons réalisé pour chaque Screen.

  • Screen 1 : on affiche simplement le logo de Polybot pendant 4 secondes puis on ouvre le Screen suivant. La fonction "when clock1.timer" va permettre de synchroniser des actions (lance une sorte de chrono). Dans la partie interface, on peut choisir la fréquence de la Clock (par exemple 1s ou 200ms).
Code pour le Screen 1
  • Screen 2 : on initialise les variables globales qui nous indiqueront si les valeurs ont été cochées (1) ou décochées (0), c'est à dire si on souhaite les afficher par la suite ou non. On aura donc une variables globale pour chaque donnée à afficher (distance parcourue, tension, vitesse, position...).
Initialisation des variables globales

Ensuite, toutes les secondes on vient inspecter l'état des Checkbox pour voir si elles sont cochées ou non puis on modifie la variable globale correspondante en fonction de cela : 0 si décochée, 1 si cochée.

Modification des variables globales

On va ensuite stocker les valeurs de nos variables globales dans la base de donnée de l'application. Nous avons besoin de faire cela afin de pouvoir récupérer ces valeurs dans le Screen suivant. Une fois toutes les variables stockées correctement, on ouvre le Screen suivant.

Stockage des variables
  • Screen 3 : à l'ouverture du Screen on va récupérer les valeurs des variables globales dans la base de donnée. En fonction de leur valeur (0 ou 1) on rendra visible ou non les données correspondantes. Par exemple, si la variable box_tension vaut 1 alors les valeurs de la tension seront rendues invisibles sur l'écran. On met donc toutes ces fonctions dans le bloc "when Screen3.initialize", c'est à dire qu'on passera une fois dans ce bloc lors du lancement du screen.
Récupération des variables globales
Visibilité de chaque valeur

On configure ensuite le bouton qui nous permet d'aller nous connecter au périphérique souhaité (ici notre module HC-06). Il affiche la liste des périphériques Bluetooth connecté, après en avoir sélectionné un on affiche "Périphérique Connecté".

Connexion au périphérique Bluetooth

Ensuite, on créé et on initialise une variable globale nommée flag (à ne pas confondre avec le flag envoyé par la STM) qui va nous permettre de bien synchroniser la réception des données. En effet, à chaque parcours de boucle on ne veut recevoir qu'une seule donnée (par exemple la tension) et au tour de boucle suivant, on affichera la donnée suivante uniquement (par exemple la vitesse). Et afin de synchroniser parfaitement l'envoi et la réception on commence détecter la réception d'une donnée précise (le flag de la STM) valant -9999. Nous avons choisi cette valeur car elle ne pourra jamais être atteinte par aucune des données affichées donc pas d'erreur possible. Une fois qu'on a reçu cette donnée valant -9999 on sait que les données reçues ensuite seront, dans l’ordre, la distance parcourue (encodeurs), la tension de la batterie, la vitesse, la position x et la position y. On chaque fin d'un tour de boucle, on incrémente le flag.

Réception et affichage des données

Stockage des données

Le reste des fonctions créés sont utiles pour le stockage.

  • On commence par initialiser la variable texte "fichier" qui correspond au chemin d'accès au fichier de stockage : "stockage_data_robot.csv". Si la variable globale "stockage" vaut 1 (c'est à dire si l'utilisateur à coché la case stockage) alors on va aller lire ce fichier grâce à la fonction ci-dessous.
Indication du chemin d'accès au fichier
Lecture du fichier "stockage_data_robot.csv"
  • Une fois que le fichier a été lu (Fichier.GotText = 1) alors on lance la fonction "nettoyer_fichier".
Appel à la fonction "nettoyer_fichier"

Cette fonction détaillée ci-dessous permet de nettoyer le fichier .csv à chaque nouveau lancement de l'application. En effet, à chaque nouveau lancement on va aller supprimer les données stockées précédentes. Si on veut stocker les données précédents il faudra alors faire des screen ou alors copier les données avant que celles-ci soient supprimées.

Fonction "nettoyer_fichier"

Dans cette fonction "nettoyer_fichier", on commence par remplacer le fichier .csv par une liste vide puis on ajoute ensuite une ligne contenant les noms des valeurs (tensions, vitesse..etc). Enfin, on sauvegarde la nouvelle ligne.

  • On a ensuite créé la fonction "stockage_data" que l'on appelle à chaque début d'une nouvelle boucle d'envoi de données (c'est à dire juste après le flag qui signifie qu'on se trouve au début de la boucle). On va ainsi pouvoir ajouter les données dans le fichier stockage à chaque nouveau cycle d'envoi de données.
Appel à la fonction "stockage_data"

Voici comment est composé la fonction "stockage_data" :

Fonction "stockage_data"

Dans cette fonction, on créé une ligne qui va contenir toutes les nouvelles données mises à jour puis on sauvegarde la ligne dans le fichier de stockage.

Explication du code et lien vers le Git

Explication du Code STMCubeIDE

Comme nous l'avons expliqué dans le rapport nous avons utilisé les fonctions suivantes dans notre code sur STMCubeIDE ;

HAL_UART_Transmit_IT(&huart4, (uint8_t*) txt_a_envoyer,sizeof(txt_a_envoyer));
HAL_Delay(temps) qu'on remplacera par osDelay(temps) avec l'utilisation de FreeRTOS

La fonction HAL_UART_Transmit permet de transmettre une chaine de caractère sur l'UART souhaité. Les fonctions HAL_Delay et osDelay permettent d'ajouter un temps d'attente entre les différents Transmit afin de laisser suffisamment de temps au microcontrôleur pour envoyer les données.

Réglage des paramètres de l'UART4

On pourra ainsi envoyer des données et aller les récupérer via un terminal (connecté au module Bluetooth) ou a une application.

Réception des données

Pour rappel, nous avons affichés à l'écran les données suivantes :

  • Tension de la batterie
  • Distance parcourue
  • Vitesse du robot
  • Coordonnées du robot (position x et y)


Pour transmettre les différentes valeurs souhaitées, nous avons ajouté dans le code de la STM les fonctions mentionnées plus haut. On envoie ensuite les données dans un ordre précis : on commence par envoyer le flag qui va nous permettre de marquer le début de chaque nouveau while, nous avons choisi de lui donner la valeur -9999 car cette valeur ne peut être atteinte par aucune autre données que nous affichons. Il n'y a donc pas de problème possible de ce côté là. Ce flag nous sera utile pour la suite car cela signalera à l'application qui réceptionne les données quand nous serons au début de la boucle while du code. Cela permet donc de synchroniser l'envoi des données. On convertit ensuite chacune des valeurs a envoyer en texte afin de pouvoir les envoyer sous forme de texte à l'aide de la fonction sprintf.

  • On synchronise donc les données de manières temporelles, afin que l'application reçoive les données régulièrement et ait le temps de les traiter et de les afficher, d'où la présence de "osDelay" dans le code de la STM32. Il faut aussi accorder l'horloge de l'application afin qu'elle soit en phase avec le code de la STM32. Par exemple, si on choisit d'écrire dans le code de la STM "osDelay(200)" entre chaque Transmit alors on devra régler la Clock de l'application sur 200. Si on ne fait pas ça l'affichage ne sera pas synchronisé.
  • Concernant la valeur de la tension de la batterie, il faut récupérer cette valeur sur le bus CAN1 car elle est gérée par une autre STM32 qui communique avec la STM principale par bus CAN. La communication n'étant pas encore en place, nous ne pouvons pas encore récupérer la valeur de tension. De ce fait, nous retournons une valeur fixe de 17V. Lorsque la communication avec le bus CAN sera réalisée, il sera possible de modifier la fonction pour que l'on renvoie la valeur réelle de la tension.
  • Pour calculer la vitesse du robot, sa position et la distance parcourue, on a besoin de récupérer les valeurs renvoyées par les encodeurs. Les encodeurs nous indique précisément le nombre de tours qu'a réalisé chaque roue du robot. Ils sont gérés par un contrôleur MCP233 sur le robot, qui est connecté à l'UART1 de la STM. On doit donc récupérer les valeurs des encodeurs à travers l'UART1 et le MCP233. On utilise des fonctions déjà crées par les équipes de Polybot, à savoir :
uint8_t MCP233_readEncoderCountM1(MCP233_t *mcp, int32_t *count) 
uint8_t MCP233_readEncoderCountM2(MCP233_t *mcp, int32_t *count) 

Ces fonctions permettent de récupérer les valeurs d'incrémentation des encodeurs et les stockent à des adresses (int32_t *count). L'argument (MCP233_t *mcp) permet quant à lui de lire dans le contrôleur MCP233.

  • Afin d'obtenir les différentes données à envoyer, à savoir la vitesse, la distance parcourue, ainsi que la position (x,y) du robot, nous devons mettre en place des calculs spécifiques. On notera que l'on ne peut pas reset les encodeurs au début de chaque boucle (plus facile pour calculer la différence de tour par rapport à la boucle précédente) car ceux ci servent aussi à asservir les moteurs du robot en position. On va donc d'abord mettre en place quelques lignes permettant de faire nos calculs comme si nous avions un reset des encodeurs. On commence par stocker les valeurs des encodeurs avant que ceux ci soient mis à jour avec la fonction de lecture des encodeurs, on récupère ensuite les nouvelles valeurs puis on réalise la différence entre ces 2 valeurs. On obtient alors le nombre de tours en plus (ou en moins dans le cas d'une marche arrière) par rapport au while précédent.
encRg_save = encRg + encRg_save; //encRg_save et encRd_save sont définis ici pour être la valeur des encodeurs avant le relèvement des encodeurs
encRd_save = encRd + encRd_save;
MCP233_readEncoderCountM1(&mcp,&encRg); //relèvement de la valeurs des encodeurs et mises dans encRg (encodeur gauche)
MCP233_readEncoderCountM2(&mcp,&encRd); //relèvement de la valeurs des encodeurs et mises dans encRd (encodeur droit)
encRg = encRg - encRg_save; //on corrige ici encRg et encRd pour qu'ils correspondent aux valeurs d'encodeurs d'un cycle (et non total)
encRd = encRd - encRd_save;

On en vient maintenant aux calculs en eux même. Pour la distance totale parcourue, on met en place des variables qui calculent le cumul des incréments des encodeurs depuis le démarrage du robot, on calcule ensuite la moyenne des valeurs (des 2 encodeurs) afin d'obtenir la distance parcourue par le centre du robot. Finalement, on vient multiplier cette résultante par 2*pi*R/incr (incr étant le nombre incréments de l'encodeurs lorsqu'il effectue un tour et R le rayon des encodeurs). Dans notre cas on aura incr = 4096 et R=44mm.

distRd = distRd + encRd;  //calcul de la valeur total de l'encodeur droit depuis le démarrage du robot
distRg = distRg + encRg;  //calcul de la valeur total de l'encodeur gauche depuis le démarrage du robot
distTot = ((M_PI*2*R/incr)*(distRd+distRg))/2;  //à noter que le résultat est en mm ici //calcul de la distance totale

Pour la vitesse, on doit d'abord calculer la distance parcourue par le robot entre 2 prises de valeurs d'encodeurs, afin d'avoir une vitesse le plus instantané possible. On calcule donc cette distance exactement de la même manière que précédemment sauf qu'on ne cumule pas les valeurs d'incréments des encodeurs, en effet, on veut ici les valeurs d'incrémentation momentanées. On vient ensuite faire un rapport dist/time (dist étant la valeur que l'on vient de calculer, time étant le temps d'exécution d'une boucle d'envoie des données, on estime sa valeur par rapport aux "osDelay") :

dist = (M_PI*2*R/incr)*((encRd+encRg)/2); //en mm   
speed = (dist/time)*100; // en cm/s   

Pour la position (x,y) du robot, on calcule d'abord l'angle du robot par rapport à son angle d'origine :
angle = ((M_PI*2*R/incr)*((distRd-distRg)/LargRobot)); //angle en radian On calcule ensuite les positions x et y en faisant respectivement le cosinus et sinus de l'angle multiplié par la distance parcourue entre 2 relevés d'encodeurs auxquels on ajoute les positions precédentes afin de pouvoir voir le robot se déplacer comme s'il était dans un repère orthonormé :

posx = (cos(angle)*dist)+posx;   //posx en mm  
posy = (sin(angle)*dist)+posy;   //posy en mm  
  • On en vient maintenant à l'envoie des données. On commence par concaténer nos valeurs à envoyer dans des buffer char grâce à la fonction sprintf :
sprintf(buff_enco,"%5d",(int)distTot);    // distance parcourue en mm  
sprintf(buff_tens,"%5d",(int)Voltage);    // pas encore opérationnel   
sprintf(buff_vit,"%5d",(int)speed);   
sprintf(buff_posx,"%5d",(int)posx);    // en mm   
sprintf(buff_posy,"%5d",(int)posy);    // en mm   

On passe ensuite à l'envoie. On utilise la fonction mise à disposition par l'outil STM32CubeIDE :

HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);   

L'argument (UART_HandleTypeDef *huart) sert à sélectionner l'uart sur lequel est branché notre module HC-06
L'argument (uint8_t *pData) est celui sur lequel on va rentrer notre buffer où est contenue la données (on mettra (int8_t*)buffer car la fonction attend un buffer en int8_t* alors que notre buffer est en format char de base).
L'argument (uint16_t Size) sert à spécifier la taille du buffer : sizeof(buffer)
On établit donc le code que l'on va utiliser pour envoyer :

HAL_UART_Transmit_IT(&huart3, (uint8_t*) buff_enco,sizeof(buff_enco)); // encodeurs
osDelay(200);
HAL_UART_Transmit_IT(&huart3, (uint8_t*) buff_tens,sizeof(buff_tens)); // tension batterie
osDelay(200);
HAL_UART_Transmit_IT(&huart3, (uint8_t*) buff_vit,sizeof(buff_vit)); // vitesse robot
osDelay(200);
HAL_UART_Transmit_IT(&huart3, (uint8_t*) buff_posx,sizeof(buff_posx)); // position x
osDelay(200);
HAL_UART_Transmit_IT(&huart3, (uint8_t*) buff_posy,sizeof(buff_posy)); // position y
osDelay(400);

Récupérer le code général

Pour pouvoir accéder au code général du robot vous devez :

  • Créer un compte GitLab
  • Contacter le responsable de Polybot (Errikos Messara) pour qu'il vous donne l'accès aux Git de Polybot
  • Accéder au dossier concerné
  • Télécharger le master
  • Ouvrir le dossier avec STMCubeIDE


Si vous souhaitez uniquement regarder la tâche relative à notre partie du projet, vous pourrez la trouver sous format .txt au lien suivant : Code .txt

Utilisation des modules Bluetooth HC-06

Changer le nom, le mot de passe, ou le baudrate des modules HC-06

Logo arduino.png

Pour modifier le nom, le mot de passe ou le baudrate des modules Bluetooth vous aurez besoin d'une carte Arduino Leonardo.

Suivez ensuite les consignes expliquées sur ce lien : http://idehack.com/blog/configurer-le-module-bluetooth-hc-06/

Pour le moment, les 2 modules se nomment : Polybot_Robot1 et Polybot_Robot2; leur mot de passe est sur le Drive Polybot; et le baudrate est a 115200. Pour changer le baudrate la commande a taper sur le moniteur série d'Arduino IDE est : AT+BAUDx

Ex: si vous voulez changer le baudrate en 9600 tapez AT+BAUD4. Le module devrait répondre OK9600. (Note: 1 pour 1200, 2 pour 2400, 3 pour 4800, 4 pour 9600, 5 pour 19200, 6 pour 38400, 7 pour 57600, 8 pour 115200).

Câblage des modules sur la STM32

Concernant le montage du montage sur la STM32, il suffit de brancher les 4 pins du module sur la STM32 de la façon suivante :

Pin HC-06 Pin STM32
VCC 5V
GND GND
RXD PA0 (UART4)
TXD PA1 (UART4)

Voir et traiter les données enregistrées - Tracer la trajectoire du robot

Pour visualiser les données que vous avez enregistrées :

  • Ouvrir l'application "Cx Explorateur de fichiers" (ou connecter votre périphérique à un PC)
  • Ouvrez le dossier "AppInventor" puis "asset"
  • Cliquez ensuite sur le fichier "stockage_data_robot.csv" pour lire les données enregistrées au format .csv

Pour traiter ces données et les afficher dans un tableau par exemple :

  • Branchez vous téléphone sur un PC
  • Ouvrez sur le PC le fichier "stockage_data_robot.csv" qui se trouve dans le dossier AppInventor/asset de votre téléphone
  • Sélectionner le tableau de données en entier
  • Cliquer sur "Données" puis cliquer sur "Convertir" et choisir : délimité, virgule, identif de texte ", standard puis TERMINER
  • Sélectionnez les colonnes de pos x et pos y
  • Cliquez sur "Insertion nuage de point" et vous obtiendrez le tracé de votre trajectoire

REMARQUES :

  • Vous ne pourrez pas enregistrer le fichier modifié, il faudra l'enregistrer sous un autre nom et un autre format.
  • A chaque nouveau lancement de l'application, les données précédentes sont supprimées. Si vous souhaitez les conserver pensez donc à copier-coller le fichier quelque part.
  • En cas de problème, vérifiez bien que vous cocher bien bouton "Stockage" lors du lancement de l'application.

Idée : communication entre 2 modules (1 sur chaque robot)

Une idée intéressante serait de fixer un module sur chaque robot pour les faire communiquer entre eux pendant la compétition. Nous avons donc réfléchi à cela est voici les contraintes que nous avons trouvées:

  • Un module Bluetooth peut être connecté à un seul périphérique à la fois. Donc si on veut faire communiquer les robots entre eux + recevoir les données sur l'application, il faudrait installer 2 modules Bluetooth sur chaque robot (1 pour la communication avec l'autre robot et 1 pour la communication avec l'application).
  • Le module Bluetooth HC-06 ne fonctionne que comme un esclave (il ne peut pas être pas être maître) il ne pourra donc pas envoyer d'ordre à un autre module. Dans ce cas, il faudra que les modules utilisés pour faire communiquer les 2 robots entre eux soit des modèles HC-05; qui fonctionnent en maître/esclave (contrairement au HC-06).
  • Une fois ces conditions réunies il devrait être tout a fait possible de réaliser une communications entre les 2 robots.