Actuellement, mon croquis vérifie une broche d'entrée à chaque fois dans la boucle principale. S'il détecte un changement, il appelle une fonction personnalisée pour y répondre. Voici le code (réduit à l'essentiel):
int pinValue = LOW;
void pinChanged()
{
//...
}
void setup()
{
pinMode(2, INPUT);
}
void loop()
{
// Read current input
int newValue = digitalRead(2);
// Has the input changed?
if (newValue != pinValue) {
pinValue = newValue;
pinChanged();
}
}
Malheureusement, cela ne fonctionne pas toujours correctement pour des changements très courts sur l'entrée (par exemple de brèves impulsions), surtout si elle loop()
fonctionne un peu lentement.
Existe-t-il un moyen de faire en sorte que l'Arduino détecte le changement d'entrée et appelle automatiquement ma fonction?
Réponses:
Vous pouvez le faire en utilisant des interruptions externes. La plupart des Arduinos ne prennent en charge cela que sur un nombre limité de broches. Pour plus de détails, consultez la documentation sur
attachInterrupt()
.En supposant que vous utilisez un Uno, vous pouvez le faire comme ceci:
Cela appellera
pinChanged()
chaque fois qu'un changement est détecté sur l'interruption externe 0. Sur l'Uno, cela correspond à la broche GPIO 2. La numérotation des interruptions externes est différente sur les autres cartes, il est donc important de vérifier la documentation pertinente.Il y a cependant des limites à cette approche. La
pinChanged()
fonction personnalisée est utilisée comme routine de service d'interruption (ISR). Cela signifie que le reste du code (tout ce qu'il contientloop()
) est temporairement arrêté pendant l'exécution de l'appel. Afin d'éviter de perturber un timing important, vous devriez viser à rendre les ISR aussi rapides que possible.Il est également important de noter qu'aucune autre interruption ne s'exécutera pendant votre ISR. Cela signifie que tout ce qui s'appuie sur des interruptions (comme le noyau
delay()
et lesmillis()
fonctions) peut ne pas fonctionner correctement à l'intérieur.Enfin, si votre ISR doit modifier des variables globales dans l'esquisse, elles doivent généralement être déclarées comme
volatile
, par exemple:C'est important car il indique au compilateur que la valeur peut changer de manière inattendue, il convient donc de ne pas en utiliser de copie / cache obsolète.
la source
pinChanged()
devrait être aussi court que possible. Par conséquent, le temps minimum devrait généralement être le temps pour exécuter lapinChanged()
fonction elle-même.volatile
, si la variable globale est plus large que 1 octet, comme l'est certains numéros, vous devez vous protéger contre l'interruption de changement de broche qui se produit entre les accès en octets par le programme. Une déclaration commesomeNumber +=5;
implique l'ajout des octets bas et l'ajout des octets hauts avec report inclus. Ces deux (plus, pour les variables plus larges) ne doivent pas être divisés par une interruption. La désactivation des interruptions et leur restauration (respectivement) avant et après l'opération est suffisante.Tout état de changement sur n'importe quelle broche configurée comme entrée numérique peut créer une interruption. Contrairement aux vecteurs uniques pour les causes d'interruptions par INT1 ou INT2, la fonction PinChangeInt utilise un vecteur commun, puis la routine de service d'interruption (aka ISR) pour ce vecteur doit ensuite déterminer quelle broche a changé.
Heureusement, la bibliothèque PinChangeInt facilite cela.
la source
Dans le cas où vous souhaitez détecter une tension dépassant un seuil , plutôt que d'être simplement HAUT ou BAS, vous pouvez utiliser le comparateur analogique. Exemple d'esquisse:
Cela peut être utile pour des choses comme les détecteurs de lumière, où vous devrez peut-être détecter un changement (disons) de 1 V à 2 V sur une entrée.
Exemple de circuit:
Vous pouvez également utiliser l'unité de capture d'entrée sur le processeur, qui se souviendra de l'heure exacte de certaines entrées, en enregistrant le nombre actuel de Timer / Counter 1. Cela vous permet de stocker le moment exact (enfin, presque exact) que l'événement de l'intérêt s'est produit, plutôt que d'introduire le délai (probablement de quelques microsecondes) avant qu'un ISR puisse être utilisé pour capturer l'heure actuelle.
Pour les applications à synchronisation critique, cela peut donner une précision quelque peu accrue.
Exemple d'application: Transformez votre Arduino en testeur de condensateur
la source