Aller au contenu


Contenu le plus aimé


Réseaux de neurones & algorithme génétique d'apprentissage

Publié Harry le 24 mai 2011 - 08:26 in Intelligence Artificielle

Après de longs mois d'inactivité, je suis de retour avec ce petit tutoriel qui vous donnera - je l'espère - le goût du développement d'intelligence(s) artificielle(s). L'objectif de ce tutoriel est de vous expliquer le fonctionnement d'un "cerveau" pour que vous puissiez en développer un pour votre robot, de telle sorte qu'il apprenne de lui-même à éviter les obstacles... Vous avez bien lu : le robot que je vous propose d'étudier pourra éviter les obstacles après avoir appris à le faire, tout seul !

Bref, passons directement dans le vif du sujet !

Sommaire :

1. Constitution du robot
2. Établissement manuel du réseau de neurone
3. Algorithme génétique d'apprentissage

Constitution du robot

Partie "hardware"

Voici les principaux composants de notre robot
 
 
  •  
  • en vert : 2 moteurs à courant continu
  • en jaune, orange et rouge : 6 capteurs de distance
  • non représenté : un micro-rupteur (= interrupteur) qui se déclenche si le bord du robot touche un obstacle.

Image IPB

Je ne détaille pas l'alimentation, l'électronique employée, etc... l'objectif de ce tutoriel étant de comprendre le fonctionnement des réseaux de neurones : ce tutoriel sera donc applicable à n'importe quel robot ayant cette configuration et pouvant être programmé à vos souhaits.

Partie "software" : le réseau de neurone proprement dit

Un réseau de neurone relie les entrées d'un système à ses sorties.

Image IPBLes entrées et les sorties sont appelés des nœuds. Le "lien" qui relie deux nœuds est appelé un axiome. Ceci n'est donné qu'à titre informatif, il n'est pas indispensable de retenir ce vocabulaire pour comprendre ce tutoriel.

Voici un schéma détaillant la notation que l'on va utiliser pour repérer les capteurs et les moteurs :

Image IPB

J'en ai profité pour dessiner notre premier réseau de neurone. Pour simplifier la compréhension, on ne va s'intéresser qu'au moteur gauche de notre robot.

On distingue clairement sur ce schéma - grâce aux traits en gras - que toutes les entrées (les Ci) sont reliées au moteur (M1). Sur chaque lien, on peut voir d'autres notations : P11, P21, P31, P41, P51 et P61 (ou encore les Pik - P indice i indice k - avec i allant de 1 à 6, et k valant 1 puisqu'on n'étudie que le moteur gauche) C'est ce qu'on appelle les poids. Grâce à ces notations, voici l'équation du réseau de neurone que l'on vient de créer - pour le moteur gauche uniquement :

Image IPB

Les valeurs des capteurs sont données par les capteurs eux-même, en fonction de la distance qui les séparent d'un obstacle extérieur. Les valeurs des moteurs sont contrôlées par le logiciel qui est sur votre robot... ici, il sera contrôlé grâce au réseau de neurone, dont on a écrit l'équation juste au-dessus. Il nous manque donc plus qu'à connaître les valeurs des poids (Pik)... c'est justement ces poids que le robot doit apprendre à déterminer, de lui-même ! Pour comprendre comment lui faire faire cela, nous allons d'abord essayer de voir quelles valeurs pourraient fonctionner pour nos Pik, pour que notre robot puisse éviter les obstacles...

Établissement manuel du réseau de neurone

Comportement désiré

Pour que tout le monde suive, on va mettre à plat le comportement du robot. Le robot doit toujours avancer, sauf dans les cas suivant :

  •  
  • si un obstacle se présente sur la gauche, le robot doit tourner à droite (c'est à dire que le moteur gauche doit "avancer" - tandis que le moteur droit doit "reculer")
  • si un obstacle se présente sur la droite, le robot doit tourner à gauche (c'est à dire que le moteur gauche doit "reculer" - tandis que le moteur droit doit "avancer")
Et si un obstacle se présente au centre ? Ceci est un faux problème car les capteurs ne donneront jamais constamment la même valeur à droite et à gauche : on rentrera donc systématiquement dans un des deux cas précédents. Si vraiment cela devait arriver, je suis sûr que vous saurez palier à ce problème une fois que vous aurez compris comment faire un réseau de neurone. Mais pour l'instant, on va simplifier les choses : aucun obstacle ne se présentera pic poil au milieu, et le robot ne PEUT PAS se planter (admettez-le, ou remettez ce problème à plus tard... ne restez pas bloqué à cause de ce cas).

Nous allons donc traiter ces deux cas, l'un après l'autre, ce qui nous permettra de donner des valeurs fonctionnelles pour P11, P21 et P31 d'une part, puis P41, P51 et P61 d'autre part.

Si un obstacle se présente sur la gauche...

... dans ce cas, les capteurs de gauche, C1, C2 et C3 auront une valeur importante (les capteurs de distance renvoie une valeur d'autant plus importante que l'obstacle est proche). Or, on voulait que si un obstacle se présente à gauche, le moteur gauche devait avancer... pour cela, on doit lui envoyer une valeur positive. Je rappelle notre équation du RdN (réseau de neurone) :

Image IPB

Vu ce que l'on cherche à faire, le plus simple pour répondre à cette demande serait - en premier lieu - d'imposer P11 = 1, P21 = 1 et P31 = 1 (ce sont des valeurs possibles). Notre équation devient donc :

Image IPB

Image IPBOui, mais attends, tu en fais quoi des valeurs des 3 autres poids ?

Je ne les ai pas oublié, soyez patients !

Si un obstacle se présente sur la droite...

... alors là, à l'inverse, ce sont les capteurs C4, C5 et C6 qui auront une valeur importante. Or, on voulait que si un obstacle se présente à droite, notre robot doit tourner à gauche, et pour cela, le moteur gauche doit "reculer"... pour cela, il faut lui envoyer une valeur négative. Vous l'aurez compris, on va imposer P41 = -1, P51 = -1 et P61 = -1. Ainsi :

Image IPB

Pour ceux qui auraient des doutes...

Image IPBAttends c'est n'importe quoi ce que tu fais là ! Tu détermines les valeurs de la moitié des poids pour un cas, et l'autre moitié avec un autre cas ! Ca ne pourra jamais marcher... !!!

Je conviens que la méthode employée n'est pas très catholique : cependant, cela fonctionne ! Vérifiez par vous-même... si un obstacle arrive à gauche, C1, C2 et C3 auront une valeur importante, et C4, C5 et C6 auront une valeur faible... d'autant plus faible que l'objet est loin, voire nulle si l'objet est à l'infini... on peut donc considérer que dans le cas où un obstacle arrive sur la gauche, seules les valeurs de C1, C2 et C3 sont pris en compte... et regardez l'équation dans ce cas là :

Image IPB !!! notre moteur gauche va donc "avancer" !

Et ça marche aussi si un obstacle arrive à droite : C1, C2 et C3 sont faibles cette fois-ci, voire négligeable... alors que C4, C5 et C6 auront une valeur importante, et dans ce cas, l'équation devient :

Image IPB !!! notre moteur gauche va donc "reculer" !

Et le moteur droit alors ?

Cela pourrait faire un très bon exercice... je vous laisse chercher (il suffit de suivre exactement le même schéma que précédemment), mais voici la réponse :

Image IPB

Algorithme génétique d'apprentissage

Introduction

Nous avons créé un réseau de neurone, et nous avons trouvé des valeurs possibles pour les poids de ce réseau. Je vous avais pourtant dit au début que votre robot allait apprendre à le faire de lui-même ! Vous aurais-je menti ? Non, mais je voulais que vous ayez bien compris la constitution d'un réseau de neurone et son fonctionnement. Maintenant que cela est fait, nous allons imaginer que nous ne connaissons pas les valeurs de ces poids, et nous allons faire faire ce dur labeur à notre robot.

Image IPBAttends, c'est complètement idiot de faire ça ! On connaît des valeurs qui marchent, pourquoi ne pas lui donner directement les valeurs et tester ?

Vous avez raison : vous pouvez tester ces valeurs sur votre propre robot. Et ça marchera. Très bien même. Et puis vous aurez deux possibilités :
 
  •  
  • vous êtes content de ce que vous avez appris et cela vous suffit : dans ce cas, merci d'avoir lu ce tutoriel et au revoir ! Bonne journée !
  • vous avez envie d'en apprendre plus, en particulier sur l'algorithme génétique d'apprentissage, et vous avez même envie que l'apprentissage se fasse le plus simplement possible : dans ce cas, je vous invite à lire la suite
Et pour ceux qui trouvent que c'est dommage de rester sur le même exemple - déjà résolu qui plus est - pour apprendre le fonctionnement de l'algorithme génétique d'apprentissage, je répondrai ceci : c'est un choix que j'ai fait en toute connaissance de cause. En effet, si on reste sur un exemple déjà bien connu, les termes que je vais employer auront un aspect "concret", tandis que si je pars sur un autre exemple, ce sera un peu plus subjectifs, et certains risquent de ne pas suivre.

Je vous invite donc à rentrer dans le vif du sujet de cette grosse bête qui paraît si méchante... et qui ne l'est pas du tout en fait o_O

Algorithme d'apprentissage simple

Le principe de l'apprentissage simple est le suivant : on choisit des valeurs aléatoires pour les poids, puis le robot le teste de lui-même. Pour qu'il puisse les tester, on va lui dire d'utiliser un capteur qu'on n'a pas encore utilisé, mais que j'ai indiqué au tout départ, souvenez vous :
Citation de : Harry
Citation

Voici les principaux composants de notre robot
  •  
  • en vert : 2 moteurs à courant continu
  • en jaune, orange et rouge : 6 capteurs de distance
  • non représenté : un micro-rupteur (= interrupteur) qui se déclenche si le bord du robot touche un obstacle.
Nous allons donc demander à notre robot d'utiliser ce micro-rupteur : si celui-ci se déclenche, cela voulait donc dire que les valeurs de nos poids (choisis aléatoirement) étaient "mauvais". Il faut donc faire un autre "jet" (c'est à dire qu'on va choisir d'autres valeurs aléatoires pour les poids). Et ainsi de suite... jusqu'à ce que le robot évite tous les obstacles !

Image IPBAttends... mais ça peut prendre un temps fou ça !

Oui, mais observez un bébé qui apprend à attraper un verre : un coup, sa main passe au dessus, le coup d'après sa main se cogne contre la table ("ouille" :mort: "ouinnnn" Image IPB ), le coup d'après il envoie le verre sur la lune (là, c'est le papa qui n'est pas content :colere: -> fessée)... puis après en avoir cassé plusieurs, il arrive enfin à l'attraper ! Tout cela prend du temps ! Si vous voulez, vous pouvez créer un "simulateur de robot" qui pourra vous permettre de tester votre algorithme pour obtenir la valeur des poids plus rapidement ^^

Algorithme génétique d'apprentissage

On a failli oublié la partie "génétique" dans tout ça dites donc... meuh non, ne vous inquiétez pas ! Image IPB

Cependant, la partie "génétique" est tellement simple que j'ai honte de la détailler... faisons le tout de même. Dans la partie précédente, on a effectué une série de jets sur les poids.

Ce que l'on va faire maintenant, c'est d'enregistrer une dizaine de jet, et, pour chaque jet, lancer notre robot dans une arène pendant disons une dizaine de minute. Puis on regarde les résultats obtenus pour le nombre de fois où le robot s'est cogné pour chaque jet. La "sélection génétique" de cette "génération" va consister à sélectionner le jet qui aura obtenu le meilleur score, c'est à dire le jet pour lequel le robot s'est cogné le moins souvent.

Puis on passe à la génération suivante : cette génération est issu du jet "sélectionné". Je veux dire par là qu'au lieu de faire des choix aléatoires pour tous les poids à chaque nouveau jet, on va en conserver 1 (d'une manière aléatoire, mais on en conserve au moins 1 du jet "parent" pour chaque nouveau jet). Puis on re-fait nos tests, et on refait une sélection du meilleur.

A la génération suivante, on va conserver cette fois-ci 2 valeurs de poids...

A la génération suivante, on va en conserver 3...

et ainsi de suite...

Petit à petit, vous verrez que les enfants issus des "meilleures" sélections auront les mêmes comportements que ceux de leurs parents, mais améliorés (les parents ont transmis leur "savoir" à leurs enfants qui à leur tours font leur vie et enseignent ce qu'ils ont appris à leurs enfants).

Je trouve ce concept passionnant et pourtant d'une facilité déconcertante une fois qu'on a compris de quoi il s'agissait, n'est-ce pas ?

N'hésitez pas à poser vos questions sur le forum !


Montage d'un Rocbot.

Publié ashira le 13 novembre 2017 - 08:50 in Robot complet

Aide au montage du Rocbot.

 

rocbot3.gif  rocbot1.gif  rocbot2.gif

 

Ce tutoriel vous aidera à construire votre rocbot en illustrant un exemple de montage pas à pas.
Le montage se fait en 2 étapes :
 

  • Montage des éléments électroniques et mécaniques.
  • Programmation du robot.

 
Pour le montage j'ai utilisé :
 

  • Un fer à souder et de l’étain.
  • Une petite pince à bec.
  • Une petite pince coupante.
  • Un tournevis cruciforme.

 Fichier 3D:
Fichier attaché  Rocbot_stl_1.00.zip   350,3 Ko   323 Nombre de téléchargements

Fichier attaché  Rocbot_stl_1.01.zip   426,62 Ko   190 Nombre de téléchargements
 
Programme:
Fichier attaché  Rocbot_BT.zip   499 octets   217 Nombre de téléchargements
 
Première étape : Montage des éléments électroniques et mécaniques.
 
Je commence par souder une arduino pro mini sur le pcb avec des broches. J'utilise la pince à bec pour enfoncer les broches comme sur la photo.
 
1.jpg
 
Le but est de souder ces connecteurs sur l'arduino par le dessus et de garder une longueur suffisante pour connecter autre chose directement sur l'arduino.
 
Je soude les connecteurs 3 par 3 pour pouvoir enlever facilement le plastique noir.
 
2.jpg 3.jpg
 
4.jpg
 
Ensuite je soude l'arduino pro mini sur le pcb.
 
5.jpg
 
Soudure des 3 connecteurs qui serviront à brancher les servomoteurs et du petit condensateur (il n'y a pas de polarisation sur ce condensateur).
 
6.jpg
 
Soudure des connecteurs femelles. 
 
7.jpg 8.jpg
 
9.jpg 10.jpg
 
Maintenant je soude l'autre pcb, en commençant par le chargeur de batterie.
 
11.jpg
 
Soudure de l'interrupteur et des connecteurs mâles.
 
12.jpg
 
13.jpg 14.jpg
 
Soudure de la batterie. 
 
15.jpg 16.jpg
 
17.jpg
 
J'ai fixé la batterie avec un morceau de scotch double face, mais ce n'est pas obligatoire. La partie montage électronique est terminée, je vais monter tout ça sur le châssis du robot .
 
Je commence par visser les 2 supports en nylon.
 
18.jpg
 
Ensuite je fixe le premier pcb avec 2 autres supports en nylon, plus grands que les premiers.
 
19.jpg
 
J'ajoute le 2eme pcb et je le fixe avec 2 visses en nylon. Entre temps on remarque que j'ai ajouté un connecteur femelle sur le premier pcb.
 
20.jpg
 
Je monte les roulements avec une vis et une rondelle montées comme sur la photo.
 
21.jpg
 
Pour monter les barbotins arrières il suffit d'enfoncer les roulements à l’intérieur.
 
J’insère 2 servomoteurs en faisant passer les câbles dans les fentes. On peut les laisser montés serrés ou les fixer à la colle ou avec des petites vis.
 
22.jpg
 
Pour monter les barbotins de devant, j'ai coupé les palonniers des servomoteurs comme sur la photo qui suit.
 
23.jpg
 
Un aperçu du dessus.
 
24.jpg
 
Maintenant je m'occupe du système de tir. J'utilise une vis et un écrou en nylon avec un ressort que je coupe en deux.
 
25.jpg
 
Et je monte le tout de cette manière :
 
26.jpg
 
Je m'aide de la pince et du tournevis.
 
27.jpg
 
Ensuite je coupe un palonnier en forme d'hélice pour le servomoteur de tir.
 
28.jpg
 
Je fixe ce servomoteur avec de la colle ou des vis.Je monte les maillons de chaînes ensembles (16 maillons pour une chaîne) puis je monte les chaînes de chaque côté.
 
29.jpg 30.jpg
 
Dans cet exemple, je choisis de contrôler mon rocbot par bluetouth. Je soude le connecteur du module bluetouth de cette manière :
 
31.jpg
 
Et je le monte sur le robot :
 
32.jpg
 
 
Deuxième étape : programmation du robot.
 
 
Pour connecter le robot au PC, j'utilise un convertisseur FTDI. Pour le sens du branchement : « DTR » à droite, « GND » à gauche.
 
33.jpg
 
Ensuite ouvrez le programme « Rocbot_BT » et dans « outil » sélectionnez la bonne carte arduino et le port COM correspondant.
Téléverser le programme:
 


Pour contrôler le robot j'utilise l'application Bluetouth electronics.
 
34.jpg
 
Installez l'application et configurez votre télécommande, placez un pad et un bouton poussoir.
 
35.jpg
 
Réglez le bouton poussoir comme si dessous en appuyant sur « Edit » en bas à droite de l'écran.
 
36.jpg
 
Ensuite après avoir appairé votre smartphone avec le module hc-05, connectez vous au module avec l'application.
 
37.jpg
 
Démarrez votre télécommande en appuyant sur « run ».
 
38.jpg
 
Vous pouvez maintenant contrôler le robot !
 
 
39.jpg




RobArchi X.XX

Publié Gyro49 le 28 janvier 2017 - 03:09 in Robot complet

Si comme moi vous avez interdiction de faire rouler vos créations dans la maison sous peine d'entendre "Qu'est-ce que c'est que ce truc qui fait du bruit" ou encore "J'ai encore faillit marcher dessus va dehors".
 
Seule solution, en effet, faire rouler mes projets dehors.
 
Problématique d'un robot d'extérieur
 
La garde au sol doit être plus grande que les herbes du jardin.
J'ai bien réalisé un premier projet, mais avec sa garde au sol inférieur à 2 cm, il est juste bon à rouler sur la terrasse.
 
Mots-clés
 
Raspberry, atmega328, ardiuno, batterie 12v, L298N, motoréducteur, I2C
 
Objectifs principaux
 
Disposer d'une base évolutive et pouvant se déplacer en extérieur.
 

 
RobArchi X.XX
 
P1040221.JPG
 
La liste des courses
 
C'est une liste très réduite, il faudra forcément des vis, un clou, des résistance et des condensateurs, sinon principalement il faut :

raspberry pi                                                     50€00 amazon
atmega328P                                                      6€00 amazon
plaque stripboard de 50 x 12cm                      21€00 (chez mon fournisseur local)
deux roues de diam 25cm                               38€00 bricodepot
connecteur à souder                                         2€60 hobbytronics
deux moteurs à engrenage                             35€00  sud-import-express.com
deux engrennages                                            6€00  amazon
deux motoréducteurs                                       14€50 amazon
un L298N                                                          3€52 amazon
une plaque de médium prédécoupé                 5€00 leroymerlin
une batterie 12v 7Ah                                       20€00 amazon
i2c level shifter                                                   4€00 hobbytronics
 
La partie bois
 
Dans la plaque de bois de 80 x 60 cm il faut placer:
- un cercle de 50 cm de diamètre;
- deux rectangles de 13 x 28,2 cm;
- un rectangle de 19 x 12,4 cm
plaque.png
 
Puis dans les rectangles de 13 x 28,2cm. Cette plaque accueillera le moteur.
coté.png
 
Pour finir, afin que les cotés restent perpendiculaire avec le fond du robot il y a une plaque au centre. Les trois gros trous sont là uniquement des passes câbles, donc d'un diamètre libre. 
Attention dans le bas de cette plaque il faudra casser les angles (non dessiné) avec une râpe à bois.
milieu.png
 
Les moteurs + roues
 
De base, le bloc tourne en sortie de réduction à 400 tr/min ce qui est trop important pour le projet.
Le moteur est alimenté en 12V et il a un diamètre de 38mm (3,8cm).
 
P1040222.JPG
 
J'ai donc choisi de mettre à la place un motoréducteur avec 150tr/min en sortie d'arbre ce qui fera à la roue environ 4tr/min.
Je pense qu'un 250 tr/min aurait été plus judicieux.
 
Nouveau moteur et nouveau pignon prennent un axe différent par rapport à l'original. Avec un foret de 10mm il faudra faire un deuxième axe dans la coque plastique.
P1040224.JPG
 
Il faudra également ouvrir le capot du dessus pour laisser passer le pignon qui est trop gros. Ce n'est pas très joli mais il n'y a pas le choix.
P1040227.JPG
 
Pour le raccordement des moteurs, j'ai placé un condensateur 100 micro non polarisé entre les deux bornes d'alimentation.
 
Les roues font donc 25 cm de diamètre avec un axe de 20mm sur roulement à bille.
 
Pour le raccordement au moteur j'ai été au plus simple -> deux bouts de tuyau en PVC de diamètres 50mm et de longueur 5 cm et 4cm.
le tube 1: Le 5 cm sera relié à la roue après avoir fait des encoches.
le tube 2; Le 4cm il faut lui enlever sur la longueur une bande de 2cm environ puis le serrer pour le faire rentrer dans le tube 1 puis lui faire les encoches coté moteur.
P1040230.JPG
 
 
Comme vous pouvez le remarquer, l'axe de la roue c'est du 20mm et celui du groupe-moteur c'est du 12mm.
Donc acheter un tube de 12mm, une plaque de fixation métallique et faire un peu de soudure.
La plaque ne servant qu'au maintien du tube de 12 lors des démontages réguliers.
 
P1040234.JPG
 
A chaque extrémité du tube de 12mm j'ai insérer 8cm de tige filetée en laissant dépasser 15mm. Par la suite il faut percer le tube de par en par avec un foret le plus petit possible, en prenant la tige filetée. Un morceau de clou dans le trou fera office de clavette.
 
Il faut trouver de quoi combler l'espace entre le tube de 12mm et l'intérieur de l'axe de roue.
J'ai donc découpé 10cm d'un tube d'acier diamètre 20 et récupérer une cheville plastique de montage de mes WC suspendu. Il est possible d'utiliser un bout de tube PER d'alimentation en eau récupérer chez un ami qui fait de l'auto construction. Le reste du jeu pourra être comblé par du scotch renforcé.
 
L'électronique
 
Pour l'électronique, j'ai choisi d'utiliser une plaque à bande car tout le monde n'a pas forcément accès à une graveuse.
Donc une plaque stripboard de 17,5 x 12cm.
P1040212.JPG
 
Il faut faire quelques modifications en suivant les croix
stripboard.png
 
composants.png
 
Pour les vérifications j'ai suivi le tuto paperduino.
 
Attention, il ne faut pas oublier le strap sous le support de l'Atmega et les condensateur entourant le quartz sont de 22pf et non 22nf
 
Pour charger le code arduino j'ai suivi le tuto de chez Arduino
 
J'ai placé entre l'Atmega et le Raspberry un i2c level shifter car il travail respectivement en 5V et en 3,3V.
 
J'ai écarté légèrement les pattes du connecteur du raspberry car j'avais peur de faire de mauvaise soudure.
P1040216.JPG
 
Avec des straps, vous avez juste à relier les SDA et les SCL ensemble au travers du I2C level.
De plus la partie de droite sur la photo correspond aussi à la partie de droite sur le plan de grattage de la face cuivré.
J'ai placé à la suite un 7812,7809,7805 et un LD1086v33
P1040235.JPG
 
 
Les codes informatique
J'ai fait l'impasse sur le formatage de la Raspberry et sur l'installation de l'I2C.
 
il y a plusieurs version du code informatique.
Version X.01 -> Test de l'atmega pour le contrôle des moteurs
 
Avec le code suivant les roues vont dans un sens puis dans l'autre.
// moteur droit
int MD = 11;
int in1 =10;
int in2 = 9;
// moteur gauche
int MG =  6;
int in3 = 7;
int in4 = 8;
void setup()
{
  pinMode(MD, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(MG, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
}
void demoOne()
{ digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);//AVANCE
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);//AVANCE
  analogWrite(MD, 250);
  analogWrite(MG, 250);
 
  delay(8000);
  //ARRET TOTAL
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
 
}
void demoTwo()
{ 
  digitalWrite(in1, HIGH); //RECUL
  digitalWrite(in2, LOW);
  digitalWrite(in3, HIGH); //RECUL
  digitalWrite(in4, LOW);
  analogWrite(MD, 250);
  analogWrite(MG, 250);
  delay(8000);
 
  //ARRET TOTAL
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
}
void loop()
{
  demoOne();
  delay(1000);
  demoTwo();
  delay(1000);
}
Version X.02 -> Test de la connexion I2C entre la Raspberry et d'Atmega
 
Rien de bien compliqué, je tout copier/coller sur le net
 
Code Atmega
#include <Wire.h>

#define SLAVE_ADDRESS 0x12
int dataReceived = 0;

void setup() {
    Serial.begin(9600);
    Wire.begin(SLAVE_ADDRESS);
    Wire.onReceive(receiveData);
    Wire.onRequest(sendData);
}

void loop() {
    delay(100);
}

void receiveData(int byteCount){
    while(Wire.available()) {
        dataReceived = Wire.read();
        Serial.print("Donnee recue : ");
        Serial.println(dataReceived);
    }
}

void sendData(){
    int envoi = dataReceived + 1;
    Wire.write(envoi);
}
Code Raspberry
#!/usr/bin/env python
# coding: utf-8

import smbus
import time

# Remplacer 0 par 1 si nouveau Raspberry
bus = smbus.SMBus(0)
address = 0x12

print "Envoi de la valeur 3"
bus.write_byte(address, 3)
# Pause de 1 seconde pour laisser le temps au traitement de se faire
time.sleep(1)
reponse = bus.read_byte(address)
print "La reponse de l'arduino : ", reponse
Version X.03 -> Commande de RobArchi par ssh
Code Atmega
#include <Wire.h>

#define SLAVE_ADDRESS 0x12
String dataReceived;
String sens;
String angle;

// moteur droit
int MD = 11;
int in1 =10;
int in2 = 9;
// moteur gauche
int MG =  6;
int in3 = 7;
int in4 = 8;

void setup() {
    pinMode(MD, OUTPUT);
    pinMode(in1, OUTPUT);
    pinMode(in2, OUTPUT);
    pinMode(MG, OUTPUT);
    pinMode(in3, OUTPUT);
    pinMode(in4, OUTPUT);
    
    Serial.begin(9600);
    Wire.begin(SLAVE_ADDRESS);
    Wire.onReceive(receiveData);
    Wire.onRequest(sendData);
}

void loop() {
    delay(100);
}

void receiveData(int byteCount){
  dataReceived = NULL;
  int numOfBytes = Wire.available();
  Serial.print("len:");
  Serial.print(numOfBytes);

  byte b = Wire.read();  //cmd
  Serial.print("cmd:");
  Serial.print(b);
  Serial.print(" ");
   // Read serial input:
   for(int i=0; i<numOfBytes-1; i++){
     char c = (char) Wire.read(); // Recevoir un caractere
    dataReceived += (char) c; //Concateneer les caractères reçus
  }
  Serial.print("Donnee recue : ");
  Serial.println(dataReceived);
 
  int str_len = dataReceived.length() + 1;

  // Préparation d'un tableau à la longueur des données reçues
  char char_array[str_len];

  // Copie des données reçues dans le tableau
  dataReceived.toCharArray(char_array, str_len);
 
  // Recupération de la première données
  sens =strtok(char_array,",");
  Serial.println(sens);
 
  // Recupération de la deuxième données
  angle =strtok(char_array,",");
  Serial.println(angle);
 
  if(sens == "g") // G COMM GO DONC AVANCE
    {
    digitalWrite(in1, LOW);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, LOW);
    digitalWrite(in1, LOW);
    
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);//AVANCE
    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);//AVANCE
    
    analogWrite(MD, 250);
    analogWrite(MG, 250);    
    }
  else if(sens == "b") // B COMME BACK DONC RECUL
    {
    digitalWrite(in1, LOW);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, LOW);
    
    digitalWrite(in1, HIGH); //RECUL
    digitalWrite(in2, LOW);
    digitalWrite(in3, HIGH); //RECUL
    digitalWrite(in4, LOW);
    
    analogWrite(MD, 250);
    analogWrite(MG, 250);    
    }
  else if(sens == "l") // L COMME LEFT DONC GAUCHE
    {
    digitalWrite(in1, LOW);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, LOW);
        
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);//AVANCE
    digitalWrite(in3, HIGH); //RECUL
    digitalWrite(in4, LOW);
    analogWrite(MD, 250);
    analogWrite(MG, 250);    
    }
  else if(sens == "r") // R COMME RIGHT DONC DROITE
    {
    digitalWrite(in1, LOW);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, LOW);
    
    digitalWrite(in1, HIGH); //RECUL
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);//AVANCE
    
    analogWrite(MD, 250);
    analogWrite(MG, 250);    
    }
  else
    {
    //ARRET TOTAL
    digitalWrite(in1, LOW);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, LOW);
    }  
}

void sendData(){
  int str_len = dataReceived.length() + 1;

  // Préparation d'un tableau à la longueur des données reçues
  char char_array[str_len];

  // Copie des données reçues dans le tableau
  dataReceived.toCharArray(char_array, str_len);
 
  // Recupération de la première données
  char *envoi =strtok(char_array,",");
  Wire.write(envoi);
}
 
Code Raspberry
#!/usr/bin/env python
# coding: utf-8

import smbus
import time
import os

# display system info
print os.uname()

bus = smbus.SMBus(1)

# I2C address of Arduino Slave
i2c_address = 0x12
i2c_cmd = 0x01

def ConvertStringToBytes(src):
    converted = []
    for b in src:
        converted.append(ord(b))
    return converted

# send welcome message at start-up
bytesToSend = ConvertStringToBytes("S")
bus.write_i2c_block_data(i2c_address, i2c_cmd, bytesToSend)

# loop to send message
exit = False
while not exit:
    r = raw_input('Enter something, "q" to quit"')
    print(r)
    
    bytesToSend = ConvertStringToBytes(r)
    bus.write_i2c_block_data(i2c_address, i2c_cmd, bytesToSend)
    
    if r=='q':
        exit=True
Ca marche, se connecter au raspberry en SSH via le WIFI forcément.
Les commandes sont:
g-> avance
b-> recul
l-> gauche
r-> droite
 
A bientôt pour la version 1.XX qui aura une autonomie avec un capteur ultrason.


Robot Cocotix V2

Publié robocop le 09 mai 2010 - 09:23 in Robot complet

Ca y est, vous avez construit Cocotix, le petit robot coccinelle qui évite les obstacles.
Celui-ci vous a permis de débuter dans la robotique, de vous rendre compte des problèmes mécaniques et de découvrir l'électronique.

Mais voilà, maintenant, il faut progresser, et je vous propose maintenant une nouvelle version de Cocotix.
Ce robot sera un peu plus compliqué de réalisation que le précédent, car il intègrera un circuit imprimé.

Présentation du robot

Eh oui, ce nouveau robot sera capable de suivre la lumière, tout en évitant les obstacles.

Image IPBMais moi, je n'ai pas le matériel pour réaliser un circuit électronique !

Rassurez-vous, le schéma est très simple, et vous pourrez le réaliser sur une simple plaque d'essai en bakélite.

Image IPB
Alors, vous êtes tenté? C'est parti !

Une vidéo

Tout d'abord, je vous propose une petite vidéo du robot, de façon que vous puissiez voir quelles sont ses possibilités et ses fonctions :




Quelques informations techniques...

Pour ce robot, pas besoin de pic, d'atmel ou autres micro-contrôleurs. Toute la partie commande est analogique, à partir de simples transistors. Nous utiliserons des photo-résistances en guise de capteurs de lumière.

Liste des composants

Pour réaliser ce robot, vous aurez besoin de :

petits moteurs
1 interrupteur on/off
4 résistances de 100 ohms
2 résistances de 220 ohms
1 DEL rouge et 1 DEL verte
2 résistances variables de 10 k
2 microrupteurs (type switch)
2 transistors BC547C
2 photorésistances LDR
2 transistors BC557C
1 plaque de bakélite
2 supports à 2 piles AAA

Le schéma électronique

Le schéma électronique est assez simple à comprendre (cliquez sur l'image pour aggrandir le schéma):

Image IPB

Note : GND correspond au 0V ("-" de la pile) et VCC au +V ("+" de la pile).

Commençons par le système pour éviter les obstacles. Il est beaucoup plus simple que celui de Cocotix.

Image IPB
Le courant circule de "C" à "NC" quand l'interrupteur ne détecte pas d'obstacle : le moteur tourne normalement et le robot avance tout droit.

Maintenant, imaginons que l'interrupteur détecte un obstacle.

Le courant circule donc de "C" à "NO" ou plutôt, il ne circule plus, puisque "NO n'est branché à aucun fil".

Conclusion : le moteur s'arrête.
Les fils des interrupteurs seront comme dans la V1 du robot, croisés.

Ainsi, quand l'interrupteur de gauche rencontre un obstacle, le moteur droit s'arrête et le robot tourne à droite : l'obstacle est évité.

Voyons maintenant le système pour suivre la lumière.

Pour chaque commande de moteur, on utilise un transistor BC547C (de type NPN) et un transistor BC557C (de type PNP).

Image IPB

Voici donc l'effet que cela produit :
  • Quand le courant d'entrée (1) est élevé, le courant de sortie (2) est faible.
  • Quand le courant d'entrée (1) est faible, le courant de sortie (2) est élevé.
Ainsi, quand il y a peu de lumière dans une photo-résistance, il y a une forte résistance, et donc un faible courant d'entrée (1).

Résultat : le courant de sortie (2) est élevé et le moteur tourne rapidement.

Au contraire, quand il y a beaucoup de lumière dans une photo-résistance, le courant d'entrée (1) est élevé et le courant de sortie (2) est faible.

Le moteur tourne doucement voir s'arrête : le robot se dirige vers la lumière !

Partie électronique

Nous allons réaliser la carte électronique sur une plaque de bakélite.
Vous pouvez vous aidez de ce schéma, si vous avez du mal à comprendre le schéma vu précédemment :
Image IPB
Un immense merci à Alex93 pour la réalisation de cette image !
Image IPB

Il faut mettre les composants sur la face sans pastille et les souder du côté pastille.

Ensuite, on réalise les pistes en étalant de l'étain sur les pastilles.

Voilà, maintenant que vous avez compris, à vous de jouer.

Image IPBSerrez au maximum : la taille de votre robot dépendra de la taille de votre circuit !

Voilà le mien :

Image IPB

J'ai tellement voulu serrer les composants que l'on ne voit pas grand-chose o_O .

Assemblage des pièces

Cette fois-ci, le support n'est plus un calendrier en carton, mais une plaque de P.V.C.
Ainsi, le robot gagne en solidité Image IPB .

Voici les dimensions du châssis (en mm), mais n'hésitez pas à les adapter à la taille de votre plaque électronique :

Image IPB

Image IPB

Comme dans Cocotix V1, il n'y a pas de roue, et c'est l'axe du moteur qui touche directement par terre. L'interrupteur sert de troisième appui.

Collez les moteurs, les micro-rupteurs, les photo-résistances, le circuit électronique et les deux supports à piles AAA avec de la colle chaude et réalisez les connexions :

Image IPB
Prévoyez également deux trous pour les DEL :
Image IPB

Les 4 piles sont branchées en série.

Derniers réglages


Votre robot est presque opérationnel, encore un petit réglage.

Avec un petit tournevis, régler les résistances variables. Plus la résistance sera petite, plus le robot réagira à la lumière, et moins il ira vite. Le truc, c'est de trouver le réglage parfait pour que le robot ait suffisamment de vitesse pour avancer et qu'il réagisse bien à la lumière.

Enfin, vous pouvez lui rajouter une petite coque en carton, comme sur cocotix V1.

Votre robot est alors terminé !

Voilà, ce tutoriel touche à sa fin. J'espère que vous avez pris plaisir à le lire et à construire ce petit robot.
N'hésitez pas à poser vos questions sur le forum, notamment si vous avez un problème. Montrez-nous vos réalisations Image IPB .


Comment programmer une Arduino connecte en USB a un raspberry PI, depuis son PC.

Publié Bobox le 20 juin 2017 - 09:54 in Programmation

Introduction
 
Comme je le décris un peu dans l'interview qu'à fait Path (lien), je trouve que pour démarrer un robot 'autonome' la combinaison d'une arduino et d'un raspberry PI est une très bonne solution.
L'arduino pour connecter la majorité des capteurs et des drivers moteur, le raspberry PI pour la partie 'cerveau' et connectivité.
Comment faire alors pour programmer cet arduino, sans débrancher et rebrancher le cable USB en permanence.
C'est ce que nous allons voir dans ce tutoriel avec plusieurs méthodes, non exhaustives,  pour programmer une arduino connectée à un raspberry PI, depuis son PC.
 
Pré-requis
 
Je suppose ici que l'arduino est connecté à un raspberry PI par l'un de ses ports USB.
Je suppose aussi que le raspberry PI n'est pas connecté à un écran clavier, mais est accessible par le wifi/ethernet depuis un autre PC, depuis SSH.
Ce tutoriel n'explique pas ces étapes préliminaires.
 
A. Comment copier des fichiers depuis son PC sur le raspberry PI
 
Il est souvent nécessaire de transferer des fichiers depuis votre PC vers le raspberry PI. Vous pouvez le faire à travers le protocol SSH. 
 
Si votre PC tourne sous windows
 
vous pouvez utiliser winSCP (lien).
 
L'addresse IP et les identifiants sont ceux que vous utilisé pour SSH.
 
Si votre PC tourne sous linux
 
vous pouvez directement utilisé la commande 'scp':
scp monfichier  monlogin@addressIpRaspberry:.
Ces solutions sont parfaites pour transferer des fichiers d'installation, voir vos sources. Meme si pour les sources d'autres méthodes seront proposées plus loin.
 
Mais revenons à notre problématique d'origine, la programmation de l'arduino.
 
B. Comment utiliser l'IDE arduino sur le raspberry PI grace à un bureau distant.
 
Avantages:
  • Simple, on utilise l'IDE classique pour programmer l'arduino.
  • La méthode s'applique pour acceder à d'autres application graphique sur le raspberry PI
Inconvénients:
  • Vous etes limité à la résolution graphique de l'OS de votre raspberry PI
  • Utilisé l'IDE arduino sur le raspberry peut-être 'lent'
  • Utilisé d'autres IDE pour éditer vos sources peut-être encore plus lent
  • En fait ça ne marche probablement que si vous avez une raspberry PI 3.
  • Il faut une installation du raspberry PI avec le support graphique
C'est la solution qui je pense nécessite le moins d'apprentissage, parce qu'elle utilise l'habituel IDE arduino.
Elle nécessite que le raspberry PI contienne une installation de linux avec support des applications graphiques. C'est le cas si vous avez installé une Raspian ou une Ubuntu-Mate. Ce n'est pas le cas si votre installation est une Ubuntu-serveur, dans ce cas, voir l'autre solution.
 
Installation d'un bureau distant.
 
Je propose d'utilisé NoMachine (lien)  
Télécharger et installer la version correspondant à l'OS de votre PC depuis le lien.
Télécharger depuis votre PC la version DEB correspondante à votre version et installation de raspberry PI :  armv6 pour Raspian , armv7 pour Ubuntu-mate sur raspberry PI 3.
Transferer le fichier DEB sur votre raspberry PI avec la méthode décrite dans la section précédente par exemple.
 
Après vous être connecté en SSH, lancer l'installation sur le raspberry PI :
sudo dpkg -i nomachine_XXXXXXX_armhf.deb
L'installation sur le raspberry PI installe le client, mais aussi le serveur.
Vous pouvez maintenant lancer NoMachine depuis votre PC, le programme va chercher les PC qui ont un serveur NoMachine sur le réseau local :
Voici ce qu'il trouve pour moi, mon PC fix and ma raspberry PI:
Screenshot from 2017-06-19 22-10-24.png

Double cliquer sur le raspberry PI et c'est parti, vous allez démarrer un bureau distant sur votre petite board. Les login/mot de passe sont ceux que vous utilisez pour SSH.
 
Astuces :
  • La résolution graphique est surement basse, pour changer cela il faut forcer le mode 'hdmi, même s'il n'y a pas d'écran physique de connecté':
    Editez le fichier /boot/config.txt
    Décommenter les ligne :
    hdmi_force_hotplug=1
    hdmi_group=1
    hdmi_mode=31
    Reboot
  • Si vous passez la souris dans le coin en haut à droite de la fenêtre vous pouvez refaire apparaitre le menu de configuration de NoMachine
Programmation de l'arduino
 
Avec le bureau distant vous pouvez maintenant installer l'IDE arduino en ouvrant un navigateur sur le site d'arduino et suivre la procédure standard d'installation.
 
Attention : N'oubliez pas de télécharger la version linux-ARM, c'est la seule compatible avec le raspberry PI
 
C. Comment programmer l'Arduino sur le raspberry PI en ligne de commande.
 
Avant de voir en détails les solutions possible, il faut d'abord se poser une question préliminaire.
 
Comment éditer les fichiers sources des programmes pour l'Arduino
 
Comme nous n'utilisons pas l'IDE dans cette section, il va falloir éditer les sources des programmes autrement.
 
Voici plusieurs solution possible :
  • Vous êtes un guerrier, vous éditez vos sources directement en ligne de commande, sur la raspberry PI !
    Rien besoin de spéciale, un simple SSH et un édieur qui fonctionne dans le terminal comme ne/vim.
  • Vous éditer les fichiers sur le PC avec votre éditeur préféré, et vous les transferer sur le raspberry PI avec winscp
    C'est la méthode de la section A, appliquée aux fichiers sources.
  • Vous êtes un programmeur consciencieux et vous voulez utiliser un gestionnaire de code source avec versioning ! Je vous le dis vous êtes sur la bonne voie.
    Je vous conseille d'utiliser git et github. Voici une vidéo expliquant les principes de base : Github qu'est ce que c'est
    Dans notre cas, on va avoir une version du repository sur votre PC, dans lequel vous éditez les sources.
    On va aussi avoir une version du repository sur le raspberry PI.
    La séquence devient alors :
    Modifier les sources sur le PC
    Pusher les sources sur github depuis le PC
    Puller les sources depuis github sur la raspberry PI
 
Comment compiler les sources et les uploader sur l'arduino
 
Méthode simple
 
Une méthode simple est proposée par Path dans son tutoriel :  Compilation sur rPI et Upload sur arduino directement depuis le PI en ligne de commande
Je la recommande vivement pour commencer, elle est fonctionnelle et relativement facile à mettre en oeuvre.
 
Méthode platformio
 
Je vous propose une deuxième méthode ici, plus générale puisque pouvant s'adapter à la programmation d'autres cartes et microcontrolleur uilisé dans l'embarqué.
Cette méthode s'appuie sur l'environement  platformio core 
 
Installation : 
sudo pip install -U platformio
Vous pouvez l'installer aussi que pour l"utilisateur local, en omettant le 'sudo'
 
Creation d'un projet:
 
Pour chaque nouveau programme que vous voudrez créer pour l'arduino il faut créer un nouveau repertoire projet :
mkdir blinkProject
cd blinkProject
platformio init -b uno
Cette dernière commande initialisee le projet pour une board Arduino uno, si vous avez une autre type de board il faut trouver son nom dans la liste retournée par la commande 'platformio boards'.
 
Modification des sources
 
Le fichier source principale devra etre  'src/main.cpp' il n'y a pas d'extension .ino ici.
Exemple pour notre blink project :
src/main.cpp:
#include "Arduino.h"

void setup() {
    pinMode(13,OUTPUT);
}

void loop() {
    digitalWrite(13,LOW);
    delay(500);
    digitalWrite(13,HIGH);
    delay(500);
}

Compilation du code
 
La compilation du code se fait avec la commande:
platformio run
Si c'est la première compilation pour cette board la commande va télécharger toutes les librairies nécessaires.
 
Upload du code
 
Comme pour l'IDE arduino on peut compiler et uploader dans la même commande
platformio run -t upload
Après ces manipulations de base et pour des usages plus avancés, je vous recommande d'aller voir le site de platformio, qui contient beaucoup d'explication et de documentation sur les différents usages.


Arduino, les servomoteurs et la MLI (PWM)

Publié Hexa Emails le 02 juillet 2012 - 06:26 in Programmation

0) Je ne suis pas prof diplômé... (pas encore)

Je tiens à dire que je fais ce tuto dans le but de rendre service, il n'est pas exhaustif, s'il contient des erreurs veuillez me le signaler, il n'a pas pour but de faire du lecteur un doctorant en électronique numérique, et n'est peut être pas compréhensible par tout le monde (j'essaierai tout de même de faire au plus simple)
Les explications se limitent à l'univers de l'Arduino (bien que cela puisse être sans doute réadapté à pas mal d'autres situations), et aux servomoteurs dits "de modélisme", piloté par un signal bien particulier (voir plus bas) et ne concerne pas les servos contrôlés par I²C par exemple.


1) Qu'est-ce que la MLI (PWM) ?

Bon alors, comme dit Wikipédia, la Modulation de largeur d'Impulsions (MLI, PWM en anglais) c'est une succession de différents états logiques, (0 et 1), de différentes durées, à intervalles réguliers.

Dans le cas de l'Arduino: il s'agit de succession de 0/5V, qui permet, en modifiant la durée de chacun de ces états, de faire que tout se passe comme si on avait une source de tension continue;
Si l'on fait une MLI avec 20% d'états hauts, on aura 20% de 5V et 80% de 0V: on aura l'impression d'avoir 1V.

Il y a deux principales caractéristiques d'une MLI: son rapport cyclique et sa fréquence de découpage;
le rapport cyclique étant la proportion d'état haut par rapport au total (souvent exprimé en %, compris entre 0 et 1)
la fréquence de découpage: ben c'est la fréquence, l'inverse de la période. Une fréquence trop basse et l'on verra les clignotements de la LED, ou le moteur se mettra à vibrer; une fréquence trop haute et l'électronique ne suivra plus.


2) Comment pilote-t-on un servomoteur?

Un servomoteur c'est quoi?
C'est une boite de plastique, avec un rotor en sortie, qui peut être piloté de sorte à obtenir l'angle que l'on souhaite en sortie, entre 0 et 180°; on peut lui dire d'aller à 0°, puis à 153°, puis à 18°... (dans la limite de la précision de la commande ET du servomoteur, et a condition de ne pas éxcéder son couple maximal (l'effort maximum qu'il peut fournir)


Les servos ont trois fils qui sortent (ou entrent, suivant les optimistes/pessimistes) de leur boitier :
2 fils d'alimentation (alimentation entre 6 et 4V continus le plus souvent), et 1 fil de commande, en 0-5V

Et à l'intérieur?
Un moteur (CC à balais le plus souvent), des engrenages (pour augmenter le couple)
De l'électronique, et un capteur (un potentiomètre rotatif le plus souvent)

Quel rapport entre la MLI et les servomoteurs? Hé bien beaucoup moins que certains veulent le faire croire!
voici un signal de commande de servomoteur(pas à l'échelle et fait sous Paint hein):
Image IPB
Comme on peut le voir, on a une succession d'états hauts et d'états bas, la durée de l'état haut permet de dire au servomoteur l'angle que l'on souhaite qu'il atteigne: plus le niveau bas est court, plus l'on se rapproche de 0°, plus il est long, plus l'oon se rapproche de 180°.
On peut dire que ce signal est un peu étrange pour une MLI. Pourquoi?
Parce que l'on reste cantonné à un état haut de durée comprise entre 1 et 2 millisecondes, sur 20ms, soit entre 5% et 10% de la durée totale. Et de plus on peut noter la période de ce signal: 20 ms. Cela peut sembler rapide, mais en électronique c'es plutot lent.



3) A quoi correspondent les Pins notées "PWM" sur mon Arduino?

Les plateformes de prototypage Arduino sont basées sur des microcontrôleurs ( ATMega328, ATMega1280 et ATMega2560 le plus souvent, certaines anciennes versions avec des ATMega168, les autres versions sont VRAIMENT anciennes)
Ces microcontrôleurs permettent de créer facilement des signaux de MLI (ils ont étés conçu, à l'intérieur, avec des portes logiques qui permettent facilement de faire de la MLI).
Ce qui permet d'utiliser l'instruction suivante:
analogWrite(pin_pwm , nombre_entre_0_et_255)
et d'obtenir une MLI sur la broche notée "PWM".
MAIS!
Piloter les servomoteurs avec ces instructions n'est pas une bonne idée. Pourquoi?

a)la fréquence:
Une MLI de base faite avec analogWrite a une fréquence de découpage de 480Hz, voire 1kHz suivant les ports.
Pour piloter un servo il faudrait une fréquence de 50Hz (1/0.02), je ne vais pas m'étendre dessus mais c'est assez compliqué de modifier la fréquence et cela peut empiéter sur d'autre fonctions comme delay(), millis(), car cela oblige (en gros) l'ATMega à compter moins vite...

b)la résolution:
Vous vous souvenez que j'ai dit que le signal de servo n'utilise que 5% de la durée totale de la MLI?
C'est un autre souci. Avec analogWrite(), on peut prendre 256 durées différentes entre 0 et 100%. ça veut dire un peu moins de 13 valeurs différentes entre 5 et 10% ! c'est très peu quand on veut le piloter de 0 à 180°, cela voudrait dire qu'il ne peut prendre que 13 valeurs d'angle différentes, par exemple:
0°, 14°, 28°... (aux arrondis près).
Et il serait impossible de prendre des valeurs entre celles-ci. Pas terrible...

4)Et donc comment je fais?

Pas de panique, l'équipe de développeurs d'Arduino a codé une librairie <servo.h>, qui permet de créer des signaux de commande de servomoteurs, sur n'importe quelle sortie digitale. Ce qui veut dire:
les pins digitaux 0 à x, notés PWM OU PAS;
les pins analogiques A0 à Ax -qui sont des sorties digitales en même temps!-
(sauf les ports A6 et A7 sur les arduinos basés sur un ATMega328 monté en surface, qui ne sont pas des sorties digitales mais uniquement des entrées analogiques)
On peut avoir 12 servos en même temps sur un Arduino basé sur un 328 (et 168), et 48 pour un Arduino basé sur un 2560 (et 1280). Selon moi on pourrait en contrôler encore plus en même temps, mais les devs ont mis cette limite afin de ne pas trop peser sur le reste du programme.

Toutes les infos sur la librairie <servo.h> et les fonctions qu'elle permet d'utiliser sont disponibles à l'adresse suivante(En français, je ne vais pas réinventer le roue non plus...)

5)EN BREF!

La MLI, c'est une forme de signal digital (ne contenant que des états hauts et bas), et périodique.
Les ports noté PWM sur l'Arduino permettent de faire facilement de la MLI (par l'instruction analogWrite)
La librairie <servo.h> permet de contrôler 12 servomoteurs simultanément (48 sur les MEGA), sur n'importe quelle sortie digitale.


Faire parler un PC avec VB.NET

Publié julkien le 18 juin 2012 - 02:58 in Programmation

Principe

Le but de ce tutoriel est de faire tout simplement parler l'ordinateur en un minimum de lignes
Ici on lui feras simplement annoncer l'heure.


Prérequis

  • VisualBasic 2010 Express
  • WindowsSeven

I) Vérification et configuration des voix pardefault de Windows

Windows ne contient pas par default de langue française,(ben oui il ne parle que l'Américain , ou le chinois ^^) , alors ilfaut ajouter la voix Virginie (de la societe Nuance (ex Scansoft)) en français, cliquer sur ce Mon lien ,decompresser l'archive et installer RSSolo4FrenchVirginie.exe pour tester la voix, appuyer sur la touche Windows* et la touche 'R' pour ouvrir la fenêtre "Exécuter" , taper :"C:\Windows\SysWOW64\Speech\SpeechUX\sapi.cpl" puis cliquer sur ok.

une fenêtre s'ouvre et vous propose plusieurs voix sélectionner: "ScanSoft Virginie_Dri40_16kHz"
rentrer un texte (en français correctement orthographier!;)/> ) et cliquer sur "Tester la voix"
Voilà maintenant que l'on sait que ça marche on vapourvoir coder

*=(la touche Windows est entre la touche 'CTRL' et 'ALT'!:P/>)


II) Créer le projet sous Visual Basic 2010 Express

Ouvrer Visual basic 2010 Express et cliquer sur nouveau projet
Sélectionner : application Windows forms
Renseigner le nom du projet : "Mon_Prog_donne_lheure"et cliquer sur ok
Nous avons donc la form mais elle est un peu vide

Image IPB

Ajoutez un bouton ( il se trouve dans la barre d'outils,un glisser/déposer suffit à le mettre en place )
Ajoutez maintenant une Combo Box
Hein, Quoi ?! Combo Box toi-même ! Non rassurez-vous ce n'est pas une insulte mais juste le menu qui nous permettras de sélectionner nos voix
Il se trouve toujours dans la barre d'outil
Au final on devrais avoir une fenêtre qui ressemble à ça:

Image IPB

Et du coup ça y est on a fini l'interface de commande :)/>.C'est l'avantage de vb.net: facile d'accès, du moins jusque-là ! ( je dis juste ça pour vous faire peur! :P/> )


III) Le code

Contrairement à l'Arduino qui exécute la fonction Loop en boucle, en VB ontravaille par évènement.
Bon ok jusque-là c'est simple mais comment lui dire defaire telle tâche au démarrage ?
Ben en fait c'est vraiment pas compliqué il vous suffitde faire un double clic sur la Form1 précédemment créé !
Et tout d'un coup il nous sort tout un code :

Public Class Form1

Private Sub Form1_Load(ByVal sender AsSystem.Object, ByVal e As System.EventArgs) Handles MyBase.Load

End Sub

End Class


Je ne vais pas vous expliqué en détail le VB il a d'autres sites plus sympas pour apprendre [/font][/size]
Si on décompose le code on trouve 2 groupe [/font][/size]

En première place on trouve la déclaration de la class

PublicClass Form1
End Class


C'est la dedans que l'on met notre code en réalité
En 2eme nous avons la fonction : Chargement de la forme

Private Sub Form1_Load(ByVal senderAs System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub


Je vous invites à coller dans la place de celui existant ce texte :[/font][/size]


Imports System.Speech

Imports System.Speech.Synthesis

Public Class Form1

Dim s As SpeechSynthesizer = New SpeechSynthesizer() ' declaration du systeme de narration

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'au chargementde la forme:

Dim listevoix =s.GetInstalledVoices 'listevoix est egale a la liste des voix installer

For Each v As InstalledVoice In listevoix 'je charge chaque voix installer

ComboBox1.Items.Add(v.VoiceInfo.Name) '

Next

End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click ' quand je clics sur le bouton1

Dim texte As String = "Il est " & Now.Hour & " heure et " & Now.Minute &"Minute" 'declaration du texte

Dim voix As String = ComboBox1.SelectedItem 'la voixest egale la selection du combobox

s.SelectVoice(voix) ' je choisi la voix

s.Speak(texte) 'je lis le texte

End Sub

End Class


Vous avez remarquer ? il y a des lignes de surligné !
C'est normale
Il nous manque une dll pour que le logiciel parle
Le truc c'est que l'on est sous du code en .net(prononcer DotNet)
Il nous donne pas mal d'avantage et nous offre par la mêmeoccasion tout une bibliothèque lié à Windows
comme par exemple:
des module qui permette l'interaction avec les fichier, réseau,les Port de communication( ah ça sera certainement le sujet d'un autre tuto! ;)/>)
etc


pour ajouter la DLL , il suffit de cliquer sur le menu Projet => Ajouter une référence
une fenêtre s'ouvre cliquer sur l'onglet ".Net"
choisissez dans le menu System.speech et cliquer sur Ok


Conclusion

Voilà on as un programme fonctionnel

Oups, j'ai failli oubliez, cliquez sur le bouton lecture pour lancer l'application
Sélectionner la voix " ScanSoft Virginie_Dri40_16kHz" dans le menu et cliquez sur button1

Elle devrais vous dire avec une voix douce : "il est 12 heures et 21 minutes" ....
Enfin la voix douce et l'heure est relatif :D/>

J'espère que ça aideras !
Merci de m'avoir lu


Julkien


Utilisation du module RTC DS1307

Publié arobasseb le 23 octobre 2017 - 04:53 in Electronique

Bonjour à tous,
 
Aujourd'hui nous allons voir comment utiliser le module RTC DS1307 disponible sur la boutique Robot Maker.
Pour ce tuto nous allons également utiliser : (d'autres composants intéressants sont également disponible sur la boutique, n'hésite pas à y faire un tour ! )
 
Présentation
 
Tout d'abord, qu'est ce qu'un module RTC ? 
 
RTC signifie Real Time Clock soit en français horloge temps réel. 
 
OK, donc je peux l'accrocher dans mon salon ? Pas vraiment Image IPB
 
En fait ce module, une fois configuré, compte le temps qui passe et ce, de façon autonome et précise grâce à sa pile s'il n'est pas branché.
 
Et du coup à quoi ça sert, c'est pas une pendule et on peut déjà compter le temps avec une arduino par exemple ?
 
Avec ce module on peut faire des montages qui agissent en fonction du temps réel, par exemple allumer les lampes à 18h, ou le grille pain à 6h Image IPB mais aussi en fonction du jour, mois, ... en effet il connait la date et l'heure réelle.
Son avantage réside dans le fait qu'en cas de coupure d'alimentation il continue de compter, et aucune instruction ne risque de le ralentir, à l'inverse d'une arduino ou, dans ce cas, il y aurai une dérive de temps. 
Il se pilote via un bus I2C, ce qui le rend facile d'utilisation avec justement une arduino.
 
Quelques photos de notre star du jour : 
 
ds1307_cote.jpg
ds1307_recto.jpg
ds1307_verso.jpg
 
Le montage
 
Le schéma :
shema.png
(dans le schéma, le module n'est pas du même fabricant, mais les connections sont les même)
 
En vrai :
ds1307_montage.jpg
 
Le montage est simple grâce à l'I2C ; il faut connecter les broches SDA des 2 modules sur la broche A4 de l'arduino et les broches SCL sur la broche A5 , les broches VCC au 5V et GND au GND Image IPB
Attention pour une utilisation avec une arduino par exemple il faudra utiliser un convertisseur de tension (ce point sera peut-être aborder plus tard)
 
C'est cool tout est branché et maintenant ?
 
La programmation
 
Voici le code avec les commentaires qui suffisent à eux même : 
#include <Wire.h>    // Bibliothèque pour l'I2C
#include "RTClib.h"  // Bibliothèque pour le module RTC
#include <LiquidCrystal_I2C.h> // Bibliothèque pour l'écran

RTC_DS1307 RTC;      // Instance du module RTC de type DS1307
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); ////Instance d'écran

void setup(void) {
  //Initialisation de l'éran
  lcd.begin(16,2);
  lcd.clear();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.setCursor(0, 1);
  
  // Initialise la liaison I2C  
  Wire.begin();
  
  // Initialise le module RTC
  RTC.begin();
 
  //Initialise la date et le jour au moment de la compilation 
  // /!\ /!\ Les lignes qui suivent sert à définir la date et l'heure afin de régler le module, 
  // pour les montages suivant il ne faut surtout PAS la mettre, sans à chaque démarrage 
  // le module se réinitialisera à la date et heure de compilation
  
  DateTime dt = DateTime(__DATE__, __TIME__);
  RTC.adjust(dt);
  
  // /!\
  ////////////////////////////////////////////////////////////////////////////////////////////
}

void loop(){
  
  DateTime now=RTC.now(); //Récupère l'heure et le date courante
  
  affiche_date_heure(now);  //Converti la date en langue humaine
  
  delay(1000); // delais de 1 seconde
}

//Converti le numéro de jour en jour /!\ la semaine commence un dimanche
String donne_jour_semaine(uint8_t j){ 
  switch(j){
   case 0: return "DIM";
   case 1: return "LUN";
   case 2: return "MAR";
   case 3: return "MER";
   case 4: return "JEU";
   case 5: return "VEN";
   case 6: return "SAM";
   default: return "   ";
  }
}

// affiche la date et l'heure sur l'écran
void affiche_date_heure(DateTime datetime){
  
  // Date 
  String jour = donne_jour_semaine(datetime.dayOfWeek()) + " " + 
                Vers2Chiffres(datetime.day())+ "/" + 
                Vers2Chiffres(datetime.month())+ "/" + 
                String(datetime.year(),DEC);
  
  // heure
  String heure = "";
  heure  = Vers2Chiffres(datetime.hour())+ ":" + 
           Vers2Chiffres(datetime.minute())+ ":" + 
           Vers2Chiffres(datetime.second());

  //affichage sur l'écran
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(jour);
  lcd.setCursor(0, 1);
  lcd.print(heure);
}

//permet d'afficher les nombres sur deux chiffres
String Vers2Chiffres(byte nombre) {
  String resultat = "";
  if(nombre < 10)
    resultat = "0";
  return resultat += String(nombre,DEC);  
}


J'ai joins le fichier de code ainsi que  les librairies pour le module RTC et LCD.
 
une petite vidéo :
 
 
 
N'hésite pas à laisser un commentaire.

Fichier(s) attaché(s)




Roby, mon premier robot Arduino

Publié robocop le 03 octobre 2010 - 11:04 in Robot complet

Bonjour,

Je vous propose ici la construction d'un nouveau robot, Roby, qui pédagogiquement pourra se placer après avec les deux Cocotix, Cocotix V1, et Cocotix V2.
Roby sera programmable avec la plateforme arduino et intègrera différents capteurs : capteurs d'obstacles et de lumière comme dans cocotix V1 et V2, mais également d'autres comme capteurs de distance infrarouge ou ultrason si vous le désirez : le robot se veut extensible.

-------------------------------------
Liste des composants (par microrupteurman2) :

- 2 servomoteurs type s3003 modifiés en rotation continue
- 1 arduino
- 2 micro-rupteurs
- Les piles indiquées sur le schéma avec leur boîtier
- Une plaque d'essai (breadboard)
- Des roues pour servo, facilement réalisables
- Une roulette pour le 3e point d'appui
- fil électrique,
- vis
- matériel de soudure
- 1 interrupteur
- 2 résistances de 10k0
- 1 capteur Sharp Gp2d112
-------------------------------------

Le robot aura comme base mécanique la structure présentée ici.
Bien évidemment, vous pouvez utiliser la structure de votre choix, mais dans le code du robot, j'utiliserai bien deux servomoteurs pour la propulsion.

Image IPB

But du robot

Comme vu sur la vidéo, Roby aura pour but de naviguer dans une pièce, en évitant les obstacles, soit grâce a un capteur infrarouge de distance, soit avec des "antennes", des capteurs de contact.



Roby, robot basé sur une carte arduino

Par la suite, si vous le souhaitez, encore une fois, vous pourrez très simplement rajouter des capteurs, de l'enregistrement de données sur carte SD, une petite caméra, une liaison sans fil, etc.

Tout cela se fait très simplement avec certains modules pour Arduino.

Structure mécanique

Le structure mécanique est axée sur deux servomoteurs modifiés en courant continu.
Si vous n'avez pas d'idées, vous pouvez vous inspirer de ce tutoriel.

Image IPB

L'Arduino

Image IPB

Toute l'électronique du robot sera basée sur la carte Arduino Duemilanove. Arduino Duemilanove est une carte électronique qui comporte un microcontrolleur atmel ATmga328 et des composants supplémentaires pour faciliter la programmation du composant.

Ainsi la carte intègre directement un port usb pour programmer la carte en USB, un quartz 16MHz, un régulateur linéaire de tension 5, différentes LED, un bouton de reset, bref, pleins de bonnes choses pour commencer très rapidement sans soucis.
Cerise sur le gâteau, la carte est très accessible, moins de 30 euros.

Installation de la carte

Pour pouvoir programmer la carte, il faut déjà installer les drivers et les outils de programmation sur votre ordinateur.
La carte fonctionne aussi bien sur une architecture windows que linux.

Pour l'installation, je vous renvoi sur le chapitre dédié à l'installation d'Arduino sur l'ouvrage débuter avec Arduino

Test de la carte

On va voir si l'installation s'est bien passée en faisant clignoter une DEL.
La carte arduino équivalente à une carte clone Arduino Uno intègre d'office une petite DEL sur la patte 13.

On va donc mettre successivement la patte de 0 à 1, et de 1 à 0, toutes les 1.5 secondes.

On ouvre donc leur IDE, et on tape le programme suivant :
Code : C
int ledPin = 13;

void setup() {
// On initialise la patte 13 en pin de sortie
pinMode(ledPin, OUTPUT);
}

void loop()
{
digitalWrite(ledPin, HIGH); // on met la patte à 1
delay(1000); // on attend une seconde
digitalWrite(ledPin, LOW); // on met la patte à 0
delay(1000); // on attend une seconde
}
On remarque que chaque code possède au minimum deux fonctions, setup() et loop().
setup() est appelée au lancement de la carte, et loop() et executée en boucle, tant que la carte reçoit du courant.

Compilez votre code, puis envoyer le sur la carte.
Au bout de quelques secondes, la DEL de la carte devrait clignoter.
 
Ressources


Pour à peu près tout, il existe une librairie pour votre carte arduino : vous pouvez controler un servomoteur avec la librairie de servomoteurs, controler un écran LCD, communiquer avec l'ordinateur à travers le port USB, etc.

Voici un lien qui présente pleins d'exemples amusant à réaliser, et un autre, qui présente rapidement le langage avec lequel vous travaillez.

Amusez-vous bien !

Alimentation

Il y a dans ce robot deux alimentations : une pile 9 V pour alimenter l'arduino et 4 piles 1.5 V en série pour alimenter les servomoteurs et autres capteurs.

L'avantage de ce système, c'est que l'on peut alimenter l'arduino par la prise USB lorsque l'on écrira le programme, tout en gardant alimenté les servomoteurs : le débogage est donc plus aisé.

Attention cependant : il faut faire attention a bien relier les deux masses entre elle, cela peut être source de bogues assez vicieux.
Vous pouvez fixer vos piles commme sur cette photo :

Commencez par fixez les deux alimentation comme sur la photo :

Image IPB

Faites un trou au milieu du robot pour laisser passer les fils de l'alimentation et un trou sur le coté pour fixer l'interrupteur.
L'idéal c'est d'avoir un interrupteur capable d'avoir de couper/alimenter deux circuits à la fois. De cette façon, vous pourrez éteindre ou allumer votre robot en une fois.
Maintenant, si vous n'avez que deux interrupteurs normaux, ça fonctionnera aussi.

Fixez sur le robot l'arduino et la plaque d'essai.

Cablez alors les alimentations, l'arduino et les servomoteurs de cette façon :

Image IPB

Vous avez donc avec ce schéma 6V pour les deux servomoteurs et 9 V pour l'arduino.
Les deux masses sont bien reliées entres elles.
Sur la plaque d'essai, la première ligne correspond donc aux +6V et la deuxième à la masse.
Voici une photo de mon robot à cette étape :

Image IPB

Test des moteurs

On va écrire dans un premier temps un programme qui fait avancer le robot tout droit.

Tout d'abord, nous allons écrire une fonction toute simple, getNeutral(moteur) qui retournera la valeur du neutre de vos servomoteurs :
Code : C++
#include <Servo.h>

#define SERVOG 1
#define SERVOD 0

Servo servog;
Servo servod;

int getNeutral(int s)
{
if(s == SERVOG)
return 86;
else
return 84;
}
Chaque servomoteur est représenté par un entier naturel : le servomoteur gauche 1 et le servomoteur droit 0.
Remplacez les valeurs 86 et 84 respectivement par les valeurs du neutre que vous trouvez pour le servomoteur gauche et pour le servomoteur droit de votre robot.

Essayez de faire bouger vos servomoteurs en utilisant cette fonction.
Tout va bien ? Ok, nous allons écrire une fonction handleS(servomoteur, vitesse) qui envoit une commande au servomoteur. Cette commande est caractérisé par une vitesse qui va de -5 à 5. Si la vitesse est négative, on dira au moteur d'aller dans un sens et si le vitesse est positive on dira au robot d'aller dans l'autre sens.

Les différentes vitesses sont obtenues en se rapprochant du neutre. Je vous conseil de faire vos propres tests.
Attention cependant : nos servomoteurs ne sont pas dans le même sens. Pour avancer tout droit, un des servomoteurs doit aller dans un sens, et l'autre servomoteur doit aller dans l'autre sens.
On ne va donc pas oublier d'inverser le sens de rotation pour un des moteurs.
Code : C++
void handleS(int s, int speed)
{
//Vitesse :
// 0 -> 0; 1 -> 1; 2 -> 3; 3 -> 8; 4 -> 10; v => 5 -> 30
int tab[6] = {0,1,3,8,10,30};
int pos = getNeutral(s);

int acc;
// A chaque vitesse on fait correspondre un nombre qui est la différence de ce que l'on va envoyer au servomoteur par rapport au neutre.
// Les valeurs que je donne sont mes valeurs, je vous conseille de chercher vos propres valeurs, cela dépend de votre servomoteur.
if (speed < 0)
acc = - tab[abs(speed)];
else
acc = tab[speed];

if(s == SERVOG)
servog.write(pos += acc);
// On inverse le sens de rotation pour le moteur droit car les deux servomoteurs ne sont pas montés dans le même sens.
else
servod.write(pos -= acc);
}
A partir de là, on peut écrire une fonction move(direction) qui fait déplacer le robot dans une direction donnée :
Code : C++
#define AVANT 1
#define ARRIERE 0
#define GAUCHE 2
#define DROITE 3

#define VMAX 5

void move(int direction)
{
int m1 = 0, m2 = 0;
switch(direction)
{
case DROITE: m1 = 1; m2 = -1; break;
case GAUCHE: m1 = -1; m2 = 1; break;
case AVANT: m1 = 1; m2 = 1; break;
case ARRIERE: m1 = -1; m2 = -1; break;
}
handleS(SERVOG, m1*VMAX);
handleS(SERVOD, m2*VMAX);
}
Rien de bien compliqué : en fonction du déplacement, on indique dans quel sens doit se déplacer chaque moteur.

Code complet


On va, en utilisant toutes ces fonctions, demander au robot d'avancer tout droit :
Code : C++
#include <Servo.h>

#define AVANT 1
#define ARRIERE 0
#define GAUCHE 2
#define DROITE 3

#define SERVOG 1
#define SERVOD 0

#define VMAX 5

Servo servog;
Servo servod;

int getNeutral(int s)
{
if(s == SERVOG)
return 86;
else
return 84;
}


void handleS(int s, int speed)
{
//Vitesse :
// 0 -> 0; 1 -> 1; 2 -> 3; 3 -> 8; 4 -> 10; v => 5 -> 30
int tab[6] = {0,1,3,8,10,30};
int pos = getNeutral(s);

int acc;
if (speed < 0)
acc = - tab[abs(speed)];
else
acc = tab[speed];

if(s == SERVOG)
servog.write(pos += acc);
else
servod.write(pos -= acc);
}


void move(int direction)
{
int m1 = 0, m2 = 0;
switch(direction)
{
case DROITE: m1 = 1; m2 = -1; break;
case GAUCHE: m1 = -1; m2 = 1; break;
case AVANT: m1 = 1; m2 = 1; break;
case ARRIERE: m1 = -1; m2 = -1; break;
}
handleS(SERVOG, m1*VMAX);
handleS(SERVOD, m2*VMAX);
}



void setup()
{
servog.attach(10);
servod.attach(9);
move(AVANT);
}

void loop()
{
delay(15);
}
Cela est très simple avec la fonction move : move(AVANT);
Maintenant, on va faire faire avancer le robot pendant 8 secondes, lui faire faire un demi-tour, le faire avancer pendant 8 secondes, et ainsi de suite.
Pour faire tourner le robot, on va le faire tourner vers la gauche pendant un certain temps.
Personnellement, je trouve qu'il faut le laisser tourner 2 secondes pour qu'il fasse un demi-tour complet.
Ainsi, tout naturellement, le code est le suivant :
Code : C++
void loop()
{
move(AVANT);
delay(8000);
move(GAUCHE);
delay(2000);
}

Capteurs de contact : détecter les obstacles


Nous allons rajouter des capteurs de contact de type UPDD comme dans Cocotix. Il faut donc les connecter a deux pattes de l'arduino, et nous allons simplement regarder les états des deux pattes de l'arduino : si l'une est à 1, il faut enclencher un virage Image IPB.

Voici donc le schéma de ce montage :

Image IPB

Les deux résistances sont des résistances de "pull-down", reliées à la masse pour éviter d'avoir des pattes flottantes et pour forcer l'état normal des deux pattes à 0.

Le code pour faire éviter les obstacles fait reculer, puis de tourner le robot à la détection de chaque obstacle :
Code : C++
#define UPDDG 3 // on utilise la patte 2 pour le capteur de gauche et 4 pour le capteur de droite.
#define UPDDD 4

void handleUPDD(int updd)
{
if(digitalRead(updd) == HIGH) //Si le capteur est enclenché
{
move(ARRIERE); // on recule d'abord pendant 0.4 sec
delay(400);

if (updd == UPDDG) // Puis on tourne dans le sens inverse du capteur détecté...
{
move(DROITE);
}
else
{
move(GAUCHE);
}
delay(600); // ...pendant 0.6 sec
}
}

Voici le schéma complet du robot à ce stade :

Image IPB

Et le code complet :
Code : C++
 
#include <Servo.h>

#define AVANT 1
#define ARRIERE 0
#define GAUCHE 2
#define DROITE 3

#define SERVOG 1
#define SERVOD 0

#define UPDDG 3
#define UPDDD 4

#define VMAX 5

Servo servog;
Servo servod;

int getNeutral(int s)
{
if(s == SERVOG)
return 86;
else
return 84;
}


void handleS(int s, int speed)
{
//Vitesse :
// 0 -> 0; 1 -> 1; 2 -> 3; 3 -> 8; 4 -> 10; v => 5 -> 30
int tab[6] = {0,1,3,8,10,30};
int pos = getNeutral(s);

int acc;
if (speed < 0)
acc = - tab[abs(speed)];
else
acc = tab[speed];

if(s == SERVOG)
servog.write(pos += acc);
else
servod.write(pos -= acc);
}


void move(int direction)
{
int m1 = 0, m2 = 0;
switch(direction)
{
case DROITE: m1 = 1; m2 = -1; break;
case GAUCHE: m1 = -1; m2 = 1; break;
case AVANT: m1 = 1; m2 = 1; break;
case ARRIERE: m1 = -1; m2 = -1; break;
}
handleS(SERVOG, m1*VMAX);
handleS(SERVOD, m2*VMAX);
}

void handleUPDD(int updd)
{
if(digitalRead(updd) == HIGH)
{
move(ARRIERE);
delay(500);

if (updd == UPDDG)
{
move(DROITE);
}
else
{
move(GAUCHE);
}
delay(800);
}
}



void setup()
{
pinMode(UPDDG, INPUT);
pinMode(UPDDD, INPUT);

servog.attach(10);
servod.attach(9);
move(AVANT);
}

void loop()
{
handleUPDD(UPDDG);
handleUPDD(UPDDD);
move(AVANT);
delay(15);
}

Capteur de distance infrarouge

Pour finir je vous propose de rajouter un capteur de distance pour détecter les obstacles sans les percuter.
Nous allons utiliser un capteur Sharp gp2d120 qui permet de voir de 4 cm à 80 cm.
Le capteur est simplement composé de 3 fils, deux pour l'alimentation (+5v et masse) et un pour la sortie analogique : le capteur renvoie une tension comprise entre 0 et 5v proportionnel à la distance des objets.

Image IPB

Branchez donc le capteur sur l'arduino : le fil rouge sur le +5V, le fil noir à la masse, et le jaune sur la patte 4 de l'arduino, qui est une patte analogique : on peut directement lire la tension envoyée à cette patte.

Vous pouvez le fixer sur le robot comme sur cette image :

Image IPB


Pour lire une patte la valeur de la tension envoyée à la patte 4, il suffit de faire :
Code : C++
int v = analogRead(4);
Après quelques tests de mon capteur, j'ai constaté que si v était supérieur à 180 (obstacle à 10 cm), alors il fallait reculer pour éviter l'obstacle, alors que si v est supérieur à 100 (obstacle à 30 cm) il suffisait de ralentir d'un coté pour éviter l'obstacle.

Voici donc le code que je vous propose :
Code : C++
void sharp()
{
int v = analogRead(4);
if (v >= 180) // si on est à moins de 10 cm d'un obstacle
{
move(ARRIERE); //on recule
delay(300);
move(DROITE); //puis on part sur la droite
delay(900);
}
else if (v >= 100) //sinon si on est à moins de 30 cm d'un obstacle
{
handleS(SERVOG, VMAX);
handleS(SERVOD, 0); // on ralentit simplement la roue droite pour engager un virage en douceur
delay(1500);
}
}
Au final, voici le code complet :
Code : C++
#include <Servo.h>

#define AVANT 1
#define ARRIERE 0
#define GAUCHE 2
#define DROITE 3

#define SERVOG 1
#define SERVOD 0

#define UPDDG 3
#define UPDDD 4

#define SHARP 4

#define VMAX 5

Servo servog;
Servo servod;

int vLdr = 5;

int getNeutral(int s)
{
if(s == SERVOG)
return 86;
else
return 84;
}


void handleS(int s, int speed)
{
//Vitesse :
// 0 -> 0; 1 -> 1; 2 -> 3; 3 -> 8; 4 -> 10; v => 5 -> 30
int tab[6] = {0,1,3,8,10,30};
int pos = getNeutral(s);

int acc;
if (speed < 0)
acc = - tab[abs(speed)];
else
acc = tab[speed];

if(s == SERVOG)
servog.write(pos += acc);
else
servod.write(pos -= acc);
}


void move(int direction)
{
int m1 = 0, m2 = 0;
switch(direction)
{
case DROITE: m1 = 1; m2 = -1; break;
case GAUCHE: m1 = -1; m2 = 1; break;
case AVANT: m1 = 1; m2 = 1; break;
case ARRIERE: m1 = -1; m2 = -1; break;
}
handleS(SERVOG, m1*VMAX);
handleS(SERVOD, m2*VMAX);
}

void handleUPDD(int updd)
{
if(digitalRead(updd) == HIGH)
{
move(ARRIERE);
delay(500);

if (updd == UPDDG)
{
move(DROITE);
}
else
{
move(GAUCHE);
}
delay(800);
}
}

void sharp()
{
int v = analogRead(SHARP);
if (v >= 180)
{
move(ARRIERE);
delay(300);
move(DROITE);
delay(900);
}
else if (v >= 100)
{
handleS(SERVOG, VMAX);
handleS(SERVOD, 0);
delay(1500);
}
}
void setup()
{
pinMode(UPDDG, INPUT);
pinMode(UPDDD, INPUT);

Serial.begin(9600);
servog.attach(10);
servod.attach(9);
move(AVANT);
}

void loop()
{
handleUPDD(UPDDG);
handleUPDD(UPDDD);
sharp();
move(AVANT);
delay(100);
}
Comme vous pouvez le voir, rajouter un capteur n'a pas été difficile Image IPB.

Roby, robot basé sur une carte arduino.

Et voilà, c'est fini pour ce tutoriel.
Évidemment, la réalisation proposée ici n'est qu'une base à améliorer.
N'hésitez pas à nous faire par de vos améliorations, quelles soient électronique ou algorithmique soit en postant sur le forum, soit en créant votre tutoriel Image IPB.

Remerciement : cgizmo, avec qui j'ai écrit le code du robot.


R.Cerda, Un robot Raspberry Pi pour 100-120€

Publié sky99 le 12 avril 2013 - 01:10 in Robot complet

Description: Je vous propose un prototype de robot Raspberry Pi aux alentours d'une centaine d'euros (disons jusqu'à 120) tout compris. Ce tutoriel est fait pour que quelqu'un n'ayant aucune base puisse faire son robot, et le faire fonctionner.
Vous pourrez également trouver une version wiki en plusieurs pages distinctes de ce tutoriel, exportable en PDF, à cette adresse : 
http://nagashur.com/...e:r_cerda:start
R.Cerda, un robot Raspberry Pi à conduite différentielle - Partie 1/5 : Introduction et présentation du robot
Bonjour à tous! Dans ce post, je voudrais vous présenter mon second robot "officiel", cad qui a dépassé le niveau de prototype
de tests. Le précédent était basé sur un Arduino Uno, et m'a permis de comprendre les bases. Maintenant, celui ci est basé
sur un Raspberry Pi, et est une base qui permettra de faire bien plus.



Ce robot utilise deux moteurs DC (à courant continu) commandés par des L293D interfacés au Pi par un MCP23017. Un MCP3008 permet de lire les entrées d'un capteur ultrasonique Maxbotix LV-EZ4.

Le principe général
Ce robot possède deux roues parallèles, entraînées chacune par un moteur électrique DC. On utilise deux puces L293D en parallèle pour commander individuellement les deux moteurs. Le MCP3008 ajoute un convertisseur analogique au Raspberry pi, et grâce à cela, nous pouvons détecter la distance aux obstacles frontaux en utilisant un capteur ultrasonique ou infrarouge. Il y a un MCP23017 pour ajouter des GPIO.
Un ball caster sert de troisième point de contact, et le robot peut ainsi se déplacer, tout en étant stable, avec un minimum de friction.

Il y a 5 batteries dans un compartiment pouvant en accepter 6. Cela sert à avoir une tension de 5 à 6V, qui alimente directement les moteurs.
Dans le même temps, le courant qui sort des batteries est régulé par un petit composant qui s'assure ainsi de fournir du 5V en sorte, de façon stable.
Cette tension est alors fournie au Raspberry Pi, qui peut alors commander les puces et les moteurs. On pourrait envisager deux sources d'alimentation,
une pour le pi, et l'autre pour les moteurs, mais c'est plus simple avec une seule. Le régulateur de tension que j'ai utilisé est très efficace, et ne gaspille donc que très peu d’énergie.

Le capteur ultrasonique est placé sur la face avant du robot, et indique la distance aux obstacles se situant dans l'arc frontal. Ainsi, le robot peut tourner pour les éviter.


Liste du matériel
  • Raspberry Pi modèle B, 512Mo - environ 36€;
  • Carte SDHC 8Go - environ 10€, une 4Go suffit;
  • Une clé USB Wifi - inutile pour le robot même, je m'en sers pour le programmer à distance 10€;
  • Deux moteurs DC avec rapport réducteur 180:1 - environ 8€;
  • Deux roues -~5€;
  • Un "ball caster" -~1€, mais je vous conseille plutôt celui ci, à 3€;
  • Deux puces L293D ~4€;
  • Un MCP23017 pour ajouter 16 GPIO ~2.5€;
  • Un MCP3008 pour ajouter un convertisseur ADC ~ 3€;
  • Un capteur de distance ultrasonique (Maxbotix LV-EZ4) ~20€, mais on peut aussi utililiser un capteur IR ~12€ ;
  • Un convertisseur de tension produisant du 5V ~4€;
  • Une trappe à batteries ~2-3€ en comptant le jack power;
  • 5 Batteries AA ~10€;
  • Quelques fils ~3€;
  • Des "Jumper Wire ~3€".
En pratique, on s'en sort pour 80 à 120€, selon les options, si l'on a déjà des batteries, etc.
Voici une photo de l'ensemble du robot, le module de commande n'étant pas fixé sur le module de propulsion:
Image IPB


Contrôle des moteurs
Les moteurs sont contrôlés par deux puces L293D. Les deux sont en parallèle, car elles peuvent fournir 600mA au maximum par canal, alors que les moteurs en demandent 800. J'ai donc connecté les deux puces en parallèle, elles peuvent ainsi fournir jusqu'à 1200mA par canal, ce qui est largement suffisant. Le Raspberry Pi est connecté à un MCP23017, qui ajoute 16GPIO, et le MCP23017 est connecté aux L293D. Dans l'absolu, on peut se passer du MCP23017, et connecter directement les L293D aux GPIO du Raspberry, mais j'ai choisi d'utiliser cette puce, car j'en ai au moins une pour chacun de mes Pi, et que cela permet d'envisager des extensions ultérieures, en ajoutant par exemples des boutons sur les coins pour détecter d'éventuels contacts.
On peut voir le montage ci dessous :
Image IPB

Capteurs et détection des obstacles
Le principe du fonctionnement est donc d'éviter les obstacles détectés. Pour cela, j'utilise un Maxbotix LV-EZ4, qui détecte les objets grâce à un faisceau à ultrasons entre 6 pouces (environ 15cm) et 6 mètres. Le Pi est connecté à un convertisseur analogique vers numérique (un MCP3008), qui permettra de récupérer les données analogiques du capteur de distance. Le capteur ayant une sortie linéaire, la mesure est directement proportionnelle à la distance.
La puce de gauche sur la photo du dessus est le MCP3008, et on peut voir le capteur de distance à ultrasons sur la photo suivante, à l'avant du robot:
Image IPB
A noter que le gros oeil rouge ne fait pas partie du robot, c'est simplement un autre Raspberry pi.



Alimentation électrique et autonomie
J'ai testé l'autonomie d'un Raspberry Pi modèle alimenté par 5 batteries AA et un convertisseur de tension efficate, et streamant un flux webcam en wifi. Vous trouverez plus de détails sur ce post sur un autre forum (lien externe). On obtenait 3-4 heures d'autonomie. Ici, si on garde la clé Wifi, la consommation devrait être approximativement la même, environ 800mA. La consommation maximale de chaque moteur est de 800mA, ce qui fait qu'en théorie, si les moteurs forcent au maximum en permanence, nous diviserons l'autonomie par 3, soit environ 1h à 1h20.

En pratique, on peut s'attendre à ce que les moteurs ne forcent pas à fond en permanence, donc en étant conservateurs, disons qu'ils seront à 50%.
Cela signifie que nous aurons donc 800mA de consommation pour les deux moteurs, donc un total de 1600mA. Les batteries étant données pour 2700mAh,
on obtient donc théoriquement 2700/1600=1h36minutes. En pratique, si on divise par 2 l'autonomie du pi tout seul, on obtient 1h30 à 2h d'autonomie théorique, donc ça colle assez bien.

Ici, je parle d'un scénario ou le robot roulerait en permanence... En pratique, on peut également s'attendre à ce qu'il ne se déplace pas tout le temps, s'il fait des tâches diverses. Dans ce cas, on gagnerait encore en autonomie. Mais on a une estimation de l'autonomie minimale
Vous pouvez voir sur les images suivantes (cliquables pour une version HD) les batteries et le convertisseur :

Image IPBImage IPB



Le programme
Le programme du robot est alors assez simple, puisqu'il s'agit de l'algo suivant :
boucle infinie :
distanceObstacle=lireDistanceCapteurUltrasons();
Si (distanceObstacle<8pouces) reculer;
Sinon Si (distanceObstacle<12pouces) tourner à gauche;
Sinon avancer;
Attendre(5ms);

Le code est fait en python, et le robot évalue les données toutes les 5ms.
L’étroitesse du faisceau cause quelques problèmes, il faudra sans doute adapter
les distances, ou monter le détecteur sur un servomoteur pour l'orienter.

Plan du tutoriel
Après cette présentation du robot, voyons le plan du tutoriel.
Nous verrons d'abord en page 2 comment choisir les composants du robot, et nous choisirons une configuration type.
Nous verrons ensuite en page 3 le schéma fonctionnel du robot, ainsi que le schéma de la partie électronique.
En page 4 nous détaillerons les instructions d'assemblage et des idées pour faire un châssis économique et solide.
Enfin, en page 5, nous programmerons notre robot qui sera alors assemblé.








=================================================================================================================
=================================================================================================================
=================================================================================================================

Partie 2 - Faire un robot simple mais extensible avec le Raspberry Pi : le choix du matériel
Dans cette partie, nous étudierons une liste de matériel, pièces, et alternatives possibles. Ce n'est pas le robot ultime, ni un cylon, mais un petit robot sympa, sur lequel
on peut se faire la main, et prévu pour pouvoir beaucoup évoluer. Notez bien qu'ici je vais vous présenter une longue liste de matériel, mais que je retiendrai une configuration pour la suite.
Si vous choisissez d'autres solutions, il y aura nécessairement un peu d'adaptation à faire, mais rien d'extrêmement compliqué.
Pour un robot simple, il faut:
  • un système de propulsion;
  • De quoi transformer la rotation des moteurs en mouvement horizontal;
  • un circuit de commande;
  • un système fournissant l'alimentation électrique;
  • éventuellement des capteurs.
Voyons donc ce qu'il faut en faisant "pas cher" (sachant que tout sera réutilisable).


1-Le système de propulsion : motorisation
On part sur un robot à conduite différentielle, c'est à dire disposant de deux moteurs. Pour avancer, les deux moteurs tournent dans le sens A, pour reculer ils tournent dans le sens B, et pour tourner on fait les deux tourner en sens inverse. On peut ainsi avancer, reculer, tourner à droite, et tourner à gauche.
En bref, il faut donc deux moteurs, ou tout autre système capable de tourner dans un sens ou dans l'autre. On a donc plusieurs solutions :
  • La récupération : les lecteurs CD/DVD possèdent chacun un petit moteur DC qui permet d'ouvrir/fermer le chariot, et ce moteur à une petite boite de vitesse. Mon premier robot, R.Berion, utilisait ce genre de systèmes. Il faut toutefois bidouiller un peu, mais c'est une solution qui permet de faire de la récup.
  • Des moteurs DC avec boite de vitesse : c'est une option durable et économique, ce genre de moteurs vaut environ 5$ pièce, donc on s'en sort pour 10$ sans compter les roues.
  • Des servomoteurs à rotation continue : on peut trouver des servomoteurs pouvant tourner à l'infini dans un sens ou dans l'autre. C'est la solution la plus chère, mais c'est extrêmement facile à contrôler, et on élimine le besoin d'avoir un circuit de commande supplémentaire. En revanche, chaque servo vaut environ 14$ sur Adafruit (soit une dépense nécéssaire de 28$), et ces servos ne peuvent pas servir à des usages classiques de servomoteurs, pour orienter un bidule quelconque, puisqu'on a plus d'informations sur l'angle ou est tourné le servo. Ils sont difficilement recyclables pour d'autres projets. D'autre part, on a finalement peu de contrôle sur chaque moteur, car on peut en gros les faire tourner dans un sens, dans l'autre, ou les stopper, mais pas trop contrôler leur vitesse de rotation (ou alors plus difficilement). En outre, il faut faire attention au sens de branchement, sous peine de les brûler. En revanche, ils ont pas mal de couple.
La solution de la récup est intéressante, le problème est donc de pouvoir fixer des roues dessus. Dans mon cas, j'ai trouvé un bout de plastique sur lequel je pouvais visser les roues de mes servos (dont j'avais grillé un des deux, et du coup avec un seul servo on ne peut pas trop avancer ^^). En revanche, comme c'est de la récup, rien n'interdit de coller un vieux CD sur l'axe de rotation pour faire la roue...
Et on peut ajouter un élastique sur le contour du CD pour faire un pneu et avoir un peu d'adhérence.

La solution des moteurs DC est ma préférée, car elle est économique, et pour le prix d'un servo, on a 3 moteurs DC, ce qui permet d'en avoir un de rechange par exemple, mais on peut facilement décider d'en prendre 4 ou 6 pour faire un véhicule à 4 ou 6 roues motrices. De plus, pour ces moteurs, il existe une très grande variété de roues et chenilles adaptées, et le système fait qu'on peut facilement changer les roues. Ces moteurs intègrent une boite de vitesse réductrice avec un rapport X:1, ce qui signifie que quand le moteur fait X tours, l'axe de la roue en fait 1. C'est très important, car sans cela, le couple serait trop faible,et le robot n'avancerait pas. Plus le rapport réducteur est important, moins les roues tourneront vite (et donc plus le robot sera lent), mais plus il aura de couple, et sera capable
d'emporter une charge importante/de continuer à avancer malgré des obstacles. Il existe des moteurs avec boite de vitesse metallique, mais c'est plus cher, au moins 15$ pour les plus petits (par contre, ils sont fatalement plus solides). Je conseillerais des "pololu plastic gearmotors" On en trouve principalement en 120:1 et 180:1. Prenez ceux qui ont le "3mm D-Shaft", il s'agit de l'axe du rotor, qui fait 3mm de diamètre, en forme de D. Prenez ceux qui ont l'axe en métal, ce sera plus solide. L'intérêt c'est qu'on a besoin de rien d'autre pour fixer les roues, et qu'en plus les roues s'enfoncent sur cet axe sans outil, et restent solidement en place. Et en plus il existe une très grande variété de roues adaptées à ces modèles. Je n'ai pas regardé pour les axes de 2mm, ni ceux en plastique. Et en plus, si plus tard vous décidez d'upgrader avec des "micro metal gearmotors", les roues seront compatibles. Pour moi l'idée c'est d'essayer de faire que tous mes robots puissent partager des éléments, ça rend la logistique plus facile Image IPB
 
Pour le choix du site, pololu a pas mal de bidules "robotique". En revanche, ils n'ont pas beaucoup d'autres catégories. Sur pololu, j'ai commandé uniquement mes moteurs et roues. Toutefois, Alpha-Crucis a les moteurs de pololu, leurs roues, mais également tout plein d'autres items. De plus, c'est un site français, qui vous expédie par colissimo, pour 5€ de FDP, et gratuitement au delà de 250€. Bien sur, pour les DOM, ça n'a rien à voir, mais ça reste modéré, avec 30€ de FDP pour une commande d'environ 250€, et je crois bien qu'ils m'ont décompté la TVA, ce qui revient au même (en Guadeloupe on est pas censés payer la TVA "normale", mais la douane peut prélever une taxe à l'arrivée. Toutefois, par colissimo et sur des montants de cet ordre, il ne le font presque jamais. En plus pour des composants électroniques, ça fait une facture avec des dizaines de références à petit coût, le douanier n'aura pas envie de lire tout ça pour calculer les taxes). Bref, j'ai commandé chez eux hier, et ils m'ont l'air vraiment bien, ça risque d'être mon second site apres Adafruit.Seul défaut, les fiches ne sont pas toujours complètes, mais le catalogue est énorme (ils ont AUSSI des trucs d'Adafruit!). Au passage, Snootlab va bientôt distribuer les produits pololu, donc encore une bonne source d'approvisionnement!

Enfin bref, ça fait 3.77€ par moteur sur Alpha-Crucis, ou 5.49$ par moteur chez Pololu. Il en faut au moins 2, donc ça fait 7.54€ pour les moteurs, ou 10.98$ sur pololu. Prenez en bien deux ayant le même rapport réducteur. Le "droit" ou "coudé", c'est à vous de voir. Le droit est plus long, mais moins large, le coudé c'est le contraire. Dans tous les cas, ça ne change pas grand chose, juste peut être l'organisation de l'espace. Moi j'en ai pris de chaque, mais j'aime bien les droits, parcequ'on peut facilement les coller sur le bord du châssis du robot sans avoir a découper le dit châssis. Mais on peut aussi fixer les coudés sous le châssis, sans faire de découpe... Bref, c'est un choix à faire.

2-Transformer la rotation des moteurs en mouvement du robot : transmettre la puissance à la "route".
Maintenant que nous avons des moteurs, il faut transmettre la puissance à la "route", pour faire bouger le robot. On a deux solutions simples :
  • Deux roues, qui seront accompagnées d'une troisième roue omnidirectionnelle (en fait, une bille dans un logement) qui servira de troisième point de contact -le nom anglais c'est "ball caster"-;
  • Des chenilles, qui sont auto-suffisantes.
Pourquoi choisir l'un ou l'autre? Les roues ont l'avantage d'être disponibles en de multiples dimensions, de 2-3cm de diamètre à presque 10. On en trouve des larges, des étroites, avec divers designs. Plus la roue sera grande, plus le robot ira vite. En revanche, le couple disponible sera moins important, puisque la distance à l'axe sera supérieure (le couple est exprimé en g-cm. Si votre moteur à un couple de 1kg-cm, il pourra faire tourner une charge de 1kg à 1cm, 500g à 2cm, etc.) Pour ma part, j'ai pris des roues de 4,6 et 9cm. Plus la roue est petite, plus le bas du robot sera proche du sol, et donc plus les obstacles pourront le bloquer. L'avantage de la roue est donc de pouvoir l'adapter au terrain visé, et pouvoir ainsi ajuster la vitesse/le couple du robot. L’inconvénient, c'est qu'il faut un troisième point de contact, le "ball caster". Et le ball caster franchit bien moins facilement les obstacles que les roues. Cependant, plus le Ball caster est gros, plus ça sera facile.
En face, les chenilles sont disponibles souvent en diverses longueurs, mais pas tellement pour des diamètres de roues différents. En revanche, la chenille est "tout terrain", et il ne faut rien d'autre que le kit de chenilles. Donc sur une surface irrégulière, et même avec des obstacles, la chenille pourra mieux se débrouiller. Elle devrait passer sans problème par dessus un gros câble d'alimentation de PC au sol, la ou la bille du ball caster pourrait rester bloquée. Et s'il s'agit d'aller sur du bitume, de la terre, ou autre, le Ball caster ne passera tout simplement pas. En revanche, la chenille sera sans doute plus lente, du fait du faible diamètre des roues d'entrainement de la chenille. De plus le système de chenille provoque une résistance, et réduit le couple disponible/augmente la puissance consommée pour un couple donné. Par contre la stabilité devrait être impeccable, et il n'y a presque aucun risque de se retrouver coincé.
Notez toutefois qu'avec 4 roues motrices, on évite la nécessite du Ball caster et on peut aller un peu partout, et franchir beaucoup d'obstacles avec de grandes roues. On peut également avoir 4 roues, dont deux motrices. Idéalement il faudrait que les roues non motrices puissent tourner, mais ça peut parfaitement fonctionner même si elles sont fixes.

En bref : en appartement, sur des surfaces relativement régulières, les roues et le ball caster seront plus efficaces, iront plus vite, et gaspilleront moins d'énergie que les chenilles. En revanche, celles ci sont plus adaptées au terrains difficiles, et peuvent franchir des obstacles divers facilement. De plus , si on a le kit de chenilles, il n'est pas nécéssaire d'acheter autre chose, et on a une surface de contact importante avec le sol pour transmettre la puissance, mais également une grande stabilité de ce fait. On risque peu de patiner, glisser, déraper... Sans compter le look "cool" des chenilles.

Donc, au choix :   
Des chenilles de 9cm de long, pour 8.91€ , et les mêmes chenilles de 9cm de long sur pololu pour 12.95$;
Des chenilles plus longues (12-15cm peut être) pour 10.28€ , et les mêmes chenilles longues sur pololu pour 14.95$;
 
Sachant qu'un seul kit est nécessaire, et contient les deux chenilles avec tout l'équipement qui va avec (les "roues" de 35mm d'entrainement et libres, les axes, etc), cela fait environ 9 ou 10€ selon la longueur souhaitée. Pour ma part, je pense qu'il faudrait idéalement que la chenille soit aussi longue ou un peu plus longue que le robot. Ainsi, la partie avant de la chenille peut entrer en contact avec l'obstacle, levant le robot, et permettant le franchissement. Si le bord du robot est devant la chenille, le bord pourra se coincer contre l'obstacle, et le robot ne pourra pas avancer.
OU BIEN
  • n'importe quelle paire de roues de cette section (donc pas les "idler sprockets", elles n'ont pas la fixation pour l'axe de moteur. Au mieux, ça peut faire des roues libres, si vous prenez également deux roues du même diamètre avec la fixation moteur, qui seront entrainées par les deux moteurs. Dans ce cas, vous aurez 4 roues dont 2 motrices, inutle de prendre le ball caster) . Les roues sont vendues par paire, inutile d'en acheter 2 fois Image IPB
  • n'importe quel ball caster de cette section (ou n'importe quel bal caster tout court!), sachant que les plus gros franchissent mieux les obstacles. Je penche pour les 1/2 pouce a 1 pouce.
Cela fait donc 7 à 10$ pour les roues selon la taille (une paire), plus 3 a 7$ pour le ball caster, soit 10 a 17$ pour une configuration complète de roues sur pololu.
Chez alpha-crucis, il faudra de la même façon prendre n'importe quel ball caster (roulette, en français, en fait!) de cette section, pour 2 à 6€;
et l'une de ces paires de roues :
 
De manière générale, les "Pololu wheels". Vérifiez qu'il y a le trou en "D" pour l'axe du moteur, de 3mm.
ça revient donc de 7 à 13.5€ pour les roues et la roulette. Les roues sont également vendues par paire. Pour le choix de la couleur, une couleur claire peut servir
à réfléchir un faisceau, ce qui pourra servir à faire un détecteur permettant de mesurer la rotation de la roue. Toutefois on peut aussi utiliser un faisceau de part
et d'autre qui sera interrompu par les montants de la roue s'il y en a... En pratique, on peut sans doute adapter n'importe quoi à n'importe quel système.
La couleur des roues peut également servir à reconnaitre les robots, ou si on a des roues de couleur différentes, à déterminer de quel coté on voit le robot
(dans une optique "computer vision", ou un algo analyserait avec openCV le flux d'une webcam, et pourrait identifier le sens dans lequel le robot se trouve par ex.
Mais on peut aussi mettre un autocollant différent de chaque coté, ou n'importe quoi d'autre.)

Si vous optez pour les servomoteurs à rotation continue, il faudra donc également prendre une roulette (n'importe laquelle ira), ou alors des roues libres.

3-Le circuit de commande, et des puces additionnelles facultatives
Nous avons des moteurs, des roues/chenilles adaptées, maintenant il faut commander tout cela. Pour appliquer l'algorithme de conduite différentielle, il faut un circuit capable
de faire tourner les moteurs dans un sens ou dans l'autre à volonté. Nous allons utiliser pour cela des circuits implémentant des ponts en H. On utilisera donc deux puces L293D
pour commander nos moteurs. Pourquoi deux? chaque puce L293D est donnée pour 600mA par canal. Les moteurs que nous avons sélectionné consomment jusqu'à 800mA
s'ils sont bloqués. En mettant les deux L293D en parallèle, on double la puissance disponible, avec du coup 1200mA par canal. On peut aussi prendre un seul L293D, et espérer
qu'il tienne le coup en cas de blocage des moteurs. ça devrait marcher, mais ce n'est pas un comportement garanti. Notez qu'en refroidissant les puces (un petit rad sur la puce)
on peut augmenter la puissance disponible, donc on peut également se contenter d'une puce mieux refroidie. Pour ma part, j'ai pris 2 puces pour avoir plus de puissance disponible,
et les puces étant peu chères, j'ai trouvé plus simple d'en prendre 2.

Il y a déjà un tutoriel sur l'utilisation de la puce L293D pour commander un ou deux moteurs avec le Raspberry Pi sur PCInpact (je le porterai sur ce forum plus tard). La seule différence est qu'ici nous mettrons les deux puces en parallèle. En pratique, le câblage sera le même, sauf qu'on ajoutera une seconde puce en connectant les pattes correspondantes des deux puces entre elles. Mais on verra cet aspect plus tard.

Si vous avez choisi les servomoteurs, ces puces ne sont pas nécessaires.
En pratique, il faudra donc :
  • Deux L293D pour 2.3€ pièce soit 4.6€ au total;
Il existe aussi les puces SN754410, qui sont compatibles broche à broche avec les LM293D (on peut donc utiliser exactement le même câblage d'après pololu). Dans la doc, je lis 1A de courant en sortie. Cependant, je ne parviens toujours pas à comprendre si c'est 1A au total, ou 1A par canal. Si c’est 1A par canal, alors cette puce permet de remplacer les deux L293D dans notre montage, si c'est 1A au total, elle n'a aucun intérêt par rapport aux L293D. J'en ai pris 3, mais je ne les ai pas encore testées. Vous pouvez tenter, si vous comprenez mieux la doc que moi, faites moi signe. j'écrirai à Pololu pour leur demander. Sinon dans le doute, les L293D, je peux vous confirmer qu'elles fonctionneront pour le circuit, pour les avoir testées sur 3 prototypes de robots. Mais si vous commandez chez pololu, seule la SN754410 est disponible, et du coup je vous conseille d'en prendre au moins 2 pour être sur (deux en parallèle, et pourquoi pas une troisième au cas ou, en stock).
Dans tous les cas, le schéma de câblage sera le même.

Ajouter des GPIO au Raspberry Pi (optionnel, mais pratique, facile, et peu coûteux)
Sur le schéma que je vous fournirai dans un premier temps il y aura également une puce MCP23017, qui permet d'ajouter 16GPIO (je ferai un second schéma simplifié sans cette puce). Il est possible de se passer de cette puce, le souci c'est que les puces de contrôle des moteurs utilisent 5 à 6 GPIO sur les 17 du Pi. Avec le MCP23017, on utilise 2GPIO spécifiques, qui restent de plus utilisables par d'autres puces, et on ajoute ainsi 16GPIO protégés, pouvant qui plus est fournir plus de courant que les GPIO normaux. Cette puce ne coûte pas très cher, puisque le MCP23017 est à 2.88€ sur Alpha-Crucis. Si cette puce est trop grosse,
mais que vous voulez quand même utiliser ce principe (ajouter des GPIO protégés), il est possible d'utiliser un MCP3008, qui coute 1.95$ sur Adafruit et ajoute 8GPIO et moins de pattes.

J'ai fait un tutoriel sur le forum de PCInpact sur l'ajout de GPIO au Raspberry Pi en utilisant le MCP23017 ou le MCP23008.

Ajouter un circuit convertisseur analogique-numérique pour lire des capteurs analogiques (optionnel, mais très pratique, simple et économique)
De même, sur le schéma d'un robot de base, je vais utiliser une puce MCP3008, qui permet d'ajouter 8 entrées analogiques au Raspberry Pi. Cette puce n'est pas nécessaire,
et on peut faire un robot télécommandé/contrôlé à distance/utilisant une webcam pour se déplacer, de sorte que le robot n'aura pas de capteurs analogiques à lire.
Toutefois, je recommande fortement cette puce, car le MCP3008 est à 3.22€ sur Alpha-Crucis, et pourrait permettre d'ajouter une grande variété de systèmes extrêmement utiles. Par exemple,
un capteur de distance pour détecter automatiquement les obstacles, mais aussi un capteur infrarouge orienté vers le sol devant le robot, qui permettrait de détecter les trous
pour éviter de tomber dedans, ce qui peut être utile même en contrôle manuel. On peut imaginer toutes sortes de capteurs qui permettraient au robot de s'adapter automatiquement
à diverses situations, ou même tout simplement un capteur de courant pour que le robot puisse mesurer sa consommation, on peut utiliser la puce pour mesurer la tension
des batteries et estimer l'autonomie restante, ou encore utiliser des capteurs divers pour mesurer le nombre de rotations des roues, un accéléromètre, gyroscope ou autres
pour avoir des infos sur le déplacement du robot... Bref, une puce très utile, rajoutant donc 8 entrées analogiques, en échange de 4GPIO.

Il y a un tutoriel sur la façon de connecter un MCP3008 au Raspberry pi pour lire des valeurs analogiques sur le forum de PCinpact, et d'autres tutoriels montrant comment connecter des capteurs dessus (luminosité (lien externe), température (lien externe), distance (lien externe), ...)

4-L'alimentation électrique de l'ensemble
Maintenant, il faut alimenter le Raspberry Pi, mais également les moteurs. Pour cela, il faudra une source électrique de 5V, stable, pour le Raspberry Pi, et
une source de 5 ou 6V non régulée pour les moteurs. On aura besoin d'une puissance de 700mA au minimum pour le Pi, et 800mA au maximum par moteur,
soit 1600mA au maximum pour les moteurs. Il nous faut donc une source capable de débiter 2300mA ou plus. Avec des piles AA rechargeables, il nous en faudrait 5
de 2300mAh ou plus. avec des piles non rechargeables, 4 suffiront. Si on alimente tout avec des piles rechargeables, il faudra un régulateur de tension pour le Raspberry Pi.
La meilleure option que j'ai pu trouver jusqu'ici, c'est le régulateur S7V7F5 de chez pololu, qui vaut 4.95$, et est une petite merveille. Il peut fournir du 5V à partir de tensions allant de 2.7 à 11.8V. Si il fournit une tension supérieure à la tension d'entrée, il peut fournir 500mA. Si il baisse la tension, il fournit 1000mA. Il est réellement minuscule, et ne consomme rien (0.1mA) quand il ne fait rien. Son efficacité énergétique est de 90%, ce qui veut dire qu'il ne gaspille que 10% de l’énergie fournie pour la conversion.Dans le même style, chez Alpha-Crucis, il n'y a malheureusement que le D15V35F5S3, pour 10€. Il est bien plus cher, et ne peut réguler la tension qu'à la baisse, mais a toujours une
efficacité de 90%. Il est un peu plus gros, mais en échange peut fournir jusqu'à 3.5A. On peut donc imaginer s'en servir pour réguler une batterie plus grosse et plus puissante,
et fournir 5V au pi, aux moteurs et à tout autre système 5V.

Une autre solution, très économique, mais peu efficace, est d'utiliser un simple régulateur linéaire, comme le 7805, à 1.2€ sur Alpha-Curcis, très simple a utiliser, mais nécessitant une tension d'entrée plus importante (7V au moins) et gaspillant une partie plus importante de l'énergie, puisque la différence de tension entre l'entrée et la sortie est consommée avec le même courant que ce celui qui est consommé en sortie. Donc à 1A, pour une entrée de 7V, on consomme 2W pour la régulation, et cette énergie est gaspillée en chaleur. La puissance utile disponible est donc de 5W, ce qui fait qu'on gaspille 40% de l'énergie.

On peut également utiliser une source 5V et se passer des régulateurs, comme nous le verrons plus bas.

Il faudra alors un endroit ou mettre les batteries, par exemple:

    Un compartiment pour 6 batteriesAA, qu'on modifiera un peu pour n'en utiliser que 5, pour 4€
    Un compartiment pour 2 batteries AA en série avec un compartiment pour 3 Batteries AA, pour un peu moins de 3€ au total.

Il existe une dernière solution, c'est d'avoir une batterie régulée 5V, telle que celle ci sur Alpha-Crucis, pour 22€. Elle peut fournir 5V avec 2A en sortie, ce qui sera assez pour à la fois
alimenter le pi et les moteurs dans la plupart des cas. Il manque 10% de puissance, mais ça devrait passer. J'en ai commandé 2, je ferai l'essai. Toujours en utilisant cette batterie, il est
également possible d'ajouter une trappe de 4 Batteries AA pour l'alimentation des moteurs (non régulée), et d'alimenter le Pi avec la batterie 5V régulée. Dans les deux cas, on se passe
du régulateur de tension. L'utilisation d'un pack de 4 Batteries AA permet de séparer les deux sources d'alimentations, et c'est en théorie mieux. L'intérêt de la batterie régulée, c'est
qu'elle utilise des batteries au lithium qui sont plus légères à capacité égale. On gagne donc sur la masse du robot, et on peut sans doute démonter la batterie pour enlever le panneau solaire, et
la coque pour réduire la taille si on veut. Attention toutefois au batteries, celles au Lithium étant fragiles et dangereuses quand on les malmène.

Il y a un post décrivant un montage utilisant des batteries AA et un régulateur de tension pour alimenter un Raspberry Pi autonome, ainsi que des tests d'autonomie (lien externe).

5-Les capteurs
On peut se passer de capteurs, et télécommander le robot. On peut également utiliser une webcam pour analyser les images et se déplacer ainsi (plus complexe, il faut maitriser openCV ou autres librairies de vision informatique)
Il est cependant possible d'ajouter des capteurs simples, tels que des capteurs de distance en infrarouge, ou à ultrasons, pour détecter les obstacles Le cout sera de 10 ou 20€.
On peut également utiliser des poutons poussoirs pour faire des capteurs de contact. n'importe quel bouton poussoir fera l'affaire, mais certains sont plus adaptés, tels que ceux ci :
 
    Microswitch avec levier long, pour environ 1.25€
    Microswitch avec levier à roulette, pour 1.6€.
 
Avec deux de ces switches, on peut détecter de quel coté se trouve l'obstacle, et ainsi éviter les obstacles. Pour ces switches, on a pas besoin d'utiliser le convertisseur analogique, uniquement des entrées numériques.
On peut ensuite ajouter de nombreux autres capteurs, par exemple pour détecter les trous, avec un capteur infrarouge à faible portée, un accéléromètre, un gyroscope pour le guidage inertiel, etc...

On peut également trouver des capteurs purement numériques, dont certains utilisent par exemple le protocole I2C pour communiquer. Dans ce cas, on utilisera pas le MCP3008.

Voici au passage un petit récapitulatif sur les divers capteurs les plus courants.
Il y a également un tutoriel sur la lecture d'un bouton poussoir (pour les microswitches), et un autre tutoriel sur l'utilisation d'un capteur de distance ultrasonique ou infrarouge.

Récapitulatif
En fin de compte, voici des "packs" mis a jour, récapitulant le matériel nécéssaire.
Il nous faut bien sur un Raspberry Pi, des jumper wire, une breadboard, une carte SD avec Raspbian (ou autre) dessus, et le câble d'alimentation. Je ne reviendrai pas
la dessus, si vous en êtes à faire un robot, c'est que vous avez déjà probablement ces composants et sans doute déjà essayé divers montages. Passons donc maintenant
aux éléments spécifiques au robot.

Robot de base, avec moteurs DC et chenilles
Il nous faudra donc :
 
    Deux puces L293D - 4,5€
    Deux moteurs DC 120:1 ou 180:1 - 7.5€
    Un kit de chenilles - 10€
    Un circuit à d'alimentation 1-10€
    Une boite à batteries AA - 2€
    5 Piles AA rechargeables - 10€
 
Ces composants sont les composants minimaux pour faire ce robot à chenille. En l'état, il n'aura pas de capteurs, et ne pourra donc être que télécommandé.
On a donc un total de 44€ au maximum si l'on compte les batteries AA. Une autre solution est de remplacer le circuit d'alimentation, la boite à batteries et
les piles rechargeables par une batterie portable USB, ce qui revient à 22€, soit un total d'exactement 44€.

Robot de base, avec moteurs DC et roues+roulette
On conserve le même matériel que pour le précédent, sauf qu'on remplace les chenilles par des roues et une roulette :

    petites roues larges 42*19mm - 5€
    roulette d'un demi pouce, en plastique - 3€

Du coup on passe a 42€.
On peut utiliser de plus grandes roues :

    grandes roues 90*10mm - 7€
    roulette de 0.75 pouces en métal - 3.3€

Pour cette variante, le prix reste à 44€.

Options
Voyons maintenant quelques options intéressantes, qui seront utilisées pour le prochain tutoriel :

    Le MCP3008 pour lire les valeurs de capteurs analogiques, +3.22€
    Le MCP23017 pour ajouter 16GPIO protégés, + 2.88€

Ces deux puces extrêmement utiles augmenteront la facture de 6.1€, ce qui nous fait un total de 50€.
On peut enfin ajouter des capteurs :

    deux Microswitch avec levier long, pour un total de +2.5€
    Un capteur de distance Ultrasonique +20€ ou à infrarouges, +10€
On ajoute donc 22.5€ ou 12.5€ pour un grand total de 72.5€ au maximum (62.5€ en infrarouge, 52.5€ avec juste les capteurs de contact).

A partir de là, vous avez tout le matériel nécessaire à la construction d'un robot (plus ou moins autonome selon les capteurs), et pour chaque élément utilisé, il y a un tutoriel dans (ce fil de discussion (lien externe)). Je vais toutefois faire d'autres tutoriels, spécifiques, reprenant dans les grandes lignes ce qu'il faut faire pour monter ce robot, le programmer, et l'améliorer.


La partie suivante sera consacrée au schéma de principe du robot, et au schéma de montage électronique.




=================================================================================================================
=================================================================================================================
=================================================================================================================
Partie 3/5 : schéma de principe et montage électronique du robot.
Nous allons maintenant détailler le principe général du robot, avant de voir le schéma électronique.
Nous reprenons donc les pièces dont nous avons parlé juste avant, dans la seconde partie.

Pour ce modèle, nous partons sur un robot à deux moteurs (roues ou chenilles, le montage électronique est le même!
Pour cet exemple, le robot sera représenté avec des chenilles, mais le principe est valable pour 2 roues motrices et deux roues libres,
deux roues motrices et une roulette, ou des chenilles. L'important est que les roues motrices doivent être entraînées par des moteurs DC.)

Principe de fonctionnement
Voyons maintenant le principe de fonctionnement général. Pour cela, voici un schéma fonctionnel :
Image IPB

Le Raspberry et l'alimentation
Nous avons donc un Raspberry Pi, modèle A ou B. L'alimentation électrique provient d'une source 5V régulée depuis 5 Batteries AA. Cela nous permet d'avoir entre 5 et 6V (selon la charge des batteries) pour le moteur, et 5V pour le Raspberry Pi. Il est bien sur possible d'utiliser deux sources séparées, ou toute autre configuration compatible avec vos moteurs.

Le MCP23017 : plus de GPIO.
Le Raspberry Pi est connecté à un MCP23017 via le bus I2C, et rajoute 16GPIO. Cela nous permet de prévoir large, et de pouvoir étendre les capacités du robot.
On pourra ainsi, par exemple, ajouter des bumpers (boutons poussoirs) pour détecter les collisions. Comme nous avons 16 GPIO, on peut donc en mettre une bonne quantité, d'autant que ces capteurs sont peu chers.

La commande des moteurs : les L293D
Deux puces L293D sont branchées en parallèle, et connectées à 5 ou 6 broches du MCP23017 (dans le schéma, je connecterai à 6 broches. Cela permet de pouvoir faire fonctionner séparément un moteur ou l'autre. De base, ce n'est pas utile, et on peut commander l'activation des deux moteurs avec un seul GPIO, et simplifier légèrement la programmation. Toutefois, utiliser deux GPIO nous permettra de programmer plus précisément les déplacements, la rotation, et par exemple ajuster la vitesse de chaque roue indépendamment).
Les L293D sont connectés via 4 fils aux deux moteurs, et les commanderont par ce biais. Au passage, les batteries sont connectées directement aux L293D (sans régulation donc) pour fournir le +Vmotor, la tension qui sera appliquée aux moteurs.

Lecture de capteurs analogiques : MCP3008.
Le MCP3008 est connecté au Raspberry par le bus SPI, et permet d'ajouter 8 entrées analogiques. Nous pourrons donc lire les valeurs de 8 capteurs analogiques de cette façon. En pratique, pour ce modèle, nous utiliserons un capteur ultrasonique Maxbotix (cela fonctionne avec d'autres capteurs ultrasoniques), mais il est possible d'utiliser un capteur de distance infrarouge avec le même montage, et un code source sensiblement similaire. Le capteur de distance sera utilisé pour détecter les obstacles. Si toutefois vous décidez d'utiliser uniquement des switchs pour la détection de contact, le MCP3008 n'est plus nécessaire.

Schéma électronique du robot
Voyons maintenant le schéma électronique du robot, décrivant le câblage à réaliser pour faire fonctionner notre robot:
Image IPB
Si vous suivez ce câblage, vous disposerez d'un robot fonctionnel. Une seule chose n'est pas présente sur ce schéma : la méthode utilisée pour mettre les deux L293D en parallèle. Pour cela, il suffit de connecter la patte 1 de la puce A avec la patte 1 de la puce B, et ainsi de suite pour les 15 autres pattes. C'est assez simple à faire avec du jumper wire. Cela permet de cumuler la puissance disponible pour les deux puces.

Il est à noter qu'il s'agit d'UN schéma de câblage possible, mais on peut utiliser n'importe lesquels des GPIO du MCP23017. J'ai utilisé ceux que vous voyez sur le schéma afin de faire en sorte que celui ci soit le plus lisible possible, en minimisant les croisements.

Je ne détaillerai pas outre mesure les câblages, car il s'agit simplement d'une synthèse de tutoriels (liens externes): =================================================================================================================
=================================================================================================================
=================================================================================================================
Partie 4/5 : montage pratique du robot : construction d'un châssis, fixation des roues, etc.
Matériel et matériaux nécessaire
Poursuivons donc sur la configuration précédente. Dans cet exemple, on utilisera deux roues et une roulette.
Avant tout résumons le matériel :
  • Un Raspberry Pi;
  • Une grande breadboard ;
  • Deux L293D;
  • Un MCP23017;
  • Un MCP3008;
  • Un Maxbotix LV-EZ0, 1, 2, 3, ou 4 , ou bien un capteur infrarouge, ou tout autre capteur de distance (facultatif, si vous utilisez uniquement les capteurs de contact);
  • Du fil électrique (pour électronique, pas du gros câble);
  • Une trappe pour 6 batteries AA;
  • Deux roues;
  • Une roulette;
  • Une carte SD;
  • Du jumper wire;
  • un convertisseur DC-DC fournissant du 5V
  • Une planche de bois d'environ 20cm*15-20cm;
  • Une petite planchette pour visser la roulette (récupérez une chute, par ex un bout de 5*5cm);
  • Des vis à bois de 3mm de diametre, et de 12-20mm de long;
  • Deux petites plaques de plexi, plastique, ou n'importe quel matériau que vous pourrez coller sur les moteurs;
  • un câble micro-USB;
  • Un adaptateur power jack-USB (on peut s'en passer si on couple le câble USB pour accéder directement aux fils +5v et à la masse);
  • Un power Jack (on peut également s'en passer dans le même contexte);
  • Deux switches pour les capteurs de contact (facultatif, si vous n'utilisez que le détecteur à distance).
Pour les outils, il nous faudra :
  • Un tournevis;
  • Des ciseaux ou une pince à dénuder/pince coupante;
  • Potentiellement un fer à souder et de l'etain, mais on peut faire sans en torsadant les fils entre eux;
  • De la colle adaptée pour coller les moteurs à leurs supports (j'ai utilisé de la super glu, pour coller le corps en plastique du moteur au plexi).
  • Éventuellement une perceuse si vous prenez des plaquettes de plexi, en bois on peut visser sans percer.
Nous avons maintenant tout ce dont nous pouvons avoir besoin, on peut commencer le montage.

Installation des roues et de la roulette.
La première étape sera de coller les petites plaques sur le corps des moteurs, comme sur ces photos :
Image IPB Image IPB
Vous pouvez voir que dans mon cas, j'ai utilisé du plexiglas, et il y a deux trous qui permettront de fixer le moteur sur le châssis.

Pour le châssis, j'ai simplement pris une planche de bois. On peut voir sur l'image ci dessous que j'ai tracé un trait permettant de
placer les deux moteurs au même niveau, et également un trait perpendiculaire au milieu pour centrer la roulette.
Image IPB
On peut alors visser les moteurs sur le châssis :
http://nagashur.com/...537-300x194.jpg

Pour la roulette, nous allons d'abord visser le support de la roulette sur une planchette, avant de mettre la bille de la roulette en place et de visser la planchette sur le châssis:
http://nagashur.com/...538-150x150.jpg http://nagashur.com/...539-150x150.jpg http://nagashur.com/...540-150x150.jpg http://nagashur.com/...541-150x150.jpg

L'installation des roues sur les moteurs est très simple, car l'axe des moteurs à un profil en D, et il y a un trou de la forme correspondante au centre de la roue.
Il suffit donc d'enficher la roue sur l'axe. On peut donc facilement installer et changer les roues facilement:
http://nagashur.com/...542-300x300.jpg http://nagashur.com/...543-300x221.jpg http://nagashur.com/...553-300x188.jpg
Le moteur est soudé à des fils, avec au bout un connecteur femelle de "jumper wire". J'ai simplement pris deux câbles femelle-femelle, et je les
ai coupés en 2. Il suffit de dénuder le bout coupé, et de le fixer sur le moteur, idéalement, en le soudant.




Partie électronique
Passons maintenant à l'installation des divers éléments électroniques sur l'autre face du châssis.
La breadboard principale contient le régulateur de tension, avec les fils partant vers les batteries, et le jack de sortie,
le MCP23017, le MCP3008, et les deux L293D. Des câbles partent également vers les moteurs, les capteurs, et le Raspberry Pi.
Image IPBImage IPB
Sur l'image de gauche, on voit l'ensemble de la breadboard, et sur celle de droite, on peut voir la méthode utilisée pour
mettre en parallèle les deux L293D : des fils rigides connectent les pattes d'une puce à celle de l'autre. J'ai utilisé une bobine
de fil de fer gaîné pour réaliser ces connections.

Pour fixer la plaque, j'ai utilisé 4 vis à bois, vissées directement dans le bois du châssis. Elles sont vissées de part et d'autre des ergots sur le haut
de la breadboard, de façon à la caler horizontalement. Deux vis en bas bloquent la breadboard dans le sens vertical, de sorte que maintenant celle ci
ne bouge plus :
Image IPBImage IPBImage IPB

On fixe maintenant le Raspberry Pi lui même sur le châssis, en vissant celui ci avec deux vis, en passant par les deux trous prévus à cet effet sur le Raspberry Pi:
Image IPB
On peut maintenant fixer le logement des batteries AA sur le châssis. On notera que sur les 6 emplacements, l'un d'entre eux ne contient pas de batterie,
mais un fil à la place, ce qui permet d'obtenir du 6V au lieu d'avoir du 7.2V. Le logement est vissé au châssis par deux vis, par les trous prévus à cet
effet:
Image IPBImage IPB
Il nous faudra également un câble jack vers USB et un câble micro-USB:
Image IPB
Cependant, il est également possible de couper le câble USB, et d'accéder directement aux fils +5V et masse. Dans ce cas, l'adaptateur USB-PowerJack et le jack power mâle sont superflus.


Les capteurs
Passons maintenant à l'installation des capteurs.
Le capteur à ultrasons est simplement vissé sur la face avant du châssis, et les capteurs de contact sont vissés sous le châssis.
Les boutons poussoirs qui servent de détecteurs de contact possèdent des trous par lesquelles peuvent passer les vis servant à les fixer :
Image IPBImage IPBImage IPB

Le tout en place
On peut voir sur les images ci dessous la disposition des éléments lorsque l'ensemble est en place:
Image IPBImage IPBImage IPB
On note sur la photo de droite que les diodes d'état, et la diode de la clé wifi sont visibles depuis le dessus du robot.

Option Webcam
On peut également ajouter une webcam, sur l'un des ports USB. Pour cela j'utilise une petite équerre en acier, vissée sur
le châssis, sur laquelle la webcam s'accroche :
Image IPBImage IPB













=================================================================================================================
=================================================================================================================
=================================================================================================================
Partie 5/5 : Programmation d'un robot Raspberry Pi R.Cerda pour une exploration automatique avec évitement d'obstacles.
Il est maintenant temps de transformer cet assemblage de matériel en un vrai Robot. Pour cela, nous allons maintenant voir l'ultime étape : la programmation. Nous verrons trois algorithmes, du plus simple au plus avancé. Cela devrait vous permettre d'avoir une base pour programmer votre robot comme vous le souhaitez, et pourquoi pas quelques idées Image IPB/>

Commençons tout de suite, en rentrant dans le vif du sujet. Ce robot utilise le MCP23017 pour commander les L293D qui à leur tour commandent les moteurs. J'ai donc choisi python pour écrire le programme des robots, puisque c'est sur cette base que nous avons vu l'utilisation du MCP23017.
En premier lieu, voici le lien vers le GitHub ou je met les divers fichiers relatifs au code du robot Cerda.

Dans ce dépot, vous trouverez divers fichiers, donc la classe I2C d'Adafruit, et la classe permettant de gérer le MCP23017.
Assurez vous d'avoir ces deux fichiers dans le répertoire contenant les fichiers de votre robot, ils sont nécéssaires pour son fonctionnement,
et doivent être importés dans le script du programme de votre robot.
Vous noterez également un script robotStop.py, qui sert simplement à arrêter les moteurs du robot. Sur mon raspberry pi, j'ai fait un alias de ce script vers la commande stop, ce qui fait que je peux arrêter le déplacement du robot en tapant stop dans un terminal, n'importe ou.

Divers scripts sont présents, pour tester divers éléments : N'hésitez pas à tester vos capteurs avant de lancer le robot, pour vérifier si tout va bien. J'intégrerai également ultérieurement des scripts pour tester les moteurs.

Passons maintenant au programme principal du robot lui même. Voyons d'abord vite fait l'algorithme :
dans une boucle infinie, on répète les instructions suivantes :
Lire la distance mesurée devant le robot par le capteur à ultrasons.
Si cette distance est inférieure à 8 pouces, on recule.
Sinon, si cette distance est inférieure à 16 pouces, on tourne,
Sinon, on avance.

Et c'est tout! Ce simple algorithme suffit déjà à permettre au robot d'éviter des obstacles!
Cet algorithme est implémenté dans le programme r1.py, dont la source se trouve sur le GitHub.

Je vais détailler un peu le code. Au début, vous verrez tous les "import", qui récupèrent les fonctions nécéssaires.
En dessous, vous retrouverez notre fonction "readadc", que nous avons vue avec le MCP3008 (le tuto sur cette puce est disponible ici), qui nous permet de lire une entrée analogique (ici le capteur à ultrasons) sur les 8 que propose le MCP3008. Voyez donc ces deux liens pour plus de détails sur le sujet. En dessous viennent les variables définissant les broches utilisées pour le SPI; je vous renvoie encore aux précédents tutoriels pour plus d'explications. SI vous avez suivi les schémas de montage de R.Cerda, il n'y a rien à changer ici.

Vient ensuite le corps du programme à proprement parler. Vous verrez alors une série de fonctions, dont la fonction "readDistanceInch", qui permet de récupérer la distance en pouces plutot que la valeur brute. SI vous utilisez un autre capteur, il faudra adapter (ou bien utiliser la valeur brute, en faisant des essais). Les fonctions suivantes servent à commander directement le robot :
def moveForward(m1a,m1b,m1e,m2a,m2b,m2e):    
mcp.output(m1a, 1)    
mcp.output(m1b, 0)    
mcp.output(m1e, 1)    
mcp.output(m2a, 1)    
mcp.output(m2b, 0)    
mcp.output(m2e, 1)
Cette fonction par exemple permet mettre les broches de commande du moteur 1 à 1 et 0, la broche enable à 1 pour activer ce moteur, et idem pour le moteur 2. J'ai fait ces fonctions, car si le câblage change, il suffira de modifier les valeurs dans ces fonctions plutot que dans le main. De la même manière, on a une fonction pour reculer, arrêter les moteurs, tourner à gauche, et à droite.
Cette fonction ne définit pas la durée pendant laquelle vous voulez faire une action. Une fois que vous appelerez l'une de ces fonctions, le robot continuera à exécuter cet ordre jusqu'à ce que vous l'arrêtiez. Ce qui veut dire que si vous souhaitez avancer d'une petite distance, vous devrez faire:
moveforward(...)
time.sleep(X)
stopMotors(...)


Plus bas, je définis les broches sur lesquelles sont connectés les détecteurs de contact, et deux fonctions pour lire leur valeur. En pratique, ces fonctions retournent 0 si le contact n'est pas pressé, et 1 si il est pressé, au lieu de 0 si le contact est pressé, et une valeur non nulle dans le cas contraire.

Les broches du MCP23017 qui commandent les deux moteurs sont définies juste en dessous, et on peut alors mettre les broches en sortie pour les moteurs, ou en entrée pour les détecteurs de contact.[/left]
Passons maintenant au corps du programme en lui même :
try:
#boucle principale et infinie du moteur
while (True):
#lecture de la distance de l'obstacle le plus proche
d=readDistanceInch(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
#en dessous de 8 pouces, le robot recule pendant au moins 0.2s
if(d< 8):
    moveBackward(m1a,m1b,m1e,m2a,m2b,m2e)
    #time.sleep(0.2)
#entre 8 et 16 pouces, le robot tourne pendant au moins 0.2s
elif(d<16) :    turnLeft(m1a,m1b,m1e,m2a,m2b,m2e)
    time.sleep(0.2)
#le reste du temps le robot avance pendant 0.05s
else :
    moveForward(m1a,m1b,m1e,m2a,m2b,m2e)
time.sleep(0.05)
    except KeyboardInterrupt:
print "" print "stopping motors"
stopMotors(m1a,m1b,m1e,m2a,m2b,m2e)
print "motors stopped, exiting."
sys.exit(0)
Vous noterez un bloc try et un bloc except. La partie dans "try" est le code du robot à proprement parler.
Il s'agit de l'implémentation de l'algorithme décrit plus haut. On notera toutefois que j'ai introduit un délai quand le robot tourne, pour l'obliger à tourner au moins d'un certain angle. Comme mon robot est large et avec des angles proéminents, ça lui évite de coincer ses coins sur les bords de l'obstacle. La durée d'attente dépend de votre robot, à vous de tester!
Dans tous les cas, avant de recommencer, j'ai mis un temps d'attente de 50ms, à vous de voir si ça vous convient également. C'est une attente que j'ai mise qui correspond à la fréquence de rafraîchissement du capteur de distance que j'utilise.

Le bloc "except KeyboardInterrupt" sert à gérer le CTRL+C qu'on utilise pour quitter le programme. Dans la précédente version, il n'y avait pas ce bloc, et du coup, quand on faisait CTRL+C pour arrêter l'exécution de l'algorithme, le robot restait bloqué sur la denrière instruction, par exemple, avancer, jusqu'à ce qu'on lance la commande robotStop.py.

Ici, il arrêtera les moteurs avant de quitter le programme.

Voici en pratique ce que donne cet algorithme sur mon R.Cerda, sur youtube[/url].


La seconde version de ce code, r2.py, cette fois, tient compte des capteurs de contact, qui sont prioritaires sur le capteur à ultrasons (si un contact est détecté, alors le robot recule, puis tourne dans la direction opposée, quoi que dise le capteur à ultrasons).
Le reste du code est le même qu'avant.

Voici maintenant d'abord le second algorithme tel que décrit ici[/url].[/left]


Nous avons également une troisième version, r3.py, qui introduit le fait qu'au lieu de toujours tourner à droite, le robot tourne un certain nombre de fois du même coté, puis commence à tourner dans l'autre sens pour éviter les obstacles. Il compte comme "tourner d'un coté" comme l'action continue entre le moment ou il commence à tourner et le moment ou il arrête de tourner. Cela évite qu'il fasse des allers retours de gauche à droite.
Mais également la version qui change de coté au bout d'un moment : .




Enfin, la dernière version du robot, r4.py est la plus évoluée. On intègre tout ce qui a été fait avant, mais cette fois ci, quand le robot détecte un obstacle avec le capteur à ultrasons entre 8 et 16 pouces, il tourne à gauche, mesure la distance de ce coté, tourne à droite, mesure la distance de ce coté égalment, et choisit de tourner du coté ou la distance est la plus grande. Pour éviter face à des obstacles équidistants de tourner à gauche puis à droite en boucle, le robot tourne dans la direction qu'il à choisie jusqu'à ce que l'obstacle soit au delà de la distance de 16 pouces. Encore une fois, cela donne de bons résultats, car sur un obstacle rectiligne, le robot tournera du coté ou le mur "s'éloigne", donc choisira le coté ou il a le moins à tourner. Pour certains obstacles, il peut ne pas prendre la décision optimale (obstacle semi circulaire par exemple), mais ne se retrouvera pas bloqué.
Voici une vidéo illustrant le fonctionnement de cet algorithme :


Je ne l'ai pas encore uploadée, manifestement, mais ça sera bientôt fait. Dans une prochaine mise à jour, j'intégrerai le code.
Si des versions plus avancées sont développées, je ne les décrirai pas forcément, mais je les enverrai sur le GitHub. en général j'essaie de faire du code commenté, et clair.

N'hésitez pas à me faire part de vos remarques et questions dans les commentaires Image IPB


Regulateur de tension basique

Publié microrupteurman2 le 14 août 2012 - 04:02 in Electronique - Schémas

Ce montage m'a servi a reguler la tension d'un panneaux solaire (6v-400mah) d'ou l'utilisation d'un regulateur Low dropout voltage, c'est à dire faible tension de chute. Il me permet d'avoir une source de courant de 5v. "Low dropout voltage" : Les regulateurs ont une tension de chute, c'est ce que le regulateur 'consomme' en quelque sorte. Plus la tension de chute est elevée, plus vous perdez d'energie.

Composant necessaire :
- Un regulateur, ici un LM2937-5v ou compatible broche a broche (LM78xx, les xx etant le voltage desiré en sortie ex : LM7805, attention a bien prendre un regulateur de courant positif)
-Une resistance de 100ohm (marron-noir-marron)
-Une led 3mm rouge qui sert de temoin
-2 condensateur de 10µF

Voici la portion de plaque d'essai necessaire (il faut coupé sur le trait) :
Image IPB

Le shema electronique :
Image IPB


Implantation des composant sur la stripboard :


b2 => b3 => b4 : Regulateur
c2 => c3 : condensateur (c2 : +)
c4 => c5 : resistance debout
e3 => e4 : condensateur (c4 : +)
g3 => g5 : led (g5 : +)






Image IPB




Pour tester, il suffit de connecté le fil Vin a une batterie d'au moin 7v pour un lm7805. SI la led s'allume, c'est bon, sinon, ben il y a un souci !



Voici une photo du montage terminé :
Image IPB


MIT Inventor2 - Création Appli Android de pilotage robot mobile

Publié gerardosamara le 17 juillet 2018 - 01:56 in Programmation

Bonjour les makers,
 
Ce tutoriel propose de créer une application de pilotage de robot mobile  à l'aide de l'outil cloud de création d'application MIT Inventor2 , basé sur cet exemple d'écran de pilotage robot  :
 
Screenshot_20180704-074510.png
 
 
Nous suivrons les étapes suivantes du développement de l'application Android :
 
- Prérequis 1 : Ouverture d'un compte MIT Inventor2 et créer  le projet "Tuto appli MIT pilotage robot mobile"
- Prérequis 2 : Installation de l'app Android "MIT A2 Companion" pour installer l 'app de pilotage du robot sur le smartphone Android.
- Prérequis 3 :  Le robot mobile basé RPI est connecté en wifi
- Implanter sur l'écran du smartphone les objets  de type bouton , étiquette , retour vidéo de la caméra PI
- Programmer le fonctionnement attendu de ces objets de pilotage du robot mobile ( programmation par blocks )
-  Mettre en place un protocole de communication en Wifi entre le RPI3 du robot et l'application Android
 
 
Non pris en compte dans le tutoriel  pour le moment :

- Evolutions / améliorations possibles de l'appli MIT ( commande demi-tour .... )
- Amélioration du script python du RPI3 robot pour exécuter les ordres recus ( AV , AR ...)
 
1) Ouverture compte MIT Inventor et création projet "Tuto appli MIT pilotage robot mobile"
 
Pour utiliser MIT Inventor 2 , il faut d'abord aller sur le site ai2.appinventor.mit.edu qui va vous rediriger vers une page de connexion à MIT.edu avec une adresse mail existante "gmail.com"  ou qui va vous permettre la creation de compte gmail.com si vous n'en avez pas ( ....  c'est une appli developpée par Google et maintenu par le MIT donc ..)
 
login mit edu.PNG
 
 
Une fois sur le site MIT App EDU ,  Cliquez sur le bouton "Start new projet "  , un écran de smartphone vide est affichée sur la page du projet 
 
start new projet Mit edu.PNG
 
 
La prochaine étape sera de positionner  sur l'écran du smartphone les différents objets qui serviront à piloter le robot mobile.
 
 
2) Implanter sur l'écran du smartphone les objets  de type bouton , étiquette , retour vidéo de la caméra PI
 
L'outil MIT visualisé contient :
 
- une colonne "palette" avec les objets d'interfaces utilisateur   : bouton ... et connectivity : web
- une colonne de composants  correspondants aux objets interface utilisateurs que nous avons fait glisser de la colonne palette vers l'écran du smartphone , en respectant la position voulue
- une colonne properties pour modifier les paramètres des objets utilisés
 
Dans notre cas cela devrait apparaitre comme ceci , après avoir fait glisser les objets sur l'écran du smartphone à la bonne position et paramétrer les bonnes données "properties" des objets :
 
- TableArrangement = 3 colomns , 2 rows , width = fill parent
- Button 1 à 6 : witdh = 33% pour faire tenir 3 boutons sur une rangée
- Label1 et Label : width = 50% pour ... vous savez pourquoi
- Web ( fonction http post )
 
MIT ecran.PNG
 
 
Reste à renommer les objets pour ( boutons et Etiquettes ) et le titre de l'écran qu'ils correspondent à  l'écran proposé pour le tuto ..... et sauvegarder
 
Tuto MIT Ecran 1.PNG
 
 
 
3)  Programmer le fonctionnement attendu de ces objets de pilotage du robot mobile ( programmation par blocks )
 
Pour accéder au mode  "Block" , quitter le mode Designer en clickant sur le bouton "Block"  .
 
Une page est  affichée avec une colonne de catégories de blocks ( controle , ... )  et un espace vide destiné à recevoir les blocks  ayant été "déposés" de la colonne  Blocks vers l'espace de programmation Blocks.
 
Tuto MIT Ecran 2.PNG
 
A ce stade nous allons mettre le minimum de blocks pour  tester la chaine complète de l'installation de l'appli MIT sur un smartphone  soit :
 
- 2 variables adresse IP:Port du robot  ( rpi et Pi Cam )
- le bouton de retour à l'écran d'accueil  ( fleche arrière sur le smartphone)
- L'affichage du flux video de la PI Cam
 
 
Tuto blocks 1.PNG
 
 
4) Installation de l'app Android "MIT A2 Companion"
 
Sur le play Store , chercher l"application "MIT AI2 Companion" et l'installer  .
A l'ouverture de MIT AI2 Companion , cet écran est affiché .
La fonction "scan QR code" sera utilisé  avec MIT inventor 2 lorque l'application aura été générée afin de l'installer sur le smartphone
Dans l'onglet Connect de MIT Inventor2 , sélectionner MIT AI2 companion
 
 
MIT AI2 Companion.png
 
5) Installation de l'application MIT minimum sur le smartphone Android
 
Le projet  ayant été sauvegardé , lancer  la fabrication de l'appli MIT en sélectionnant l'onglet "Build"  +  app (  Provide Qr code for .apk )
 
Tuto MIT Ecran 3.PNG
 
 Ensuite dans MIT AI2 Comanion ,  Clicker sur "Scan QR Code" pour scanner le QR code affiché dans MIT Inventor 2   et installer l'application sur le smartphone
 
Une fois installée , ouvrir l'application "Tuto App Robot mobile ed1 ".
L'écran ci-dessous doit s'afficher .
Le retour video sera affiché , si vous avez une PI Cam opérationnelle sur le RPI du robot mobile connecté en Wifi.
Le bouton "flèche arrière" du smartphone fonctionne ( fermeture application)
Les boutons ne sont pas encore programmés pour  commander le robot
 
 
tuto app mit.png
 
 
6) Complément de programmation pour les boutons et  affichage de la la trace des messages de commande échangés avec le robot
 
Les blocs  de programmation relatifs aux boutons et étiquttees de visualisation des messages de pilotage du robot ont été ajoutés dans MIT Inventor2  ( pour un bouton seulement )
.
L'application envoie des messages HTTP/POST/Commande robot  vers le robot mobile avec réponse HTTP/200 OK . Cela suppose que le RPI du robot puisse recevoir ces messages de commande du robot ( start , avant .. )  , les traiter et répondre "200 OK"
( voir chapitre 8)
 
 
tuto blocks .png
 
 
7) Présentation des boutons sous forme d'icones
 
 
La présentation des boutons de commande du robot sous forme d'icone  permets d'avoir un design plus "sexy"  et  ajouter cette fonction consiste à :
 
- Télécharger dans MIT Inventor2  / Media les 6 fichiers contenant les icones pour les boutons de commandes
- Dans les propriétés de chaque bouton ( start dans l'exemple ) ,  cliquer sur "Image" pour affecter un fichier image
 
 
icon bouton.PNG
 
 
Pour terminer ce tutoriel , il reste à générer l'application dans MIT inventor2 puis à l'installer sur le smartphonr avc MIT AI2 Companion et à tester.
 
Suite appui sur le bouton "Start" , la commande robot est bien affichée ( <start>  ) mais sans réponse du robot "200 OK"  car la communication avec le robot n'a pas été faite dans le tutoriel pour traiter le message <start>
 
tuto app final.png
 
 
8) Mise en place d'un protocole de communication en WIFI entre le RPI3 et l'application Android
 
Principe :

Un script python installé sur le serveur RPI3 du robot et basé sur le protocole sockets TCP permets de tester entre le Rpi3 et l'app Android pour la transmission des commands du robot ( Start , Stop , AV AR ... ) :

- L'app Android envoie  une requette Http POST recue vers le serveur RPI3
- le serveur RPI3 réponds un HTTP/1.1 200 OK avec les headers à l'app Android
- Le message envoyé et la réponse recue sont affichés dans l'app Android
 
Script python dans le RPI3 du robot


#!/usr/bin/python3.4
# coding: utf-8 # -*-coding:Utf-8 -*

import socket

host = ''
port = 8481

connexion_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connexion_server.bind((host, port))
connexion_server.listen(5)
print("Le serveur écoute à présent sur le port {}".format(port))

connexion_client, infos_connexion = connexion_server.accept()
print(infos_connexion)

msg_recu = b""
# header response code 200
h = 'HTTP/1.1 200 OK\n'
h += 'Server: Simple-Python-HTTP-Server\n'
h += 'Content-Length: 0\n'
h += 'Connection: keep-alive\n\n'
# Boucle  
while msg_recu != b"Stop":
    msg_recu = connexion_client.recv(1024)
    if msg_recu:
         print(msg_recu.decode())
         connexion_client.send(h.encode())
         print(h) # response code 200
         print(infos_connexion)
 
print("Fermeture de la connexion")
connexion_client.close()
connexion_server.close()


 
 

 
 
 
 
 
 
 
 
 
 
 
 
 

 
 
 



RobArchi 1.XX

Publié Gyro49 le 05 janvier 2018 - 04:53 in Robot complet

RobArchi 1.XX

 

 

Ce tutoriel vient en complément du RobArchi X.xx qui était la base de départ.

Cette nouvelle version a pour objectif de proposer une surveillance du niveau de charge de la batterie.

Mots clefs :
Atmega 328p, Raspberry,  I2C, batterie, NPN 2N2222, eeprom, 24LCXXX

Avertissements :
Comme pour la version X.xx, vous ne devez pas chercher, dans RobArchi, la solution à vos problèmes mais plus une approche de laboratoire de test et d'apprentissage.
En effet, multiplier les Atmegas comme je l'ai fait, n'ai pas la solution ultime. En terme de coût, ce n'est pas exorbitant, mais il serait difficile de tous les loger dans un gabarit de robot plus petit.

Objectifs :
Comme présenté ci-dessus la version 1.XX va apporter un contrôle régulier du niveau de charge de la batterie et cela à la demande de la carte Raspberry.

Il me semble qu’un robot d’exploration qui ne surveille pas la décharge de sa batterie prend beaucoup de risque.

Histoire de pousser le vice au maximum, j’ai décidé de jouer également avec une eeprom en I2C.

La carte du X.xx a donc subi une petite modification par l’implantation de l’eeprom 24LC128 juste au-dessus de la carte Pi mais toujours sur la ligne I2C coté 3V (annexe1 et 2 en bas de page).

Préambule :
Lors de mes tests sur la version X.xx je passais mon temps à monter et démonter mon Atméga à chaque modification du code… l’horreur.

Pour cette nouvelle étape je suis passé par un banc de tests : une plaque de test 840 points et Arduino Nano à la place d’un simple Atméga. Et une carte Raspberry avec un connecteur GPIO.

Déroulement du tuto :
Chapitre 1.1 : Création du shield accueillant la gestion de la batterie
Chapitre 1.2 : Mesure de la tension de la batterie arduino uniquement
Chapitre 1.3 : Mesure de la tension de la batterie à la demande du Raspberry
Chapitre 1.4 : Utilisation d’une eeprom entre l’Atmega et la Raspberry
Chapitre 1.5 : Mesure de la tension toutes les deux minutes via un job CRON

Annexes :
Annexe 1 - Mise à jour de la carte Version X.XX - Composants
Annexe 2 - Mise à jour de la carte Version X.XX - Stripboard
Annexe 3 – Création du shield batterie - Composants
Annexe 4 – Création du shield batterie - Stripboard

Chapitre 1.1 - Création du shield accueillant la gestion de la batterie
Je suis donc parti sur un deuxième shield fait maison qui sera ajusté à la carte de la version X.xx.

Les deux plaques sont mises en communication via un groupe de 2x6 « long header » pour envoyer sur le shield batterie l’alimentation et la connexion I2C.
La tension arrive directement sur la plaque 1.xx. Etant du genre distrait, j’ai mis un pont de diode afin de garantir la bonne polarité dans le circuit.
P1040585.JPG
P1040584.JPG

En regardant sur le web il y a beaucoup de référence sur le sujet.
J’ai choisi de suivre le blog suivant :
http://www.chicoree.fr/w/Mesurer_une_tension_avec_un_ATmega328P

Histoire d’éviter une consommation d’énergie trop important, j’ai associé un transistor 2N2222 dans mon circuit afin d’envoyer du 12V dans le pont diviseur uniquement au moment de la mesure.

Voici mon schéma de principe sans le pont de diode.
 
batterie.png

 

Chapitre 1.2 - Mesure de la tension de la batterie
La première étape sera la mesure de la batterie par « l’Atméga batterie ».

Le code arduino de l’Atmega

#include <stdlib.h>

// Constants
const int analogInPin = A0; // Analog pin the voltage divider is attached to
const float Vcc = 5; // µC Vcc (V)
const float R1 = 27000; // Voltage divider R1 (Ohm)
const float R2 = 10000; // Voltage divider R2 (Ohm)

const int pause = 60*1000; // delay between samples (ms)

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
}

void loop() {
  // read the analog in value:
  int sensorValue = analogRead(analogInPin);

  // Serial.println(sensorValue); // for debug / calibration
  float v_pin = Vcc*sensorValue/1023.;
  float v_bat = v_pin/(R2/(R1+R2));

  // Convert to string using the format ddd.dd
  char buffer[21];
  dtostrf(v_bat, 6, 2, buffer);
  buffer[6] = 0;
 
  // Display result
  Serial.println(buffer);
 
  // wait before the next loop
  delay(pause);
}

Chapitre 1.3 - Mesure de la tension de la batterie à la demande du Raspberry
En reprenant une bonne partie du code de la version X.xx, c’est déjà plus facile.
Les tests ont été effectué sur une carte Arduino Uno puis une Arduino Nano et à mon grand bonheur, pas de difficulté.
Maintenant une fois le code transféré sur Ateméga « baterrie » grosse déception, au lieu de 11.56 V (mesure multimètre) je n’avais que 3.49V. Après trois jours de recherche j’ai capitulé en multipliant par 3.4 la mesure en entrée A0.

int sensorValue = analogRead(analogInPin)*3.4;

Je hercherais un autre jour la solution avec AREF certainement.

Le code arduino de l’Atmega

#include <Wire.h>
#include <stdlib.h>

#define SLAVE_ADDRESS 0x14

String dataReceived;
char dataSend[6] ;
int index = 0;

// Constants
const int analogInPin = A0; 
const int T2N = 9;
const float Vcc = 5;
const float R1 = 26500; // Voltage divider R1 (Ohm)
const float R2 = 9910; // Voltage divider R2 (Ohm)

void setup() {   
  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(receiveData);
  Wire.onRequest(sendData);
  
  pinMode(T2N, OUTPUT);  
}
 
void loop() {
	/* Il n'y a rien dans la boucle infinie */
}

void receiveData(int byteCount){
  dataReceived = NULL;
  int numOfBytes = Wire.available();
  
  byte b = Wire.read();  //cmd
  
  for(int i=0; i<numOfBytes-1; i++){
    char c = (char) Wire.read(); 
    dataReceived += (char) c; 
  }
  
  digitalWrite(T2N, HIGH);
  int sensorValue = analogRead(analogInPin)*3.4;

  float v_pin = Vcc*sensorValue/1023;

  float v_bat = v_pin/(R2/(R1+R2));
  
  dtostrf(v_bat, 6, 2, dataSend);
  dataSend[6] = 0;
  digitalWrite(T2N, LOW);  
  }

void sendData(){
  Wire.write(dataSend[index]);
    ++index;
    if (index >= 6) {
         index = 0;
    }
  }

Coté Raspberry

#!/usr/bin/env python

import smbus
import time
import os

bus = smbus.SMBus(1)

# I2C address of Arduino Slave
i2c_add_batterie = 0x14
i2c_cmd = 0x01

def ConvertStringToBytes(src):
  converted = []
  for b in src:
    converted.append(ord(b))
  return converted

data = ""
# loop to send message
exit = False
while not exit:
  r = raw_input('Enter something, "q" to quit"')
  print(r)

  bytesToSend = ConvertStringToBytes(r)
  bus.write_i2c_block_data(i2c_add_batterie, i2c_cmd, bytesToSend)

  time.sleep(0.1)

  for i in range(0, 5):
    data += chr(bus.read_byte(i2c_add_batterie));
  print data
  time.sleep(1);
  data = ""

  if r=='q':
    exit=True

Après connexion au raspberry en SSH, il suffit de taper une lettre pour recevoir de l’atmega la tension de la batterie.

Chapitre 1.4 - Utilisation d’une eeprom entre l’Atmega et la Raspberry

 

Ne fondez pas de grand espoir dans cette partie car si cela fonctionne presque sur la plaque d'essai, c'est une véritable perte de temps après mise en place sur le robot.

Je vous mets les codes pour info ou tout simplement si vous voulez tenter le coup.

Histoire de préparer la version 2.xx j’ai décidé de jouer avec une eeprom en I2C forcément.

Pour la mise en place il y a beaucoup de tuto sur le net, il suffit de taper dans un navigateur :
arduino eeprom I2C

L’eeprom doit être du côté 5v du réseau I2C. En mettant les pins 1 à 4 à la masse, l’eeprom aura l’adresse 0x50.
Contrairement au Raspberry, l’Atmega (ou simplement l’Arduino) peut accepter d’être aussi bien esclave que maître mais forcément pas en même temps.

La démarche et simple, au démarrage, l’Atmega est en esclave jusqu’au moment de recevoir la commande du Raspberry. A ce moment-là, il ouvre une connexion I2C en qualité de maître vers l’eeprom pour y déposer la valeur de la tension de batterie puis revient à l’écoute du Raspberry.

Le raspberry attend 5 secondes puis va voir sur l’eeprom ce qu’a déposé l’atméga.

Dans le pays à Oui-Oui c’est comme ça que ça marche. Maintenant, il y a toujours un problème qui vient contredire la théorie. Dans la pratique, lorsque la Rpi affiche une erreu de connexion avec l’eeprom pour une histoire de délai dépassé. A première vue, l’Atméga semble garder un lien avec l’eeprom même lorsque la connexion est terminée avec :

 

Wire.endTransmission(deviceaddress);

Une solution c’est de rebooter l’Atméga. Coté informatique je n’ai pas trouvé, j’ai donc choisi la méthode électronique. Un 2222 en parallèle du bouton RESET avec une commande depuis le PIN 5. C’est un peu brutal mais ça marche (Sur la plaque d'essai).
 
Le code arduino de l’Atmega

#include <Wire.h>
#include <stdlib.h>

#define SLAVE_ADDRESS 0x14
#define I2C_add_eeprom 0x50

String dataReceived;
char dataSend[6] ;
unsigned int address = 0;

// Constants
const int analogInPin = A0; 
const int T2N = 9;
const int RESET = 13;
const float Vcc = 5;
const float R1 = 26500; // Voltage divider R1 (Ohm)
const float R2 = 9910; // Voltage divider R2 (Ohm)

void setup() {   
  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(receiveData); 
  
  pinMode(T2N, OUTPUT);  
  pinMode(RESET, OUTPUT); 
}
 
void loop() {
	/* Il n'y a rien dans la boucle infinie */
}

void receiveData(int byteCount){
  dataReceived = NULL;
  
  int numOfBytes = Wire.available();
  
  byte b = Wire.read();  //cmd
  
  for(int i=0; i<numOfBytes-1; i++){
    char c = (char) Wire.read();
    dataReceived += (char) c; 
  }
  
  digitalWrite(T2N, HIGH);
  
  int sensorValue = analogRead(analogInPin)*3.4;

  float v_pin = Vcc*sensorValue/1023;

  float v_bat = v_pin/(R2/(R1+R2));
  
  dtostrf(v_bat, 6, 2, dataSend);
  dataSend[6] = 0;
  digitalWrite(T2N, LOW);
  	
  writeEEPROM(I2C_add_eeprom, address);
  
  delay(1);
  
  digitalWrite(RESET, HIGH);  
  }

void writeEEPROM(int deviceaddress, unsigned int eeaddress) 
{
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  for(int i=0; i<strlen(dataSend); i++){
    Wire.write(dataSend[i]);
    }  
  Wire.endTransmission(deviceaddress);
 
  delay(1);
} 

Coté Raspberry

#!/usr/bin/env python

import smbus
import time
import os

bus = smbus.SMBus(1)

# I2C address of Arduino Slave
i2c_add_batterie = 0x14
i2c_add_eeprom = 0x50
i2c_cmd = 0x01

def ConvertStringToBytes(src):
  converted = []
  for b in src:
    converted.append(ord(b))
  return converted

level = ""
# loop to send message
exit = False
while not exit:
  r = raw_input('Enter something, "q" to quit"')
  print(r)

  bytesToSend = ConvertStringToBytes(r)
  bus.write_i2c_block_data(i2c_add_batterie, i2c_cmd, bytesToSend)

  time.sleep(5)
  memory_address = 0
  data=""
  bus.write_byte(i2c_add_eeprom, memory_address >> 8)
  bus.write_byte(i2c_add_eeprom, memory_address & 0xff)
  for i in range(0,10):
    data =bus.read_byte(i2c_add_eeprom)
    if data>45 and data<58:
      level +=chr(data)
  print level
  time.sleep(1)
  data = ""
  level = „“
  if r=='q':
    exit=True
} 

Chapitre 1.5 - Mesure de la tension toutes les deux minutes via un job CRON
Pour terminer cette version 1.xx je voudrais connaître le temps de décharge de la batterie sans surveillance de ma part.
Je vais donc créer un nouveau fichier Python au nom de « batterie.py » qui sera dans le répertoire : /home/pi/batterie.py

 

Je suis reparti sur la base du chapitre 1.3

Ne pas oublier de créer le répertoire data

 

Code Raspberry : fichier batterie.py

#!/usr/bin/env python

import smbus
import time
import os
import datetime

bus = smbus.SMBus(1)

# I2C address of Arduino Slave
i2c_add_batterie = 0x14
i2c_cmd = 0x01

def ConvertStringToBytes(src):
  converted = []
  for b in src:
    converted.append(ord(b))
  return converted

data = ""

bytesToSend = ConvertStringToBytes("m")
bus.write_i2c_block_data(i2c_add_batterie, i2c_cmd, bytesToSend)

time.sleep(0.1)

for i in range(0, 5):
  data += chr(bus.read_byte(i2c_add_batterie));
print data
time.sleep(1);

fichier = open("/home/pi/data/batterie.txt", "w")
fichier.write("\n" + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " " + data)
fichier.close()

Avec la commande « crontab –e » dans le terminal SSH, nous avons accès à la liste des Job CRON.
Il faut mettre cette ligne à la fin du fichier

*/1  *  *  *  *   sudo python /home/pi/batterie.py

Lorsque le fichier batterie.txt ne sera plus rempli, nous pourrons en déduire la tension minimale à la batterie pour que le système fonctionne.

 

Histoire de compléter le système vous pouvez créer un serveur Samba pour accéder facilement au fichier batterie.txt

 

En annexe 5 le fichier batterie.txt avec comme unique consommation électrique le PI et les Atmegas. les moteurs étant débranchés.

Annexes

Fichier attaché  base_composants.pdf   121,37 Ko   231 Nombre de téléchargements

Fichier attaché  base_stripboard.pdf   123,46 Ko   257 Nombre de téléchargements

Fichier attaché  shield_composant.pdf   118,01 Ko   160 Nombre de téléchargements

Fichier attaché  shield_stripboard.pdf   117,03 Ko   181 Nombre de téléchargements

Fichier attaché  batterie.txt   4,19 Ko   159 Nombre de téléchargements

 

 




Registre à décalage 74HC595

Publié arobasseb le 20 août 2017 - 12:12 in Electronique

Aujourd'hui je vous présente un composant fort utile le 74hc595.
 
Qui est-il ? C'est un registre à décalage de 8 bits.
 
A quoi sert-il ? il sert à convertir une information série en parallèle. Mais on l'utilise aussi pour économiser le nombre de broche utilisée en sortie.
C'est d'ailleurs pour ce dernier cas que je vais présenter la chose :).
 
En effet, au dessus de 3 sorties à piloter, il peut être intéressant d'utiliser ce composant afin d'économiser des broches sur votre carte de commande. Pourquoi 3, car c'est le nombre minimum de broche nécessaire au fonctionnement du composant.
 
Comment ça fonctione ? Afin de mieux comprendre le fonctionnment j'ai fait ces quelques images ci-dessous : 
 
Diapositive1.GIF
Diapositive2.GIF
Diapositive3.GIF
Diapositive4.GIF
Diapositive5.GIF
Diapositive6.GIF
 
Comme on peut le voir, il y a 2 grandes phases : 
La première on place les données que l'on veut 
La deuxième est la validation des données
 
Maintenant passons à la pratique.
 
Dans cet exemple, le but sera d'allumer des LED car c'est le plus simple électriquement. En effet, on peut également piloter des moteurs, des relais, des électrovannes, ... mais cela nécessite une interface de puissance, ce qui n'est pas le sujet de ce tutoriel.
 
cablage_74HC595.png
 
comme on peut le voir le schéma est très simple : 
Nous avons d'une part le microcontroleur qui alimente et pilote le 74HC595
puis le 74HC595 qui fait le lien avec les LED
et enfin les LED
 
Il est tant, maintenant, de faire fonctionner tout ça.

//constantes pour les broches de commande du 74HC595
int DS_pin = 8;   // broche de donnée
int STCP_pin = 9; // broche de validation de la donnée
int SHCP_pin = 10;// broche de validation compléte (latch)

boolean registre[8]; //c'est un tableau de 8 bit correspondant aux sorties du 74HC595 à l'état voulu
                      // pour se programme j'ai fait le choix du tableau car cela reste simple pour un tutoriel

void setup()
{
    //configure les broches en sortie
    pinMode(DS_pin,OUTPUT);
    pinMode(STCP_pin,OUTPUT);
    pinMode(SHCP_pin,OUTPUT);
}

//Cette fonction "écrit" le contenu du tableau dans le registre
//pour chaque bit, on met la brohe de validation du bit à 0, on place la broche de donnée à l'état contenu dans le tableau et ensuite on valide le bit
//à la fin on valide le tout
void EcrireRegistre()
{
  
  digitalWrite(STCP_pin, LOW);
  
  for (int i = 7; i>=0; i--)
  {
    digitalWrite(SHCP_pin, LOW);
    digitalWrite(DS_pin, registre[i] );
    digitalWrite(SHCP_pin, HIGH);
  }
  
  digitalWrite(STCP_pin, HIGH);
}


//Dans la boucle du programme plusieurs séquences différentes sont jouées
void loop()
{
   //Allume successivement les sorties
   for(int i = 0; i<8; i++)
   {
    registre[i] = HIGH;
    delay(300);
    EcrireRegistre();
   }

   //éteint successivement les sorties
   for(int i = 7; i>=0; i--)
   {
    registre[i] = LOW;
    delay(300);
    EcrireRegistre();
  
   }

   //séquence qui allume une LED sur 2 alternativement
    bool b = 0;
    for(int i = 0; i<4; i++)
    {
        
      for(int j = 0; j<8; j++)
      {
        registre[j] = j%2 xor b;
      }
      EcrireRegistre();
      b = not b;
      delay(300);
    }

    //remise à zéro de toutes les LED
    for(int j = 0; j<8; j++)
    {
      registre[j] = 0;
    }
    EcrireRegistre();
}

 
 
Pour aller plus loin
 
Je vais vous donner deux astuces afin d'étendre un peu le sujet.
 
Astuce 1 : avoir plus de 8 sorties
 
Pour avoir plus de 8 sorties, naturellement on se dit qu'il faut un deuxième 74hc595 et l'on clône le montage en utilisant les autres pins disponibles. Mais si c'était ça je n'aurai pas pris la peine d'écrire cette astuce.
En effet, vous l'avez peut-être remarqué sur le schéma, il y a une broche Q7'. Et c'est de là que vient l'astuce. En effet on peut chainer les 74HC595 entre eux, en reliant la broche Q7' du premier, sur la broche DS (souvenez-vous la broche de donnée) du suivant.
Enfin, afin de synchroniser les deux 74HC595 il suffit de connecter leurs broches ST_CP et SH_CP entre eux.
 
 
Au niveau du code, au lieu de boucler sur 8 bits, il faut boucler sur 16 bits. Et voilà, avec le même nombre de fils on augmente notre circuit de 8 sorties supplémentaires. 
 
 
En théorie vous pouvez en chainer autant que vous voulez, mais en pratique, avec un arduino le temps de mise à jour des registres deviendra de plus en plus long et donc nuira au fonctionnment du programme.
 
Astuce 2 : s'en servir pour augmenter le nombre d'entrée
 
Les puristes ne vont surement pas aimer, et cette astuce se révèle plus être une bidouille. M'enfin, je me lance :)
 
Imaginons que nous ayons 8 interrupteurs, mais que 4 broches de libres sur notre arduino. On se dit c'est mal barré, on a pas d'autre arduino, c'est fin ; et soudain vous vous souvenez qu'il vous reste un 74HC595. La bidouille peut commencer.
 
Le principe est simple, on va faire se décaler un bit à travers le registre (juste un seul), du coup pour les interrupteurs en sortie, seulement 1 seul sera alimenté et si tous les interrupteurs sont raccordés sur une seule entrée de l'arduino, alors on connait l'état d'interrupteur.
 
 
Bon j'avoue, c'est un peu empirique :)


UNE INTERFACE DE PUISSANCE POUR ARDUINO.

Publié Nulentout le 12 avril 2017 - 08:54 in Electronique

Dans l'ouvrage :

 

http://www.robot-maker.com/ouvrages/interface-puissance-arduino/
 
joint je vous propose un didacticiel sur une interface secteur.
 
Ce petit montage très simple vous permettra de piloter avec un quelconque module microcontrôleur un appareil branché sur le secteur électrique 220V alternatif, pouvant consommer jusqu'à 16 ampères soit une puissance maîtrisée de 3,5kW.
Ce tutoriel s'adresse aux débutants. Tout est expliqué de façon théorique et surtout de manière pratique, avec beaucoup de schémas et d'images.
Attention à la facture d'électricité !
 
Amicalement : Nulentout




Circuit avec Photorésistances

Publié Refrobot le 30 septembre 2013 - 07:03 in Programmation

Matériel nécessaire pour la construction:
-2 transistors T1 et T2 BD139
-1 LDR -1 Lampe L 12 V/2 W
-1 résistance R1 de 120 KΩ
-1 résistance R2 de 2.2 KΩ
-1 résistance R3 de 1.5 KΩ
-1 Alimentation continue 12 V
-1 multimètre

Le montage 1 représente un circuit fonctionnant de la façon suivante :

Lorsque la LDR est éclairée, sa résistance est faible et le transistor T1 reçoit à sa base une faible tension non suffisante pour le rendre conducteur.

De ce fait, la tension de base de T2 est forte et T2 est conducteur provoquant l’allumage de la lampe L.

Lorsque la LDR est dans l’obscurité, sa résistance dépasse 60 KΩ et T1 reçoit sur sa base une tension suffisante pour le rendre conducteur.

Ceci provoque une chute de tension sur la base de T2 qui se bloque.

La lampe s’éteint de ce fait.

Si vous voulez voir la suite du tutoriel, regardez sur le site: Ici

Vous pouvez me suivre sur Twitter: @refrobot


Certifié Refrobot©


Small bot V2

Publié microrupteurman2 le 17 mars 2013 - 08:01 in Robot complet





Bienvenue dans ce tuto, ici je vous expliquerai comment fabriquer un petit robot.




Materiel necessaire:

-Un atTiny85/45
-Un condensateur seramique 0.047µf
-Un support DIP 8pin
-Un capteur IR
-Des fils electrique
-Un fer a souder
-Un pistolet a colle (colle chaude)
-Un coupleur de pile 3xAA (R6)
- Deux micro servo 9g
-Deux petites roues
-Une portion de stripBoard (14 trous par 8 bandes de cuivre)

Pour la programmation de l'atTiny :

-Une arduino UNO (IDE 1.0)
-Une breadboard
-Deux librairie :
https://github.com/d...hive/master.zip (a decompresser et coller dans /arduino/hardware
http://bateaux.trucs...ftwareServo.zip SoftWare servo a decompresser et copier dans /arduino/librairie


Modification des servo en servo a rotation continue:

-Devisser les 4 vis sous le servo
-Enlever le cache haut et le cache bas.
-Dessolidarisé le circuit imprimer
-Sur l'un des pignon, il y a une butée, la coupé avec un cutter
-Repairer les fils du potentiometre.
-Dessouder celui du milieu du potentiometre sur le circuit imprimé et un des deux autre
-Souder une resistance metal de 10ko ou etait souder les deux fils
-Dessouder le 3e fil du potentiometre du circuit, y souder
une meme resistance vers l'autre patte de la resistance
ou etait le fil du mileu du potentiometre.
-Refermé le tout.

Si vous avez des difficulter, n'hesitez pas a laisser un commentaire ou m'envoyer un mp.

Progammation de l'AtTiny :

-PinOut de l'attiny/25/45/85:

Image IPB


La pin Reset n'est a n'utiliser en aucun cas (sauf lore de la programmation).

-Preparation de la UNO :

Toujours debrancher votre Arduino de la prise usb lors de la manipulation du montage. Vous aurez prealablemet telecharger les deux librairies cité plus haut.

1-Lancer l'IDE arduino (1.0)
2-Cliquez sur Fichier/exemple arduinoISP
3-Selectionné votre carte en cliquant sur outils/type de carte/uno
4-Cliquez sur televerser.

Maintenant votre Arduino est programmé pour programmé les attiny.

Faite le montage suivant :

Image IPB

Le condensateur n'est pas obligatoire.


-Allez dans ( Outils/Type de carte) cliquez sur ( Attiny85 internal 8 MHz clock )
-Allez à nouveau dans ( Outils/Programmateur ) cliquez sur ( Arduino as ISP) pour signaler à l'IDE que l'UNO est utilisé comme programmateur.
-Si votre ATtiny est neuf, et que vous souhaitez le le faire travailler à 8MHz, vous devez maintenant aller sur ( Outils ) et cliquer sur ( Graver la séquence d'initialisation )
-Cliquez sur l'icône vérifier Image IPB
-Cliquez sur Téléverser ou sur l'icône Image IPB
-Debrancher le cable USB, retiré l'AtTiny .




Et televerser y le code suivant :

#include <SoftwareServo.h> // librairie pour controle servo attiny

SoftwareServo servoD;
SoftwareServo servoG;// create servo object to control a servo 
                        // a maximum of eight servo objects can be created 


#define REFRESH_PERIOD_MS 20
int pos = 0; 
int sensorValue;

void setup()
{
servoD.attach(0);
servoG.attach(3);
}
void loop()
{
sensorValue = analogRead(1);

if (sensorValue <10)    // changer cette valeur par celle qui corespond a votre capteur
{
  for(pos = 0; pos < 25; pos += 1)  // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    servoD.write(150);
  delay(10);
  SoftwareServo::refresh();
  servoG.write(150); 
  delay(10);
  SoftwareServo::refresh();       // generates the servo pulse
  } 
  
}
else
{
  servoD.write(10);
  delay(10);
  SoftwareServo::refresh();
  servoG.write(150); 
  delay(10);
  SoftwareServo::refresh();
}

}



Implementation des composant :

Pour plus de complexiter j'ai cadrillé la stripboard

b5 -> f5 : Strap
b10 -> c10 : condensateur
d2 : cmde Servo 1
f14 : cmde Servo 2
b11-c11-d11: connecteur HE10 male
f4 : Gnd servo 1
f3 : Gnd servo 2
f1 : Gnd (accus)
c12 : +5v servo 1
c13 : +5v servo 2
c14 : +5v (accus)

Ne pas oubler de couper les pistes sous le µc, d'ou le trait.

Image IPB

Une foit ce cricuit realiser, emboiter votre µc dans le support en faisant attention au sens !

Coller a la colle chaude les servo modifier sous l'avant du boitier de pile, fixer les roues sur les servos et ajouter une 3e point apuis (j'ai mis un petit cube de bois) .



Et une petite video pour finir :


https://www.youtube.com/watch?feature=player_detailpage&v=Xhm8_Sl2bZQ





Desoler pour la mise en page, mais j'ai pas pu faire autrement. Je pense continué a amelioré ce tuto, car il manque encore quelques chose.


Programmation d'un pic sous MicroC

Publié Harry le 13 octobre 2009 - 07:17 in Programmation

Introduction


Bonjour,

Ce cours a pour but de vous apprendre à programmer ce qu'on appelle un microcontrolleur :heu: ... Non ! Ne partez pas ! Je vous assure que c'est utile et accessible à tous ! Mais ce n'est pas simple, je le conçois ... Je vais faire en sorte que ça passe en douceur.

Image IPBCe cours nécessite de savoir programmer en C...

 

Une présentation des pics et de l'environnement de développement


Je vais commencer par décrire ce qu'est un pic : c'est un micro contrôleur qui intègre un processeur. Voilà, c'est fait et personne n'a rien compris. Donc on va décrire plus simplement... en disant à quoi ça ressemble et à quoi ça peut servir.

A quoi ça ressemble un pic ?

Un pic est un parallélépipède noir avec des "pattes" métalliques :

Image IPB

Mais, à quoi ça sert ce truc ?!?

Ce type de pic sert à gérer à peu près tout et n'importe quoi en robotique, grâce au processeur qui est intégré dedans : votre PC est rempli de ces processeurs et les pics les plus polyvalents actuellement (Février 2008) sont les pics dont la référence commence par 18F*****. En gros, grâce à ça, vous allez pouvoir gérer les contacteurs, les capteurs de distances, les moteurs, vos lumières... bref tout ce qui fait joli dans un robot Image IPB

Où puis-je m'en procurer ?


Vous pouvez vous en procurer à deux endroits :
- Tout magasin d'électronique qui se respecte devrait pouvoir vous en vendre certaines catégories pour environ une quinzaine d'euros chaque...
- Sinon, si vous avez un mail "étudiant" (j'entends par là, autre que Yahoo et Hotmail...), vous pouvez recevoir 2 échantillons gratuit par mois sur le site de microchip.


Image IPBBon, maintenant que j'ai mon pic, ... je fais comment pour le programmer ?

Image IPBCette question a une réponse simple : il vous faut un programmateur de pic qui permet de relier le pic au PC, et c'est ce qui est expliqué juste après.

La carte de développement

Le programmateur de pic - ou carte de dév (développement) - est un élément essentiel pour "FLASHER" votre pic : en gros cela consiste à charger votre programme (compilé grâce à un logiciel dont vous aurez tous les secrets plus tards Image IPB ) sur votre pic, et ce, grâce à un câble qui relie le PC au pic.

Différents programmateur

Il existe différentes carte de dév... certaines que vous pouvez faire vous-même, d'autres que vous pouvez acheter à divers endroits (en particulier sur le net ?

Où puis-je me procurer un schéma si je veux le faire moi-même ?

Voici un site qui donne un schéma d'un programmateur, mais je ne sais pas du tout ce qu'il vaut...

Où puis-je en acheter un tout prêt plutôt que de m'embêter à le faire moi-même ?

Pour ça, je vous conseille de préparer votre porte-feuille... certains ne coûtent effectivement pas cher, mais ils n'ont pas les del rouges, très utiles, surtout au début, pour voir en "live" si votre programme fonctionne, avec des boutons poussoirs qui permettent de tester la réactivité de vos programmes...

Voici le mien :

Image IPB

J'utilise personnellement l'EasyPic5 de MikroElectronika (hé oui, c'est en anglais... mais ce dont vous avez besoin se trouve dans la section "Developpement Tool" en haut) et après, il faut que votre programmateur de pic puisse utiliser les pics que vous aurez commandés chez microchip... l'EasyPic5 a l'avantage de justement pouvoir programmer tous les PIN-40 (c'est-à-dire tous les pic ayant 40 pattes : les 16F, et les 18F entre autres), ainsi que tous les autres pics de forme rectangulaire.

Sinon vous pourrez aussi en trouver sur eBay mais bon, là aussi, il faut faire attention à ce que vous faites...

A vous de choisir la solution qui vous convient. Sachez que les pics de forme rectangulaire sont plus faciles à manipuler que ceux à forme carré (avis personnel).

Euh, ça coûte trop cher je trouve... je peux essayer de juste programmer, sans le tester sur mes pics ?

Oui, bien sûr ! Un simulateur est intégré dans le logiciel que je vais détailler... mais il reste très rudimentaire ! Mais au moins, vous pourrez déjà savoir si la programmation d'un pic peut vous plaire ou non...

Lisez la notice d'utilisation de votre programmateur !

Une fois que vous aurez votre programmateur en main, n'hésitez pas à lire sa documentation, surtout pour le branchement et la mise en marche !

On a le pic, on a (peut-être...) la carte de développement, il nous manque une dernière chose : le logiciel qui va nous permettre de programmer notre pic !

Le logiciel de développement

Alors là, vous avez encore plusieurs possibilités qui s'offrent à vous... Mais bon, je vous conseille d'utiliser le même logiciel que moi si vous voulez suivre ce cours, c'est-à-dire la première des solutions que je vous propose.

La solution MicroC + PicFlash

Si vous avez commandé chez MikroElectronika, normalement un CD vous est fourni. Alors installez les logiciel PicFlash (qui vous permettra de flasher votre pic à partir du PC) et MicroC (qui vous permettra de programmer C... vous avez aussi MicroBASIC, etc...). Ces deux logiciels se trouvent normalement sous le dossier "zip" de la racine du CD. Installez-les.

D'autres logiciels de programmation

Le compilateur SDCC

Vous pourrez le trouver ici

Le programmateur MpLab de microchip

Vous pourrez le trouver ici

D'autres logiciels pour flasher votre pic

Logiciel de programmation des composants IC-Prog

Vous pourrez le trouver ici

J'utilise personnellement le logiciel MicroC avec PICFlash... Toute la suite est basée sur ce logiciel, mais si vous n'avez pas ce logiciel, vous pouvez toujours lire la suite pour apprendre à lire la datasheet, qui sera votre outil indispensable dans le futur pour programmer n'importe quel pic...

 

Première étape : préparer son espace de travail


L'espace de travail

Maintenant que vous avez tous les outils, il faut les préparer. Ceci implique donc 3 étapes.

Branchez votre pic sur la carte de développement

Normalement, la notice d'utilisation de votre carte de développement devrait vous indiquer comment faire. Voici à quoi ça ressemble chez moi :

Image IPB

Branchez votre carte de développement au pc

Là, de la même manière, la notice d'utilisation vous indique comment faire. Chez moi, il suffit de brancher la carte au pc via un câble USB qui permet également d'alimenter la carte en électricité.

Installez vos logiciels de programmation et de compilation

Là aussi, référez-vous à la documentation des logiciels que vous avez choisi (et pour MicroC et PICFlash, je l'ai déjà rapidement décrit).

Une fois que votre espace de travail "physique" est prêt, il faut préparer l'espace "virtuel"...

Documentation du pic

Toute programmation de pic nécessite absolument d'avoir la documentation du pic que l'on est en train de coder. Certes, c'est en anglais, donc rébarbatif, mais ne vous inquiétez pas, si vous suivez mes conseils, cela passera en "douceur".

Repérer la référence du pic que vous avez

Prenons ce pic :

Image IPB

La référence est écrite dessus (je sais, ce n'est pas un 18F... à vous de vous adapter ^^). Dans notre exemple, c'est un 16F877A

Trouver la datasheet

Une datasheet (littéralement « feuille de données ») est un fichier donnant toutes les caractéristiques d'un élément électronique. Il faut aller la chercher sur le site du constructeur.

Allez là et remplissez le champ en haut qui correspond à votre pic (pour moi, c'est donc le 16F877A) :

Image IPB

Image IPB

Cliquez sur la ligne correspondant à la "Sillicon Product", vous devriez obtenir :

Image IPB

Enfin cliquez sur l'icône "pdf" pour télécharger la Datasheet. Voici celle de mon pic, à la page la plus intéressante :

Image IPB

Vous remarquerez que j'ai regroupé les "RAi", "RBi", "RCi", "RDi" et "REi" sous des couleurs différentes. En réalité A, B, C, D et E sont les ports programmables. Les "i" varient (en gros) de 0 à 7 : vous aurez reconnu là la formation d'un octet: chaque RAi est un bit (un chiffre binaire, c'est à dire un 0 ou un 1) de l'octet correspondant au port A.

On est fin prêt pour créer notre premier projet !

Créer un projet

Je vais décrire comment créer un projet proprement sous MicroC... Et désolé pour ceux qui n'utilise pas ce logiciel :|

Fermez les projets qui seraient déjà ouverts

Avant tout, fermez tous les projets en cours (Project --> Close Project) :

Image IPB

Créez un projet sous MicroC

Puis créez votre premier projet (Project --> New Project) :

Image IPB

Ensuite, mettez le nom de votre programme, choisissez l'endroit où vous voudrez l'enregistrer (cliquez sur "choose"), sélectionnez votre PIC dans la liste, mettez le "clock" à 010.000000, et cliquez sur "Default" puis sur OK :

Image IPB

Oh le joli écran noir ! :tare: Non, sérieux, ne vous inquiétez pas, c'est normal ^^

Et voilà ! On peut ENFIN commencer à coder en tant que tel Image IPB




Deuxième étape : votre premier code


Les règles de base

Pour vous aider à faire votre premier code, je vais faire comme suit : d'abord je vais vous donner les règles à respecter, ensuite je vous laisserai vous exercer.

Les 5 commandements tu respecteras

Image IPBA partir de maintenant, voici les règles à respecter quoi qu'il en soit :
  • Les instructions en minuscules sont propres au C
  • Les instructions en MAJUSCULES sont propres aux micro contrôleurs
  • "0b" (zero Image IPB indique que la suite est écrite en binaire (0 ou 1)
  • un nombre écrit tel quel indique qu'il est écrit en décimal (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
  • "0x" (zero x) indique que la suite est écrite en héxadécimal (0, 1, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E et F... pas très utile)
Quelques instructions

A partir de là, j'ai décidé de travailler sur le port B. Voici les instructions de base à connaître et à utiliser à bon escient (le code suivant ne sert qu'à vous donner des définitions):

TRISB

L'attribution de TRISB permet de configurer le port B en entrée ou en sortie (ou à moitié en entrée et à moitié en sortie...)

TRISB = 0; //Le port B est configuré en mode sortie (le pic envoie des ordres à un système extérieur via ce port, par exemple à un moteur)

TRISB = 1; //Le port B est configuré en mode entrée (le pic reçoit des informations d'un système extérieur via ce port : capteur, autre pic, etc...)

Imaginons qu'on ait besoin que de 4 bits sur les 8 disponibles pour recevoir une information, et qu'on ait besoin que de 4 bits pour envoyer des données ; au lieu de «gâcher» 2 ports (1 en entrée, 1 en sortie), on peut utiliser la moitié du port B en entrée et l'autre moitié en sortie : il est alors plus lisible d'écrire la valeur en binaire :
TRISB = 0b11110000; //Les pattes 7, 6, 5 et 4 du port B sont configurées en mode entrée (0b11110000) et les pattes 3, 2, 1 et 0 sont configurées en mode sortie (0b11110000)

Rem : Au dessus, au lieu d'écrire TRISB = 0 on pouvait donc écrire TRISB = 0b00000000.

PORTB

Image IPBImaginons qu'on ait configuré le port B en sortie, comment affecter une valeur à ce port ? (valeur qui sera interprété par exemple par le moteur d'une roue : avancer, reculer, vitesse…)

Il faut attribuer une valeur à PORTB:
PORTB = 0b01111111; //La patte 7 du port B prend la valeur 0 (une DEL qui s'éteint...) alors que les pattes 6, 5, 4, 3, 2, 1 et 0 prennent la valeur 1 (des DEL qui s'allument...)

Bien sûr, si on écrit PORTB = 1; tous les bits du port B prennent la valeur 1; et si on écrit PORTB = 0; tous les bits du port B prennent la valeur 0.

Image IPBEt physiquement, qu'est-ce qui se passe ?

Physiquement, si un bit d'un port est sur 1, il envoie une tension seuil 5 Volts à la patte correspondante (voir alors la Datasheet) et s'il est sur 0, il envoie du 0 Volt ; logiquement vous avez branché un fil, imaginons que ce fil soit relié à un moteur, ce moteur modifiera son comportement selon qu'il reçoit du 5 Volts ou du 0 Volt.

Image IPBOui, d'accord, mais moi, j'ai configuré la moitié de mon port en entrée et l'autre moitié en sortie, et bien sûr il ne faut pas modifier les valeurs d'entrées, comment envoyer quelque chose en sortie proprement ?

Il faut alors configurer chaque bit de sortie un par un. Pour accéder à un bit précisément, il faut utiliser : PORTB.Fnumbit
Exemple :
PORTB.F0 = 0; //Attribue 0 au bit 0 du port B

Image IPBEt si mes ports sont en entrée ? Comment je fais pour savoir ce que j'ai reçu ?

Bien évidemment, si le port B est en entrée, on ne va pas attribuer des valeurs aux bits de ce port (risque de conflits), mais lire les valeurs qu'il a pris. On utilise alors des tests logiques.
Ex :
Code : C

 
if (PORTB.F0==1) //si je lis 1 sur le bit 0 du port B
{
PORTC.F0=0; // alors, j'envoie 0 sur le bit 1 du port C (par ex, je demande au moteur de freiner (très vulgarisé))
}
else //sinon, si je lis 0 sur le bit 0 du port B
{
PORTC.F0=1; // alors, j'envoie 0 sur le bit 1 du port C (par ex, je demande au moteur d'accélérer (très vulgarisé))
}
DELAY_MS

DELAY_MS(1000); //Fait une pause de 1000ms = 1s - ATTENTION A BIEN CRÉER LE PROJET COMME J'AI DIT (en particulier pour la valeur du timer à 100)

L'opérateur ~

PORTB = ~PORTB; //Inverse la valeur de chaque bit de PORTB (0 --> 1 et 1 --> 0) exemple : 01100011 --> 10011100 (le "~" se fait en faisant "Alt Gr + 2" puis "espace" sous azerty)

Ces codes peuvent être utilisés n'importe où dans le programme.

Certains conseils tu suivras

Maintenant, pour alléger votre code, vous pouvez utiliser des define, comme en C, à mettre avant le main :

#define sortie PORTB //A mettre avant le main... Il faudra mettre "sortie = 0;" dans le main pour avoir effectivement PORTB en sortie

Il y a quelque chose de remarquable avec MicroC... Vous pouvez non seulement créer des variables dans le main... mais aussi en dehors de n'importa laquelle de vos accolades !!! C'est pourquoi je vous conseille fortement de déclarer toutes vos variables en "globales", au début de vos programmes de pic.

Des exercices tu feras

Bon, c'est pas tout ça, mais vous ne bossez pas beaucoup... Allez, à vous de coder ! Un sujet ? Ok, pas de problème, voici une question à laquelle vous allez répondre :

Image IPBComment faire clignoter toutes les DEL du plateau alors ?

Image IPBRéponse possible :

Code : C
 
#define sortie TRISB
void main (void)// N'OUBLIEZ PAS LE SECOND "VOID" !!!
{
sortie = 0;
PORTB = 0;
while(1)
{
delay_ms(1000);
PORTB = ~PORTB;
}
}
Image IPBMais on fait comment pour que les dels clignotent ? Parce que le programme il est joli, mais je veux que les leds clignotent, moi !!

Image IPBAlors, déjà, il faut que vous ayez connecté votre pic à votre pc, qu'il soit allumé (moi j'ai un bouton on/off) et que votre pc le reconnaisse. Ensuite, une fois votre programme écrit, faites "Ctrl + F11" pour compiler ET flasher le pic. Si vous ne voulez que le compiler, faites "Ctrl + F5" et juste pour le flasher, faites "F11".

Sinon, vous pouvez toujours simuler le projet, et c'est le thème de la partie suivante.

Le simulateur

Avant de tester directement votre programme sur le pic, vous pouvez aussi le simuler sur votre PC... et c'est d'ailleurs la seule méthode qu'ont ceux qui n'ont pas de kit de développement pour vérifier si leur programme pourrait marcher...

Le simulateur de MicroC

Pour utiliser ce simulateur, sélectionnez d'abord votre simulateur. Ici allez dans "Debugger --> Select Debugger --> Software Pic Simulator" :

Image IPB

Puis cliquez sur "Run --> Start Debugger". Vous arrivez sur cette page :

Image IPB

Vous avez plusieurs boutons. Dans l'ordre :
Image IPBStart Debugger (F9) : permet de placer le curseur au début de votre programme
Image IPB Run/Pause Debugger (F6) : permet de remettre en marche ou de mettre en pause votre programme
Image IPB Stop Debugger (Ctrl + F2) : permet d'arrêter votre programme
Image IPBStep Over (F8) : permet de passer à l'étape suivante de votre programme. Ce bouton est essentiel pour voir évoluer votre programme (mais d'abord, il faut rajouter vos variables, ce que nous allons faire avec un autre bouton plus loin)
Image IPB Step Out (Ctrl + F8) : permet d'exécuter votre programme en entier
Image IPB Run To Cursor (F4) : permet d'exécuter votre programme jusqu'à l'endroit où vous aviez placé le curseur
Image IPB Step Into (F7) : euh... à tester, je ne sais pas
Image IPB Jump To High Priority Interrupt (F2) : permet d'aller à votre interruption principale (j'expliquerai plus tard ce que sont les interruptions)

Puis, les boutons qui vous permettent de placer et d'éditer vos variables dans la fenêtre d'état du dessous :
Image IPB Permet d'ajouter une variable particulière dans la liste de variables à "simuler", après l'avoir sélectionnée dans le menu déroulant juste en dessous
Image IPB Permet de supprimer une variable de simulation particulière que vous avez sélectionné dans la liste
Image IPB Permet de rentrer dans les propriétés d'une variable particulière que vous avez sélectionné dans la liste pour en changer sa valeur en temps réel par exemple (vous pouvez aussi double-cliquer sur la variable pour avoir ces propriétés aussi)
Image IPBPermet d'ajouter toutes les variables dans la liste de simulation
Image IPB Permet de supprimer toutes les variables de la liste de simulation

Pour votre première simulation (l'exemple écrit dans le premier paragraphe), je vous conseille pour ne pas vous embêter de cliquer sur Add All, puis d'appuyer une seule fois sur "F9" (ou cliquez sur Start Debugger). Puis pour voir votre programme avancer, appuyer sur "F8" (ou cliquez sur "Step Over") à plusieurs reprises. Vous allez ainsi pouvoir voir votre curseur se déplacer dans votre fenêtre de code, et voir l'état des variables changer.

<1> Au départ (F9), votre curseur se place sur "sortie = 0;". (je vous rappelle que sortie est une variable se référant au TRISB et que la valeur qui lui est affectée - 0 - permet de configurer tout le port B en sortie).

Image IPB


Pour pouvoir exécuter la ligne sélectionnée, appuyez une fois sur (F8). La valeur n'est donc pas modifié puisque de base les pics sont configurés en sortie donc la ligne correspondant à TRISB reste à 0 (dans la colonne "Value").


<2> Ensuite, votre curseur est placé sur "PORTB = 0;".

Image IPB

De même, appuyez sur (F8) pour exécuter cette ligne et la valeur du port B ne change pas puisque de base il vaut 0.

<3> Ensuite, votre curseur est placé sur "delay_ms(1000);". Remarquez en bas au milieu de la fenêtre que la valeur du temps qui s'est écoulé est : "Time = 2.00 Us" (deux micro-secondes).

Image IPB

Ainsi, en appuyant sur (F8), vous exécutez cette ligne et du coup on obtient : "Timer = 1003.39 Us"... Mais d'où sort ce 1.39 Us de trop ?!? Rhhaa là-là, sachez que le pic prend du temps pour traiter les ordres que vous lui donnez, et ça, microC les simule aussi ^^

<4>Donc votre curseur est maintenant sur la ligne : "PORTB = ~PORTB;" :

Image IPB

Appuyez maintenant sur (F8) : la valeur de PORTB passe à 255 d'un seul coup (!!!) :

Image IPB

Image IPBMais pourquoi ça fait ça ?

Image IPBJe vous rappelle que le tild "~" permet de changer la valeur de TOUTES les pattes du pic. Donc tous les 0 passent à 1 et réciproquement. Ici PORTB=0 au départ. Donc on a bien zéro. Mais les valeurs affichées sont en décimal, et non en binaire ! Donc ça n'affiche pas 11111111, mais sa traduction en décimal, c'est à dire... 255 ! Mais si vous voulez avoir sa valeur en binaire, double cliquez sur la variable et sélectionnez "décimal" ^^

Voilà, maintenant, vous avez compris la simulation d'un projet ! Vous n'avez plus qu'à appliquer cette méthode quand vous voulez !

C'est intéressant tout ça, mais... je ne suis pas sûr que vous compreniez ce que vous faites... d'ailleurs si vous n'avez pas utilisé exactement les mêmes données que moi, ça NE MARCHE PAS, et j'ai envie de dire que... c'est normal. Mais ne vous inquiétez pas ! Il suffit juste d'adapter votre code à VOTRE pic. Mais pour cela, il faut que vous arrivez jusqu'à la partie "La structure d'une datasheet" en me faisant confiance jusque là... Pour l'instant, je vais juste vous prouver que tous les codes que vous avez utilisé se trouvent dans la datasheet, et c'est l'objet de la prochaine partie.

Explications

Voici quelques explications intéressantes qui vont vous permettre de faire une petite pause...

Un peu de vocabulaire sur ce qu'on vient de faire

On a utilisé plein de codes propres au pic. Ces codes se trouvent dans la datasheet (je rappelle qu'une datasheet est un fichier qui décrit votre composant, et que vous avez téléchargé...).

Ces codes sont reconnus sous la dénomination de "registre" ("register" en anglais). Ils sont reconnus par le pic, et donc par tous les logiciels de programmation de pic (normalement...). Voici à quoi ça ressemble chez moi :

Image IPB

Pour trouver cette page chez vous, faites une recherche de mot ("Ctrl + f"), et tapez "register file map". Appuyez sur entrée et vérifiez bien que vous êtes sur la page correspondant à votre pic. Pour moi, il y a marqué, au centre en haut : PIC16F876A/877A (seul ce qu'il y a marqué en gras m'intéresse). Il y a marqué aussi, en haut à droite : PIC16F87XA. Le "X" signifie que n'importe quel nombre peut-être mis à cette place.

En cherchant bien dans ce tableau, vous remarquerez que vous connaissez déjà PORTA, PORTB, PORTC, PORTD, PORTE (au début de la première colonne) et TRISA, TRISB, TRISC, TRISD, TRISE (deuxième colonne). Et pour l'instant, c'est tout !

Mais, je ne vois pas delay_ms !

L'autre code que je vous ai dit n'est pas propre au pic, (delay_ms) mais au logiciel microC.

Pour le retrouver, revenez sur microC et allez dans l'onglet Qhelp à gauche de la fenêtre (si vous n'avez pas ces onglets, allez dans "View --> Code explorer") :

Image IPB

Si vous êtes arrivé jusqu'ici en me faisant confiance, bravo ! Si vous êtes arrivé jusqu'ici en vous entraînant ne serait-ce qu'avec le pic que j'utilise, et le simulateur, c'est mieux ! L'idéal étant bien évidemment ceux qui ont un kit de développement qui marche avec le pic que j'utilise pour mes explications... Maintenant, faites une pause, parce que ce qui suit risque d'en décourager plus d'un... seulement c'est la partie suivante qui vous rendra définitivement indépendant dans ce monde impitoyable des pic




Troisième étape : les interruptions et... la datasheet


Les interruptions

Alors nous allons maintenant nous attaquer à un gros morceau de l'utilisation du pic : les interruptions !

Sous ce nom pas si barbare que ça se cache une notion SIMPLE.

En fait, votre robot va évoluer en fonction de ce qu'il se passe autour de lui. L'exemple le plus simple est si jamais il rencontre un obstacle : pour détecter un contact avec l'extérieur, vous pouvez placer des contacteurs, ou encore appelés "Microrupteurs". En réalité, c'est juste une lame qui lorsque on appuie dessus fait passer le courant par une broche, sinon il passe par une autre.

Dès que le courant passera par l'une de ces broches, le pic va l'interpréter comme un "1", et le programme s'arrêtera : d'où le nom d'interruption. En réalité, pendant cette interruption, il effectuera certaines tâches qui sont prévues pour cette interruption (par exemple un robot adverse qui vient nous pousser Grrrr....)

Suivez bien ce qui va suivre : ça va vous permettre de comprendre entièrement la structure d'une datasheet ! Et si vous comprenez entièrement une datasheet, vous n'avez plus besoin de ce tutoriel Image IPB.

Image IPBLe travail qui suit, est vraiment difficile... Faites le à tête reposée, en étant motivé pour faire cette partie et la suivante d'un trait, c'est le meilleur pour votre compréhension finale.

Nous allons commencer par repérer la page qui va nous intéresser dans la datasheet pour gérer les interruptions dans le PORTB :

Image IPB

Pour trouver cette page, j'ai lancé une recherche (Ctrl + f) et j'ai lancé la recherche pour "interrupt" jusqu'à arriver à une page ayant la structure précédente : les deux encadrés rouges permettent de repérer la structure. D'abord le nom du registre décrit sur cette page, puis - sachant qu'un registre est formé de huit bit - la description des huit bit (7 à 0) dans l'ordre. Je ne suis pas arrivé sur la page ci-dessus de suite, mais sur une autre qui ne m'intéressait pas. Pour trouver celle du dessus, j'ai regardé dans le texte de description si la page parle des interruptions dans un PORT. Le second que j'ai trouvé concernait le PORT B.

Sur cette page, INTCON est le nom du registre. Ce registre sert (comme c'est marqué en anglais en haut de la page...) à modifier la valeur des bits de type "ENABLE" et "FLAGS" des dépassements du timer0 (dépassements : en gros la valeur du timer0 a dépassé une valeur limite définie par défaut, et c'est ce qui est considérée comme interruptions pour le timer0... bon de toutes façons, on reverra la gestion du temps plus tard) ; ce registre sert aussi à modifier les valeurs des bits de type "ENABLE" et "FLAGS" des interruptions (provenant de l'extérieur) au niveau du PORTB du pic(et ça, ça nous intéresse au plus haut point ^^)

=> Les bits de type "ENABLE" permet d'AUTORISER la réalisation de certaines actions. Ici on cherche à autoriser les interruptions dans le PORTB. Cherchez à quel bit il correspond et notez-le (notez les tous s'il y en a plusieurs : réponse plus loin).

=> Les bits de type "FLAG" qui permettent de SAVOIR S'IL Y A EU UN CHANGEMENT QUELCONQUE DANS TOUT LE PORT. Ici, on va vouloir savoir si le PORTB a changé d'état ou non. Cherchez le ou les bits qui permettent de savoir si le PORTB a changé d'état ou non.

Solution dans le chapitre suivant...

La structure d'une datasheet

Voici la réponse aux recherches effectuées dans le précédent chapitre...
La page sur laquelle vous êtes arrivés est en fait accessible via le plan de la datasheet qui est affichée à gauche (ici, on regarde les interruptions : donc cherchez un chapitre qui parle d'interruption et cliquez dessus pour revenir sur une page comme celle ci-dessus. Si vous ne tombez pas sur la même page, cherchez dans les pages suivantes)

Une fois que vous avez vu que c'est accessible via le menu de gauche, vous remarquez les différents autres chapitres et sous chapitres qui existent. Essayez de comprendre un peu leur structure, et lisez rapidement leurs textes descriptifs pour savoir de quoi ils parlent. Vous aurez ainsi un aperçu de ce que vous pouvez faire avec votre pic.

J'ai parlé de bits de type "ENABLE" et "FLAGS". Sachez que les bits ENABLE doivent être mis à 1 pour pouvoir utiliser les fonctions qui leurs correspondent (et qui sont décris dans le texte descriptif en anglais, ainsi que sur le schéma de votre pic - qui se trouve au tout début, si vous vous rappelez bien). Les bits "FLAGS" permettent de connaître l'état de certaines pin ou bit d'un ou de plusieurs registres de votre pic. En gros, cela permet de savoir qu'est-ce qui a changé.

Il faut donc que vous réinitialisiez vos bits "ENABLE" et "FLAGS" après chaque changement !

Maintenant, vous pouvez travailler un peu plus tout seul !




D'autres outils du pic


Les timers

Je manque de temps pour terminer ce tutoriel. Je vais donner des axes d'études pour que vous puissiez continuer un peu seul. Voici la première aide pour utiliser les timers...
Enfin, pour travailler avec les interruptions, il faut que vous utilisiez la structure suivante, en dehors du main :

Code : C

void interrupt(void)
{
// votre code qui s'effectuera lors d'une interruption
}


Mettez le moins de choses possible dans la structure "interrupt". Elle ne doit vous permettre que :
  • de savoir si quelque chose a changé au niveau des entrées
  • d'enregistrer ces changements dans une variable globale (qui est donc définie au tout début du programme, et en dehors du main, via la commande :
Code : C

double ma_variable ma_valeur;


* et de réinitialiser vos registres "ENABLE" (que vous utilisez) à 1 et "FLAGS" à 0

Il ne faut surtout pas faire de calcul ou de traitement complexe (if for etc...) dans une interruption, sinon ça va "ramer" et ça risque surtout de planter.

Dans "Interrupt", il ne faut pas non plus utiliser de fonctions que vous utilisez aussi dans le main ! Cela est perçu comme une "redondance". En effet, imaginez que vous essayez d'utiliser la fonction cos dans le main, et que pendant que le pic fait le calcul, il y a une interruption... et que pendant cette interruption, vous essayez aussi de faire la fonction cos... eh bien, sachant que la fonction est programmée à "un seul endroit", vos variables utilisées dans l"interrupt" vont ecraser celles du main... du coup, plantage.

Pensez à aller voir la datasheet et google pour compléter vos connaissances sur le timer !

Se répérer dans un plan

Pour vous repérer dans un plan, vous devrez mettre des capteurs au niveau de vos roues, et ces capteurs peuvent être des encodeurs optiques ou "roues codeuses"...

Si vous avez compris tout ce qui précède, déjà, vous pouvez vous débrouiller - avec un peu de logique et de recherche - pour utiliser
* des contacteurs (des interrupteurs)
* des roues codeuses... en fait, le signal d'UNE SEULE roue codeuse est composée de deux bits en sortie (des interrupteurs qui sont activés puis désactivés) qui peuvent chacun avoir deux valeurs. Seulement, leur séquence est bien définie :

110011001100 : --__--__--__

011001100110 : _--__--__--_

A gauche, c'est la description de leurs états en séquence de 1 et de 0, et à droite, un "semblant de chronographe" qui leur correspond. Vous pouvez remarquer que leurs signaux sont identiques, à ceci près qu'ils sont décalés d'1/4 de période. Cela permet de savoir dans quel SENS la roue tourne ! en effet, si vous "lisez" la séquence dans le sens inverse, le signal n'est pas le même ! Il faut pouvoir interpréter cela sur un pic, grâce aux interruptions qui se déclenchent sur les front montants de l'un des bits seulement. Pour plus de détails sur les roues codeuses, voici la définition que j'ai rédigée sur le dicobot concernant les roues codeuses :

Ce composant est un capteur qui envoie des impulsions au fur et à mesure que son axe tourne. En clair, il peut-être utilisé comme capteur d'angle, indispensable si on veut savoir précisément où son robot se trouve.

Le signal envoyé peut avoir un codage dit "GRAY" ou alors en "QUADRATURE DE PHASE".
Ces roues codeuses possèdent deux fils d'alimentation (5V et la masse en général), plus d'autres fils qui dépendent du type de codage... Dans chaque cas, le codage représente le signal envoyé au fur et à mesure que l'axe tourne (chaque ligne correspond à un angle différent sur la roue codeuse), sur chaque fil (chaque colonne correspond à un fil différent sur la roue codeuse) : le 1 correspond au 5V utilisé par un pic par exemple, ou le 24V utilisé pour certaines certaines cartes d'acquisitions, et le 0 représente le 0V.

Roue codeuse à codage GRAY :

Ces roues codeuses possèdent plusieurs autres fils (au moins 3 de plus). Je vais détailler le signal envoyé par des roues codeuses 4 bits (donc avec 4 fils de plus, soit 6 fils au total) sur deux colonnes (lire chaque ligne de la colonne de gauche de haut en bas, puis celle de droite) :
0000|----|1100
0001|----|1101
0011|----|1111
0010|----|1110
0110|----|1010
0111|----|1011
0101|----|1001
0100|----|1000

Le signal ainsi envoyé se répète en recommençant à la première ligne une fois que la roue a fait un tour complet. On peut donc connaître facilement à tout instant l'angle actuel de la roue.

Avantage : angle facile à obtenir
Inconvénient : il y a beaucoup de fil, ce qui limite l'utilisation du pic, et ce genre de codeur coûte plus cher que celles à codage en quadrature de phase

Roue codeuse à codage en QUADRATURE DE PHASE

Ces roues codeuses possèdent deux autres fils. Voici un schéma du code reçu (signal en quadrature de phase) au cours du temps :

Image IPB


On remarque que le signal est très simple, et qu'il se répète indéfiniment. Mais attention cependant, une période de ce signal ne correspond pas à un tour complet, mais à seulement à 1/n ème de tour de la roue ! Plus "n" est grand, plus la roue codeuse est précise !

Vous pouvez remarquer que les deux signaux sont identiques, à ceci près qu'ils sont décalés d'1/4 de période. Cela permet de savoir dans quel SENS la roue tourne ! En effet, si vous "lisez" la séquence dans le sens inverse, le signal n'est pas le même !

Avantage : seuls deux fils sort de cette roue qui coûte moins cher qu'une roue à codage gray

Inconvénient : si vous prenez une roue trop précise, et que votre axe tourne trop vite... la fréquence d'envoi d'une période risque d'être trop importante pour un pic... Mais en gros, une précision de n = 50 pas par tour est facilement utilisable. De plus, ce n'est pas un codage absolu en angle ! En effet, le code se répète tous les 1/n tours... en fait, vous allez pouvoir connaître de combien a tourné votre axe par rapport à sa position antérieure.

Image IPBComment le codage est réalisé dans ces roues ?

C'est tout simple : un disque avec des trous, puis un laser et un capteur de lumière de l'autre côté du disque et le tour est joué : c'est ce capteur de lumière qui envoie "1" lorsque la lumière du laser traverse le trou et "0" lorsque la lumière est arrêté par le disque.

ATTENTION : la description que j'ai donnée pour les roues codeuses correspond à une description de roues codeuses avec deux signaux en codage binaire en "quadrature de phase" - comme on dit dans le jargon. Il existe d'autres types de roues codeuses, avec plus de bits, et dont le codage est dit "GRAY". Il en existe d'autres...

ATTENTION 2 : le signal des roues codeuses mécaniques est particulièrement merdique... Il faudra donc penser à utiliser des condensateurs pour affiner la courbe que vous pourrez obtenir avec ces roues lorsqu'elles tourneront, voire même utiliser un montage d'hystérésis pour ne prendre que les fronts montants et descendants aux valeurs que vous définirez pour obtenir des signaux carrés vraiment "jolis" et utilisables par un pic

* des moteurs à courant continu

* des moteurs pas à pas

Je donne quelques explications sur l'utilisation de ces deux moteurs dans les deux derniers chapitres.
Vous pourrez trouver plein d'autres capteurs que les roues codeuses pour vous repérer... Des pistes seront données en conclusion finale.

PWM : contrôle moteurs

PWM = Pulse Width Modulation ou Signal Modulé en Fréquence... C'est grâce à cette fonction du PIC que vous pourrez contrôler la vitesse d'un moteur à courant continu par exemple !
PWM = Pulse Width Modulation...

Bon en gros c'est la manière de fournir le courant continu au moteur à courant continu... En réalité, si on envoie une tension et un courant plus ou moins puissant dans le moteur, le moteur va logiquement plus ou moins vite. Du coup, comme c'est difficile d'envoyer de tels signaux, on utilise des composants qui font ça à notre place, et ces composants nécessitent un signal dit "carré"...

Signal carré

Ce signal possède deux état : un dit "HAUT" et l'autre dit "BAS". On dit aussi état 1 ou 0 (1 pour la tension maximale et 0 pour 0V). Ce que fait le composant dont je vous ai parlé, c'est de transformer ce signal en un signal "moyen". Si la moitié du temps il a du 5V et l'autre moitié il a du 0V, il enverra alors une tension moyenne de 2,5V... Si par contre 80% du temps il a 5V et les 20% restants il a 0, il sortira du 4V moyen... Vous vous apperevrez alors que votre moteur ira plus vite !

Le pourcentage représentant la fréquence où la tension est à l'état haut est appelé "Rapport cyclique" et comporte généralement la lettre "alpha".

Vous pouvez essayer d'utiliser des moteurs à courant continu (en utilisant un signal PWM) en passant par un circuit intermédiaire qui va transformer le rapport cyclique de votre PWM en tension continue à puissance nominale (je vous conseille les LM621).

Voici un code que j'ai écris et qui fonctionne (à condition de faire le montage qui correspond...) :

Un robot avec deux roues motrices à courant continu, contrôlés à vitesse maximale ou nulle ou négative via des interrupteurs à 3 positions (la mise en marche d'une courroie et d'une porte à l'arrière du robot étaient aussi commandés via deux autres interrupteurs)

Code : C
 
// --------------------------------------------
// Liste des ports utilisés pour gérer le robot
// --------------------------------------------

// Vitesse du moteur de la roue Gauche (VG) et Vitesse du moteur de la roue Droite (VD) [VITESSE ==> FREQUENCE] <=> à gérer avec le PWM et la fréquence d'envoi des données
#define VG CCPR1L // 1 bit
#define VD CCPR2L // 1 bit
#define SENSG1 PORTC.F3 // 1 bit : 1 si vers l'avant 0 vers l'arrière sauf si SENSG1 = SENSG2 ==> STOP
#define SENSG2 PORTC.F0 // 1 bit : 1 si vers l'arrière 0 vers l'avant sauf si SENSG1 = SENSG2 ==> STOP
#define SENSD1 PORTD.F0 // 1 bit : 1 si vers l'avant 0 vers l'arrière sauf si SENSG1 = SENSG2 ==> STOP
#define SENSD2 PORTD.F1 // 1 bit : 1 si vers l'arrière 0 vers l'avant sauf si SENSG1 = SENSG2 ==> STOP
// Télécommande : ordonne l'avancée et le recul des roues gauche et droite
#define ARG PORTD.F6
#define RRG PORTD.F7
#define ARD PORTD.F4
#define RRD PORTD.F5

// -------------------------
// Définition des constantes
// -------------------------
double PI = 3.14159265;
double VGMAX = 30;
double VDMAX = 30;
// double K = 0.001396; // = 2 * PI * 80mm / ( 15 * 24 ) CONSTANTE de réduction roue codeuse

// --------------------------
// Définition des variables :
// --------------------------
double t;

//==============================================================================
//==============================================================================
//==============================================================================

// Fonction qui permet de gérer le temps
// Nécessite :
void Temp(void)
{
if (INTCON.F2) // Gestion du temps : [0 ==> 100000] temppetit ==> x100000 ==> [0 ==> 100000] tempmoyen ==> x100000 ==> [0 ==> taille(double)] tempgros
{
t = t + 1;
TMR0L = 0;
}
}

//==============================================================================

// Fonction qui permet de gérer les interruptions
// Nécessite :
void interrupt(void)
{
Temp();
INTCON = 0b10100000;
}

//==============================================================================
//==============================================================================
//==============================================================================

// ===================
// Programme principal
// ===================

void main(void)
{
// -----------------------------
// Liste des variables utilisées
// -----------------------------

// ---------------------------------------------------------------------
// Définition des ports pour les interruptions sur le PORTB et le timer0
// ---------------------------------------------------------------------
T0CON = 0b10000100; // Utiliser le TMR0 en 16 bits et prescaler de TMR0 initialisé à 1/16
TMR0L = 0;
//TMR0L = 0b00011110; // Les interruptions s'effectueront toutes les : 1 s (si on est sur 16 bits)
//TMR0H = 0b00000000; // Uniquement sur 16 bits
INTCON = 0b10100000; // Autoriser les interruptions, celles de TMRO
ADCON1 = 0b00001111; // Utiliser les 4 premiers bits du port B en mode analogic [= analogique en anglais] uniquement (et non pas en digital = numérique en anglais)

// ---------------------------------------------------------------------
// Configuration du PWM à 4 kHz (hmmm plus en fait) Vitesse maximale 125
// ---------------------------------------------------------------------
PR2 = 0b00111111 ;
T2CON = 0b00000101 ;
CCP1CON = 0b00001100 ;
CCP2CON = 0b00111100 ;

// ---------------------
// Initialisation du pic
// ---------------------
TRISC = 0; // sortie
TRISD = 0b11110000; // 4 en sortie et 4 en entrée
PORTC = 0;
PORTD = 0;
VG = 0;
VD = 0;

// -----------------
// Boucle principale
// -----------------

while(1)
{
if (ARG)
{
VG = VGMAX; SENSG1 = 1; SENSG2 = 0;
if (ARD)
{
VD = VDMAX; SENSD1 = 1; SENSD2 = 0;
}
else if (RRD)
{
VD = VDMAX/2; SENSD1 = 0; SENSD2 = 1;
}
else
{
VD = 0; SENSD1 = 0; SENSD2 = 0;
}
}
else if (RRG)
{
VG = VGMAX/2; SENSG1 = 0; SENSG2 = 1;
if (ARD)
{
VD = VDMAX; SENSD1 = 1; SENSD2 = 0;
}
else if (RRD)
{
VD = VDMAX/2; SENSD1 = 0; SENSD2 = 1;
}
else
{
VD = 0; SENSD1 = 0; SENSD2 = 0;
}
}
else
{
VG = 0; SENSG1 = 0; SENSG2 = 0;
if (ARD)
{
VD = VDMAX; SENSD1 = 1; SENSD2 = 0;
}
else if (RRD)
{
VD = VDMAX/2; SENSD1 = 0; SENSD2 = 1;
}
else
{
VD = 0; SENSD1 = 0; SENSD2 = 0;
}
}
}
}

Pour ce dernier robot, j'ai fait aussi le schéma électrique

Avec votre pic, vous devriez pouvoir créer un ou plusieurs signaux PWM... renseignez vous avec la datasheet !

Moteurs pas à pas

Voici un exemple de code de contrôle d'un moteur pas à pas. Vous trouverez une explication sur certains moteurs ici.
Moteur pas à pas qui tourne en même temps que tourne une roue codeuse :

Code : C
 
// --------------------------------------------
// Liste des ports utilisés pour gérer le robot
// --------------------------------------------
// CONTacteurs
#define CONT PORTB.F2
// Roues codeuses gauche et droite
#define RCG1 PORTB.F0
#define RCG2 PORTB.F3
#define RCD1 PORTB.F1
#define RCD2 PORTB.F4

// Vitesse du moteur de la roue Gauche (VG) et Vitesse du moteur de la roue Droite (VD) [VITESSE ==> FREQUENCE] <=> à gérer avec le PWM et la fréquence d'envoi des données
#define VG CCPR1L // 1 bit
#define VD CCPR2L // 1 bit
#define SENSG1 PORTD.F0 // 1 bit : 1 si vers l'avant 0 vers l'arrière sauf si SENSG1 = SENSG2 ==> STOP
#define SENSG2 PORTD.F1 // 1 bit : 1 si vers l'arrière 0 vers l'avant sauf si SENSG1 = SENSG2 ==> STOP
#define SENSD1 PORTD.F2 // 1 bit : 1 si vers l'avant 0 vers l'arrière sauf si SENSG1 = SENSG2 ==> STOP
#define SENSD2 PORTD.F3 // 1 bit : 1 si vers l'arrière 0 vers l'avant sauf si SENSG1 = SENSG2 ==> STOP

// Vitesse de la Courroie (VC) avant : [VITESSE ==> FREQUENCE] <=> à gérer avec la fréquence d'envoi des données
#define VC PORTC.F4 // 1 bit
#define SENSC1 PORTD.F4 // 1 bit
#define SENSC2 PORTD.F5 // 1 bit
// Vitesse de la Porte (VP) arrière : [VITESSE ==> FREQUENCE] <=> à gérer avec la fréquence d'envoi des données
#define VP PORTC.F6 // 1 bit
#define SENSP1 PORTD.F6 // 1 bit
#define SENSP2 PORTD.F7 // 1 bit



// --------------------------
// Définition des objectifs :
// --------------------------

// -------------------------
// Définition des constantes
// -------------------------


typedef enum Sens {AVANT,ARRIERE} Sens;

// --------------------------
// Définition des variables :
// --------------------------
char t;
Sens SRCG; // Sens Roue Codeuse Gauche
char NbPasCG; // Nombre de pas de roue codeuse gauche



//==============================================================================
//==============================================================================
//==============================================================================



// *****************************
// Liste des fonctions utilisées
// *****************************


//==============================================================================



//==============================================================================
//==============================================================================
//==============================================================================


// Fonction qui permet de gérer le temps
// Nécessite :
void Temp(void)
{
//if (INTCON.F2) // Gestion du temps : [0 ==> 100000] temppetit ==> x100000 ==> [0 ==> 100000] tempmoyen ==> x100000 ==> [0 ==> taille(double)] tempgros
{
t = t + 1;
//TMR0L = 0;
}
}



//==============================================================================


// Fonction qui permet de changer l'état du PORTD à chaque fois qu'il y a une interruption
// Nécessite :
void CodeurG(void)
{
if (RCG2 == 1)
{
SRCG = AVANT;
NbPasCG++;
}
else
{
SRCG = ARRIERE;
NbPasCG--;
}
}



//==============================================================================


// Fonction qui permet de gérer les interruptions
// Nécessite : Temp()
void interrupt(void)
{
if (INTCON.F2 == 1)
{
Temp();
INTCON.F2 = 0;
}
if (INTCON.F1 == 1)
{
CodeurG();
INTCON.F0 = 0;
}

INTCON = 0b10110000; // Réinitialise les options d'interruptions
}


//==============================================================================
//==============================================================================
//==============================================================================


// ===================
// Programme principal
// ===================

void main(void)
{
// -----------------------------
// Liste des variables utilisées
// -----------------------------


// ---------------------------------------------------------------------
// Définition des ports pour les interruptions sur le PORTB et le timer0
// ---------------------------------------------------------------------
T0CON = 0b10000100; // Utiliser le TMR0 en 16 bits et prescaler de TMR0 initialisé à 1/16
//TMR0L = 0b00011110; // Les interruptions s'effectueront toutes les : 1 s (si on est sur 16 bits)
//TMR0H = 0b00000000; // Uniquement sur 16 bits
INTCON = 0b10110000; // Autoriser les interruptions, celles de TMRO et INT0 (B.0)
ADCON1 = 0b00001111; // Utiliser les 4 premiers bits du port B en mode analogic [= analogique en anglais] uniquement (et non pas en digital = numérique en anglais)

/*
// ---------------------------------------------------------------------
// Configuration du PWM à 4 kHz (hmmm plus en fait) Vitesse maximale 125
// ---------------------------------------------------------------------
PR2 = 0b00111111 ;
T2CON = 0b00000101 ;
CCP1CON = 0b00001100 ;
CCP2CON = 0b00111100 ;
*/

// ---------------------
// Initialisation du pic
// ---------------------
TRISA = 0;
TRISB = 0b11111111;
TRISC = 0;
TRISD = 0;
TRISE = 0;
PORTA = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
PORTE = 0;
t = 0;

// ************************
// DEFINITION DES OBJECTIFS
// ************************

while(1)
{
PORTD = t;
PORTC = NbPasCG;
if (SRCG == AVANT)
{
PORTA.F4 = 0;
}
else
{
PORTA.F4 = 1;
}
}
}



Vitesse du Moteur pas à pas contrôlé par la roue codeuse

Code : C

// Roues codeuses gauche et droite
#define RCG1 PORTB.F0
#define RCG2 PORTB.F3
#define RCD1 PORTB.F1
#define RCD2 PORTB.F4

typedef enum Sens {AVANT,ARRIERE} Sens;

char t;
Sens SRCG; // Sens Roue Codeuse Gauche
char NbPasCG; // Nombre de pas de roue codeuse gauche

int pas;


// Fonction qui permet de gérer le temps
// Nécessite :
void Temp(void)
{
//if (INTCON.F2) // Gestion du temps : [0 ==> 100000] temppetit ==> x100000 ==> [0 ==> 100000] tempmoyen ==> x100000 ==> [0 ==> taille(double)] tempgros
{
t = t + 1;
//TMR0L = 0;
}
}



//==============================================================================


// Fonction qui permet de changer l'état du PORTD à chaque fois qu'il y a une interruption
// Nécessite :
void CodeurG(void)
{
if (RCG2 == 1)
{
SRCG = AVANT;
NbPasCG++;
}
else
{
SRCG = ARRIERE;
NbPasCG--;
}
}



//==============================================================================


// Fonction qui permet de gérer les interruptions
// Nécessite : Temp()
void interrupt(void)
{
if (INTCON.F2 == 1)
{
Temp();
INTCON.F2 = 0;
}
if (INTCON.F1 == 1)
{
CodeurG();
INTCON.F0 = 0;
}

INTCON = 0b10110000; // Réinitialise les options d'interruptions
}


void wait_ms(int x)
{
int i;
for(i=0;i<=x;i++)
{
delay_ms(1);
}
}


void majEtat(void)
{
int etat = pas%4;
if (etat<0) etat += 4;
if ( etat == 0 )
PORTD = 0b00101000;
else if ( etat == 1 )
PORTD = 0b00000101;
else if ( etat == 2 )
PORTD = 0b00000011;
else // etat = 4
PORTD = 0b00011000;
}


void main (void)
{
int x, Vmax, Vmin, Da, Dc, Df, SAVE, V, S; // Distance de : Acceleration, constante, freinage

// ---------------------------------------------------------------------
// Définition des ports pour les interruptions sur le PORTB et le timer0
// ---------------------------------------------------------------------
T0CON = 0b10000100; // Utiliser le TMR0 en 16 bits et prescaler de TMR0 initialisé à 1/16
//TMR0L = 0b00011110; // Les interruptions s'effectueront toutes les : 1 s (si on est sur 16 bits)
//TMR0H = 0b00000000; // Uniquement sur 16 bits
INTCON = 0b10110000; // Autoriser les interruptions, celles de TMRO et INT0 (B.0)
ADCON1 = 0b00001111; // Utiliser les 4 premiers bits du port B en mode analogic [= analogique en anglais] uniquement (et non pas en digital = numérique en anglais)

/*
// ---------------------------------------------------------------------
// Configuration du PWM à 4 kHz (hmmm plus en fait) Vitesse maximale 125
// ---------------------------------------------------------------------
PR2 = 0b00111111 ;
T2CON = 0b00000101 ;
CCP1CON = 0b00001100 ;
CCP2CON = 0b00111100 ;
*/

// ---------------------
// Initialisation du pic
// ---------------------
TRISA = 0;
TRISB = 0b11111111;
TRISC = 0;
TRISD = 0;
TRISE = 0;
PORTA = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
PORTE = 0;
t = 0;
pas = 0;
Vmax = 5;
V = 30;
Vmin = 80;
Da = 100;
Df = 100;
Dc = 200;
SAVE = NbPasCG;
S = 1;

while(1)
{
if (S == 1)
{
if(NbPasCG > SAVE)
{
if(V>Vmax)
{
V--;
}
}
else if (NbPasCG < SAVE)
{
if(V<Vmin)
{
V++;
}
else
{
S = -1;
V = Vmin-1;
}
}
pas++;
}
else
{
if(NbPasCG < SAVE)
{
if(V>Vmax)
{
V--;
}
}
else if (NbPasCG > SAVE)
{
if(V<Vmin)
{
V++;
}
else
{
S = 1;
V = Vmin-1;
}
}
pas--;
}
SAVE = NbPasCG;
wait_ms(V);
majEtat();
}
}
Avec un peu de recherche sur la datasheet et en pensant au composant LM621, vous devriez arriver à vos fins avec un peu de recherche sur le net (je manque vraiment de temps pour terminer convenablement le tutoriel).

Par manque cruel de temps, ce tutoriel a été littéralement "bâclé" sur la fin. Vous avez néanmoins suffisamment de bagage pour pouvoir faire vos recherches un peu seul...

Vous pouvez par la suite essayer de vous intéresser aux réseaux I2C qui permettent à plusieurs pic de communiquer entre eux de manière assez "facile" (vous n'avez pas à programmer vous-même le protocole de communication) ou encore les Conversion Analogique Numérique et inversement (CNA/CAN). Vous pouvez également essayer d'utiliser les entrées/sorties analogique (au lieu du tout ou rien) qui permettront de recevoir un signal en provenance d'un capteur de distance par exemple... Ce sont autant de pistes pour vous aider à continuer à vous améliorer.

Sur ce, j'espère que ce tutoriel vous aura quand même beaucoup aidé, et si certains sont motivés pour re-rédiger ce tutoriel en tout ou partie, il est totalement libre, je demande juste à ce qu'il le reste.


Trigonométrie

Publié Harry le 14 avril 2016 - 05:53 in Concepts

Bonjour, ce tutoriel est plus une liste de formules très utiles en robotique qu'un vrai tutoriel, mais il peut être très efficace de l'avoir à portée de main...

Voici le cercle trigonométrique, son rayon étant pris égal à 1 :

Image IPB


Image IPB Sur le cercle est positionné l'angle que fait le vecteur OA avec l'horizontale : on l'appelle alpha.

Vous remarquerez que l'angle entre OB et AB est 90° : OAB est donc rectangle en B. Prenons ce triangle rectangle.

On pose trois fonctions indispensables en mathématiques que sont cosinus, sinus et tangente, qui sont écrits, si alpha est un angle : cos(alpha), sin(alpha) et tan(alpha)

Ils sont définis par (à connaître par coeur avec le schéma qui va avec) :
cos(alpha) = côté adjacent / hypoténuse
sin(alpha) = côté opposé / hypoténuse
tan(alpha) = côté opposé / côté adjacent


sachant que dans le triangle rectangle OAB :
côté adjacent = OB
côté opposé = BA
hypoténuse = OA

alors on obtient (à connaître par coeur avec le schéma qui va avec) :
cos(alpha) = OB/OA
sin(alpha) = BA/OA
tan(alpha) = BA/OB


Image IPB

Image IPB Un symbole bizarre (en jaune) est introduit sur le schéma : il s'appelle PI et vaut environ 3,1415... (le nombre de chiffre après la virgule est infini).
L'unité utilisé en trigonométrie pour les angles n'est pas le degré (noté °), mais le radian (noté rad)
Ainsi, PI rad = 180°


Image IPB Le cosinus de l'angle fait entre OA et l'horizontale se trouve en projetant A sur l'horizontale (soit B ce point). Son sinus est trouvé en projetant A sur la verticale (soit C ce point). Certaines valeurs de cosinus et de sinus sont à connaître par cœur :


Image IPBcos (0) = sin(PI/2) = 1
cos(PI/6) = sin(PI/3) = racine(3)/2
cos(PI/4) = sin(PI/4) = racine(2)/2
cos(PI/3) = sin(PI/6) = 1/2
cos(PI/2) = sin ( 0 ) = 0


Image IPBExercice : trouver la valeur des tangentes de ces nombres

Image IPBOn remarque que sin(alpha)/cos(alpha) = tan(alpha) (il suffit d'écrire la relation avec les longueurs pour s'en convaincre). Ainsi, connaissant les valeurs de sin(alpha) et cos(alpha) on retrouve les valeurs facilement.

tan(0) = 0
tan(PI/6) = 1/racine(3)
tan(PI/4) = 1
tan(PI/3) = racine(3)
tan(PI/2) = l'infini



Vous devez retrouver l'équivalent des angles mis sur le schéma suivant, et les connaître par cœur, et savoir les positionner sans problème sur le cercle trigonométrique, ainsi que leurs cosinus, sinus et tangente :

Image IPB

Un sens positif et un sens négatif sont indiqués : en réalité l'angle en radian n'est pas un angle simple. Il est dit "algébrique" car il peut être négatif comme positif. Cela a donc une conséquence sur les valeurs des sinus et des cosinus. En clair, il faut savoir refaire le schéma précédent par cœur.


Formules trigonométriques à savoir - si on prend "a" et "b" deux angles algébriques :

sin(-a) = -sin(a)
cos(-a) = cos(a)
cos (a + B ) = cos(a).cos( B ) - sin(a).sin( B )
sin (a + B ) = sin(a).cos( B ) + cos(a).sin( B )
cos²(a) + sin²(a) = 1
cos(2a) = cos²(a) - sin²(a) = 2.cos²(a) - 1 = 1 - 2.sin²(a) (à savoir retrouver)
sin(2a) = 2.sin(a).cos(a) (à savoir retrouver)


Formules à savoir retrouver (ça peut faire d'excellents exercices) :
cos( PI/2 - a ) = sin(a)
sin( PI/2 - a ) = cos(a)
cos( PI/2 + a ) = sin(a)
sin( PI/2 + a ) = -cos(a)
cos( PI - a ) = -cos(a)
sin( PI - a ) = sin(a)
cos( PI + a ) = -cos(a)
sin( PI + a ) = -sin(a)
cos( a - B ) = cos(a).cos( B ) + sin(a).sin( B )
sin( a - B ) = sin(a).cos( B ) - sin( B ).cos(a)


Très utiles à savoir retrouver :

Image IPB

Formule à utiliser quand vous en aurez besoin :

Image IPB

Loi des sinus : formule valable pour un triangle quelconque ABC(en prenant A, B et C les angles et a, b, c leurs côtés opposés respectifs)

a/sin(A) = b/sin( B ) = c/sin( C ) = 2R


Enfin, loi des cosinus (ou loi d'Al-kashi) : des formules qui donne des relations entre le cosinus d'un angle et les longueurs d'un triangle quelconque ! Extrêmement utile en robotique pour effectuer des calculs sans utiliser des librairies lourdes pour un pic pour calculer des relations particulières :

a² = b² + c² - 2b.c.cos A ==> On en déduit la valeur de cos A
b² = c² + a² - 2c.a.cos B ==> On en déduit la valeur de cos B
c² = a² + b² - 2a.b.cos C ==> On en déduit la valeur de cos C


Voilà, j'espère que cette liste de formules vous sera utile.


[Composant] le L298

Publié Mike118 le 19 mai 2016 - 09:22 in Electronique

On a tous au moins un composant qui est super pratique mais mal foutu … Et moi, Mike 118, aujourd’hui je vais vous parler de mon préféré de cette catégorie : Le L298N (plus connu sous sa forme multiwatt 15V …)

 

l298.jpg

 

Tout d’abord pour ceux qui ne le connaissent pas encore : qu’est-ce que c’est que ce composant ? Et bien c’est un double pont en H capable de délivrer 2A par pont fonctionnant jusqu’à 46V ! Il est donc idéal pour une grande gamme de moteurs CC et pas à pas.
Pour ceux qui ne savent pas ce qu’est un pont en H je les invite à se renseigner ici par exemple : http://fr.wikipedia.org/wiki/Pont_en_H.
Autre remarque : je vais employer volontairement des mots anglais afin de vous familiariser un peu avec certains termes employé dans les documentations anglaises en vigueur : aussi appelé les datasheet ! Mais ne vous inquiétez pas cela ne sera que ponctuel !

 

Je vais commencer par décrire un peu le composant :
Comme le composant contient deux ponts en H on les notera pont A et pont B. Le L298 a 15 pattes qui se répartissent ainsi :

  • 3 pattes pour l’alimentation qui est commun aux pont A et B. On a donc la masse : Gnd pour "ground", la tension d’alimentation de forte puissance : VS comprise entre 5 et 50V et la tension d’alimentation « logique » noté Vss = 5V (point très intéressant puisque le composant est donc compatible avec tous vos composants favoris tournant en 5V : Pic, Arduino, Aop, Ne555, etc…)
  • 4 pattes pour les deux paire de sorties que l’on nomme output 1 output 2 output 3 et output 4. Avec output 1 et 2 appartenant au pont A et output 3 et 4 appartenant au pont B. C’est là qu’on va brancher notre moteur par exemple et ce sont ces sorties qui seront capable de délivrer 2A en continue et des pics jusqu’à 3A mais à éviter le plus possible.
  • 4 pattes pour les 2 paires d’entrées que l’on note input 1 input 2 input 3 input 4 de chaque pont, là aussi input 1 et 2 appartenant au pont A et input 3 et 4 appartenant au pont B. C’est sur ces pattes qu’on va brancher nos composants préféré qui vont commander les pont A et B. En effet, imposer une tension de 5V sur input 1 va permettre d’imposer la tension VS sur output 1 et imposer 0V va permettre d’imposer 0V sur output1 … de même pour input 2 sur output 2 etc…
  • Cela fait déjà 11 pattes, et on a vu comment on pouvait utiliser le composant dans ces grandes lignes mais il manque encore 4 pattes …
  • Enable A, enable B, current sensing A, current sensing B

A quoi peuvent-elles bien servirent ?
Tout d’abord, chaque pont est pourvu d’une sécurité, d’où les pattes notées « enable A et enable B ». Pour pouvoir utiliser le pont A : à savoir output 1 et output2, il faut qu’une tension de 5V soit appliqué sur enable A sinon le pont est « en roue libre » et dans ce cas on a donc output 1 et 2 qui ne sont relié à rien du tout ! Ni à la masse ni au 24V quel que soit l’état des input1 et input2. De même pour pouvoir utiliser le pont B il faut 5V sur enable B…

 

Cela fait 2 pattes supplémentaires qu’on peut gérer avec nos composants favoris tournant à 5V ! Très intéressant si on veut ajouter un bouton d’arrêt d’urgence par exemple car il suffit de le relier entre la masse et l’enable du port qu’on veut pouvoir arrêter avec le bouton d’arrêt d’urgence… On peut même relier les deux enables ensemble pour pouvoir couper les deux ponts en même temps !

Notez une chose : Si vous n’en avez pas l’utilité, n’oubliez pas de brancher les enables au 5V !

Bon courage ! Il reste plus que deux pattes …
Ce sont des pattes qui permettent de connaitre le courant I circulant dans chaque pont noté current sensing A et B ! Il suffit pour cela de mettre entre une résistance de valeur R entre curent sensing et la masse et de lire la tension U présente à cette patte : On aura I = U/R. Par contre attention ! Il faut choisir une résistance capable de dissiper suffisamment de puissance (2A ce n’est pas rien ! Petit rappel en notant R la valeur de votre résistance on P = R*I² … Donc avec une résistance de 1ohm et du 2A ça fait déjà au moins 4W à dissiper …) De même il est recommandé de ne pas dépasser les 3V sur cette pattes … donc Il est recommandé d’utiliser dans ce cas une résistance inférieur ou égale à 1 ohm et dissipant suffisamment de puissance pour vos applications ! Comme il ne faut pas dépasser une consommation de 3A, que ces pattes nous permettent de connaître la consommation en temps réel de chaque pont et que les enables nous permettent de couper les ponts si besoin … Il ne faut pas chercher bien loin pour se rendre compte qu’on peut faire une régulation du courant consommée dans les pont du L298 en utilisant ces 4 dernières pattes !

 

Bon maintenant que je vous ais embêté avec ça : sachez que si vous n’avez pas besoin de connaître la consommation en courant dans les ponts vous pouvez tout simplement bancher les current sensing à la masse ! (Et ceci résout le problème du choix de la résistance x). )
Maintenant une petite image pour tout récapituler et montrer qui est où sur le composant :

l298-shema.jpg

 

Pour plus d’info sur le composant je vous invite à lire la datasheet du composant disponible ici : Fichier attaché  l298-sgs-thomson-microelectronics-1.pdf   190,37 Ko   420 Nombre de téléchargements
Bon tout ça c’est bien beau on est d’accord… Vous auriez pu savoir tout ce que je viens de dire en lisant cette datasheet … Mais rappelons-nous j’ai dit que ce composant était « mal foutu »… Pourquoi donc ?
C’est l’organisation de ces pattes ! Sur une seule ligne c’est bien joli :

l298-shema2.jpg

 

Il y a juste la patte VS qui aurait peut-être put être à côté de la masse… mais bon rien de grave !
Le problème voilà… et bien par ce que nous on utilise généralement c’est ce genre de truc :

veroboard-breadboard.jpg

 

Qui eux sont compatible avec le format “Dip” = espacement entre les pattes 2.54mm et dans le cadre de composants sur deux rangées , les deux ranges sont aligéens avec espacement entre 2 rangées de pattes côte à côte 7.62mm (= 3*2.54mm).

 

Or le L298 est ainsi :

l298-shema3.jpg

 

Donc lui aussi est sur 2 rangées, chaque patte de chaque rangé a bien un espacement de 2.54mm mais l’espacement entre les deux rangées n’est pas de 7.62 mais d’environ 5mm. Mais le pire c’est que les deux rangées ne sont pas alignées ! Arg… Pour le rendre compatible il faut plier un peu les pattes … Soit …
On prend donc notre pince préférée si nécessaire, toute notre délicatesse et on s’exécute …

 

N’ayez pas peur ça se fait assez facilement … Les pattes sont plus solides qu’elles en ont l’aire faut juste pas trop répéter l’opération !
La preuve en image , ainsi cela s’adapte parfaitement au standart Dip :

montage-l298-veroboard.jpg

 

Bon c’est cool tout va bien … C’est très simple … Cependant voilà …

 

De manière schématique ce qu’on obtient au choix…

 

l298-l298.jpg

 

Et là stupeur ! nouveau casse tête … Ce qui était si bien ordonné quand tout était en ligne ne l’est plus en deux ligne ! Deux input d’un côté et deux de l’autre … les output de chaques côté … idem pour la masse et le 5V … Et du coup l’interfaçage avec quoi que ce soit et lui aussi un véritable casse tête … C’est la croix et la banière comme diraient certaines … en effet n’aurait il pas tellement été plus simple d’avoir ceci ?

 

schema-l298.jpg

 

Rien de plus simple pourtant … Il suffit de plier les pattes un peu différement !

 

l298-casse.jpg

 

Et c’était jusqu’à maintenant mon petit secret avec ce composant que je vous partage aujourd’hui ! Ce n’est peut-être pas très beau mais c’est monstrueusement efficace !

 

Je ne sais pas vous mais moi mais moi en tout cas je trouve ça 10 fois plus pratique … Et voilà pourquoi avec un petit exemple d’interfaçage :

 

interface.jpg

 

Vous pourrez remarquer que l’interfaçage est beaucoup plus facile : tout ce qui a besoin d’être gérer par nos composants préféré : microcontrôleur etc… est mis du côté droit (représenté en vert). Tout ce qui est sortie et alimentation est du côté gauche… Il ne reste plus qu’à y mettre vos connecteurs préférés et vous avez votre propre shield pour contrôler deux moteurs à courant continu dans les deux sens !
Vous pouvez aussi rajouter 8 diodes rapides 2A au montage afin de protéger le L298 des surintensités dans le cas où un moteur tourne alors qu’il ne devrait pas au vu de la commande… Ce qui arrive en général quand on demande à un moteur de s’arrêter alors qu’il tournait vite … car il met un peu de temps à le faire du à son inertie ! Il faut placer 2 diodes par sortie de la façon ci-contre sur le côté :

2-diodes-par-sortie.jpg

 

De plus je trouve que les pattes inputs et enables sont particulièrement bien agencées ! Cela ne vous rappel pas un autre composant vous ? Moi si ! Quelqu’un me souffle le L297 pour commander les moteurs pas à pas ? Bingo !

 

Regardons de plus près :

 

L297-pour-commander-les-moteurs-pas-a-pas.jpg

 

Et oui !
Correspondance parfaite
pour ces 6 pattes entre
les deux composants !
Voilà aussi de quoi simplifier l’interfaçage entre ces deux composants !