Utiliser la carte NANO en Automobile


ARDUINO NANO

Avant-propos

Depuis longtemps je me suis essayé à faire quelques petits montages électroniques pour mes véhicules, mais toujours en électronique classique (sans recourir à des microcontrôleurs).

Ces dernières années, grâce à un forumeur qui proposait un circuit S&S réalisé à partir d'une carte Arduino, j'ai franchis le pas et j'ai réalisé plusieurs circuits décrits dans mon blog automobile à partir de cartes Arduino Nano :

https://bernyblogvitara.blogspot.com/

  • Gestion de la caméra de recul.

  • Visualisation de l'activité des systèmes automatiques de passage en 4x4 (AllGrip Suzuki)

  • Automatisation des rétroviseurs (maquetté, mais pas monté sur véhicule).

  • Visualisation du cycle de régénération d'un Filtre A Particules

  • ... et peut-être quelques autres projets à venir.

Etant amateur débutant, ne comptez pas trouver ici un tuto éclairé et exhaustif sur le sujet.
Cet article qui recense ma petite expérience est surtout fait pour démystifier le domaine, et vous donner l'envie d'utiliser ces cartes pour vos projets.

Leur mise en œuvre est bien plus simple que ce à quoi on pourrait s'attendre de prime abord.

Introduction - choix de la carte

Les avantages à utiliser une carte Arduino pour faire de petits montages dans le domaine automobile sont évidents :
Réaliser des fonctions assez sophistiquées, modifiables et évolutives, avec un hard (schéma électrique) relativement simple.

Parmi les cartes proposées par Arduino, la carte NANO est à mon avis la carte la mieux adaptée pour réaliser des montages simples dans un encombrement réduit.

  • Sa puissance est amplement suffisante pour ces petites applications (horloge à 16 MHz, 32 kB de mémoire Flash , 2kB de RAM ...).

  • Elle possède suffisamment d'entrées et de sorties (14 E/S digitales et 8 entrées analogiques).

  • Elle est dépourvue d'interfaces de communication (bus, BT, WiFi), mais elle possède une entrée USB pour sa programmation.

  • Enfin, on trouve sur internet des clones très peu chers, pratiquement identiques à la carte originale ...

MATERIEL

Il est bien sûr nécessaire de concevoir un minimum de hard pour faire fonctionner une carte Arduino dans une automobile, mais cela se borne à de l'interfaçage.

La carte Nano est en technologie 5V (alimentation, Entrées et Sorties), mais elle intègre un régulateur analogique qui permet de l'alimenter par une tension continue comprise entre 7 et 12V.

Une connaissance rudimentaire des lois d'Ohm est suffisante pour concevoir ces interfaces ...

Caractéristiques électriques des cartes Nano :

I - Alimentation

La carte Nano comporte un régulateur de tension pour générer son alimentation 5 V interne à partir d'une source de tension comprise entre 7 V et 12 V.

Le "petit problème" est que sur une voiture la tension peut varier de 11,5 V à presque 15 V. avec des parasites et des transitoires.

Une alimentation directe sur le 12 V automobile n'est, ni viable ni fiable, même si dans certains cas la carte peut le supporter.

Le 2ème paramètre déterminant à prendre en compte pour concevoir l'alimentation est le courant consommé par la carte.

A vide (carte seule) sa consommation est d'environ 20 mA, mais elle peut consommer beaucoup plus suivant les charges sur ses sorties qui peuvent atteindre 40 mA max par sortie, dans la limite d'un total de 200 mA à ne pas dépasser pour la totalité de la carte.

D'autre part il est possible de ne pas utiliser le régulateur interne est d'alimenter directement la carte en 5V, mais ce doit être un 5V propre et précis.

On se doute donc que, suivant la consommation et l'architecture du montage complet, et l'option retenue (avec ou sans le régulateur interne), il y a une infinité de montages possibles.

On trouvera ci-après quelques propositions de pistes ...

1 - 1 ) Utilisation du régulateur de tension de la carte

C'est une bonne solution si on intercale entre le 12V du véhicule et l'alim Vin de la carte un premier système de régulation, car on a alors 2 régulations en cascade, ce qui est favorable pour obtenir un 5V parfaitement filtré et régulé.

On peut dans certains cas créer une chute de tension à partir du 12V de la voiture, à l'aide d'une simple résistance série que l'on devra convenablement dimensionner :

  • D'une part en valeur, pour rester dans la fourchette 7 - 12 V, dans toutes la plage de la tension d'entrée (par exemple 11 à 15V), et dans toute la plage des courants débités.

  • D'autre part en puissance, en appliquant l'incontournable formule P = R . I^2.

Mais la plus part du temps, à cause d'un courant trop élevé, un tel compromis n'est pas possible, et il faudra envisager réaliser un circuit un peu plus complexe, par exemple :

  • Stabilisation par une diode Zéner D4 (de par exemple 9V) montée en écrêteur classique, qui pourra être épaulée par un transistor ballast si le courant à fournir est important.

Pour le calcul de R7 il faudra tenir compte du courant qui la traverse :

. Au courant maximal la chute de tension dans cette résistance ne devra pas excéder (Ve min - VD4).

. Et, à Ve max, et I min dans la carte Arduino, il faudra vérifier que le courant dérivé dans D4 ne provoque pas un dépassement de la puissance dissipable admissible dans cette diode Zéner (formule P=V.I).

  • Montage avec diode Zéner (D2) en série, pour réaliser une chute de tension constante d'environ 3 à 4V si on se raccorde à un 12 V véhicule.

Au courant maximal il faudra vérifier que la puissance (P=V.I) dissipée dans la diode Zéner soit soit inférieure à sa puissance maximale admissible.

La diode D1 des 2 montages précédents évite la décharge du condensateur de filtrage, par exemple lors des brusques chutes de tension causées par de brèves impulsions parasites négatives, qui peuvent être présentes sur les réseaux d'alimentation des véhicules

  • Enfin, la solution "royale", et aussi la plus simple à mettre en œuvre (moins de calculs à effectuer !), est d'intercaler un simple régulateur analogique, ou éventuellement un convertisseur d'alimentation continu/continu, qui a un meilleur rendement et tolère en général une plus grande variation de la tension d'entrée.

Idéalement, la tension de sortie de ce régulateur sera choisie entre 8 et 10V.

A mon avis, un régulateur de type L7809 (flanqué de ses 2 condensateurs de filtrage), peu cher, qui délivre une tension de sortie de 9V, et qui supporte 35V en entrée, est une des meilleures solutions !

1 - 2 ) Alimentation en 5V

Si on alimente la carte Nano directement en 5 V, le plus pratique est d'implanter un petit module convertisseur 12 V --> 5 V que l'on pourra par exemple raccorder au connecteur USB de la carte Arduino.

Quelle que soit la solution retenue il faudra se placer dans "les cas les plus défavorables", de tension d'entrée et de courant consommé, et vérifier que dans ces cas, les limites de la carte ne sont pas dépassées, et que les composants ajoutés sont correctement dimensionnés en valeurs et en puissances.

Si on n'utilise pas un module d'alim acheté tout fait, il faudra prévoir des circuits de filtrage (habituellement par simple ajout de condensateurs).

II - Interfaces d'entrée

On distingue les entrées logiques et les entrées analogiques, mais dans tous les cas on doit rester dans la plage 0V - 5V sur toutes les entrées des cartes Arduino.

2 - 1 ) Entrées Logiques

Pour les entrées numériques il faut respecter les tensions des niveaux logiques pour ne pas rester dans la zone logique indéterminée (voir tableau).

L'interfaçage avec des signaux 12 V pourra être réalisé avec des ponts de résistances, mais avec des protections (écrêtages par diodes Zéner, ou diodes de dérivation au 5V, etc.), pour rester impérativement dans la fourchette 0-5V malgré les fluctuations de la tension d'entrée et les parasites.

(pour info R1 = R3 = 6,8 kOhm, et R2 = R4 = 3,3 kOhm dans cet exemple "Visualisation de l'activité du système AllGrip")

Une solution courante, et bien plus sure pour la carte, consiste à utiliser des transistors de commutation avec collecteurs référencés au 5V.

Par exemple ici des transistors NPN montés en émetteur commun, dont les collecteurs sont connectés au 5V via des résistances de quelques kOhm.

Le signal 12V sera appliqué sur la base du transistor par une polarisation adaptée (pont de résistances ou autre ...).

Avec un tel interface il faudra tenir compte dans le logiciel que le signal logique est inversé.

2 - 2 ) Entrées Analogiques

Dans ce cas il faudra faire une conversion linéaire du signal pour convertir la plage de variation du signal d'entrée, à la plage 0 - 5V de la carte.

Si on n'est pas sûr de la plage de variation de la tension d'entrée (surtensions, parasites ...), il faudra prévoir des protections, par exemple un écrêtage par diodes Zéners de valeurs proches de 5V (exemple ci-contre), ou éventuellement des diodes Schottky (à faible seuil), anodes connectées aux entrées, et cathodes connectées à l'alim 5V.

Au contraire si le signal analogique à mesurer est faible, il faudra l'amplifier pour ne pas perdre en précision lors de la conversion Analogique/Numérique.

III - Interfaces de sortie

Les sorties Arduino sont toutes de type numérique (niveaux 0V - 5V).

Les charges sur les sorties peuvent être des LEDs, des relais (5V), des commandes de transistors bipolaires, FET, MOS, ou C-MOS IGBT, etc., ...

Dans tous les cas le courant, entrant ou sortant, ne devra pas dépasser 40 mA, pour un total inférieur à 200 mA pour la carte.

![|200x185](https://1.bp.blogspot.com/-j1n9j482p98/YIGecXm3TwI/AAAAAAAAD_0/xVT1K94Wpr8hMLFSwiRlkGs3BPaEoW6xQCNcBGAsYHQ/w200-h185/Diodes%2Bde%2Broue%2Blibre.jpg "Diodes de "Roue libre"")

Pour commander une charge selfique (relais, électroaimant, bobine, ...), ne pas oublier de connecter une diode de "roue libre", en inverse, et au plus près de cette charge.

Cette diode laissera passer le courant de rupture à l'ouverture du circuit, et on évitera ainsi les surtensions sur les sorties de la carte.

(Diodes D3 et D4 de l'exemple ci-contre)

On remarquera que les cartes Arduino comportent des Entrées Analogiques bien définies, ... mais pas de Sorties Analogiques !

En fait 6 Sorties Logiques programmables en "PWM" permettent de créer des sorties analogiques :
Se reporter au paragraphe 4 - 5, à la fin de cet article.

LOGICIEL

I - Préliminaire

Quand (comme moi) on n'a pas une formation d'informaticien il y a quelques précautions méthodologiques à prendre avant de se lancer dans l'aventure du codage !

On trouve de très bons tutos sur internet, mais j'ai été déçu en feuilletant dans les librairies des ouvrages du genre "... pour les nuls", qui sont souvent très fouillis, reposent sur des exemples, et où on a du mal à synthétiser une base de connaissances solide et claire.

Par contre j'ai été conquis par le livre de Christian Tavernier (professeur des universités) au titre : "Arduino Maîtrisez sa programmation et ses cartes d'interface (shields)", édition DUNOD, ... que j'ai fini par acheter !

Ce livre explique très clairement les bases de la programmation C++ Arduino : les différents types de variables, les types d'Entrées et de Sorties, la description et la syntaxe des instructions et des structures de contrôle.

II - Méthodologie

En tant que novice on est souvent tenté de bruler les étapes, et de vouloir commencer à coder alors que l'on a qu'une vague idée de ce que l'on veut obtenir.

Mieux vaut donc essayer de respecter une certaine méthodologie pour ne pas pondre un programme brouillon, mal structuré, et rempli de bugs.

1) Définition du "Besoin"

Dans l'industrie le "besoin" est exprimé par un "Donneur d'ordre" par un document nommé "Cahier des charges", qui est le plus souvent rédigé en langage courant.

A partir de ce document, le bureau d'étude de l'exécutant (sous-traitant ...) rédige une "Spécification Technique" qui décrit le même besoin, mais en précisant et quantifiant ses moindres détails, et qui donne en général des indications sur les solutions techniques retenues.

Après négociations la Spécification Technique doit être validée par le donneur d'ordre, pour être intégré au contrat commercial.

... Tout cela pour dire que, sans s'appliquer à soi même une telle rigueur contractuelle, il vaut mieux savoir ce que l'on veut faire avant de commencer à coder !

Dans notre cas :

  • Le "Cahier des charges" pourra juste comporter quelques phrases qui expliquent les fonctions attendues du futur appareil.

  • La "Spécification technique", pourra être un, ou plusieurs, "Logigrammes" qui traduiront avec précision le comportement du système (voir ci-contre).

Ces logigrammes serviront à structurer le futur logiciel, sachant qu'un logiciel simple et bien structuré n'est pas facile à réaliser quand on n'a pas l'habitude !

Un logigramme ne doit pas être embrouillé, mais plutôt "imbriqué", c'est à dire que ses structures de contrôles (boucles) doivent s'emboiter comme des poupées Russes sans, si possible, aucunes sorties intempestives de ces boucles (éviter les "GOTO" ...).

En appliquant ces règles le logiciel sera plus lisible et plus maintenable, et on aura moins de probabilités de générer des bugs.

En pratique on ne cherchera pas forcément à tout faire apparaitre dans un seul Logigramme, on pourra créer des logigrammes partiels sur les parties plus complexes.

En utilisant un logiciel de simulation de Logigrammes tel que LARP, on pourra bien sûr vérifier son bon fonctionnement, mais en plus générer automatiquement un pseudo-code, qui sera très utile pour le codage.

2) Choix et caractérisation des Variables

Avant le codage il y a lieu de bien dénombrer et caractériser les Variables dont on aura besoin :

  • Il faudra prévoir des Variables (voire des tableaux) pour les informations lues, les informations intermédiaires à mémoriser pour faire des calculs ou des tests, et des variables qui dicteront l'état des sorties ...

  • Pour chacune de ces variables il faut se poser la question de sa nature et de ses valeurs limites : Variable booléenne, entière, flottante, signée ou non, ...

Pour cela on pourra s'aider du tableau récapitulatif suivant :

(Les astérisques indiquent les types de variables les plus utilisés)

III - Ecriture du Programme

Le programme qui est appelé "Croquis" en langage Arduino est la partie du projet la plus fastidieuse et tatillonne à écrire, car la moindre erreur de syntaxe bloquera la compilation (mais le compilateur vous aidera à trouver les erreurs).

Pour la lisibilité et la maintenabilité il est indispensable de bien commenter le code (parties après // que l'on peut abonder sans crainte car le compilateur n'en tient pas compte !).

En clair cela veut dire qu'il sera très dur de se remettre dans le bain quelques temps après, si rien n'est expliqué !

Le langage Arduino est proche du langage C++, mais le "monde Arduino" impose une structure particulière, avec les parties distinctes suivantes :

3 - 1 ) Informations préliminaires en début de programme

Dans cette partie on trouve :

  • l'affectation des broches d'entrée et de sortie.

Par exemple :

  • la déclaration des Variables globales qui sont définies pour tout le logiciel, par exemple :

  • L'intégration des "bibliothèques", qui sont des sortes de sous-programmes spécifiques, en libre accès, souvent développés pour piloter systèmes particuliers (afficheurs, bus, moteurs pas à pas, servo-moteurs, etc., etc. ...).

  • Les éventuelles fonctions d'interruption (voir paragraphe 4 - 2 ).

3 - 2 ) Le "SETUP"

Dans cette partie on trouve :

  • La nature des broches affectées précédemment : Entrées ou Sorties.

  • La partie du logiciel qui n'est déroulée qu'une seule fois,

En général il ne s'agit que de quelques parties annexes : Test de l'affichage à la mise sous tension, conversions d'unités, etc ..., et la partie principale du logiciel est dans LOOP (voir ci-dessous).

(Cependant toute règle a son exception ! Le premier logiciel Arduino que j'ai lu était intégralement contenu dans le SETUP, car il s'agissait de créer une impulsion unique après la mise sous tension pour inhiber le Stop & Start ; la partie LOOP était complètement inutile.)

3 - 3 ) La boucle "LOOP"

Cette partie est une boucle sans fin où se déroule (en général) l'essentiel du programme.

  • Les entrées sont périodiquement lues.

  • Grace aux structures de contrôle (tests, conditions, choix, boucles, etc. ...), le logiciel prend les décisions programmées.

  • Les sorties sont périodiquement rafraichies en fonction de ces décisions.

3 - 4 ) FONCTIONS ARDUINO

On trouve souvent après la partie LOOP (ou éventuellement avant la partie SETUP), des sortes de sous-programmes qui sont nommés fonctions dans le monde Arduino.

Ces Fonctions sont appelées par des instruction situées dans la partie LOOP pour faire par exemple des actions répétitives (des calculs, piloter une visualisation ou un actionneur ... ).

Les Fonctions permettent aussi de mieux structurer les logiciels, les rendre plus lisibles, et plus maintenables.

On trouve bien sûr sur internet des indications pour l'utilisation de Fonctions. Les points essentiels sont donnés ci-après.

3 - 4 - 1 ) La déclaration d'une "Fonction Arduino" est de la forme :

type NOM(typeA, typeB, typeC) {
type RESULT ;
corps de la fonction (instructions, tests, ...) ;

...

return RESULT ;

  • type : type de variable (byte, int, float, ...)

  • NOM : nom de la Fonction (qui servira à l'appeler depuis LOOP)

  • A, B, C : Variables locales qui ne sont utilisées que par cette Fonction, et qui doivent donc être déclarées dans cette fonction en précisant leur type

  • RESULT : nom de la variable locale dont la valeur sera retournée dans le programme principal

Remarque :

Si la Fonction NOM actionne quelque chose, pilote une visu, ... mais ne renvoie aucun résultat sous forme de variable dans LOOP, sa nature sera de type "void" (vide), comme les fonctions setup et loop.

Elle sera déclarée sous la forme : void NOM()

Et bien sûr la variable RESULT n'a plus de raison d'être dans ce cas là.

Exemple :

3 - 4 - 2 ) Pour appeler une "Fonction Arduino" depuis LOOP on écrira par exemple :

RETOUR = NOM (Var1, Var2, Var3) ;

Où :

  • RETOUR est la variable du programme principal qui recueillera la valeur de la variable locale RESULT

  • NOM : le nom de la Fonction

  • Var1, Var2, Var3, sont les variables (utilisées dans loop) qui contiennent les valeurs à transférer dans la fonction NOM.

Pour le transfert le nom des variables ne joue aucun rôle.

Ce qui compte est le nombre de variables (qui doit être identique), leur type (identique), et l'ordre d'écriture (Var1 -> A ; Var2 -> B ; Var3 ->C).

Exemple :

3 - 4 - 3 ) Pièges à éviter :

Même si l'on a bien compris le mécanisme de transfert des informations entre la Fonction, et l'instruction qui permet de la solliciter depuis LOOP, il faut faire particulièrement attention aux déclarations des Variables.

  • Leur type doit être cohérent et homogène, suivant les valeurs à traiter et transférer, pour assurer la continuité des formats des variables.

  • Il faut distinguer :

. Les "Variables Globales", déclarées en tout début de programme, avant le SETUP qui sont reconnues dans tout le logiciel.

. Les "Variables Locales", déclarées à l'intérieur d'une Fonction (y compris les Fonctions void setup() et void loop()), qui ne sont valables qu'à l'intérieur de ces Fonctions.

La distinction Globale/Locale est très importante car, par exemple, à chaque appel d'une fonction ses Variables Locales sont redéclarées, et donc ne peuvent pas mémoriser de valeurs entre 2 appels.

Par exemple dans la Fonction ci-après, qui est une "Centrale Clignotante" de LED appelée à chaque parcours de LOOP, et à laquelle on transmet les durées d'allumage et d'extinction souhaitées, les variables CLIGNO et TOP doivent être mémorisées entre chaque parcours de LOOP.

Ce seront donc des Variables Globales (déclarées en début de logiciel).

ALLUME et ETEINT sont les seules Variables Locales de cette Fonction.

Pour info, l'appel de cette Fonction depuis LOOP :

IV - Particularités du "Temps Réel" et remarques diverses

La plus part du temps les montages réalisés à partir de cartes Arduino doivent fonctionner en "temps réel", contrairement à de "l'informatique de gestion" où la notion de temps de réponse est certes importante pour le confort des utilisateurs, mais pas réellement fonctionnelle.

Cela signifie que quand se produit un évènement (capté par les entrées), le circuit doit réagir le plus rapidement possible en actionnant les sorties concernées.

Comme le microcontrôleur n'est pas géré par un OS (Operating System), il n'y a pas de "temps partagé", et toutes les instructions se déroulent "à la queue leu leu".

Pour cela on peut agir sur la gestion des temporisations, créer des interruptions, et créer un logiciel le plus simple et le plus limpide possible.

4 - 1 ) Temps de parcours de la boucle LOOP

Le délai de réaction du logiciel est conditionné par le temps nécessaire pour parcourir la boucle "LOOP", il faut donc faire en sorte que cette boucle soit parcourue en un minimum de temps, ne soit pas momentanément bloquée par l'instruction "delay(xx)", ou l'envoi d'informations qui ont servi au débogage.

Pour de tout petits logiciels (tel que ceux donnés dans ce blog), le parcours d'une boucle est de l'ordre de quelques centaines de µs pour une carte Nano.

Par exemple, pour un de ces petits logiciel de 3400 Octets (soit 11% de la mémoire Flash), la boucle est parcourue en 500 µs.

  • Avec une seule variable espionnée le parcours d'une boucle passe à 17 ms.

  • Avec 22 variables lues on passe à 200 ms !

Donc, ne pas oublier de supprimer les lectures de variables dans la version opérationnelle du logiciel !

A noter que la déclaration dans le Setup "Serial.begin(9600);" n'influe pas sur le temps de parcours de la boucle, on peut donc laisser cette instruction en version finale, même si elle occupe une part non négligeable de mémoire.

Par contre il faut impérativement neutraliser les lectures de variables (par exemple en les mettant en commentaires) car, même si elles ne peuvent pas être exécutées (si on a effacé la déclaration de la console dans le Setup), ces instructions ralentissent fortement la boucle (environ 100 µs par variable) .

Ma méthode de mesure :

  • Je me suis servi de la "LED Arduino" en D13 (pin 16), en la faisant changer d'état à chaque passage dans la boucle.

  • La demi-période du signal visualisé à l'oscilloscope en D13 est le temps de parcours d'une boucle.

4 - 2 ) Temporisations

Le premier écueil à éviter est la création d'une temporisation dans la boucle, pour faire clignoter une LED, ou temporiser une action quelconque ...

Le premier programme pour "débutant Arduino" est de faire clignoter une LED avec l'instruction "delay()", qui est justement l'instruction à ne jamais mettre dans la partie LOOP ! (mais si le programme ne fait clignoter qu'une LED, c'est acceptable ...)

Quand, par exemple, le programme arrive sur l'instruction "delay(1000) ; ", il attend 1000 ms (donc 1 seconde) sans rien faire d'autre, et le parcours de la boucle LOOP sera retardé d'autant ! ...

Et pendant ce temps les données d'entrée, les appuis sur des poussoirs, etc. ..., ne seront pas lus et le système ne réagira pas.

Pour pallier cet inconvénient il faut utiliser l'horloge interne à la carte qui obéit à l'instruction "millis()". C'est un compteur qui commence à compter les millisecondes dès la mise sous tension, et ceci pendant 50 jours avant de se remettre à 0 (si on laisse la carte branchée !), ensuite il recommence à compter depuis 0.

En utilisation normale sur une voiture la valeur de ce compteur sera donc toujours croissante avec le temps (pas de passage à 0), et on pourra se référer à lui pour avoir l'heure !

Donc par exemple, pour créer une temporisations de valeur TEMPO (en ms), le principe est :

  • De mémoriser dans une variable (TOP_TEMPO), la valeur du compteur au départ de la tempo.

  • Puis à chaque boucle, de comparer l'heure actuelle "millis()", à la valeur TOP_TEMPO + TEMPO.

  • Quand millis() sera supérieur à TOP_TEMPO + TEMPO, le temps de la temporisation sera écoulé.

Exemple de codage :

4 - 3 ) Interruptions

Si on a besoin d'une prise en compte immédiate d'un évènement qu'on a peur de louper par une scrutation périodique (par exemple si le temps de parcours de la boucle est long, ou si l'évènement est très bref ...) il y a la possibilité d'agir par "Interruption".

Sur les cartes Nano, seules 2 entrées (D2 et D3) sont capables de recevoir des signaux logiques pouvant générer des interruptions.

Le déclenchement d'une interruption peut se faire sur un front, un état, ou un changement d'état. Cet évènement déclenchera immédiatement le déroulement d'un petit "programme d'interruption" spécifique, qui en général avertit le programme principal que l'évènement s'est produit.
La transmission de cette information est réalisée par l'intermédiaire d'une variable dite "volatile", qui est dédiée à cette tâche.

Exemple de programme d'Interruption (placé avant le SETUP) :

Dans la boucle LOOP on traite le fait que l'évènement s'est produit (IT = 1) :

etc. ...

Dans la suite du programme la variable IT doit être remise è 0, pour que le logiciel reste à nouveau réceptif à une nouvelle Interruption.

Vous pourrez trouver des explications plus complètes dans des Tutos sur internet ...

4 - 4 ) Anti-rebonds

Le traitement de la fermeture d'un contact (interrupteur, poussoir, relais, ...) n'est pas forcément évident pour une carte Arduino ..., à cause des "fameux" rebonds !

Le rebondissement mécanique des 2 parties d'un contact qui se ferme peut faire croire à la carte Arduino qui est très réactive que (par exemple) on a appuyé plusieurs fois sur un poussoir, et elle réagit en temps réel à cette série de pousser/relâcher !

Il y a 2 façons de s'affranchir de ce problème :

  • Par filtrage hard, avec des filtres électroniques (à base de condensateurs et de selfs).
  • Par logiciel.

On peut bien sûr mêler les 2 méthodes.

Le traitement par logiciel est très efficace et très économique (pas de composants ajoutés).

Dans l'exemple donné ci-dessus il consiste simplement :

  • A noter l'heure (DEBUT_IT) à laquelle un premier appui sur le poussoir a été signalé par l'interruption.

  • Puis à attendre le temps de stabilisation du composant (parfois donné par les caractéristiques constructeur, ici on a pris APPUI = 30 ms), pour confirmer la lecture de l'état du poussoir, en sautant toutes les oscillations intermédiaires.

On s'affranchi ainsi des rebonds, mais aussi d'éventuels parasites.

4 - 5 ) Fiabilisation des données d'entrés analogiques

Pour fiabiliser les mesures issues des convertisseurs A/N, et ne pas si fier à une seule, qui risque d'être "aberrante", si par exemple la liaison est perturbée par des parasite, on peut pallier cet inconvénient en faisant des moyennes.

  • Des moyennes consécutives sur des séries contiguës de données : elles peuvent créer des discontinuités, mais elles sont facile à coder sans avoir recours à des tableaux, ni à une bibliothèque :

. A chaque passage de la boucle LOOP on ajoute une valeur mesurée à une variable "Somme"

. Quand on a atteint N Valeurs, on divise cette somme par N, et on mémorise la moyenne ainsi obtenue ; puis on réinitialise à 0, Somme et N, pour refaire un nouveau calcul.

  • Une moyenne glissante, "pure et dure" sur les N derniers résultats, en se servant d'un tableau de N valeurs, géré comme une pile informatique FIFO (First In First Out).

où à chaque nouvelle mesure :
. On intègre la nouvelle mesure à la place de la plus vieille des N mesures, qui est effacée.
. Et on recalcule à chaque fois la nouvelle moyenne, qui est ainsi mise à jour en temps réel.

En pratique le premier procédé est souvent suffisant, car pour une boucle LOOP de 500 µs, en faisant des moyennes sur 100 échantillons, on aura une moyenne rafraichie toutes les 50 ms.

On trouve sur internet des bibliothèques spécifiques (à appeler en début de programme), qui réalisent ces types de moyennes, il suffit de les paramétrer en fonction du besoin.

Le choix du traitement et du nombre d'échantillons sera un compromis entre la précision de la mesure, et la rapidité de la lecture ...

4 - 6 ) Sorties PWM

Les cartes Arduino possèdent des entrées logiques et analogiques, des sorties logiques, ... mais pas de sorties analogiques ?!

Les sorties PWM (Pulse Width Modulation) sont justement faites pour pallier cette absence, car il suffit de leur connecter un "circuit intégrateur" (généralement un simple circuit R-C), pour créer une tension continue (de 0 à 5V) que l'on pourra faire varier.

Le principe est de générer un signal carré de fréquence fixe (490 Hz), d'amplitude 5V, dont on fait varier le rapport cyclique en 256 valeurs (codage sous 8 bits => 2^8 = 256 valeurs, 0 compris)

En clair si on programme le Rapport cyclique par une variable "N" dans le logiciel, on aura :

  • Pour N = 0 : Rapport cyclique = 0 % => la sortie se met à 0 V
  • Pour N = 255 : Rapport cyclique = 100 % => la sortie se met à 5 V

Pour les valeurs intermédiaires on appliquera la relation :

N = 2,55 x Rapport cyclique

Après intégration, la tension continue résultante (V) est directement liée au rapport cyclique par la relation :

V = 5 Volts x ( Rapport cyclique (%) / 100 )

Les cartes Nano possèdent 6 sorties digitales configurables PWM.

Remarque :

Pour faire varier la luminosité d'une LED nul besoin de circuit intégrateur.

L'intégration sera faite par la rétine : A une fréquence de 490 Hz (période de 2 ms), une série d'impulsions lumineuses de plus en plus fines sera perçue comme une atténuation de la luminosité.

(pour un voyant à incandescence l'intégration se fera aussi par l'inertie thermique du filament)

Ci-dessous l'oscillogramme d'une LED clignotante, dont la luminosité est atténuée :

(Remarque : Pour un signal de ce type, qui n'est pas un signal périodique pur, l'indication 129 Hz de l'oscilloscope ne correspond à rien !)

&&&&&&&&&&&&&&&&&&&&&&&

le bar ne semble pas l'endroit approprié - déplacé dans les projets finis

Merci Berny,
Sympa pour les débutants.

Bonjour,

  • La convention usuelle du C/C++ conseille d'utiliser des noms de variables et de fonctions en minuscules et les constantes en majuscules. Cela permet aux habitués de s'y retrouver un peu plus.

  • la condition
    ìf (millis() > OCCULT + DEBUT_IT)
    fonctionne très bien sauf après un débordement. Pour éviter cela, il vaut mieux employer
    ìf (millis() - DEBUT_IT > OCCULT)
    qui fonctionne aussi aux moments des débordement. C'est aussi une bonne habitude à prendre même si dans le cas présent il est déconseillé par les pouvoirs publics de roule pendant 50 jours sans s'arrêter.
    Mais le problème peut apparaître pour les temps plus courts on utilise micros() à la place de millis() (l'incrémentation de millis() n'est pas régulière), ou si pour une question d'économie de variables, on utilise des word ou des byte pour les temporisations.

  • Pour l'alimentation, je me demande si le mieux n'est pas d'avoir un régulateur 9V externe genre 7809 que d'utiliser une zener. La puissance dissipée est nettement plus faible. Voir utiliser un régulateur linéaire ou à découpage et de renter sur le 5V.

Pour ma part, sur un clone je mesure plutôt 27mA (broche 5V), ou 32mA (VIN ou JACK).

Si la consommation de la NANO est constante (32mA), ce qui est rarement le cas, le courant dans la résistance sera égal à 32mA + le courant dans la zener.
La moindre consommation sur une sortie de l'ARDUINO (commande de module relais, 5mA par exemple) aura pour conséquence de priver la zener de courant, donc il faudra diminuer la résistance série, ce qui augmentera le courant de repos dans la zener. Cette solution, qui implique de connaître le courant maximal consommé, me paraît inadaptée pour un débutant. Pour ma part je n'en parlerais même pas.

qui pourra être épaulée par un transistor ballast si le courant à fournir est important.

Autant utiliser un régulateur, et si celui-ci peut être un modèle à découpage, c'est encore mieux.

Absolument, et j'ajouterais ceci : un nom de fonction ou de variable doit être en minuscules, et les différents mots capitalisés : digitalWrite()

Exact, grave erreur.
https://www.norwegiancreations.com/2018/10/arduino-tutorial-avoiding-the-overflow-issue-when-using-millis-and-micros/

Bonjour

Ce qui est proposé par @Berny4631 rendra sans doute service a nombre de débutants

Pour l'améliorer je propose d'utiliser le terme 'stabilisation' pour le montage proposé avec la diode zener, cqui ne constitue pas une véritable 'régulation' vue l'absence de rétroaction . (boucle de contre-réaction)
La faible efficacité de ce montage pour une alimentation a été expliquée au dessus.

Bonjour,

Merci à tous les forumeurs pour vos intéressantes remarques :

  • Bien évidemment, en tant qu'amateur, j'ignore totalement les conventions sur les majuscules et minuscules adoptées par les professionnels de l'informatique …

  • Je connaissais bien sûr les RAZ périodiques de millis() et micros(), et les risques encourus au bout de 50 jours de fonctionnement continu pour millis(), mais je n'avais jamais entendu parler de l'astuce qui permet de contourner ce problème, et donc merci pour cette information qui me sera peut-être utile, surtout si je dois utiliser micros().

  • Il est évident que la stabilisation de la tension par écrêtage par diode Zéner (qui n'est effectivement pas une régulation) demande quelques calculs à partir de la connaissance précise des caractéristiques de consommation du montage, et des variations de la tension d'entrée, … ce qui n'est pas facile pour un débutant, j'en conviens !
    J'en ai parlé parce qu'on trouve encore ces montages quand les courants sont faibles …, mais je dis aussi que l'utilisation d'un simple régulateur est bien plus facile et plus sure (j'ai un peu modifié mon texte pour insister dans ce sens).

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.