web-dev-qa-db-fra.com

Conflit de pins PWM Arduino Uno

J'ai construit ce bouclier moteur basé sur la puce L298N pour contrôler deux moteurs d'un réservoir. Il utilise les broches 5 et 6 pour un moteur et les broches 10 et 11 pour l'autre.

En essayant d’ajouter un TSOP 4838 afin de contrôler le réservoir avec une télécommande infrarouge, j’ai remarqué que le déplacement du moteur sur les broches 10/11 en sens inverse ne fonctionne à pleine vitesse - c’est-à-dire une valeur HIGH (255) sur broche 11. Toute valeur inférieure à cette valeur n’affiche rien sur la broche 11 (la tension mesurée sur ces broches est 0 V).

Pour la télécommande, j'utilise cette bibliothèque . Le récepteur IR est connecté sur la broche 2 (mais la broche importe peu). Le problème est le code de la bibliothèque elle-même. La ligne qui permet l'écoute IR irrecv.enableIRIn(); est la cause du problème. J'ai appris qu'il y avait un conflit entre les minuteries internes d'Arduino et les broches utilisées pour le PWM par le bouclier.

C'est le code pour alimenter le moteur en marche arrière:

#include <IRremote.h>

// IR receiver configuration
const int irPin = 2;
IRrecv irrecv(irPin);

// Motors configuration
const int mLeftPin1  = 10;
const int mLeftPin2  = 11;
const int mRightPin1 = 5;
const int mRightPin2 = 6;

void setup()
{
  // Start IR
  irrecv.enableIRIn();

  // Setup motors
  pinMode(mLeftPin1, OUTPUT);
  pinMode(mLeftPin2, OUTPUT);
  pinMode(mRightPin1, OUTPUT);
  pinMode(mRightPin2, OUTPUT);

  // Move left motor in reverse, slower speed
  analogWrite(mLeftPin2, 100); // This works only with 255 instead of 100
  digitalWrite(mLeftPin1, LOW);
}

Maintenant, j'ai trouvé ici que les broches utilisées par les minuteries sur Arduino Uno sont:

  • Broches 5 et 6: contrôlées par Timer0
  • Broches 9 et 10: contrôlées par Timer1
  • Broches 11 et 3: contrôlées par Timer2

Donc mes questions sont:

  1. Pourquoi le bouclier dans l'instructable utilise-t-il les broches 10 et 11 pour PWM? Ils correspondent à 2 minuteries différentes. Pourquoi pas 9 et 10?

  2. Afin d’utiliser l’IR avec le blindage du moteur, quelle minuterie dois-je configurer la bibliothèque IR?

  3. Si la réponse est 2, une ligne doit être décommentée dans IRremoteInt.h. Je suppose que le Uno prendrait la branche else à la ligne 68, bien que seules les temporisations 1 et 2 soient présentes. Je me demande pourquoi timer0 ne pourrait pas être utilisé pour Uno.

Bien que je souhaite laisser des traces de coupe et de ressouder en dernier recours, une autre possibilité serait de changer les broches utilisées par le bouclier, mais lequel? Et je suppose que cela serait également associé à la configuration des minuteries en PWM sur des broches autres que celles par défaut, mais je ne connais rien aux minuteries/interruptions et ma connaissance de Arduino et C est limitée.

J'ai posé cette longue question parce que je veux apprendre non seulement à résoudre le problème, alors n'hésitez pas à en expliquer plus que ce qui est demandé.

En cherchant une solution, j'ai également trouvé d'autres conflits à garder à l'esprit lorsque vous utilisez PWM ou des minuteries:

  • Timer0 est un minuteur de 8 bits, il peut contenir une valeur maximale de 255. Il est utilisé par delay() et millis(), il y a donc des conséquences à le modifier.
  • Timer1 est un timer de 16 bits, il peut contenir un maximum de 65535 (entier non signé de 16 bits). La bibliothèque Arduino Servo utilise ce minuteur
  • Timer2 est un minuteur de 8 bits utilisé par la fonction Arduino tone()

Et, bien sûr, la bibliothèque IRremote utilise TIMER_RESET, donc, en fonction du minuteur utilisé, elle peut entrer en conflit avec les broches associées.

13
talereader
  1. Tout le matériel n'est pas conçu de la meilleure façon. Utiliser 10 et 11 est en effet une perte de temps car il nécessite deux minuteries.

2/3. Idéalement, vous utiliserez une minuterie autre que Timer0. Voici quelques détails supplémentaires sur les minuteries/interruptions:

La puce Arduino (328P) a trois minuteries. Chaque minuterie peut être utilisée à plusieurs fins. Toutefois, il est important de noter que vous ne pouvez activer qu'une seule interruption de minuterie pour chaque minuterie.

Prenez Timer0 par exemple. Il interrompt afin de générer les délais appropriés pour les méthodes delay () et delay_us (). Il est également utilisé pour les sorties PWM sur les broches 5 et 6. Cela peut arriver car les sorties PWM n'utilisent pas d'interruption de minuterie, elles utilisent des modules de comparaison de sortie séparés.

Maintenant, si vous regardez spécifiquement votre problème, il devrait fonctionne correctement, même si vous avez une sortie PWM utilisant timer2, le PWM ne prend pas d’interruption sur timer2, la bibliothèque IR doit donc être libre de l’utiliser. Cependant, en regardant dans le code de la bibliothèque IR, nous voyons ce morceau de code:

ISR(TIMER_INTR_NAME)
{
   TIMER_RESET; 

Il semble que chaque fois qu'il interrompt, il réinitialise le compte à rebours. Cela pourrait expliquer pourquoi votre sortie PWM ne fonctionne pas correctement. Le module de comparaison de sortie attend un certain nombre de ticks, et il n’atteint jamais ce chiffre. 

Pour savoir pourquoi cela fonctionne en quelque sorte à 255, nous pouvons jeter un coup d'œil au code analogWrite:

void analogWrite(uint8_t pin, int val)
{
    // We need to make sure the PWM output is enabled for those pins
    // that support it, as we turn it off when digitally reading or
    // writing with them.  Also, make sure the pin is in output mode
    // for consistenty with Wiring, which doesn't require a pinMode
    // call for the analog output pins.
    pinMode(pin, OUTPUT);
    if (val == 0)
    {
        digitalWrite(pin, LOW);
    }
    else if (val == 255)
    {
        digitalWrite(pin, HIGH);
    }

Donc, en écrivant 255, le code analogWrite ignore la totalité de la comparaison entre PWM et sortie, et écrit simplement la broche haute.

Enfin, pour résoudre votre problème, je voudrais personnellement choisir de ne pas utiliser les broches 11 et 3 (timer2). Oui, il faudra un nouveau câblage, mais vous pourrez ainsi libérer timer2 pour que la bibliothèque IR puisse l'utiliser.

Sinon, vous pouvez explorer la bibliothèque IR et essayer de la faire fonctionner sans réinitialiser le nombre.

14
user2461391

Faites attention au tableau utilisé, si vous utilisez Arduino Uno, le code responsable serait: // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc. Sinon // définir IR_USE_TIMER1// tx = broche 9 définir IR_USE_TIMER2 // tx = broche 3 endif

1
sky10

J'ai eu le même problème avec un pré-construit L298 V2 bouclier moteur.

Les épingles étaient marquées comme ceci sur le bouclier:

Moteur 1: broches 3 et 5 Moteur 2: broches 6 et 9

J'utilise PIN10 au lieu de 3 et j'utilise une petite solution de contournement: j'ai placé un câble de PIN10 à PIN3 sur le SHIELD. Mon projet était de contrôler mon robot avec une télécommande SAMSUNG TV.

0
sky10