|
|
|
/********************************************************************************************************************
|
|
TER M1 A-R
|
|
Asservissement de vitesse d'un moteur à courant continu
|
|
Ce programme est destiné à fonctionner avec la maquette "MS15 DC MOTOR MODULE" partie (Digital Control/PWM Input)
|
|
|
|
Encadrée par:
|
|
M. Benoit THUILOT
|
|
M. Fabrice DUMAS
|
|
M. Sébastien LENGAGNE
|
|
|
|
Réalisée par : Sarah AOUICHE
|
|
|
|
Mis à jour le 20/06/2022
|
|
*********************************************************************************************************************/
|
|
|
|
|
|
// Dtatsheet ATmega328P => https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
|
|
// Programme pour générer une PWM de période 22ms avec un état haut varialble (de 1ms à 2ms) selon le mode de marche moteur
|
|
// Acquisition et échantillonnage du signal de sortie de la génératrice (Tacho generator output)
|
|
// Asservissement du moteur à courant continu (en cours!)
|
|
|
|
|
|
|
|
//====================================================================================================================//
|
|
// pour avoir 2ms à l'état haut => OCR1B=OCR1A= 4000 en décimal; (bin: 0000 1111 1010 0000 ) : mode marche avant;
|
|
// pour avoir 1.5ms à l'état haut => OCR1B=OCR1A= 3000en décimal; (bin: 0000 1011 1011 1000 ) : mode arrêt;
|
|
// pour avoir 1ms à l'état haut => OCR1B=OCR1A= 2000 en décimal; (bin: 0000 0111 1101 0000 ) : mode marche arrière;
|
|
// Pour avoir une période du signal PWM d 22ms => ICR1= 44000 en décimal; (bin:1010 1011 1110 0000) : Periode_PWM
|
|
//====================================================================================================================//
|
|
|
|
//Constantes:
|
|
|
|
// valeur de temps à l'état haut de la PWM:
|
|
|
|
#define Mode_Marche_Avant 4000 // pour avoir 2ms à l'état haut => OCR1A= 4000 en décimal;
|
|
|
|
#define Mode_Marche_Arriere 2000 // pour avoir 1ms à l'état haut => OCR1A= 2000 en décimal;
|
|
|
|
#define Mode_Arret 3000 //pour avoir 1.5ms à l'état haut => OCR1A= 3000 en décimal;
|
|
|
|
// Période du signal PWM:
|
|
|
|
#define Periode_PWM 44000 // pour avoir une période du signal PWM de 22 ms => ICR1= 44000 en décimal;
|
|
|
|
//Variables:
|
|
//==========
|
|
const int Pin_PWM = 9; //Initialisation de la pin 9 du signal PWM
|
|
const int Echantillonneur_Pin = 3 ; //Initialisation de la pin 3 de l'échantillonneur de signal de la génératrice => Vout.
|
|
|
|
int compteur; //déclarer le compteur d'interruption de Timer/counter 2
|
|
int timer2_compteur_VI; //déclarer la valeur initiale de compteur TCNT2 de Timer/counter 2
|
|
int Resultat_CAN = 0; //Initialiser le Résulatat de conversion A/N
|
|
byte bit_PORTD3 ; //Déclarer la variable liée à la pin 3 pour lire son état
|
|
|
|
|
|
void setup(){
|
|
|
|
// put your setup code here, to run once:
|
|
|
|
pinMode(Pin_PWM,OUTPUT); // Pin du signal PWM
|
|
pinMode(Echantillonneur_Pin,OUTPUT); // Pin pour visualiser l'échantillionneur du signal de la génératrice
|
|
Serial.begin(9600);
|
|
|
|
|
|
//========================================
|
|
//Configuration_PWM => Timer 1 (Sortie D9)
|
|
//========================================
|
|
|
|
//Paramétrage du Timer 1 en mode de fonctionnement "FAST PWM 14" c'est à dire TOP=ICR1 => Pour plus de détails voir les pages 89:113 de la Datasheet => https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
|
|
|
|
TCCR1A=0b10000010; // bits1:0 Mode "FAST PWM 14" c'est à dire TOP=ICR1 (Note: les bits qui gèrent le mode de fonctionnement du Timer1 sont réparti sur deux registres "TCCR1A et TCCR1B")
|
|
// bits7:6 PWM en mode "non inversé"
|
|
//sortie D9 mise à 0 lorsque la valeur de timer 1 atteint la valeur de OCR1A;
|
|
//sortie D9 mise à 1 à chaque remise à zéro du timer 1 c'est à dire TOP=ICR1;
|
|
|
|
TCCR1B=0b00011000; // bits 4:3 Mode "FAST PWM 14" c'est à dire TOP=ICR1
|
|
// bits 2:0 No clock source (Timer1/Counter1 arrêté).
|
|
|
|
|
|
//==========================================
|
|
// Génération du signal PWM sur la pin D9//
|
|
//==========================================
|
|
|
|
// La pin D9 est sur le port OC1A (PB1)=> Pour plus de détails voir le schéma de la carte Arduino UNO => https://www.arduino.cc/en/uploads/Main/arduino-uno-schematic.pdf
|
|
|
|
|
|
|
|
ICR1=Periode_PWM; //ICR1 va compter de 0 jusqu'à atteindre la valeur "44000"(bin:10101011 11100000) pour avoir la période 22ms
|
|
//Note: à ne pas changer!
|
|
|
|
TCNT1=0; // Mise à 0 du compteur TCNT1 (Timer1)
|
|
OCR1A= Mode_Marche_Avant; //Valeur de temps à l'état haut du signal PWM à générer sur la sortie OC1A;
|
|
//Note: cette valeur on peut la changer selon le mode de marche du moteur indiqué en haut!
|
|
|
|
|
|
|
|
//===========================================================
|
|
//Acquisition du signal capteur( Sortie de la génératrice)//
|
|
//===========================================================
|
|
|
|
/*
|
|
Ici pour récupérer le signal du capteur qui est analogique on doit agir sur les registres de l'ADC du
|
|
mirocontroleur pour avoir la précision et l'échontillonnage voulus. La fonction analogRead est beaucoup trop
|
|
lente pour effectuer des numérisations échantillonnées à plusieurs Hz; On utilisera donc l'API Atmel, et l'accès
|
|
direct aux registres pour certaines opérations.
|
|
*/
|
|
|
|
//=======================================
|
|
//Configuration de L'ADC de l'ATmega328P:
|
|
//=======================================
|
|
//Pour plus de détails voir les pages 205:220 de la Datasheet => https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
|
|
|
|
ADMUX = 0b01000001; // bits7:6 configuration de tension d'alimentation en reference
|
|
// bit 5 pour ajuster les bits à droit (rignt ajust)
|
|
// bits3:0 sélactionner la Pin A1
|
|
|
|
ADCSRA=0b00000111; // bit 5 no Auto Trigger Enable
|
|
// bits2:0 prescaler 128
|
|
|
|
|
|
|
|
//======================
|
|
//Confiiguration timer2
|
|
//======================
|
|
//Pour plus de détails voir les pages 116:134 de la Datasheet => https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
|
|
|
|
TCCR2A=0b00000000; // bits 1:0 Mode de fonctionnement normal (simple compteur) => (Note: les bits qui gèrent le mode de fonctionnement du Timer2 sont réparti sur deux registres "TCCR2A et TCCR2B")
|
|
// bits 7:6 mode déconnecté
|
|
|
|
TCCR2B= 0; //bits 2:0 No clock source (Timer2/Counter2 arrêté)
|
|
|
|
|
|
timer2_compteur_VI=100; // Initialiser la valeur de compteur TCNT2 à 100 pour avoir 10 ms (1000ms/16Mhz= 625.10^-7 ms/top_horloge => 625.10^-7*1024= 0.064ms/prescaler => 10ms/0.064=156 => 255-155 =100 )
|
|
|
|
|
|
// end of setup
|
|
}
|
|
|
|
|
|
//Routine d'interruption timer 1
|
|
|
|
ISR(TIMER1_OVF_vect){
|
|
|
|
//Lancer le timer 2
|
|
|
|
TCNT2= timer2_compteur_VI; // Précharger le compteur de Timer 2 avec la valeur initiale "timer2_compteur"
|
|
TCCR2B= 0b00000111; // bits2:0 prescaler 1024
|
|
compteur=0; // initialiser le compteur d'interruption de timer 2
|
|
|
|
|
|
}
|
|
|
|
//Routine d'interruption timer 2
|
|
|
|
ISR (TIMER2_OVF_vect){
|
|
|
|
|
|
compteur++;
|
|
|
|
if(compteur==1){
|
|
|
|
compteur=0;
|
|
|
|
TCNT2=timer2_compteur_VI;
|
|
|
|
|
|
bit_PORTD3 = bitRead (PORTD, PORTD3);
|
|
|
|
if (bit_PORTD3 == 0){
|
|
|
|
bitSet (PORTD, PORTD3);
|
|
}
|
|
else {
|
|
bitClear (PORTD,PORTD3);
|
|
}
|
|
|
|
}
|
|
|
|
bitSet(ADCSRA, ADEN); // Activer l'ADC
|
|
bitSet(ADCSRA,ADSC); // Lancer la conversion A/N
|
|
|
|
while (bitRead (ADCSRA,ADIF)==0){
|
|
}
|
|
|
|
Resultat_CAN= ADC; // récupérer le résultat de la conversion A/N
|
|
bitSet(ADCSRA,ADIF); // Pour mettre le bit ADIF de drapeau à 0; il faut lui envoyer un 1 (c'est le constructeur qu'il l'impose!)
|
|
|
|
|
|
Serial.print(Resultat_CAN); // Envoyer le résultat de conversioon A/N au le moniteur série (la tension de sortie de la génératrice Vout)
|
|
Serial.print("\n");
|
|
|
|
// modifier OCR1A :
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//=======================
|
|
//Boucle Principale//
|
|
//=======================
|
|
|
|
void loop() {
|
|
|
|
//Boucle infinie
|
|
//Si on utilise les interruptions,on quitte cette boucle
|
|
//pour aller exécuter le code en haut avant de revenir ici
|
|
|
|
// put your main code here, to run repeatedly:
|
|
|
|
//lancer la PWM
|
|
|
|
TCCR1B= 0b00011010; //bits2:0 prescaler 8
|
|
|
|
|
|
bitSet(TIMSK1,TOIE1); // déclencher l'interruption à chaque overflow de le Timer1/Counter1
|
|
bitSet(TIMSK2,TOIE2); // déclencher l'interruption à chaque overflow pour le Timer2/Counter2
|
|
sei(); // Activer les interruptions
|
|
|
|
while(1){
|
|
}
|
|
}
|