- Introduction
- Matériel utlisé
- Le montage
- Le code expliqué
- Le code complet, copiable et téléchargeable
Introduction
Dès que l’on désire rajouter des possibilités à notre chère carte Arduino, pour un écran, Oled ou non, une horloge RTC ou autres périphériques, et pour moins de fils dans nos montages, on se tourne immanquablement vers le bus I2C.
Sur le web, pour ce sujet, il ne manque pas de tutoriels plus ou moins pertinents, tant sur la partie électronique que sur la partie logique et notre ami Google saura vous y mener sans faillir.
Malgré tout cela, même après avoir beaucoup lu et collecté nombre d’articles traitant du sujet, il est difficile de trouver les informations nécessaires à une programmation pertinente et une bonne compréhension des mécanismes mis en œuvre.
Le but :
- trouver les adresses I2c des périphériques car les achats faits en Chine sont souvent mal documentés.
- connaitre la validité des périphériques connectés sur le bus (gestion des erreurs)
- avoir un affichage des résultats du scan, sur port série, condensé, pertinent et résilient.
- éventuellement, mieux comprendre le fonctionnement de la bibliothèque Wire.h
Le sketch Arduino de scanner de bus I2C développé ici, inspiré d’exemples trouvés sur le web, est simple mais efficace.
Après initialisation, les 127 adresses possibles du bus I2C sont scannées une à une et le résultat est affiché sur le port série, sous forme d’un tableau facilement interprétable.
L’écran de résultat est divisé en trois partie :
- Le titre, une bannière en code ASCII pour le fun (vieux souvenir )
- Le tableau de résultat du scan de 16 lignes de 8 colonnes (de l’adresses 0 à 127)
- Un résumé du scan (qui gère les situations et les pluriels selon les trouvailles. )
Les valeurs du tableau de résultats représentent :
- . . . . Adresse scannée et non utilisée
- 0xxx Périphérique valide et fonctionnel (valeur hexadécimale)
- #### Périphérique présent mais en défaut
Pour relancer un scan du bus I2C, il suffit d’appuyer sur le bouton Reset de la carte Arduino.
Cela supprime toute valeur en mémoire, ré-initialise les registres internes et relance l’affichage sur le port série.
Vous trouverez le code complet en bas de page et un lien de téléchargement.
Le code n’est pas optimisé car écrit dans un but didactique et vous pourrez sans aucun doute faire mieux.
Bonne lecture et bon developpement !
Webby
Matériel utlisé
Pour réaliser ce scanner I2C, le matériel suivant à été utilisé :
- 1 carte Arduino UNO
- 1 breadboard (plaque de connexions sans soudure)
- 2 résistances 1/4 watt 10K ohms 5%
- 1 écran Oled I2C 32x128
- 1 module horloge Tiny RTC I2C avec 2 adresses I2C
- une pour l’horloge
- une pour l’EEPROM (mémoire)
- Quelques bout de fils
- un peu de patience
Le module horloge RTC et l’écran Oled ne sont la que pour leurs adresses I2C.
Tout autre périphérique I2C fera l’affaire.
Sans périphérique I2C, la détection sera plus compliquée…forcément !
Le montage
(
Le montage ne recèle pas de difficultés particulières.
Le module écran Oled et le module RTC sont enfichés sur une platine de prototypage sans soudure (breadboard).
Deux résistances de tirage, de 10 K ohms 5% chacune (code couleur Marron, Noir, Orange, Or), sur les lignes SDA et SCL du bus I2C complètent le montage. Si vous n’utilisez pas plusieurs périphériques I2C, vous pouvez activer les resistances de pull-up internes à la carte Arduino. Elles devrait être suffisantes.
La breadboard utilisée comporte deux zones d’alimentation, matérialisées par des filets rouges pour les tensions positives et des filets bleus pour le 0V/Gnd.
La zone d’alimentation supérieure (en haut de la photo du montage) sert pour l’alimentation des modules.
La zone d’alimentation inférieure (en bas de la photo du montage) sert comme bus I2C, pour éviter la prolifération des fils de connexion.
Le cablâge
Le câblage de la carte Arduino se résume à 4 fils :
- 1 fil rouge entre la Broche 5V et le pôle positif de la zone d’alimentation en haut de la breadbord (surmontée d’un filet rouge)
-
1 fil noir entre la broche GND et le pôle négatif de la zone d’alimentation en haut de la breadbord (soulignée d’un filet Bleu)
-
1 fil mauve entre la Broche A5 (SCL) et le pôle positif de la zone d’alimentation en bas de la breadbord (surmontée d’un filet rouge)
- 1 fil jaune entre la broche A4 (SDA) et le pôle négatif de la zone d’alimentation en bas de la breadbord (soulignée d’un filet Bleu)
Les fils du bus I2C sont "twistés" (tortillés ensemble façon scoubidou) pour réduire la sensibilité aux parasites (surtout) et discipliner le câblage en lui donnant plus de rigidité (un peu).
Quelques straps (les fils rigides plaqués sur la breadboard) ont assurés les liaisons manquantes.
Le schéma
Le code expliqué
Celui-ci est assez simple, ne comporte pas d’astuces et est accessible, même au plus débutant pour peu qu’il maîtrise le minimum.
Le code est copieusement commenté pour les plus novices, toute les lignes (ou presque) le sont, même les plus basiques.
Chaque traitement est ainsi plus compréhensible même si cela nuit un peu à la lisibilité.
Dans les explications suivantes, les portions de code citées ne sont pas forcément contiguës.
Pour certains passages et pour plus de clarté, des lignes non nécessaires ont été supprimées.
Elles figureront dans d’autres explications.
Le programme est divisé en quatre sections:
- Les commentaires, en en-tête du programme pour explications de celui-ci
- La partie déclarative, réduite à la seule inclusion de la librairie Wire.h
- La fonction setup(), qui contient tout le code (bannière,scan et résumé)
- la fonction loop(), inutilisée mais qui doit être présente
La fonction loop() n’est pas utilisée car tout le code est dans la fonction setup()pour avoir une seule exécution du programme, sans boucle. Ainsi l’affichage est condensé sur le terminal série et ne défile pas (voir les copies d’écrans en fin de rubrique Résumé).
Les variables sont déclarée dans la fonction setup().
Elles ne sont donc valables que pour cette fonction !
Pensez-y si vous devez modifier ce programme.
Synoptique du programme
Très simple, il se résume à 3 blocs:
Les commentaires en en-tête
Mettre des commentaires en tout début du programme, est une bonne habitude à prendre.
Ils vous permettent une bonne introduction en indiquant le but du programme, sa philosophie, sa version, …
Bref on peut y mettre une information servant à éclairer celui qui découvre autant que celui qui redécouvre comme :
- le but et les moyens du programme
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /* SCANNER I2C Version 2.00 -------------------------------------------- Scan le bus i2c a la recherche de peripheriques. Scan des adresses 1 (0x01) a 127 (0x7F) L'adresse 0 (reservee) est simulee et non lue. Affichage du resultat en grille de 16 lignes de 8 colonnes (16x8=128). L'affichage de chaque adresse est signalee par : - son adresse en hexadecimale (0x00) si elle est occupee, - 4 dieses (####) si elle est occupee par un peripherique en defaut - 4 points (....) si elle est inoccupee, Un resume indique, en fin de programme, le nombre de peripheriques trouves et, eventuellement, le nombre de peripheriques en defaut. |
- la mise en œuvre
1 2 3 4 5 | /* Pour refaire un scan, il suffit d'appuyer sur le bouton Reset car : - tout le code est dans la fonction setup() - la fonction loop() n'est pas utilisee */ |
- les améliorations possibles
1 2 3 4 5 6 7 8 9 | /* Ameliorations possibles : - Affichage en hexadecimal des adresses en defaut - Affichage des adresses en hexadecimmal et des valeurs de retour de la fonction Wire.endTransmission() - Affichage du type de peripherique detecte - ... ----------------------------------------------------------------------*/ |
La partie déclarative
Généralement, l’en-tête du programme sert à inclure les bibliothèques, déclarer et initialiser les variables globales, puis initialiser les objet comme un port série, un bus I2c ou 1Wire, une horloge RTC…
Petit rappel :
- les variables déclarées dans l’en-tête ont une portée globales et sont accessibles à toutes les fonctions.
- les variables déclarées dans une fonction ne sont valables que pour celle-ci
Inclusion de la bibliothèque Wire.h pour la gestion du bus I2C
L’inclusions d’une bibliothèque externe doit figurer avant la déclaration des variables et l’initialisation des objets car certains de ceux-ci dépendent des bibliothèques incluses.
La gestion du bus I2C est facilité par la bibliothèque Wire.h qui est fournie avec l’IDE Arduino. C’est la seule dont nous aurons besoin.
Pour l’inclure, toujours sous l’IDE Arduino, dans la fenêtre d’édition, du code positionnez votre curseur à l’endroit voulu puis Menu [Croquis] [Inclure une bibliothèque][Wire].
1 | #include <Wire.h> /* Indispensable pour la gestion de l'I2C */. |
D’elle, nous utiliserons seulement 3 fonctions :
- Wire.begin pour l’initialisation de la communication I2C
- Wire.beginTransmission() pour un dialogue à l’adresse indiquée
- Wire.endTransmission() pour la récupération de la réponse
1 | Wire.begin(); /* Initialise le bus i2C */ |
1 2 3 4 5 6 7 8 | Wire.beginTransmission(adresse); /* Commence une transmission a l'adresse indiquee */ resultat = Wire.endTransmission(); /* resultat = statut de la transmission : 0 : succès (peripherique OK) 1 : donnée trop longue pour le buffer d'émission (erreur) 2 : NACK reçu sur l'adresse de transmission (pas de peripherique) 3 : NACK reçu sur la transmission de donnée (pas de peripherique) 4 : autre erreur (erreur donc...) */ |
Déclaration des variables
Les déclarations et l’initialisation des variables se font dans la fonction setup() car c’est la seule du programme.
Elles pourraient figurer dans la partie déclarative, pour nous cela ne changerait rien.
Sous la déclaration des variables, il y a l’initialisation des objets Wire (bus I2C) et Serial (port série).
1 2 3 4 5 6 7 8 9 10 11 12 | void setup() { /* Les variables du programme */ byte adresse; /* variables de gestion des adresses */ byte resultat; /* Variable de retour d'interrogation d'une adresse */ byte nb_existe = 0; /* compteur de peripheriques trouves */ byte nb_defaut = 0; /* compteur de peripheriques en defaut */ Wire.begin(); /* Initialise le bus i2C */ Serial.begin(9600); /* Initialise le port serie */ ` |
La bannière
Quand seul le mode texte existait, les programmeurs rêvaient d’égayer les tristes écrans (monochrome de surcroît) des applications.
Leur astuce a été d’utiliser un affichage de caractères sur plusieurs lignes pour former une représentation plus graphique qu’un texte seul. Ainsi est né ce que l’on nomma l’ASCII Art.
L’ASCII est un tableau de définition de caractères (explication sur Wikipédia), mais je suis sûr que je ne vous apprend rien .
Le moniteur série ne permettant que l’affichage texte, et ne voulant pas me contenter d’un "bête" titre, même agrémenté d’un cadre lui aussi en texte, j’ai donc choisi de faire revivre cette solution…pour un résultat plutôt sympa, non ?
En langage C, pour afficher dans une chaîne de caractères les signes ’(guillemet), "(double guillemet) ou \ (antislash),
il faut les préfixer avec le caractère \. C’est à dire qu’il faut écrire \’ \" ou \\.
1 2 3 4 5 6 7 8 9 10 | /* Petite banniere en ASII... juste pour le fun Veuillez bien recopier les lignes ci-dessous pour un affichage correct PS: n'oubliez pas que le \ doit etre precede d'un \ pour son affichage */ Serial.println(" ____ ___ ____ ____ "); Serial.println(" / ___| ___ __ _ _ __ |_ _| |___ \\ / ___|"); Serial.println(" \\___ \\ / __| / _` | | '_ \\ | | __) | | | "); Serial.println(" ___) | | (__ | (_| | | | | | | | / __/ | |___ "); Serial.println(" |____/ \\___| \\__,_| |_| |_| |___| |_____| \\____|"); Serial.println(); |
Voici ce que cela donne :
Le scan
Le démarrage automatique du scan est signalé par le message "Debut du scan".
La visualisation du résultat se fait en tableau de 16 lignes de huit colonnes (soit 128 cases).
Question : Pourquoi l’affichage comporte 128 cases alors que l’on scanne 127 adresses (1 à 127) ?
1 | for (adresse = 1; adresse < 128; adresse++ ) |
Réponse : Parce que c’est plus beau d’avoir un tableau complet !
Qestion :
Alors pourquoi on ne commence pas le scan à partir de l’adresse 0x00 ?
Réponse :
Parce que l’adresse 0x00 est réservée. Elle a une fonction spéciale : "message à tous les périphériques"
Qestion :
Donc elle n’est pas testée mais simulée à l’affichage en première case du tableau ?
Réponse :
Hé oui, t’as tout compris !
Le tableau est décalé sur la gauche de l’affichage d’une tabulation (\t) pour une meilleure visibilité.
1 2 3 4 | /* Debut de la grille d'affichage ou on simule l'adresse 0 par 4 points (.... ) car elle est reservee par les fabriquants pour des fonctions speciales. PS: le tableau est decale d'une tabulation pour une meilleure lisibilite */ Serial.print("\t.... "); |
1 2 3 4 5 6 7 | if (((adresse + 1) % 8) == 0) /* Pour formatage de l'affichage en 8 colonnes */ /* le +1 c'est parce que l'on part de l'adresse 1 et non de l'adresse 0 */ { Serial.println(); /* Passage a la ligne apres avoir affiche 8 adresses */ if (adresse < 127)Serial.print("\t"); /* tabulation pour la mise en forme de l'affichage sauf apres la derniere adresse */ } |
Les adresses sont testées les unes après les autres, de 1 à 127.
1 | Wire.beginTransmission(adresse); /* Commence une transmission a l'adresse indiquee */ |
Le résultat est récupéré par la fonction Wire.endTransmission().
1 2 3 4 5 6 7 | resultat = Wire.endTransmission(); /* resultat = statut de la transmission : 0 : succès (peripherique OK) 1 : donnée trop longue pour le buffer d'émission (erreur) 2 : NACK reçu sur l'adresse de transmission (pas de peripherique) 3 : NACK reçu sur la transmission de donnée (pas de peripherique) 4 : autre erreur (erreur donc...) */ |
Il est représenté par :
.... | pour une adresse vide |
0x00 | l’adresse d’un périphérique valide |
#### | pour un périphérique présent mais en défaut |
Quand un périphérique est trouvé, la variable nb_existe est incrémentée et s’il est en défaut, on incrémente aussi la variable nb_defaut.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* Traitement du resultat */ if (resultat == 0) /* Il y a un peripherique OK a cette adresse */ { /* Mise en forme et affichage de l'adresse du peripherique en Hexadecimal */ if (adresse < 16)Serial.print("0x0"); else Serial.print("0x"); Serial.print(adresse, HEX); Serial.print(" "); nb_existe++; /* Increment le nombre de peripheriques trouves */ } else if ((resultat == 4) || (resultat == 1)) /* Indication d'un peripherique en defaut */ { Serial.print("#### "); nb_existe++; /* Increment le nombre de peripheriques trouves */ nb_defaut++; /* Incremente le nombre de peripheriques en defaut */ } else Serial.print(".... ");/* adresse inoccupee */ /* resultat = 2 ou 3 (NAK) -> pas de reponse d'un peripherique*/ |
Les adresses inférieures à 16 (en décimal) sont mises en forme sur 4 digits pour l’esthétisme et le parfait alignement du tableau..
1 2 3 4 5 | /* Mise en forme et affichage de l'adresse du peripherique en Hexadecimal */ if (adresse < 16)Serial.print("0x0"); else Serial.print("0x"); Serial.print(adresse, HEX); Serial.print(" "); |
Code complet du scan :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | Serial.println("\nDebut du scan"); /* Affiche un saut de ligne puis le debut du scan */ /* Debut de la grille d'affichage ou on simule l'adresse 0 par 4 points (.... ) car elle est reservee par les fabriquants pour des fonctions speciales. PS: le tableau est decale d'une tabulation pour une meilleure lisibilite */ Serial.print("\t.... "); /* Demarre le scan */ for (adresse = 1; adresse < 128; adresse++ ) /* Il y a 128 adresses disponibles au maximun (de 0 a 127) rappel : on ne teste pas l'adresse 0 (voir ci-dessus) */ { Wire.beginTransmission(adresse); /* Commence une transmission a l'adresse indiquee */ resultat = Wire.endTransmission(); /* resultat = statut de la transmission : 0 : succès (peripherique OK) 1 : donnée trop longue pour le buffer d'émission (erreur) 2 : NACK reçu sur l'adresse de transmission (pas de peripherique) 3 : NACK reçu sur la transmission de donnée (pas de peripherique) 4 : autre erreur (erreur donc...) */ /* Decommenter les lignes ci-dessous pour test de peripherique en defaut Adaptez les adresses (de 1 a 127) en fonction de votre configuration */ //if (adresse == 17) resultat = 4; //if (adresse == 93) resultat = 1; /* Traitement du resultat */ if (resultat == 0) /* Il y a un peripherique OK a cette adresse */ { /* Mise en forme et affichage de l'adresse du peripherique en Hexadecimal */ if (adresse < 16)Serial.print("0x0"); else Serial.print("0x"); Serial.print(adresse, HEX); Serial.print(" "); nb_existe++; /* Increment le nombre de peripheriques trouves */ } else if ((resultat == 4) || (resultat == 1)) /* Indication d'un peripherique en defaut */ { Serial.print("#### "); nb_existe++; /* Increment le nombre de peripheriques trouves */ nb_defaut++; /* Incremente le nombre de peripheriques en defaut */ } else Serial.print(".... ");/* adresse inoccupee */ /* resultat = 2 ou 3 (NAK) -> pas de reponse d'un peripherique*/ /* Decommentez la ligne ci-dessous si vous avez des erreurs de lecture */ //delay(25); /* temps d'attente pour ne pas generer d'erreur de lecture */ if (((adresse + 1) % 8) == 0) /* Pour formatage de l'affichage en 8 colonnes */ /* le +1 c'est parce que l'on part de l'adresse 1 et non de l'adresse 0 */ { Serial.println(); /* Passage a la ligne apres avoir affiche 8 adresses */ if (adresse < 127)Serial.print("\t"); /* tabulation pour la mise en forme de l'affichage sauf apres la derniere adresse */ } /* Fin du traitement du resultat et passage a l'adresse suivante */ } |
Le résumé
En fin de scan, un résumé mis en forme (gestion du singulier et des pluriels, point terminal en fin de phrase) indique :
- le nombre (ou l’absence) de périphériques I2C reconnus
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* Affichage des resultats complementaires **/ if (nb_existe == 0)Serial.println("Aucun peripherique I2C !"); /* Pas de peripherique I2c */ else { /* Affichage d'un resume sous la forme : X peripherique(s) reconnu(s). ou X peripherique(s) reconnu(s) dont X peripherique(s) en defaut. avec gestion des pluriels et du point terminal */ Serial.print(nb_existe); /* nombre de peripheriques I2c reconnus */ if (nb_existe < 2)Serial.print(" peripherique reconnu"); /* affichage pour un seul */ else Serial.print(" peripheriques reconnus"); /* affichage pour plusieurs */ |
- éventuellement, le nombre de périphériques en défaut
1 2 3 4 5 6 7 8 | if (nb_defaut != 0) /* S'il y a des peripheriques en defaut */ { Serial.print(" dont "); /* poursuit la phrase de resume */ Serial.print(nb_defaut); /* Nombre de peripheriques en defaut */ if (nb_defaut < 2)Serial.println(" peripherique en defaut."); /* affichage pour un seul */ else Serial.println(" peripheriques en defaut."); /* affichage pour plusieurs */ } else Serial.println("."); /* Termine la phrase par un point s'il n'y a pas de peripherique en defaut */ |
- la façon de relancer un scan
1 2 3 | /* Message de fin de scan */ Serial.println("\nAppuyez sur le bouton Reset de l'Arduino pour recommencer.\n"); Serial.println(); /* Saut de ligne supplémentaire */ |
Visuels des différents écrans de résultat possibles :
Cliquez sur une des images ci-dessus
Le code complet, copiable et téléchargeable
Voici le code complet, copieusement documenté (presque chaque ligne en fait )
Vous pouvez faire un copier-coller, depuis cette fenêtre, jusqu’à votre éditeur.
Si vous préférez la version toute faite, cliquez ici !
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | /* SCANNER I2C Version 2.00 -------------------------------------------- Scan le bus i2c a la recherche de peripheriques. Scan des adresses 1 (0x01) a 127 (0x7F) L'adresse 0 (reservee) est simulee et non lue. Affichage du resultat en grille de 16 lignes de 8 colonnes (16x8=128). L'affichage de chaque adresse est signalee par : - son adresse en hexadecimale (0x00) si elle est occupee, - 4 dieses (####) si elle est occupee par un peripherique en defaut - 4 points (....) si elle est inoccupee, Un resume indique, en fin de programme, le nombre de peripheriques trouves et, eventuellement, le nombre de peripheriques en defaut. Pour refaire un scan, il suffit d'appuyer sur le bouton Reset car : - tout le code est dans la fonction setup() - la fonction loop() n'est pas utilisee Ameliorations possibles : - Affichage en hexadecimal des adresses en defaut - Affichage des adresses en hexadecimmal et des valeurs de retour de la fonction Wire.endTransmission() - Affichage du type de peripherique detecte - ... ----------------------------------------------------------------------*/ #include <Wire.h> /* Indispensable pour la gestion de l'I2C */ void setup() { /* Les variables du programme */ byte adresse; /* variables de gestion des adresses */ byte resultat; /* Variable de retour d'interrogation d'une adresse */ byte nb_existe = 0; /* compteur de peripheriques trouves */ byte nb_defaut = 0; /* compteur de peripheriques en defaut */ Wire.begin(); /* Initialise le bus i2C */ Serial.begin(9600); /* Initialise le port serie */ /* Petite banniere en ASII... juste pour le fun Veuillez bien recopier les lignes ci-dessous pour un affichage correct PS: n'oubliez pas que le \ doit etre precede d'un \ pour son affichage */ Serial.println(" ____ ___ ____ ____ "); Serial.println(" / ___| ___ __ _ _ __ |_ _| |___ \\ / ___|"); Serial.println(" \\___ \\ / __| / _` | | '_ \\ | | __) | | | "); Serial.println(" ___) | | (__ | (_| | | | | | | | / __/ | |___ "); Serial.println(" |____/ \\___| \\__,_| |_| |_| |___| |_____| \\____|"); Serial.println(); Serial.println("\nDebut du scan"); /* Affiche un saut de ligne puis le debut du scan */ /* Debut de la grille d'affichage ou on simule l'adresse 0 par 4 points (.... ) car elle est reservee par les fabriquants pour des fonctions speciales. PS: le tableau est decale d'une tabulation pour une meilleure lisibilite */ Serial.print("\t.... "); /* Demarre le scan */ for (adresse = 1; adresse < 128; adresse++ ) /* Il y a 128 adresses disponibles au maximun (de 0 a 127) rappel : on ne teste pas l'adresse 0 (voir ci-dessus) */ { Wire.beginTransmission(adresse); /* Commence une transmission a l'adresse indiquee */ resultat = Wire.endTransmission(); /* resultat = statut de la transmission : 0 : succès (peripherique OK) 1 : donnée trop longue pour le buffer d'émission (erreur) 2 : NACK reçu sur l'adresse de transmission (pas de peripherique) 3 : NACK reçu sur la transmission de donnée (pas de peripherique) 4 : autre erreur (erreur donc...) */ /* POUR TEST UNIQUEMENT : (on a pas forcement de peripherique en defaut sous la main) * Decommenter une ou les lignes ci-dessous pour simuler un ou plusieurs peripherique en defaut * Adaptez les adresses (de 1 a 127) en fonction de votre configuration * Adapter les resultats en fonction du traitement que vous envisagez */ //if (adresse == 17) resultat = 4; /* simule une erreur autre que 1,2 ou 3 */ //if (adresse == 93) resultat = 1; /* simule une erreur de données */ /* Traitement du resultat */ if (resultat == 0) /* Il y a un peripherique OK a cette adresse */ { /* Mise en forme et affichage de l'adresse du peripherique en Hexadecimal */ if (adresse < 16)Serial.print("0x0"); else Serial.print("0x"); Serial.print(adresse, HEX); Serial.print(" "); nb_existe++; /* Increment le nombre de peripheriques trouves */ } else if ((resultat == 4) || (resultat == 1)) /* Indication d'un peripherique en defaut */ { Serial.print("#### "); nb_existe++; /* Increment le nombre de peripheriques trouves */ nb_defaut++; /* Incremente le nombre de peripheriques en defaut */ } else Serial.print(".... ");/* adresse inoccupee */ /* resultat = 2 ou 3 (NAK) -> pas de reponse d'un peripherique*/ /* Decommentez la ligne ci-dessous si vous avez des erreurs de lecture */ //delay(25); /* temps d'attente pour ne pas generer d'erreur de lecture */ if (((adresse + 1) % 8) == 0) /* Pour formatage de l'affichage en 8 colonnes */ /* le +1 c'est parce que l'on part de l'adresse 1 et non de l'adresse 0 */ { Serial.println(); /* Passage a la ligne apres avoir affiche 8 adresses */ if (adresse < 127)Serial.print("\t"); /* tabulation pour la mise en forme de l'affichage sauf apres la derniere adresse */ } /* Fin du traitement du resultat et passage a l'adresse suivante */ } /* Fin du scan */ Serial.println("Fin du Scan\n"); /* Affichage des resultats complementaires **/ if (nb_existe == 0)Serial.println("Aucun peripherique I2C !"); /* Pas de peripherique I2c */ else { /* Affichage d'un resume sous la forme : X peripherique(s) reconnu(s). ou X peripherique(s) reconnu(s) dont X peripherique(s) en defaut. avec gestion des pluriels et du point terminal */ Serial.print(nb_existe); /* nombre de peripheriques I2c reconnus */ if (nb_existe < 2)Serial.print(" peripherique reconnu"); /* affichage pour un seul */ else Serial.print(" peripheriques reconnus"); /* affichage pour plusieurs */ if (nb_defaut != 0) /* S'il y a des peripheriques en defaut */ { Serial.print(" dont "); /* poursuit la phrase de resume */ Serial.print(nb_defaut); /* Nombre de peripheriques en defaut */ if (nb_defaut < 2)Serial.println(" peripherique en defaut."); /* affichage pour un seul */ else Serial.println(" peripheriques en defaut."); /* affichage pour plusieurs */ } else Serial.println("."); /* Termine la phrase par un point s'il n'y a pas de peripherique en defaut */ } /* Message de fin de scan */ Serial.println("\nAppuyez sur le bouton Reset de l'Arduino pour recommencer.\n"); Serial.println(); /* Saut de ligne supplémentaire */ } void loop() { /* Rien ici car tout s'execute dans le setup ! */ } ` |
N’hésitez pas à me faire part de vos retour.
N’hésitez pas non plus à diffuser ce code, il doit servir à tous.