Projet

Général

Profil

Publication de fichiers » Commande_PWM_acquisition_interruption_timer1_timer2_20_06_2022.ino

Code arduino - Anonyme, 21/06/2022 06:25

 
/********************************************************************************************************************
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){
}
}
(15-15/15)