SE3Trinome2022-2

De projets-se.plil.fr
Révision datée du 5 juin 2023 à 12:45 par Rex (discussion | contributions) (→‎Moteur DC : avancer/reculer/arrêter)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigation Aller à la recherche

GIT

Voici le lien vers notre GIT : https://archives.plil.fr/ccariat/SE3Trinome2022-2_Projet_2km.git

Projections

  • Dimensions : voiture 1:43 dans la mesure du possible l'électronique sera caché sous la carrosserie
  • Contrôle de la voiture : déplacement programmé (Bluetooth si le temps nous le permet)
  • Énergie : batterie LiPo accrochée sur le toit, il n'y aura qu'un port USB pour l'information et le rechargement de la batterie intégrée à la voiture
  • Éclairage : deux phares avant via deux LED RGB qui pourront servir d'IHM (infos sur la charge de la batterie par exemple)
  • Direction : roues avant orientables grâce à un moteur pas à pas glissière


Liste du matériel :

  • Voiture 1:43
  • Atmega 16u2
  • Mini-moteur continu avec réducteur + pilote DRV8210DRLR
  • Moteur pas à pas glissière
  • Connecteur USB_A
  • 2 Leds RGB
  • Batterie LiPo
  • Chargeur MAX1811
  • Module de communication Bluetooth BM71BLE01FC2

Réalisation de la carte

Schématique

Contrainte

Pour pouvoir assurer le bon fonctionnement du moteur DC, il est primordial d'utiliser une broche de l'atmega qui puisse délivrer un signal PWM. Leurs noms sont de la forme "OC.**".

Composants créés

Pour mener à bien la conception assistée par ordinateur nous avons dû créer la schématique de composants directement via Kicad :

Empreintes créés

Afin de se rendre compte de la place que prend chaque composant, il a fallu trouver/créer des empreintes pour chaque élément du montage. Pour créer une empreinte, il est nécessaire de mesurer les dimensions du composant en question. Nous avons aussi pu trouver des empreintes sur le site SnapEDA.

Voici celles que nous avons construite/trouvées :

Images de la schématique

Voici le schéma électronique produit pour ce projet :

Schéma pour une voiture télécommandée 1:43 avec roue avant orientable

Malheureusement, nous n'avons pas pu garder cette schématique : les LED RGB prenaient beaucoup trop de place et nous avons changé quelques connexions de pins afin de nous faciliter la tâche pour le PCB. Voici le schéma final :

Schématique final

PCB

Placement de l'antenne (image tirée de la datasheet)

Contraintes

Pour assurer le bon fonctionnement de la carte, nous avons dû respecter des conditions :

  • Condensateurs proches du microcontrôleur
  • Axe du moteur DC pile au niveau des roues arrières
  • Condensateurs/résistance du quartz proches de ce dernier, avec la même disposition que sur la schématique
  • Pistes USB D+ et D- de même longueur, le temps de transmission doit être à peu près le même, pour éviter des erreurs
  • Antenne Bluetooth dans un bord de la carte isolée des autres composants (voir image)


Le PCB doit au maximum comporter 2 types de piste. Il a fallu faire attention à ne pas trop rapprocher les vias. Nous avons aussi veillé à placer le moteur glissière à la verticale et les LED au bord de la carte.


Images

Ci-dessous les images de la carte routée.

face n°1
face n°2

Ci-dessous les images de la carte en 3D.

PCB de face (vue 3D)
PCB de dos (vue 3D)



Vous pouvez télécharger le dossier comportant la partie CAO Fichier:Pcb binome2.zip.

Voici ci-dessous une image de notre PCB :

Notre carte imprimée

Programmation de la voiture

Suite à un malentendu, nous n'avons pas pu obtenir notre carte à temps. Nous avons donc utilisé une carte du trinôme 6 pour la soudure et la programmation. Voici un schéma des E/S utilisées dans cette carte, ainsi que la carte avant soudure :


Connectique de l'atmega 16u2 du groupe 6
Carte utilisée, faite par le trinôme 6


Lorsque nous avons soudé le connecteur USB et le microcontrôleur, nous nous sommes assurés que le pc reconnaît l'atmega avec la commande lsusb. Ce qui n'a pas été le cas lors du premier essai, mais après l'intervention de M. Redon, il nous a expliqué que le problème venait surement d'une erreur de valeur sur un condensateur.


Premier Programme : Allumer les LED

Une fois la carte imprimée et soudée avec les premiers composants, nous la testons avec un premier programme de test pour clignoter les leds. Nous avons pris comme base les fichiers C présent dans cette page (tout en bas), notamment pour gérer les entrées sorties. Il a été nécessaire de l'adapter : l'atmega 16u2 ne possède que 3 registres d'E/S, le B, le C et le D.

L'étape suivante est d'adapter le makefile en mettant le bon nom de CPU la bonne fréquence et destination. Enfin, il est nécessaire de configurer les registres DDR* en sorties pour les broches concernées (PB4,PB5,PB6 et PB0 soit DDRB = 0x71)

Il suffit alors d'utiliser les fonctions output_set et output_unset comme dans cet exemple :

/*code...*/
#define MAX_LED	4

#define PORTB_OUTPUT	0x71

unsigned char led1[]={0x01,0x00,0x00};//led arrière à gauche
unsigned char led2[]={0x10,0x00,0x00};//led avant à droite
unsigned char led3[]={0x20,0x00,0x00};//led arrière à droite
unsigned char led4[]={0x40,0x00,0x00};//led avant à gauche

unsigned char *leds[]={led1,led2,led3,led4}; //tableau de leds

/*code...*/

while(1)
{
   // Allumer pendant 1 seconde la LED 4 (indice 3 du tableau) :
   output_set(leds,3);
   _delay_ms(1000);
   // Éteindre pendant 1 seconde la LED 4 (indice 3 du tableau) :
    output_unset(leds,3);
   _delay_ms(1000);
}

/*code...*/

Voici une vidéo du fonctionnement des LED (téléversement) :


NB : Pour tester le programme, après avoir téléversé, il est nécessaire de déconnecter puis reconnecter la carte au port USB.


Moteur DC : avancer/reculer/arrêter

Le driver du moteur continu requiert l'utilisation de signaux PWM, des signaux à fréquence variable. Selon la fréquence, le moteur est amené à tourner plus ou moins vite. En nous inspirant du code présent dans cette page, nous avons écrit :

/*code...*/
#define PWM1_DDR         DDRB
#define PWM1_PORT        PORTB
#define PWM2_DDR         DDRC
#define PWM2_PORT        PORTC

#define PWM1            7
#define PWM2            6

void PWM_init(void){               // Initialisation de la PWM
PWM1_DDR |= (1<<PWM1);             // PWM ==> sorties
PWM2_DDR |= (1<<PWM2); 
TCCR1A |= (1<<COM1A1)|(1<<COM1C1);   // Les ports PWM se comportent normalement
TCCR1A |= (1<<WGM11)|(1<<WGM10);     // Minuteur mis en mode PWM
TCCR1B |= (1<<CS10);                 // Pas de pré-diviseur, démarre le compteur
}
/*code...*/

Les broches utilisées par la carte sont PB7 et PC6, qui délivrent respectivement OCR1A et OCR1C, du timer1 de l'atmega. Ce dernier étant de 16 bits la valeur maximale d'OCR1* est de 65 536. Le registre TCCR définit le mode de fonctionnement du timer. D'après la datasheet, le mode utilisé est un PWM 10-bit (voir image ci-dessous) donc la valeur maximale que peut prendre OCR1* est 1024. Pour faire marcher le moteur, il faut donc agir, dans notre cas, sur OCR1A et OCR1C. Le moteur étant continu, il est préférable de ne pas "activer" les deux broches en même temps, mais une à la fois. On peut régler la vitesse du moteur en variant OCR1* de 0 à 1024 :

Mode de fonctionnement utilisé (extrait de la datasheet)
/*code...*/

void avancer(void)
{
OCR1A = 512;//actif, vitesse moyenne (1024/2)
OCR1C = 0;//"non-activé"
}
/*code...*/

Pour aller dans l'autre sens, il suffit d'interchanger les valeurs :

/*code...*/

void reculer(void)
{
OCR1A = 0;//"non-activé"
OCR1C = 512;//actif, vitesse moyenne (1024/2)
}
/*code...*/

Enfin, pour arrêter le moteur :

/*code...*/

void arret(void)
{
OCR1A = 0;//"non-activé"
OCR1C = 0;//"non-activé"
}
/*code...*/

Voici une vidéo du fonctionnement du moteur continu :

Moteur DC tourne dans les 2 sens + arrêt

Moteur pas à pas : direction

Un moteur pas à pas fonctionne en activant séquentiellement les bobines électromagnétiques du stator pour générer des champs magnétiques et déplacer le rotor par incréments.

Pour faire tourner le moteur, il suffit d'appliquer un courant à une broche chacune à son tour :

Schéma explicatif

Pour faire monter le moteur glissière, on actionne la broche M1 puis M3 puis M2 et enfin M4.

Pour faire descendre le moteur, c'est le contraire.

Pour gérer la direction de la voiture, nous avons opté pour un moteur pas à pas glissière. Après avoir mis PC5, PD4, PD5 et PD6 en sortie, on a :

/*code...*/

#define PORTC_OUTPUT	0x20
#define PORTD_OUTPUT	0x70

unsigned char mot_step_1[]={0x00,0x00,0x10};
unsigned char mot_step_2[]={0x00,0x00,0x20};
unsigned char mot_step_3[]={0x00,0x00,0x40};
unsigned char mot_step_4[]={0x00,0x20,0x00};

unsigned char *moteur_step[]={mot_step_1,mot_step_2,mot_step_3,mot_step_4};

void stepper(int direction)
{
  switch(direction)
  {
    case 1 :
      for(int i = 0; i<=50;i++)
      {
        // moteur 1 puis 3 puis 2 et enfin 4
	      output_set(moteur_step,0);
	      _delay_ms(100);
	      output_unset(moteur_step,0);

	      output_set(moteur_step,2);
	      _delay_ms(100);
	      output_unset(moteur_step,2);

	      output_set(moteur_step,1);
	      _delay_ms(100);
	      output_unset(moteur_step,1);

	      output_set(moteur_step,3);
	      _delay_ms(100);
	      output_unset(moteur_step,3);
      }
      break;
    case -1 :
      for(int i = 0; i<=50;i++)
      {
        // moteur 4 puis 2 puis 3 et enfin 1
	      output_set(moteur_step,3);
	      _delay_ms(100);
	      output_unset(moteur_step,3);

	      output_set(moteur_step,1);
	      _delay_ms(100);
	      output_unset(moteur_step,1);

	      output_set(moteur_step,2);
	      _delay_ms(100);
	      output_unset(moteur_step,2);

	      output_set(moteur_step,0);
	      _delay_ms(100);
	      output_unset(moteur_step,0);
      }
      break;
    default:
      return;
  }
}
/*code...*/


Voici la vidéo de fonctionnement :

Moteur pas à pas : montée/descente


Programmation via USB/LUFA

Tout d'abord,nous avons relevé l'id vendeur/produit de l'atmega grâce à la commande lsusb -vvv.

L'id vendeur est 0x03EB et l'id produit est 0x2FEF.

Nous avons ensuite repris nos codes du projet Manette et ajusté en fonction.

Dans le dossier LUFA/PolytechLille/Voiture, où nous avons mis nos fichiers C de la voiture, nous avons ajouté les fichiers Descriptors.c et Descriptors.h.

Dans ces derniers, nous avons enlevé tout ce qui était relatif au joystick pour garder que la partie actionneurs et modifié l'id vendeur que nous avions trouvé précédemment.

Dans le fichier principal, nous avons géré les actionneurs :

/*code...*/
void Gestion_ACT(void)
{
	Endpoint_SelectEndpoint(ACT_EPADDR);

	if (Endpoint_IsOUTReceived())
	{
		if (Endpoint_IsReadWriteAllowed())
		{
		  	uint16_t ACT_Report = Endpoint_Read_16_LE();

			for(int i=0; i<=3; i++)
			{
		  		if(ACT_Report & (1<<i))
           			  output_set(leds,i);
				else 
				      output_unset(leds,i);
			}
        
			//Gestion du moteur DC
			if(ACT_Report & (1<<4))
                reculer();
            else if(ACT_Report & (1<<5))
                avancer();	
			else
                arreter();

			//Gestion du moteur pas à pas
			if(ACT_Report & (1<<6))
            	stepper(1);
            else if(ACT_Report & (1<<7))
            	stepper(-1);	
                        /*utilisation de else car il ne faut pas qu'ils
                        soient actifs en même temps*/
		}
		Endpoint_ClearOUT();
	}
}
/*code...*/

Nous utilisons seulement le premier octet. Chaque bit de l'octet représente un actionneur ou une fonction (avancer, reculer etc..).

On enverra 0x5A :

Envoi de 0x5A : Moteur "reculer", Stepper "monte" et 2 LED allumées

D'après notre fonction de gestion des actionneurs, le moteur continu tournera dans un sens, le moteur glissière aussi et deux LEDs seront allumées.

Après cela vient la partie USB. Nous avons écrit un code permettant d'envoyer 16 bits (on aurait bien sûr pu faire 8 bits, mais nous avons gardé le même code que pour la manette) :

/*code...*/

int main(void) {

  unsigned char data[2] = {0x5a,0x00};//==> moteur "reculer", glissiere "monter", 2 LED avant allumées
//que le 1 er octet qui est utilisé. 
  recherche_et_envoi();

  transfert(data);

  sleep(1);
      
  free_usb();

  return 0;
}

En envoyant 0x5A, nous devons observer le moteur tourner dans un sens, le pas à pas monter et les deux LED avant s'allumer :

Conclusion

Voici la carte soudée ainsi qu'une vidéo avec toutes les fonctionnalités réalisées :

carte soudée



Nous avons d'abord planifié notre projet, avec les différentes fonctionnalités qu'on voulait implémenter. Nous n'avons pas pu tout implémenter, mais nous avons réalisé l'essentiel des fonctions demandées.

Nous aurions aimé tester le module Bluetooth, utilisant la transmission série du microcontrôleur, sur lequel nous avions travaillé au préalable (Schématique/PCB/code).

Plusieurs problèmes ont été rencontrés, comme les erreurs de soudure ou des erreurs de mesure (dimensions de la carte pour le PCB).

Le driver pour le moteur continu a été pour nous, le composant le plus dur à souder.

On pourra aussi noter que certaines de nos projections n'ont pas pu être réalisées comme l'implémentation des LED RGB.

Ce projet nous a permis d'acquérir de l'organisation, des compétences en soudure ainsi qu'en programmation.