De2115Extension : Différence entre versions
(→{{Vert|Programme relatif au contrôle des servomoteurs}}) |
(→{{Bleu|Travail S4 du binôme Baczkowski/To}}) |
||
Ligne 778 : | Ligne 778 : | ||
</pre> | </pre> | ||
+ | |||
+ | ==={{Vert|Programme relatif au sonar}}=== | ||
=={{Bleu|Travail S4 du binôme Gnagne/Gaya}}== | =={{Bleu|Travail S4 du binôme Gnagne/Gaya}}== |
Version du 24 mars 2017 à 11:41
Sommaire
Étude et conception
Présentation projet
On cherche à contrôler une tourelle pan-tilt à l'aide de 2 servomoteurs, d'un joystick ou d'un nunchuk, et d'un radar ultra-son.
Contraintes
Dimensionnement des écarts entre les connecteurs
1) Ecart entre les connecteurs MSP
C'est l'écart qui compte le plus : s'il n'y a qu'un mm de trop, la carte extension ne sert à rien. Une mesure précise de l'écart entre les broches extérieures de la MSP432, puisque celle-ci possède 2 broches doubles, donne 46mm.
2) Ecart entre les connecteurs MSP et le connecteur Altera
Une distance minimale est également nécessaire entre le connecteur Altera et les connecteurs MSP : 21mm.
3) Ecart entre les autres composants et les connecteurs MSP ou Altera
Comme le connecteur Altera a une certaine largeur, on ne peut pas placer des straps en-deçà d'une certaine distance avec l'élément. Or, comme, pour des raisons de commodité, il est très conseillé de placer toutes les pistes connectées à l'élément sur le côté inférieur de la carte, on se retrouve donc avec plusieurs straps, et il ne faut pas oublier cet élément.
De la même manière, une certaine distance est obligatoire entre les connecteurs MSP et les autres, car la carte n'a même pas exactement la largeur existante entre ses deux connecteurs, elle empatte. Cet empattement est de 5mm. Pour d'autres composants, cette distance doit être encore plus grande, car ceux-ci ont également une certaine largeur. Ainsi, la prise de la nunchuk ayant une largeur respectable, il faut une distance de 15mm entre les deux connecteurs.
Espace nécessaire à la fixation de la tourelle
La carte doit également nécessiter un espace suffisant pour fixer la tourelle pan-tilt.
Surface de la tourelle (en mm) : 33 x 37
Distances maximales entre les connecteurs et les composants
Comme les fils des composants n'ont pas une distance infinie, il y a une distance maximale entre ceux-ci et les connecteurs. Sur les 3 composants,l'un d'entre eux ne pose pas de problèmes : le nunchuk est tenu en main. Les deux restants se trouvent au même endroit : le sonar est imbriqué dans la tourelle. Cela implique donc que la tourelle doit se trouver à proximité des connecteurs des servomoteurs et du sonar.
Longueur des fils (en cm) :
- du sonar : 30
- de la tourelle pan-tilt : 24
Surface de la carte : 17 x 9
Etant donné que la surface de la carte est inférieure à la longueur des fils, la contrainte peut donc être négligée.
Cependant, dans l'optique de rendre la carte plus simple, il vaut mieux diminuer autant que possible la distance entre les composants et les connecteurs, afin de pouvoir raccourcir la longueur des fils.
Conception
Conception de la carte du binôme Baczkowski/To
Nous avons conçu notre carte en prenant en compte plusieurs paramètres.
Tout d'abord, afin de diminuer le flux entre les pistes, nous avons essayé d'éviter que celles-ci soient parallèles.
Dans un deuxième temps, pour éviter les vias, nous avons fait une carte en double face.
Nous avons eu un choix à faire au sujet des barrettes : celles-ci agissent en quelque sorte comme un interrupteur, sauf qu'il n'y a pas un état 0 et un état 1 mais, comme dans les deux cas il y a une liaison, une connexion A et une connexion B.
Comme un barrettes possède 4 pattes, on a une alternative :
- solution 1 : il y a une entrée et 2 sorties. Pour que les 4 pattes soient utilisées, on peut dupliquer l'entrée, et dans ce cas-là, il faut décaler le cavalier pour passer de la connexion A à la connexion B.
- solution 2 : on peut également se contenter d'une entrée. Mais comme le cavalier a une taille fixe, il ne peut pas être disposé sur la diagonale de la bar. On est donc obligé de disposer les sorties du cavalier de part et d'autre de l'entrée.
Dans un premier temps, nous avons retenu la première solution. Mais après la réalisation du premier prototype, nous avons préféré nous reporter sur la deuxième solution, afin de rendre l'utilisation de la carte plus simple. Mieux encore, nous avons décidé que sur chaque barrette, les positions des cavaliers auraient la même signification. Premièrement, les cavaliers sont toujours disposés de manière horizontale. Ensuite, la première position, celle du haut, relie l'élément au microcontrôleur de la carte MSP432, et celle du bas relie l'élément à la carte Altera.
Un autre défi s'est présenté à nous lorsqu'il nous a fallu dimensionner, puis stabiliser la plaque soutenant le sonar sur la tourelle. Plusieurs solutions se présentaient à nous, mais dans tous les cas il nous fallait viser les deux plaques.
Les 3 dimensions sont à prendre en compte :
- pour la largeur, des bordures en plastique permettent de la limiter, mais encore faut-il que la largeur du support du sonar corresponde avec l'écart entre les deux bordures ;
- pour la longueur, une bordure en plastique est placée à l'avant, mais il n'y a rien à l'arrière, il y a donc un risque que la carte s'échappe.
- pour la hauteur, elle est encore une fois limitée, en haut, par deux morceaux de plastique. Cependant, comme le mouvement de la tourelle est vertical, le sonar et sa plaque bougent beaucoup. C'est donc sur la hauteur que la stabilisation importe vraiment, même s'il n'y a pas pour autant de risques que le sonar s'échappe.
Conception de la carte du binôme Gaya/Gnagne
Nous avons conçu notre carte de la manière suivante :
Afin de pouvoir optimiser la carte et qu'elle soit la plus petite possible donc la moins chère possible à
fabriquer, tout en restant fonctionnelle :
- Nous avons décidé de mettre les 2 deux connecteurs 3 broches mâle-mâle, servant aux 2
servomoteurs de la tourelle côte-à- côte afin de limiter des étalements de fils.
- Nous avons bien pris les précautions nécessaires vis-à- vis des espacements entre chaque
composant.
- Afin de pouvoir souder que d’un seul côté le plus gros composant de notre carte « le
connecteur 40 broches », qui sert à la connexion avec l’Altera, nous l’avons routé que du
côté « Bottom ».
Nous avions donc le même schéma, mais nos typons étaient différents :
Programmation
Travail S3
Une fois la carte réalisée, nous avons voulu vérifier si celle-ci fonctionnait en commençant directement avec un programme complexe. Mais comme les résultats que nous a donnés celui-ci se sont avérés surréalistes, nous avons dans un second temps préféré créer 3 programmes séparés, pour chacune des 3 parties du montage :
- le premier destiné à contrôler le fonctionnement des servomoteurs, et donc la rotation de la tourelle ;
- le second destiné à soumettre cette tourelle au mouvement de la nunchuk ;
- et dans un troisième temps, faire fonctionner le sonar, c'est-à-dire émettre et récupérer un signal pour pouvoir déterminer la distance à laquelle se trouvent les obstacles les plus proches.
Programme relatif au contrôle des servomoteurs
Pour contrôler les servomoteurs, nous avons d'abord trouvé un programme test, pour vérifier le fonctionnement du servomoteur sur une plaque à essai avant la réalisation.
Pour cela, nous avons trouvé dans Energia, une plateforme de prototypage électronique permettant de rendre compatible la structure Arduino, avec les composants Texas Instruments, le programme Knob dans la bibliothèque Servo. Ce programme ne fonctionne pas avec la nunchuk, mais avec un potentiomètre.
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int potpin = PE_4; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
void setup()
{
myservo.attach(PF_1); // attaches the servo on Port F, pin 1 (Red LED pin) to the servo object
}
void loop()
{
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 4095)
val = map(val, 0, 4095, 0, 179); // scale it to use it with the servo (value between 0 and 180)
myservo.write(val); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
}
De cette manière, nous avons pu nous assurer que le montage que nous nous proposions de faire ne comportait pas d'erreur de routage.
Par la suite, avec l'aide de l'enseignant, nous avons fait un deuxième programme, servant uniquement à vérifier que la tourelle n'ait pas de problèmes.
#include <Servo.h>
Servo h_servo, v_servo;;
uint8_t horizontal,vertical;
void setup() {
//définir patte Data des servomoteurs
h_servo.attach(A15); // servomoteur horizontal
v_servo.attach(3); // servomoteur vertical
// iniatialisation de la valeur de départ
horizontal=0;
vertical=20;
}
void loop() {
// Incrémentation de la variable horizontale
horizontal += 10;
// Condition
if (horizontal > 180) // si la variable horizontale est maximale
{
vertical += 10; // Incrémentation la variable verticale
horizontal=0; // remise à zéro de la valeur horizontale
}
if (vertical > 105) vertical=20; // si la variable vertical est maximale, retour à la valeur initiale
// donne une valeur aux servomoteurs
h_servo.write(horizontal);
v_servo.write(vertical);
delay(1000);
h_servo.write(horizontal);
v_servo.write(vertical);
delay(333);
}
Nous avons toutefois rencontré des problèmes. L'un d'entre eux ne nous a pas posé de vrais problèmes, étant aisément contournable, mais il nous a agacé, car nous n'en comprenons pas la cause : la temporisation que l'on trouve dans la boucle ne pouvait pas être une autre valeur que 100 ou 333.
Comme nous cherchions une temporisation de 1000, nous avons d'abord pensé que les servomoteurs ne gardaient pas en mémoire leur valeur suffisamment longtemps, mais comme nous avons essayé également une temporisation de 250, nous avons dû admettre que ce n'était pas ça. Finalement, afin de pouvoir conserver une temporisation assez grande, nous avons compris que c'était le fait que ce soit la dernière temporisation qui posait problème, et nous avons donc rajouté une deuxième temporisation, avec cette fois-ci une valeur "admise".
Comme la rotation de la tourelle est soumise à la nunchuk, cette temporisation n'est pas si importante, même si on en aura quand même besoin pour la réception du signal par le sonar.
Programme relatif au contrôle du sonar
unsigned char trig = 17; // Définit la patte du transmetteur
unsigned char echo = 19; // Définit la patte du récepteur
float aff;
float diviseur = 64.1; // Convertit la valeur reçue en cm
void setup() {
// Déclare les pins
pinMode(trig, OUTPUT);
pinMode(echo, INPUT);
Serial.begin(9600);
}
void loop()
{
delay(500);
digitalWrite(trig, 1);
delayMicroseconds(10);
digitalWrite(trig, 0);
aff = (pulseIn(echo, 1) / diviseur);
Serial.print(aff);
Serial.println("cm");
}
Programme relatif au contrôle de la manette nunchuk
Nous avons perdu beaucoup de temps avec une erreur bête : sur Arduino, il ne faut pas mettre de pull-up, puisque le logiciel le fait automatiquement. Mais Energia ne le fait pas, il faut donc mettre une pull-up, et cet oubli nous a fait un temps précieux.
Programme Test
#include <Wire.h>
// adresse I2C du nunchuck
#define WII_NUNCHUK_I2C_ADDRESS 0x52
// définition d'une variable counter
uint8_t counter;
// définition d'un tableau de données
uint8_t data[6];
void setup() {
pinMode(10,INPUT_PULLUP); // SDA
pinMode(BLUE_LED, OUTPUT); // Déclaration de la LED
// initialisation du nunchuck
Wire.begin();
Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS);
Wire.write(0xF0);
Wire.write(0x55);
Wire.endTransmission();
Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS);
Wire.write(0xFB);
Wire.write(0x00);
Wire.endTransmission();
}
void loop() {
// on réinitialise le nunchuck pour la prochaine demande
Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS);
Wire.write(0x00);
Wire.endTransmission();
delay(1);
// on demande 6 octets au nunchuck
Wire.requestFrom(WII_NUNCHUK_I2C_ADDRESS, 6);
counter = 0; // tant qu’il y a des données
while(Wire.available()) {
// on récupère les données
data[counter++] = Wire.read();
}
//allumer la LED bleu dont la valeur est donnée par l'axe X du joystick
analogWrite(BLUE_LED, data[0]);
// un petit delai pour pas saturer la liaison série.
delay(30);
}
Programme reliant le nunchuck au servomoteurs
#include <Servo.h>
#include <Wire.h>
// adresse I2C du nunchuck
#define WII_NUNCHUK_I2C_ADDRESS 0x52
Servo h_servo, v_servo;
// iniatialisation de la valeur de départ
uint8_t horizontal = 90;
uint8_t vertical = 20;;
// définition d'une variable counter
uint8_t counter;
// définition d'un tableau de données
uint8_t data[6];
uint8_t joyX;
uint8_t joyY;
int16_t accelX;
int16_t accelY;
int16_t accelZ;
void setup() {
pinMode(10, INPUT_PULLUP); // SDA
//définir patte Data des servomoteurs
h_servo.attach(A15); // servomoteur horizontal
v_servo.attach(3); // servomoteur vertical
Serial.begin(9600);
// initialisation du nunchuck
Wire.begin();
Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS);
Wire.write(0xF0);
Wire.write(0x55);
Wire.endTransmission();
Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS);
Wire.write(0xFB);
Wire.write(0x00);
Wire.endTransmission();
}
void loop() {
// on réinitialise le nunchuck pour la prochaine demande
Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS);
Wire.write(0x00);
Wire.endTransmission();
delay(1);
// on demande 6 octets au nunchuck
Wire.requestFrom(WII_NUNCHUK_I2C_ADDRESS, 6);
counter = 0; // tant qu’il y a des données
while (Wire.available()) {
// on récupère les données
data[counter++] = Wire.read();
}
if (counter >= 5)
{
// on extrait les données
joyX = data[0];
joyY = data[1];
// dans mon exemple j'utilise uniquement les données d'accélération sur l'axe Y
accelX = ((data[2] << 2) + ((data[5] >> 2) & 0x03));
accelY = ((data[3] << 2) + ((data[5] >> 4) & 0x03));
accelZ = ((data[4] << 2) + ((data[5] >> 6) & 0x03));
}
// Si joyX est inférieur à 110
if (joyX < 110)
{
horizontal += 10; // on incrémente
}
else if (joyX > 140) // Ou si joyX est supérieur à 140
{
horizontal -= 10; // on décrémente
}
//seuil limite h_servo
if (horizontal > 190)
{
horizontal = 190;
}
else if (horizontal < 10)
{
horizontal = 10;
}
// Si joyY est inférieur à 120
if (joyY < 120)
{
vertical -= 10; // on décrémente
}
else if (joyY > 140) // Ou si joyY est supérieur à 140
{
vertical += 10; // on incrémente
}
//seuil limite v_servo
if (vertical > 160)
{
vertical = 160;
}
else if (vertical < 30)
{
vertical = 30;
}
//Serial.print("vtc = ");
//Serial.println(vertical);
// donne une valeur aux servomoteurs
h_servo.write(horizontal);
v_servo.write(vertical);
delay(100);
// un petit delai pour pas saturer la liaison série.
delay(30);
}
Programme complet
#include <Servo.h>
#include <Wire.h>
// adresse I2C du nunchuck
#define WII_NUNCHUK_I2C_ADDRESS 0x52
Servo h_servo, v_servo;
//servomteur
// iniatialisation de la valeur de départ
uint8_t horizontal = 90;
uint8_t vertical = 20;;
//nunchuck
// définition d'une variable counter
uint8_t counter;
// définition d'un tableau de données
uint8_t data[6];
uint8_t joyX;
uint8_t joyY;
int16_t accelX;
int16_t accelY;
int16_t accelZ;
//sonar
unsigned char trig = 17;
unsigned char echo = 19;
float aff;
float diviseur = 64.1;
void setup() {
pinMode(10, INPUT_PULLUP); // SDA
//sonar
pinMode(trig, OUTPUT);
pinMode(echo, INPUT);
//servomoteur
//définir patte Data des servomoteurs
h_servo.attach(A15); // servomoteur horizontal
v_servo.attach(3); // servomoteur vertical
Serial.begin(9600);
// initialisation du nunchuck
Wire.begin();
Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS);
Wire.write(0xF0);
Wire.write(0x55);
Wire.endTransmission();
Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS);
Wire.write(0xFB);
Wire.write(0x00);
Wire.endTransmission();
}
void loop() {
// on réinitialise le nunchuck pour la prochaine demande
Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS);
Wire.write(0x00);
Wire.endTransmission();
delay(1);
// on demande 6 octets au nunchuck
Wire.requestFrom(WII_NUNCHUK_I2C_ADDRESS, 6);
counter = 0; // tant qu’il y a des données
while (Wire.available()) {
// on récupère les données
data[counter++] = Wire.read();
}
if (counter >= 5)
{
// on extrait les données
joyX = data[0];
joyY = data[1];
// dans mon exemple j'utilise uniquement les données d'accélération sur l'axe Y
accelX = ((data[2] << 2) + ((data[5] >> 2) & 0x03));
accelY = ((data[3] << 2) + ((data[5] >> 4) & 0x03));
accelZ = ((data[4] << 2) + ((data[5] >> 6) & 0x03));
}
// Si joyX est inférieur à 110
if (joyX < 110)
{
horizontal += 10; // on incrémente
}
else if (joyX > 140) // Ou si joyX est supérieur à 140
{
horizontal -= 10; // on décrémente
}
//seuil limite h_servo
if (horizontal > 190)
{
horizontal = 190;
}
else if (horizontal < 10)
{
horizontal = 10;
}
// Si joyY est inférieur à 120
if (joyY < 120)
{
vertical -= 10; // on décrémente
}
else if (joyY > 140) // Ou si joyY est supérieur à 140
{
vertical += 10; // on incrémente
}
//seuil limite v_servo
if (vertical > 160)
{
vertical = 160;
}
else if (vertical < 30)
{
vertical = 30;
}
// donne une valeur aux servomoteurs
h_servo.write(horizontal);
v_servo.write(vertical);
delay(100);
// un petit delai pour pas saturer la liaison série.
delay(30);
//sonar
delay(500);
digitalWrite(trig, 1);
delayMicroseconds(5);
digitalWrite(trig, 0);
aff = (pulseIn(echo, 1) / diviseur);
Serial.print(aff);
Serial.println("cm");
}
Travail S4 du binôme Baczkowski/To
Dans la continuité de notre projet en Etude et Réalisation du S3, nous devions programmer notre carte de tels sorte que les servomoteurs et le sonar soient contrôlés par la carte Altera, c'est-à-dire en VHDL, et la nunchuk par la carte MSP432. Pour cela, nous avons suivi la même logique que nous avons utilisé lors du S3. Nous avons divisé les tâches en plusieurs partie pour résoudre petit problème par petit problème.
Nous avons :
- tout d'abord commencé par mouvoir les servomoteurs et définir leurs plages de déplacement,
- ensuite programmé le sonar et faire afficher la distance en cm avec les afficheurs 7 segments,
- puis mélangé les 2 programmes précédents,
- Enfin programmé le sonar pour qu'il affiche la distance sous forme d'un barregraphe sur l'écran LCD
Programme relatif au contrôle des servomoteurs
Nous avons commencé par faire bouger le servomoteur horizontal en définissant des valeurs en dur pour encadrer la plage de déplacement du servomoteur, puis nous avons exécuté la même manipulation pour le servomoteur vertical. Ensuite, nous avons programmé les servomoteurs de tels sorte qu'il balaye une plage pour se déplacer.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity ER_Project is port (
clk : in std_logic;
pwm : out std_logic_vector(1 downto 0)
);
end entity;
architecture Movemotor of ER_Project is
component diviseur is port (
clk : in std_logic;
eno : out std_logic
-- q : out std_logic_vector(23 downto 0)
);
end component;
component cmpt_hzt is port (
clk, en : in std_logic;
eno : out std_logic;
s_hzt : out std_logic_vector(7 downto 0)
);
end component;
component cmpt_vtc is port (
clk, en : in std_logic;
s_vtc : out std_logic_vector(7 downto 0)
);
end component;
signal timer : natural range 0 to 3900 := 0;
signal eno : std_logic;
signal s_cmpt8 : std_logic_vector(7 downto 0);
signal s_eno, s_eno1 : std_logic;
signal ref1 : std_logic_vector(7 downto 0);
signal ref2 : std_logic_vector(7 downto 0);
begin
div : diviseur port map (
clk => clk, eno => s_eno
);
cmpt1 : cmpt_hzt port map (
clk => clk, en => s_eno, eno => s_eno1, s_hzt => ref1
);
cmpt2 : cmpt_vtc port map (
clk => clk, en => s_eno1, s_vtc => ref2
);
-- realisation 78 us
process(clk)
begin
if rising_edge(clk) then
if timer = 0 then
timer <= 3900;
eno <= '1';
else
timer <= timer - 1;
eno <='0';
end if;
end if;
end process;
cmpt8:process(clk) begin
if rising_edge(clk) then
if eno = '1' then
s_cmpt8 <= s_cmpt8 + 1;
end if;
end if;
end process;
--comparaison svm hrz
process(s_cmpt8)
begin
if (s_cmpt8 < ref1) then
pwm(0) <= '1';
else
pwm(0) <= '0';
end if;
end process;
--comparaison svm vtc
process(s_cmpt8)
begin
if (s_cmpt8 < ref2) then
pwm(1) <= '1';
else
pwm(1) <= '0';
end if;
end process;
end Movemotor;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity diviseur is port (
clk : in std_logic;
eno : out std_logic
-- q : out std_logic_vector(23 downto 0)
);
end entity diviseur;
architecture arch of diviseur is
signal cmpt : std_logic_vector(23 downto 0);
begin
process (clk) begin
if rising_edge(clk) then
cmpt <= cmpt+1;
end if;
end process;
eno <= '1' when cmpt = x"FFFFFF" else
'0';
end arch;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity cmpt_hzt is port (
clk, en : in std_logic;
eno : out std_logic;
s_hzt : out std_logic_vector(7 downto 0)
);
end entity cmpt_hzt;
architecture arch of cmpt_hzt is
signal cmpt : std_logic_vector(7 downto 0) := x"0A";
begin
process (clk) begin
if rising_edge(clk) then
if en='1' then
if cmpt < x"1F" then
cmpt <= cmpt+1;
else
cmpt <= x"08";
end if;
end if;
end if;
end process;
eno <= '1' when cmpt = x"1F" else
'0';
s_hzt <= cmpt;
end arch;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity cmpt_vtc is port (
clk, en : in std_logic;
s_vtc : out std_logic_vector(7 downto 0)
);
end entity;
architecture arch of cmpt_vtc is
signal cmpt : std_logic_vector(7 downto 0) := x"0A";
begin
process (clk) begin
if rising_edge(clk) then
if en='1' then
if cmpt < x"14" then
cmpt <= cmpt+1;
else
cmpt <= x"0A";
end if;
end if;
end if;
end process;
s_vtc <= cmpt;
end arch;
Et voici le fichier de contrainte :
To,Direction,Location,I/O Bank,VREF Group,I/O Standard,Reserved CLK,Input,PIN_Y2,2,B2_N0,3.3-V LVTTL, pwm[0],Output,PIN_AC15,4,B4_N2,3.3-V LVTTL, pwm[1],Output,PIN_Y17,4,B4_N0,3.3-V LVTTL,
Programme relatif au sonar
Travail S4 du binôme Gnagne/Gaya
Le déroulement du S4 est basé sur la programmation avec la carte Altera DE2-115.
Programme de base
Ce programme permet de faire bouger la tourelle de gauche à droite et de bas en haut.
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity toto is port(
clk : in std_logic;
pwm : out std_logic
);
end entity;
architecture titi of toto is
signal timer: natural range 0 to 3900:=0;
signal eno: std_logic;
signal s_compt8: std_logic(7 downto 0);
signal ref: std_logic(7 downto 0);
begin
process(clk) begin
if rising_edge(clk) then
if timer=0 then
timer <=3900;
eno <=1;
else
timer <=timer-1;
eno <=0;
end if;
end process;
compt8:process(clk)
begin
if rising_edge(clk) then
if eno ='1' then
s_cmpt8 <= s_cmpt8 + 1;
end if;
end if;
end process;
comparateur:process(clk) begin
if rising_edge(clk) then
if (s_compt8<ref)then
pwm='1';
else
pwm='0'
end if;
end if;
end process;
ref<=x"19";
end titi;
Programme relatif au contrôle du Sonar et des servomoteurs
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity toto is
Port ( clk : in STD_LOGIC;
pwm : out std_logic_vector(1 downto 0);
sonar_trig : out STD_LOGIC;
sonar_echo : in STD_LOGIC;
-- anodes : out STD_LOGIC_VECTOR (3 downto 0);
-- segments : out STD_LOGIC_VECTOR (6 downto 0));
Unit7segs : out std_logic_vector(6 downto 0);
Diz7segs : out std_logic_vector(6 downto 0)
);
end toto;
architecture Behavioral of toto is
--composant servo
component diviseur is port (
clk : in std_logic;
eno : out std_logic
-- q : out std_logic_vector(23 downto 0)
);
end component;
component cmpt_hzt is port (
clk, en : in std_logic;
eno : out std_logic;
s_hzt : out std_logic_vector(7 downto 0)
);
end component;
component cmpt_vtc is port (
clk, en : in std_logic;
s_vtc : out std_logic_vector(7 downto 0)
);
end component;
--composant servo
component transcod7segs is
port (
I_in4 : in std_logic_vector(3 downto 0);
-- Ordre : gfedcba
Q_7segs : out std_logic_vector(6 downto 0)
);
end component transcod7segs;
-- signal sonar
signal count : std_logic_vector(16 downto 0) := (others => '0');
signal centimeters : std_logic_vector(15 downto 0) := (others => '0');
signal centimeters_ones : std_logic_vector(3 downto 0) := (others => '0');
signal centimeters_tens : std_logic_vector(3 downto 0) := (others => '0');
signal output_ones : std_logic_vector(3 downto 0) := (others => '0');
signal output_tens : std_logic_vector(3 downto 0) := (others => '0');
signal digit : std_logic_vector(3 downto 0) := (others => '0');
signal echo_last : std_logic := '0';
signal echo_synced : std_logic := '0';
signal echo_unsynced : std_logic := '0';
signal waiting : std_logic := '0';
signal seven_seg_count : unsigned(15 downto 0) := (others => '0');
--signal servo
signal timer : natural range 0 to 3900 := 0;
signal eno : std_logic;
signal s_cmpt8 : std_logic_vector(7 downto 0);
signal s_eno, s_eno1 : std_logic;
signal ref1 : std_logic_vector(7 downto 0);
signal ref2 : std_logic_vector(7 downto 0);
begin
--servo liaison
div : diviseur port map (
clk => clk, eno => s_eno
);
cmpt1 : cmpt_hzt port map (
clk => clk, en => s_eno, eno => s_eno1, s_hzt => ref1
);
cmpt2 : cmpt_vtc port map (
clk => clk, en => s_eno1, s_vtc => ref2
);
-- realisation 78 us pour servo
process(clk)
begin
if rising_edge(clk) then
if timer = 0 then
timer <= 3900;
eno <= '1';
else
timer <= timer - 1;
eno <='0';
end if;
end if;
end process;
cmpt8:process(clk) begin
if rising_edge(clk) then
if eno = '1' then
s_cmpt8 <= s_cmpt8 + 1;
end if;
end if;
end process;
--comparaison svm hrz
process(s_cmpt8)
begin
if (s_cmpt8 < ref1) then
pwm(0) <= '1';
else
pwm(0) <= '0';
end if;
end process;
--comparaison svm vtc
process(s_cmpt8)
begin
if (s_cmpt8 < ref2) then
pwm(1) <= '1';
else
pwm(1) <= '0';
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
if waiting = '0' then
if count = 500 then -- Assumes 50MHz
-- After 10us then go into waiting mode
sonar_trig <= '0';
waiting <= '1';
count <= (others => '0');
else
sonar_trig <= '1';
count <= count+1;
end if;
elsif echo_last = '0' and echo_synced = '1' then
-- Seen rising edge - start count
count <= (others => '0');
centimeters <= (others => '0');
centimeters_ones <= (others => '0');
centimeters_tens <= (others => '0');
elsif echo_last = '1' and echo_synced = '0' then
-- Seen falling edge, so capture count
output_ones <= centimeters_ones;
output_tens <= centimeters_tens;
elsif count = 1450*2 -1 then
-- advance the counter
if centimeters_ones = 9 then
centimeters_ones <= (others => '0');
centimeters_tens <= centimeters_tens + 1;
else
centimeters_ones <= centimeters_ones + 1;
end if;
centimeters <= centimeters + 1;
count <= (others => '0');
if centimeters = 3448 then
-- time out - send another pulse
waiting <= '0';
end if;
else
count <= count + 1;
end if;
echo_last <= echo_synced;
echo_synced <= echo_unsynced;
echo_unsynced <= sonar_echo;
end if;
end process;
unite : transcod7segs port map (
I_in4 => output_ones,
Q_7segs => Unit7segs
);
dizaine : transcod7segs port map (
I_in4 => output_tens,
Q_7segs => Diz7segs
);
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- zero pour allumer les LEDs
--description du composant pour sonar
entity transcod7segs is
port (
I_in4 : in std_logic_vector(3 downto 0);
-- Ordre : gfedcba
Q_7segs : out std_logic_vector(6 downto 0)
);
end transcod7segs;
architecture arch of transcod7segs is begin
with I_in4 select
Q_7SEGS <= "1000000" when "0000",
"1111001" when "0001",
"0100100" when "0010",
"0110000" when "0011",
"0011001" when X"4",
"0010010" when X"5",
"0000010" when X"6",
"1111000" when X"7",
"0000000" when X"8",
"0010000" when X"9",
"0001000" when X"A",
"0000011" when X"B",
"1000110" when X"C",
"0100001" when X"D",
"0000110" when X"E",
"0001110" when others; --X"F"
end arch;
--description des composant servo
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity diviseur is port (
clk : in std_logic;
eno : out std_logic
-- q : out std_logic_vector(23 downto 0)
);
end entity diviseur;
architecture arch of diviseur is
signal cmpt : std_logic_vector(23 downto 0);
begin
process (clk) begin
if rising_edge(clk) then
cmpt <= cmpt+1;
end if;
end process;
eno <= '1' when cmpt = x"FFFFFF" else
'0';
end arch;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity cmpt_hzt is port (
clk, en : in std_logic;
eno : out std_logic;
s_hzt : out std_logic_vector(7 downto 0)
);
end entity cmpt_hzt;
architecture arch of cmpt_hzt is
signal cmpt : std_logic_vector(7 downto 0) := x"0A";
begin
process (clk) begin
if rising_edge(clk) then
if en='1' then
if cmpt < x"1F" then
cmpt <= cmpt+1;
else
cmpt <= x"08";
end if;
end if;
end if;
end process;
eno <= '1' when cmpt = x"1F" else
'0';
s_hzt <= cmpt;
end arch;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity cmpt_vtc is port (
clk, en : in std_logic;
s_vtc : out std_logic_vector(7 downto 0)
);
end entity;
architecture arch of cmpt_vtc is
signal cmpt : std_logic_vector(7 downto 0) := x"0A";
begin
process (clk) begin
if rising_edge(clk) then
if en='1' then
if cmpt < x"14" then
cmpt <= cmpt+1;
else
cmpt <= x"0A";
end if;
end if;
end if;
end process;
s_vtc <= cmpt;
end arch;
Réalisation technique
Réalisation de la carte du binôme Baczkowski/To
Nous avons commencé par le composant le plus important, à savoir le connecteur Altera. Toutes les soudures n'étaient pas obligatoires, car la plupart des pattes n'étaient reliées à aucune piste. Néanmoins, par souci de stabilité, nous avons jugé préférable d'effectuer les 40 soudures au dos de la carte, car aucun composant ne nous gênait.
Comme nous avions besoin de souder des 2 côtés de la carte, il fallait nous assurer de sa stabilité. Pour cela, nous avons utilisé un étau.
Comme, pour les premières soudures, le fer n'avait assez chauffé, les soudures ont donc bavé. Ce petit défaut récurrent a été légèrement par la suite.
En ce qui concerne les connecteurs mâles des servomoteurs, nous avons eu affaire à une rupture de stock. Nous avons donc choisi des connecteurs femelles, et de placer des adaptateurs dessus.
Mais par la suite, nous nous sommes aperçus que la carte comportait trop d'erreurs. Beaucoup d'entre elles étaient rattrapables, mais certaines ne l'étaient pas. Plutôt que d'utiliser le système D pour tenter de faire fonctionner ladite carte, nous avons préféré tirer profit de nos erreurs, et, puisque nous en avions encore le temps.
En ce qui la fixation du sonar sur la tourelle, plusieurs solutions se présentaient à nous, mais dans tous les cas il nous fallait viser les deux plaques. Pour dimensionner la plaque, et pouvoir l'intégrer dans la structure de la tourelle, nous l'avons d'abord limée. Puis, pour la stabiliser, nous avons choisi un système à 3 vis et 4 écrous : 2 d'entre elles servent à maintenir l'écart entre la plaque et la tourelle. Seule la plaque est percée, et pour l'empêcher de descendre, un écrou est disposé juste en dessous de celle-ci. Pour éviter qu'un des côté ne s'affaisse, les 2 vis sont disposées en diagonale. La dernière vis a 2 fonctions : premièrement, éviter un affaissement diagonal, peu probable mais toujours possible. Dans un second temps, il faut absolument éviter que celle-ci ne s'avance ou ne recule. Donc, cette vis, en plus du premier écrou, doit également en posséder un deuxième, situé de l'autre côté de la plaque qu'il traverse dans un deuxième temps.
Problèmes rencontrés lors de la réalisation
1) Position et sens des connecteurs
Le premier problème que nous avons rencontré est la position du connecteur Altera. En effet, pour éviter de torsader la nappe, il fallait que le celui-ci ait un sens particulier, car la position de la carte Altera est prédéterminée. Ce problème n'est pas vraiment handicapant, car il est seulement d'ordre esthétique.
2) Problème de la carte en double face
Il s'est rapidement avéré qu'il aurait mieux valu avoir des vias et tout mettre au dos de la carte : en ayant des pistes sur la carte, cela nous empêche d'enfoncer totalement le connecteur Altera, car nous avons besoin de souder le composant des deux côtés.
À cause de cela, les soudures pistes/pastilles posent problème au top. Le plus embêtant reste lorsque les pistes viennent de l'autre côté de la carte : la soudure doit alors être faite sous le composant, ce qui pose problème.
Mais cela ne se limite pas au composant Altera : les connecteurs 4 pattes, du sonar et du nunchuk, et 3 pattes, des servomoteurs, et les barrettes, ainsi que les connecteurs de la carte MSP432, ont le même problème.
Le plus gros problème de la carte est donc d'être en double-face, une carte en simple face n'aurait pas eu tout ces inconvénients.
Cela nous a posé problème lorsque nous avons voulu vérifier l'absence de court-circuit et de faux contact.
3) Problème de la position des pistes dans les connecteurs
Le plus gros problème, qui nous a finalement conduit à considérer la première carte réalisée comme un prototype, a été la place des pistes dans les connecteurs. En effet, si pour le sonar, les fils pouvaient être dessoudés et ressoudés à loisir, ce n'était le cas ni pour les servomoteurs ni pour la nunchuk. Si on ajoute à cela le problème de l'adaptateur, comme nous avions encore du temps devant nous, nous avons jugé plus prudent de refaire une carte, quitte à flirter dangereusement, pour nous assurer d'avoir une carte qui conviendrait au projet.
4) Oubli de connexions nécessaires au protocole SPI
Nous avions également confondu les sorties du cavalier du JP4, et celle de l'Altera, nécessaire à l'utilisation du protocole SPI, la patte CS de la MSP432. En outre, nous avions oublié de connecter l'horloge SPI.
Solutions apportées
Lorsque nous avons voulu vérifier l'absence de court-circuit et de faux contact, nous avons dû employer une astuce : afin de pouvoir toucher la patte du composant située sous sa partie plastique, nous avons enroulé un fil en étain autour d'une des pointes.
Mais ces précautions prennent du temps : pour souder 5 composants, nous avons passé 1h30, et 30 min supplémentaires ont été nécessaires pour les vérifications.
Carte finale
Sur le deuxième essai, nous avons pris en compte tous ces paramètres afin de faire une carte plus simple à réaliser, à l'utilisation plus intuitive, et surtout immédiatement fonctionnelle.
Nous avons toutefois rencontré, là encore, des difficultés. En particulier, et ça a été une surprise car ça n'avait pas été le cas lors de la réalisation du prototype, lors du perçage. En effet, lors de la création du calque, nous avons sélectionné une catégorie supplémentaire, qui nous a gênés pour distinguer le diamètre des pastilles. Par mesure de sécurité, nous avons décidé de choisir, pour le perçage, un foret de 1mm pour chaque pastille, sauf pour les résistances, car nous avons rapidement vu qu'un diamètre de 0.8mm convenait.
En ce qui concerne la fixation de la tourelle sur la carte, et afin d'avoir une carte nous avions plusieurs solutions :
- premièrement, nous pouvions coller la tourelle sur la carte, en utilisant un pistolet à colle ;
- ensuite, nous pouvions placer des vis du côté supérieur de la carte, et comme celles-ci dépassent de l'autre côté, il aurait aussi fallu placer des entretoises. Comme le diamètre de ces entretoises est supérieur à celui des trous préexistants, il aurait fallu repercer la tourelle ;
- enfin, nous pouvions placer des vis du côté inférieur de la carte.
Nous avons retenu la troisième solution, qui nous a plu par sa simplicité, et afin de stabiliser la carte, nous avons également placé des plots adhésifs sous la carte, afin que celle-ci ne soit pas soutenue par les soudures.
Comme les fils du sonar et des servomoteurs étaient trop grands et gênaient, nous avons résolu le problème en raccourcissant les fils du sonar, et comme cela n'était pas possible pour les fils des servomoteurs, qui avaient une taille fixe, nous avons utilisé un collier de câblage, afin de rassembler les fils.
Réalisation de la carte du binôme Gaya/Gnagne
Nous avons commencé par souder les 6 straps qui était présent sur notre carte, puis nous avons souder notre plus gros composant le connecteur 40 broches, qui sert à la connexion avec l'Altera.
Puisque nous avions router ce composant uniquement du côté "bottom", la soudure de ce composant à été simple. Nous avons ensuite souder les 2 connecteurs 10 broches mâle-mâle, servant à la connexion avec la carte MSP432. Cependant, contrairement au connecteur 40 broches, nous avons du souder des deux côtés le reste des composants, puisqu'ils sont tous en double face.
Problèmes rencontrés lors de la réalisation
1) Espacement entre les composants
Lors de la conception de la carte nous avions mesurer les espaces entre chaque composant, et nous avons pris les distance minimales.
Et donc puisque nous n'avions pas pris en compte le bout de plastique de la carte MSP432. La carte MSP432 chevauchait le connecteur 40 broches.
2)Perçage des pastilles
Nous avons d'abord percer les pastilles des connecteurs en 0.8mm, cependant les connecteurs ne passaient pas.
3) Fixation de la tourelle
Afin que la tourelle soit la plus stable possible, nous avons décider de fixer la tourelle sur la carte.Cependant, il nous est alors venu le problème suivant:comment la fixer.
Solutions apportées
1) Espacement entre les composants
Nous avons donc choisis d’utiliser un connecteur 40 broches, tourné à 90° , ainsi le connecteur 40 broches de l'Altera et la carte MSP432 ne se chevauchaient plus.
2)Perçage des pastilles
Nous avons donc utilisé un perçage de 1mm, afin de faciliter la soudure des composants.
3) Fixation de la tourelle
Afin de fixer la tourelle, nous avons décider de percer la carte et de la fixer à l'aide de vis et de clous. Il a fallu alors mesurer les dimensions de la tourelle et choisir un diamètre de perçage. On a donc eu comme dimensions de la tourelle:
Tourelle dimensions : (37x35)(en mm)
Perçage utilisé: 2mm.
Carte finale
Après avoir résolu tous ces problèmes, nous avons pu réaliser la carte sans grand soucis:
Nous avons réaliser des tests pour vérifier l’absence de faux contacts sur la carte, à l'aide d'un multimètre. Nous avons pu constater quelques faux contacts, nous avons donc souder une deuxième fois certaines pattes de certains composants et le problème était réglé. Par soucis de stabilité de la carte, nous avons choisis de mettre 4 pieds à notre carte, afin qu'elle ne repose pas sur ses soudures, de plus cela empêche tous problème de court-circuit, si la carte serait posée sur une surface métallique.
Améliorations possibles
La carte qu'on obtient au final a un fonctionnement plutôt intuitif, mais elle est loin d'être parfaite.
Son plus gros défaut est le fait qu'elle soit alimentée seulement par la carte Altera : ça implique une dépendance à la carte DE2-115, or cette carte est assez volumineuse et prend de la place. Donc, le FPGA est très puissant, et permet de réaliser beaucoup plus d'applications que la carte MSP432, mais pour les tâches simples, le processeur suffit largement.
D'autre part, nous avons également commis une erreur en utilisant les pattes nécessaires à la liaison série pour la nunchuk. Ce problème nous empêche d'utiliser normalement la carte MSP432 : si on veut utiliser normalement la carte, on a des interférences qui rendent les données reçues par le sonar complétement illisibles. Pour pouvoir recevoir les informations normalement, et mélanger les deux programmes, il faut transformer le montage en une véritable usine à gaz, qui, visuellement, donne ceci :
Il est également certain que le programme final, mélangeant les deux précédents programmes, peut être amélioré. Mais nous avons manqué de temps pour sa simplification.