=====TP Capteur 1: Présentation Arduino et E/S numériques et analogiques===== === Objectifs === * Prise en main de l'environnement Arduino * Syntaxe C/C++ et la maquette Arduino * Utilisation haut niveau d'une communication série asynchrone pour le débugage * Utilisation des Entrées/Sorties Numériques et Analogique * Compréhension des mécanismes d'anti-rebonds mécaniques et d'hystérésis **Le TP se déroule sous Linux mais vous pouvez tout à fait utiliser la version Windows ou OS/X d'Arduino** ==== Carte Arduino pour le TD/TP ==== Arduino est une plateforme de développement open-source qui se compose d'une carte microcontrôleur et d'un environnement de développement associé. La carte Arduino UNO se compose de : * un microcontrôleur 8-bit Atmega328p cadencé à 16Mhz (exécutant une instruction par cycle d'horloge) https://www.google.fr/url?q=https://docs.google.com/viewer%3Fa%3Dv%26pid%3Dsites%26srcid%3DZGVwaW5mb25hbmN5Lm5ldHxtaW5lc3xneDo0NjFmYzI1NTdkZDU2YmE2&sa=U&ved=0ahUKEwjolNmb5MTKAhXECBoKHVDtCD4QFggWMAA&usg=AFQjCNGxQ8y7E0qcjTBHVI0f65so7he5jg * un convertisseur USB/UART TTL * une régulation de tension 5v * un connecteur au pas de 2.54mm au standard Arduino pour la connection d'une ou plusieurs carte(s) d'extension Le schéma de cette carte est visible sur: http://arduino.cc/en/uploads/Main/Arduino_Uno_Rev3-schematic.pdf Le schéma de la carte d'extension ainsi que la numérotation des broches des connecteurs Arduino sont visibles ci dessous: {{https://bvdp.inetdoc.net/files/iut/td2_capt/schemaCom.png}} Pour plus d'informations, vous reporter à http://arduino.cc/ Il existe des cartes compatibles arduino que vous pouvez acheter pour 4 euros par exemple sur: http://www.ebay.com/itm/NEW-UNO-R3-ATmega328P-CH340-Mini-USB-Board-Compatible-Arduino-/311155383820?pt=LH_DefaultDomain_0&hash=item48724e5e0c Il existe aussi des kits tels que: https://www.dx.com/fr/p/funduino-uno-r3-lcd-1602-keypad-shield-v2-0-lcd1602-expansion-board-building-blocks-deep-blue-315276?tc=EUR&gclid=CJ_Hvd645b4CFaXHtAod-1MA4A#.VMRAaTVrpwH Il est également possible d'utiliser un outils en ligne pour développer sur arduino sans rien installer sur votre machine: https://codebender.cc/ =====Exercice 1: Prise en main de l'Arduino===== ==== Branchement de la carte Arduino ==== La carte Arduino se branche au PC via un des ports USB disponibles en façade. Le connecteur côté Arduino est de type USB-A mâle et le connecteur côté PC est de type USB-B femelle. Avant de passer à la suite, connectez la carte au PC à l'aide du câble fourni. Pour votre PC, le branchement d'une carte Arduino est vu comme l'ajout d'un port de communication série par lequel vous allez pouvoir envoyer et recevoir des caractères ASCII à l'aide d'une application Console Texte (intégrée à Arduino) **La carte Arduino n'étant pas protégée, il est préférable de vérifier que la table de TP est libre de tout objet métallique afin d'éviter les court-circuits !** ==== Prise de main de l'outil Arduino IDE ==== Le système d'exploitation utilisé lors des TP de bus de communication est Debian (basé Linux). Sous Linux le lancement des utilitaires peut se faire de deux manières: * Utilisation d'un raccourci sur le bureau * Lancement au travers de la ligne de commande Pour lancer l'application Arduino au travers de la ligne de commande, suivez la suite d'instructions suivante : - Taper ALT+F2 puis saisir xterm et touche entrée - Dans le terminal, taper le nom de l'application (arduino) suffixé par & {{https://bvdp.inetdoc.net/files/iut/td1_capt/arduino_launch.png}} - Attendre le chargement de l'application, une fois l'application chargée, vous devriez avoir la vue suivante {{https://bvdp.inetdoc.net/files/iut/td1_capt/arduino_launched.png}} ==== Configuration de l'IDE ==== Dans l'onglet "Outils", accédez au menu "Port Série" et cliquez sur la valeur /dev/ttyACM0 ou /dev/ttyUSB0. Accédez aussi eu menu "Carte" et vérifiez que la valeur sélectionnée est "Arduino Uno". ==== Votre premier sketch ==== Maintenant que l'editeur est lancé, nous pouvons entrer (en copiant/collant) dans la fenêtre le programme suivant: int led = 3; //numéro de la broche Arduino pilotant la LED sur le shield PERIPH // the setup routine runs once when you press reset: void setup() { // initialize the digital pin as an output. pinMode(led, OUTPUT); } // the loop routine runs over and over again forever: void loop() { digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second Cette ligne n'a rien à faire ici, elle provoque une erreur de compilation, il faut donc l'effacer digitalWrite(led, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } Consultation des documentations: https://www.arduino.cc/reference/en/ ==== Compilation du sketch ==== Copier coller le contenu dans votre fichier et cliquez sur le bouton "Vérifier" pour le compiler. {{https://bvdp.inetdoc.net/files/iut/td1_capt/arduino_blink_verify.png}} Les erreurs de compilation apparaissent en rouge (et en anglais) dans la fenêtre de compilation en bas de l'IDE. Corriger le programme pour qu'il puisse être compilé. ==== Chargement sur la platine Arduino ==== Une fois que la compilation ne génère plus d'erreurs, chargez le fichier sur la carte Arduino (préalablement connectée sur le port USB) en cliquant sur le bouton "Téléverser" {{https://bvdp.inetdoc.net/files/iut/td1_capt/arduino_blink_load.png}} A partir de ce point, si votre code est correct, la LED doit clignoter. ==== Précautions à prendre avec la plateforme et l'IDE ==== * Sauvegarder vos programmes sous des noms différents pour chaque exercice * Lors de la sauvegarde, une fenêtre apparaît pour demander quels noms donner au programme. Si vous ne faites pas attention, cette fenêtre peut passer en arrière plan et l'IDE Arduino ne répondra plus à aucune sollicitation tant que vous n'aurez pas ré-ouvert cette fenêtre. * Pensez à sauvegarder votre code fréquemment à l'aide la combinaison ctrl+s * La carte Arduino étant "nue", faîtes attention à ne pas provoquer de court-circuit en manipulant des objets métalliques * Le carte étant posé sur la table et le cable étant branché sous la table, faites attention à ne pas accidentellement tirer sur le câble. =====Exercice 2: Communication avec la carte Arduino ===== Nous allons utiliser la librairie Serial pour échanger des caractères ASCII entre le PC et la carte Arduino de manière bidirectionnelle. Vous pouvez accéder au descriptif de cette librairie en sélectionnant le menu "Aide" puis le menu "Référence". L'utilisation de ce lien de communication va notamment permettre de deboguer votre programme en affichant par exemple la valeur de certaines variable. Le debogage de votre application pourra se faire à l'aide d'affichage vers la console MAIS il faut tenir compte du fait que le code ainsi modifié ne sera pas exactement le même code que celui sans les appels d'affichage. Egalement, vous pourrez utiliser des broches du microcontroleur pour indiquer l'entrée ou la sortie d'une portion de code, afin de tester précisément le temps nécessaire à son exécution. ==== Utilisation de la librairie Serial ==== **Repérer sur le schéma électrique de la carte les broches réservées pour la communication série. Ces brôches ne devront pas être utilisées pour une autre fonction!** L'application à programmer implémente le comportement suivant : - Configurer l'UART pour une communication 8N1 à 9600Bauds (Serial.begin) - Attendre que un caractère soit disponible sur le périphérique UART (Serial.available) - Lire le caractère (Serial.read) - Si le caractère est une minuscule, le convertir en majuscule (?) - Envoyer le caractère sur la liaison série (Serial.write) Pour des formats de trames autres que 8N1, vous trouverez les valeurs de paramètres adaptés à la méthode Serial.begin à l'adresse: http://arduino.cc/en/Serial/Begin void setup() { Serial.begin(9600); Serial.println("Hello, world?"); // Envoi de la chaîne terminée par un saut de ligne } void loop() { char car ; if (Serial.available()>0){ car = Serial.read(); if ( (car>='a') && (car<='z') ) car=car+'A'-'a'; Serial.write(car); } } {{https://bvdp.inetdoc.net/files/iut/tp_tns/TODO.jpg}} Compiler et charger ce programme sur la carte. ==== Utilisation de la console série sur le PC ==== L'IDE arduino dispose d'une console série permettant de visualiser les caractères envoyés par l'Arduino sur son port périphérique matériel. Pour accéder à la console série, il suffit de cliquer sur la loupe en haut à droite de l'éditeur de code. {{https://bvdp.inetdoc.net/files/iut/td1_capt/arduino_terminal.png}} Une console série apparaîtra alors sous la forme suivante: {{https://bvdp.inetdoc.net/files/iut/td1_capt/arduino_terminal2.png}} Il suffit alors de configurer le baudrate de la communication à l'aide la liste déroulante en bas à gauche (le régler à 9600 pour être cohérent avec le programme chargé dans l'Arduino). Pour envoyer des caractères à l'application, il suffit de les rentrer dans la zone de texte en haut de de la fenêtre, puis de cliquer sur "Envoyer". {{https://bvdp.inetdoc.net/files/iut/td1_capt/arduino_terminal_send.png}} Les caractères émis par l'UART HARD du Arduino doivent ensuite s'afficher dans la partie basse de la fenêtre. {{https://bvdp.inetdoc.net/files/iut/tp_tns/TODO.jpg}} Vérifier la communication avec la carte Arduino en utilisant le programme chargé précédemment. =====Exercice 3: Prise en main des Entrées/Sorties numériques de la carte d'extension===== Dans l'exercice 1, vous avez utilisé une sortie numérique de l'Arduino pour piloter une LED. Dans cet exercice, vous allez devoir utiliser des E/S numériques cablées sur des composants périphériques. La carte visible sur la figure suivante (ignorez les commentaires) comporte notamment 8 interrupteurs ainsi qu'un barregraphe de 8 LEDs que nous allons utiliser ici. {{https://bvdp.inetdoc.net/files/iut/td2_capt//CARTECOM.png}} Copier le squelette de programme ci dessous et s'en servir de base pour faire l'exercice. #include #define SLAVE_ADDR_8574_A (0x38+6) #define SLAVE_ADDR_8574_B (0x38+7) ////////////////////////////////////////// unsigned char LirePortB() { Wire.requestFrom((byte)SLAVE_ADDR_8574_B, (byte)1);// demande la lecture d'1 octet depuis l'adresse du pérpiphérique if (Wire.available()==1) //si l'octet est disponible return Wire.read(); // lire l'octet else return 0; } ////////////////////////////////////////// void EcrirePortA(unsigned char valeur) //cette fonction pilote les 8 leds avec la valeur 8bits fournie dans le paramètre valeur { Wire.beginTransmission((byte)SLAVE_ADDR_8574_A);//démarre la transmission avec l'adresse du pérpiphérique Wire.write(~(byte)valeur); //envoie la donnée complémentée car les LEDs s'allument à l'état 0 Wire.endTransmission(); } ////////////////////////////////////////// int sensorPin = A0; // numéro de la broche analogique à utiliser int sensorValue = 0; // variable pour stocker la valeur lue depuis la capteur ////////////////////////////////////////// void setup() { Serial.begin(9600); Serial.println("reset"); Wire.begin(); delay(100); Wire.beginTransmission((byte)SLAVE_ADDR_8574_B);Wire.write((byte)0xff);Wire.endTransmission();//configure le composant B en entrée pinMode(3,OUTPUT); } ////////////////////////////////////////// void loop() { //à compléter ici } Vous avez accès à l'état des 8 interrupteurs à l'aide de la fonction **unsigned char LirePortB()** qui retourne une valeur binaire sur 8 bits, l'interrupteur i pilotant le bit numéro i. Vous pouvez piloter les 8 LED à l'aide de la fonction **void EcrirePortA(unsigned char valeur)** qui prend en paramètre d'entrée la valeur 8 bits avec laquelle piloter les LED, le bit numéro i pilotant la LED i. La fonction **setup()** est déjà fournie complète. Vous devrez par contre compléter la fonction **void loop()** pour répondre aux questions suivantes: {{https://bvdp.inetdoc.net/files/iut/tp_tns/TODO.jpg}} Effectuer la recopie du port d'entrée sur le port de sortie. Vous devriez alors être capable de piloter les LED à l'aide des interrupteurs. {{https://bvdp.inetdoc.net/files/iut/tp_tns/TODO.jpg}} Compléter votre programme pour afficher sur la console à l'aide de la fonction **Serial.println(...)** la valeur lue sur le port d'entrée. Régler les interrupteurs dans des positions variées et vérifier que vous arrivez à interpréter correctement la valeur affichée sur les LED et sur la console. {{https://bvdp.inetdoc.net/files/iut/tp_tns/TODO.jpg}} Modifier votre programme pour n'allumer qu'une seule LED, dont le numéro doit être piloté par les bits 0 à 2 (uniquement) du port d'entrée. Pour cela vous utiliserez les opérateurs de décalage binaire (**<<** et **>>**) ainsi que les opérateurs logiques (**&**, **|** etc...). Il est conseillé d'utiliser une variable de type **unsigned char** pour stocker la valeur lue sur le port d'entrée et effectuer les différentes opérations nécessaires. Vous pourrez également utiliser **Serial.print(...,DEC)** ou **Serial.print(...,HEX)** pour afficher la valeur de cette variable respectivement en décimal ou en hexadécimal et vous aider à comprendre. Expliquer la valeur numérique permettant le pilotage du port de sortie en fonction de la valeur lue sur le port d'entrée à l'aide d'opérations mathématiques usuelles. Solution: void loop() { //à compléter ici unsigned char val=LirePortB(); Serial.print(val); Serial.print(" "); val= 1<<(val&7); Serial.println( val); EcrirePortA(val); } {{https://bvdp.inetdoc.net/files/iut/tp_pic/validation.png}} Faire valider vos réponses à l'enseignant. =====Exercice 4: Mise en place d'un anti-rebonds mécaniques===== Dans cet exercice, nous allons illustrer la notion de rebonds mécaniques sur des capteurs tout-ou-rien (TOR) de type interrupteur, mais plus généralement tout capteur impliquant un contact électrique entre deux lames, par exemple un interrupteur reed piloté par un champ magnétique: https://fr.wikipedia.org/wiki/Interrupteur_reed . Lors d'une commutation (changement de position), un tel capteur fournit une sortie faisant apparaître plusieurs commutations rapprochées dans le temps. Si l'on souhaite comptabiliser le nombre de fois qu'un interrupteur est commuté, ces commutations parasites (appelées rebonds) posent problème et il faut donc s'en prémunir à l'aide de la fonction d'anti-rebonds mécaniques. Cette fonction peut être réalisée de différentes manières: * analogiquement par exemple à l'aide d'un circuit de temporisation réglé à l'aide de composants RC. * numériquement par exemple à l'aide d'un micro-contrôleur tel que l'Arduino et d'un programme adapté. Un exemple de composant analogique permettant cette fonction est le célèbre NE555: https://fr.wikipedia.org/wiki/NE555#Fonctionnement_monostable La fonction d'anti-rebonds mécaniques peut être localisée: * au niveau du capteur, celui-ci fournira alors une sortie filtrée, exempte de fronts parasites. * au niveau du dispositif auquel le capteur est connecté. Ainsi, alors que la commutation d'un interrupteur de l'état haut à l'état bas devrait générer un chronogramme tel: {{https://bvdp.inetdoc.net/files/iut/tp_lpro_capteur/rebond4.png}} On observe plutot en pratique: {{https://bvdp.inetdoc.net/files/iut/tp_lpro_capteur/rebond1.png}} {{https://bvdp.inetdoc.net/files/iut/tp_lpro_capteur/rebond2.png}} Pour cet exercice, nous ne pouvons pas utiliser les interrupteurs du port d'entrée de la carte PERIPH, car ils sont connectés à un circuit d'interface trop lent. Nous allons donc plutôt utiliser une broche de l'Arduino configurée en entrée. L'état de la broche **pin** est habituellement obtenu dans le programme en appelant la fonction **digitalRead(pin)** qui renvoie **HIGH** ou **LOW**. Nous avons remplacée cette fonction ici par un accès direct au registre pour accélérer la lecture de l'état de la broche et rendre évident le phénomène. {{https://bvdp.inetdoc.net/files/iut/tp_tns/TODO.jpg}} Lire ce programme et le charger sur la carte arduino puis ouvrir la console série pour afficher le nombre de fronts descendants détectés. Connecter au broches **Ground** et **2** de l'Arduino différents capteurs/câbles/générateurs de fronts fournis par l'enseignant et observer l'évolution du compteur. Faire le lien avec les chronogrammes montrés précédemment. int ledPin = 3; // LED connected to digital pin 3 int inPin = 2; // pushbutton connected to digital pin 2 int val = 0; // variable to store the read value int val_ancien = 0; // variable to store the read value void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); // sets the digital pin 13 as output pinMode(inPin, INPUT_PULLUP); // sets the digital pin 7 as input with internal PULL UP val_ancien=digitalRead(inPin); // read the input pin } int compteur_front_descendant=0; void loop() { //le code suivant sert à afficher la valeur de compteur_front_descendant tout les 10000 exécutions de loop static int cpt_loop=0; cpt_loop++; if ( (cpt_loop%10000)==0) Serial.println(compteur_front_descendant); //digitalRead pour lire l'état de la broche est lent, on le remplace par une lecture directe du registre // val = digitalRead(inPin); // read the input pin val= (PIND>>2)&1; //compteur_front_descendant est incrémenté si un front descendant est détecté if ((val==LOW) && (val_ancien==HIGH)) { compteur_front_descendant++; } val_ancien=val; } {{https://bvdp.inetdoc.net/files/iut/tp_tns/TODO.jpg}} Proposer une solution pour ne comptabiliser qu'un front à chaque commutation réelle du capteur et modifier le programme en conséquence. solution soit en ajoutant un delay (bloquant) ou mieux en horodatant la détection de front et en interdisant des détections pendant une certaine durée (non bloquant) par exemple: if ((val==LOW) && (val_ancien==HIGH)) { compteur_front_descendant++; delay(50); } ou #define TEMPSMINENTREDEUXFRONTSMS 100 unsigned long date_front=0; //compteur_front_descendant est incrémenté si un front descendant est détecté if ((val==LOW) && (val_ancien==HIGH)) { if (millis()-date_front >= TEMPSMINENTREDEUXFRONTSMS) { compteur_front_descendant++; date_front=millis(); } } Programme pour générer un nombre aléatoire de fronts chaque seconde sur broche 4: #define BUTTON_IN_PIN 3 #define BUTTON_OUT_PIN 4 ////////////////////////////////// void genereRebonds() { #define NBREBONDSMAX 10 #define DELAYMIN 150 #define DELAYRAND 400 for (int i=0;i<(rand()%NBREBONDSMAX);i++){ digitalWrite(BUTTON_OUT_PIN, LOW); delayMicroseconds(DELAYMIN+rand()%DELAYRAND); digitalWrite(BUTTON_OUT_PIN, HIGH); delayMicroseconds(DELAYMIN+rand()%DELAYRAND); } //après les rebonds, faire l'état bas pendant assez longtemps pour qu'il soit détecté digitalWrite(BUTTON_OUT_PIN, LOW); delay(500); digitalWrite(BUTTON_OUT_PIN, HIGH); delay(500); } ////////////////////////////////// char previous; bool detecteFrontDescendant() { bool ret=false; char current=digitalRead(BUTTON_IN_PIN); if ( (previous==1) && (current==0) ) ret=true; delay(4); previous=current; return ret; } ////////////////////////////////// void setup() { // put your setup code here, to run once: randomSeed(analogRead(0)); pinMode(BUTTON_IN_PIN, INPUT_PULLUP); //pull up pour bouton pinMode(BUTTON_OUT_PIN, OUTPUT); digitalWrite(BUTTON_OUT_PIN, HIGH); previous=digitalRead(BUTTON_IN_PIN); Serial.begin ( 115200 ); delay(100); Serial.println ( "Serial Configuration Completed" ); Serial.println( "Compiled: " __DATE__ ", " __TIME__ ", " __VERSION__); } ////////////////////////////////// void loop() { // put your main code here, to run repeatedly: //if (detecteFrontDescendant()) //commenter cette ligne pour générer automatiquement 1 appui à peu près chaque seconde { genereRebonds(); Serial.println("genereRebonds()"); } } {{https://bvdp.inetdoc.net/files/iut/tp_pic/validation.png}} Faire valider vos réponses à l'enseignant. =====Exercice 5: Utilisation du convertisseur analogique numérique (ADC)===== Nous abordons maintenant un composant très important permettant à un système numérique tel le microcontroleur Arduino d'acquérir des informations analogique, c'est à dire pouvant varier de manière continue entre plusieurs valeurs, au contraire des informations "tout ou rien". Ce composant est le convertisseur analogique numérique (appelé Analog to Digital Converter en anglais). L'environnement Arduino propose la fonction **unsigned int analogRead(pin)** qui permet d'obtenir la valeur numérique issue de la conversion analogique vers numérique de la tension présente sur la broche **pin**. Dans le cas de la carte UNO, elle retourne un nombre sur 10 bits puisque les convertisseurs sont des convertisseurs 10 bits. Cela veut dire qu’ils sont capables de retourner une valeur entre 0 et 1023, valeur représentant une tension entre 0 et 5V. Seules les entrées nommées **A0** à **A5** peuvent être utilisée pour des signaux analogiques. {{https://bvdp.inetdoc.net/files/iut/tp_tns/TODO.jpg}} Connecter un potentiomètre en montage diviseur de tension entre les broches **5V** (fil rouge) et **Ground** (fil noir) de l'Arduino et le point milieu doit être connecté à la broche **A0** (fil vert). Demander conseil à l'enseignant en cas de doute. Compléter le programme suivant afin que la fonction **loop()** effectue la conversion analogique vers numérique de la tension fournie par le potentiomètre sur la broche **A0**. Cette valeur, appelée échantillon, doit être stockée dans une variable de type **unsigned int** dont la valeur doit être affichée sur la console en décimal à l'aide de la fonction **Serial.println()**. #include #define SLAVE_ADDR_8574_A 0x3e #define SLAVE_ADDR_8574_B 0x3f ////////////////////////////////////////// unsigned char LirePortB() { Wire.requestFrom((byte)SLAVE_ADDR_8574_B, (byte)1);// demande la lecture d'1 octet depuis l'adresse du pérpiphérique if (Wire.available()==1) //si l'octet est disponible return Wire.read(); // lire l'octet else return 0; } ////////////////////////////////////////// void EcrirePortA(unsigned char valeur) //cette fonction pilote les 8 leds avec la valeur 8bits fournie dans le paramètre valeur { Wire.beginTransmission((byte)SLAVE_ADDR_8574_A);//démarre la transmission avec l'adresse du pérpiphérique Wire.write(~(byte)valeur); //envoie la donnée complémentée car les LEDs s'allument à l'état 0 Wire.endTransmission(); } ////////////////////////////////////////// int sensorPin = A0; // numéro de la broche analogique à utiliser int sensorValue = 0; // variable pour stocker la valeur lue depuis la capteur ////////////////////////////////////////// void setup() { Serial.begin(9600); Serial.println("reset"); Wire.begin(); delay(100); Wire.beginTransmission((byte)SLAVE_ADDR_8574_B); Wire.write((byte)0xff); Wire.endTransmission();//configure le composant B en entrée pinMode(3,OUTPUT); } ////////////////////////////////////////// void loop() { // à compléter } Solution: sensorValue = analogRead(sensorPin); //lecture de l'entrée analogique Serial.println(sensorValue ); //affichage de la donnée {{https://bvdp.inetdoc.net/files/iut/tp_tns/TODO.jpg}} Lancer l'outils de visualisation de courbes d'arduino (via Outils->Traceur série), et visualiser le signal issus du potentiomètre en fonction du temps. Afin d'éviter un zoom automatique de l'application Traceur série, modifier votre programme pour que sur la ligne envoyée via la liaison série soit au format: 0 1023 valeur_lue {{https://bvdp.inetdoc.net/files/iut/tp_tns/TODO.jpg}} Compléter le programme pour que la valeur de l'échantillon permette de piloter de manière proportionnelle une unique LED du barregraphe, en utilisant la LED 0 pour une valeur d'échantillon de 0 et la LED 7 pour une valeur d'échantillon de 1023. Solution: //EcrirePortA( sensorValue>>2); //affichage en binaire sur 8 bits EcrirePortA( (1<<(int)((sensorValue*7./1023.)))); //affichage 1 bit à une position parmi 8 {{https://bvdp.inetdoc.net/files/iut/tp_pic/validation.png}} Faire valider vos réponses à l'enseignant. =====Exercice 6: Seuillage d'une valeur analogique et mise en place d'un hystérésis===== Nous allons maintenant aborder la notion de seuillage d'une grandeur analogique. Dans un capteur impliquant un dispositif analogique (par exemple une sonde de température), il est parfois souhaitable de générer une sortie "tout ou rien" dont la valeur dépend de la grandeur analogique. Ceci peut être fait en seuillant la grandeur analogique, c'est à dire en appliquant l'algorithme suivant: si grandeur_analogique Solution: unsigned int seuil=512; if ( sensorValue>seuil) digitalWrite(3,1); else digitalWrite(3,0); {{https://bvdp.inetdoc.net/files/iut/tp_tns/TODO.jpg}} Trouver une position du potentiomètre permettant de faire clignoter la LED. Au besoin ajouter la ligne suivante dans votre programme pour bruiter la valeur de l'échantillon: sensorValue+=-10+rand()%20; //ajout de bruit à la donnée lue pour rendre plus visible le phénomène Nous allons maintenant mettre en place un mécanisme de commutation à double seuil (appelé hystérésis) permettant d'éviter ces changements d'états intempestifs. Comme pour l'anti rebonds mécaniques, cette fonctionnalité peut être réalisée de plusieurs manières: * avec des composants analogiques tels que le trigger de schmitt * avec des composants numériques comme nous allons l'illustrer ici Elle peut aussi être localisée: * au niveau du capteur, celui-ci fournira alors une sortie filtrée, exempte de commutations parasites. * au niveau du dispositif auquel le capteur est connecté. Pour réaliser cet hystérésis, il est nécessaire de mettre en place une mémorisation (à l'aide d'une variable) de la plus récente commutation correspondant à l'état de la sortie. En fonction de la valeur de cette variable, l'une des deux valeurs de seuil devra être utilisée. {{https://bvdp.inetdoc.net/files/iut/tp_tns/TODO.jpg}} Modifier le programme précédent pour mettre en place un hystérésis dont les 2 seuils sont distants d’approximativement 0.1V autour de la valeur 2.5V. Solution: unsigned int ecart_seuil=20; // (20/1024)*5V = 0.1V unsigned int seuil_haut=512+ecart_seuil/2; unsigned int seuil_bas=512-ecart_seuil/2; static unsigned int etat=0; if ( (etat==0) && ( sensorValue>seuil_haut)) etat=1; if ( (etat==1) && ( sensorValue {{https://bvdp.inetdoc.net/files/iut/tp_pic/validation.png}} Faire valider vos réponses à l'enseignant.