Pololu-Zumo-Shield-Arduino-servo-arduino

De MCHobby - Wiki
Aller à : navigation, rechercher

Le code d'exemple Arduino Uno ci-dessous montre comment contrôler un simple servo en utilisant le Timer 2. Nous utilisons le Timer 2 à la place du Timer 1 parce que le Timer 1 est utilisé par la bibliothèque ZumoMotors (ce qui interfère avec la bibliothèque servo d'Arduino). Il nous faut donc gérer notre servo moteur nous même avec un autre timer (le Timer 2).

Utiliser le Timer 2 interfère avec la bibliothèque ZumoBuzzer, il ne sera donc pas possible d'utiliser le Buzzer et le Timer 2 en même temps. Vous pouvez intégrer ce code avec d'autre codes pilotant des moteurs.

/** Exemple Servo Timer 2 sur Arduino Uno
Ce code d'exemple est pour un Arduino Uno et montre comment utiliser le 
Timer 2 d'un ATmega328P pour controler un simple servo moteur. 
Cela est tule pour les gens qui ne peuvent pas utiliser la
bibliotheque Servo d'Arduino IDE.
Par exemple, la bibliotheque ZumoMotors utilise le même timer que
la bibliotheque Servo (Timer 1). Il y a donc un conflit.
 
La macro SERVO_PIN ci-dessous spécifie la broche sur laquelle
est branché le servo moteur. Cette broche doit être raccordée 
sur l'entrée signal du servo. La masse du servo doit être connecté
sur la masse de votre Arduino (masse commune). Pour finir
la masse et broche d'alimentation du servo doivent être connecté
sur une source d'alimentation adéquate.
*/
 
// Cette ligne indique quel est la broche utilisée pour envoyer
// le signal au servo moteur. Vous pouvez changer cette valeur.
#define SERVO_PIN 11
 
// Le temps depuis le dernier flan montage (rising edge) en unités de 0.5us.
uint16_t volatile servoTime = 0;
 
// Contient la largeur d impulsion désirée en unités de 0.5us.
uint16_t volatile servoHighTime = 3000;
 
// Vrai (true) si la broche servo est actuellement au niveau haut.
boolean volatile servoHigh = false;
 
void setup()
{
  servoInit();
}
 
void loop()
{
  servoSetPosition(1000);  // Envoi une impulsion de 1000 us.
  delay(1000);  
  servoSetPosition(2000);  // Envoi une impulsion de 2000 us.
  delay(1000);
}
 
// Cette routine d'interruption (ISR) est appelée après que 
// le Timer 2 ait atteind OCR2A et resets.
// Dans cet ISR, nous initialisons OCR2A pour déterminer 
// quand la prochaine interruption est déclenchée.
// Généralement, nous fixons OCR2A à 255 pour avoir une 
// interruption toutes les 128 us, mais les deux premiers
// intervales d'interruption après le flan montant (rising edge)
// seront plus petit ce qui nous empêche d'atteindre la
// largeur d'impulsion désirée.
ISR(TIMER2_COMPA_vect)
{
  // Le temps qui est passé depuis la dernière interruption est
  // égale à OCR2A + 1 parce que la valeur du timer sera égale
  // à OCR2A avant de revenir à 0.
  servoTime += OCR2A + 1;
   
  static uint16_t highTimeCopy = 3000;
  static uint8_t interruptCount = 0;
   
  if(servoHigh)
  {
    if(++interruptCount == 2)
    {
      OCR2A = 255;
    }
 
    // La broche du signal Servo est au niveau haut (high).
    // Vérifier s'il est temps d'avoir le flan descendant
    // du signal (falling edge).
    // Note: Nous pouvons utiliser == à la place de >=.
    if(servoTime >= highTimeCopy)
    {
      // La broche est au niveau haut depuis assez longtemps
      // donc on applique la flan descendant.
      digitalWrite(SERVO_PIN, LOW);
      servoHigh = false;
      interruptCount = 0;
    }
  } 
  else
  {
    // La broche du servo est au niveau bas (low).
     
    if(servoTime >= 40000)
    {
      // Nous avons atteind la fin de la période (20 ms),
      // Donc on applique un flan montant (rising edge) sur
      // le signal.
      highTimeCopy = servoHighTime;
      digitalWrite(SERVO_PIN, HIGH);
      servoHigh = true;
      servoTime = 0;
      interruptCount = 0;
      OCR2A = ((highTimeCopy % 256) + 256)/2 - 1;
    }
  }
}
 
void servoInit()
{
  digitalWrite(SERVO_PIN, LOW);
  pinMode(SERVO_PIN, OUTPUT);
   
  // Passe en mode CTC. Le Timer 2 comptera jusqu'à OCR2A, 
  // puis se réinitialise à 0 et provoque une interruption.
  TCCR2A = (1 << WGM21);
  // Initialiser le pre-scaler sur 1:8 . ce qui offre une 
  // résolution de 0.5us.
  TCCR2B = (1 << CS21);
   
  // Mettre le timer dans le bon état par défaut.
  TCNT2 = 0;
  OCR2A = 255;
   
  TIMSK2 |= (1 << OCIE2A);  // Activer le "timer compare interrupt".
  sei();   // Activer les interruptions.
}
 
void servoSetPosition(uint16_t highTimeMicroseconds)
{
  TIMSK2 &= ~(1 << OCIE2A); // Désactiver le "timer compare interrupt"
  servoHighTime = highTimeMicroseconds * 2;
  TIMSK2 |= (1 << OCIE2A); // Activer le "timer compare interrupt"
}

Basé sur "Zumo Shield for Arduino" de Pololu (www.pololu.com/docs/0J57) - Traduit en Français par shop.mchobby.be CC-BY-SA pour la traduction
Toute copie doit contenir ce crédit, lien vers cette page et la section "crédit de traduction". Traduit avec l'autorisation expresse de Pololu (www.pololu.com)

Based on "Zumo Shield for Arduino" from Pololu (www.pololu.com/docs/0J57) - Translated to French by shop.mchobby.be CC-BY-SA for the translation
Copies must includes this credit, link to this page and the section "crédit de traduction" (translation credit). Translated with the Pololu's authorization (www.pololu.com)