Mémo Arduino

Michel Llibre - Janvier 2023

Table des matières

1 Attention

2 Branchement

3 L'IDE

4 Premier Programme

5 Les types communs

5.1 Fonction F() sur string

6 Les 2 routines systèmes

7 Liaison série

7.1 La liaison série/USB

7.2 Écriture sur une liaison série

7.3 Lecture sur une liaison série

7.4 Liasons séries logicielles : SoftwareSerial

8 La gestion du temps

8.1 Temps écoulé

8.2 Pause

8.3 Les timers

8.3.1 Les valeurs des compteurs TCNTx

8.3.2 Le Prescaler : CLKPR

8.3.3 Les prédiviseurs : TCCRxB

8.3.4 Mode de comptage : bits WGMxy des registres TCCRxB

8.3.5 Les registres drapeaux TIFRx

8.3.6 Les masques d'interruption TIMSKx

8.3.7 Les registres de comparaison OCRxy

9 Les entrées/sorties numériques

9.1 Entrées numériques

9.2 Sorties numériques

9.3 Sortie pseudo-analogique PWM

9.4 Sortie tone

9.5 Conflits entre PWM et tone

10 Les entrées analogiques

11 Les interruptions

12 Ecran lcd alphanumérique LiquidCrystal

13 Ecran OLED SSD 1306

14 Keypad

14.1 Ancien soft

14.2 AdaFruit Keypad.

15 Bluetooth

15.1 Configuration interne : Commandes AT

15.1.1 Configuration interne du HC-06

15.1.2 Configuration interne du HC-05

15.2 Mode de communication bluetooth : Mode data

16 GPS

17 Centrale inertielle MPU6050

18 Convertisseur série-usb FTDI

19 Convertisseur Max232

19.1 Transmetteur/recepteur radio

20 Recepteur infra-rouge de télécommande

21 Petits composants

21.1 Bouton poussoir

21.2 Leds

21.3 Capteur de température TMP36

21.4 Interrupteur d'inclinaison

21.5 Buzzer

21.5.1 Montage en mode émetteur vibrations

21.5.2 Montage en mode capteur vibrations

21.6 Codeurs numériques rotatifs

21.7 Servo-moteurs

21.8 Moteur à courant continu et MOFSET

21.9 Moteur à courant continu et pont en H

21.10 Transistor

22 Annexe

22.1 Resets logiciels

22.1.1 Méthode brute

22.1.2 Méthode du Watchdog

22.1.3 Utilisation de la broche "Reset"

22.2 Routines utilitaires

22.2.1 Générateur aléatoire

22.2.2 Quatrième proportionnelle

23 Les différentes cartes

23.1 Connaitre la carte dans le code :

23.2 Arduino Uno

23.3 Arduino Mega

23.4 Arduino Nano

23.5 Aduino Due

24 Différents types de mémoire

24.1 La RAM

24.2 L’EEPROM

24.3 La mémoire FLASH

 

1 Attention

Le compilateur C/C++ de l'IDE Arduino n'est pas parfait. Certaines fonctions standard genre sprintf(), scanf() ne sont pas complètement bien implantées et sont à tester lors de l'utilisation. Il en est de même du switch. Les éléments d'un case doivent être mis entre { } si on ne veut pas avoir de surprise (les "case" qui suivent le premier sont parfois ignorés !).

2 Branchement

En fonctionnement autonome, l'Arduino est alimenté par son jack d'alimentation en 9V. La tension peut varier de 7 à 12V.

En mode programmation, il est alimenté par le port USB qui le relie au PC.

3 L'IDE

Télécharger l'IDE (92.6 Mo) sur www.arduino.org et l'installer.

Les applications ou projets Arduino sont appelés sketch dans la version anglaise ce qui est traduit par croquis (!!) dans la version française.

Le menu fichier/New permet de démarrer un nouveau projet avec un nom par défaut du genre sketch_moisjj que l'on changera lors de sa sauvegarde.

Sauvegarde d'un fichier : Menu Fichier/Enregistrer ou CTRL+S. Avec la boite de dialogue, sélectionner un répertoire et donner un nom au fichier, par exemple toto. L'IDE crée, dans le répertoire sélectionné, un sous-répertoire nommé toto et dans ce répertoire il crée le fichier toto.ino.

Le contenu minimal du fichier initial est constitué des 2 lignes suivantes :

void setup() {}

void loop() {}

Ce programme est exécutable. L'Arduino ne fera rien.

Pour vérifier la validité d'un programme : menu Sketch/Verify-Compile ou CTRL+R ou clic sur bouton V.

Pour charger un programme dans la carte Arduino :

Le menu Tools/Serial Monitor ouvre une fenêtre dans laquelle l'Arduino peut écrire via la liaison USB (émulation port série COMx).

Plusieurs IDE peuvent tourner en parallèle sur le pc. Ils partagent la fenêtre Serial Monitor. Quand avec un IDE on charge le projet en cours de cet IDE dans l'Arduino, il remplace le programme qui était en cours d'exécution. Ainsi pour arrêter un programme, il surfit d'ouvrir un autre IDE et d'envoyer le programme menu Files/Examples/01.Basics/Blink qui ne fait que faire clignoter la led interne de la carte.

Référence du langage : En local par menu Aide/Réfrence ou en ligne à : https://www.arduino.cc/en/Reference/HomePage

Libraires

L'installation a enregistré des librairies dans le répertoire C:\Users\Utilisateur\Documents\Arduino\libraries

 

Une librairie arduino "toto" est composée d'un couple de fichiers sources toto.cpp et toto.h. réunis dans un fichier *.zip que l'on importe à l'aide du gestionnaire de librairies de l'IDE. Il les placera dans le répertoire des librairies.

4 Premier Programme

int compte = 0;

// Routine d'initialisation

void setup() {

  // Initialise la liaison avec le PC pour écrire des résultats

  Serial.begin(9600); // 9600 bauds, cad bits/s en standard

 

  // L'Arduino envoi un texte au PC

  Serial.println("Bonjour Michel !");

 

  // On conditionne la led interne à la carte en sortie.

  pinMode(LED_BUILTIN, OUTPUT);

 

  // Impressions pour voir ce que valent ces 2 constantes

  int val1 = LED_BUILTIN;

  Serial.print("LED_BUILTIN = ");

  Serial.println(val1);

 

  int val2 = OUTPUT;

  Serial.print("OUTPUT = ");

  Serial.println(val2);

}

 

// La routine loop() qui recommence sans fin

void loop()

{

  Serial.print("compte = ");

  Serial.println(++compte);

  digitalWrite(LED_BUILTIN, HIGH);  // Allume la led

  delay(1000);                       // Attente une seconde

  digitalWrite(LED_BUILTIN, LOW);   // Eteint la led

  delay(1000);                       // Attente une seconde

}

 

Ouvrir la console de réception des messages qu'enverra l'Arduino au PC : menu Outils/Moniteur série, puis charger le programme dans l'Arduino par le bouton -> (téléverser). Il s'exécute dans la foulée, s'il n'y a pas d'erreur dans le programme. Voici ce qu'on doit recevoir :

 

Bonjour Michel !

LED_BUILTIN = 13

compte = 1

compte = 2

compte = 3

...

5 Les types communs

Les int Arduino ne sont que sur 16 bits :

char : -128  à  +127

byte:   0  à  +255

int:    -32768  à +32767

unsigned int: 0  à  +65535

long : -2147483648  à  +2147483647

unsigned long:  0  à  +4294967295

float et double (32 bits) : 3.e-38 à 3e+38 à environ 1,5e-7 de précision

 

Pour spécifier une constante unsigned long utiliser le postfixe UL : exemple :

const unsigned long secondesparjour = 60UL * 60 * 24;

Attention : Aussi bien sur le Uno que sur le Mega les double sont sur 4 octets seulement (comme les float). Pour avoir des double sur 8 octets, il faut une carte Arduino Due.

 

La classe String permet de concaténer des chaînes, y ajouter des chaînes, rechercher et remplacer des sous-chaînes, etc. Noter que les chaînes constantes, spécifiées entre "guillemets doubles" sont traitées comme des tableaux de caractères et non comme des instances de la classe String.

Membres : String(), charAt(), compareTo(), concat(), c_str(), endsWith(), equals(), equalsIgnoreCase(), getBytes(), indexOf(), lastIndexOf(), length(),  remove(), replace(), reserve(), setCharAt(), startsWith(), substring(), toCharArray(), toInt(), toFloat(), toLowerCase(), toUpperCase(), trim()

Operateurs : [ ], +, += , == , >, >=, <, <=, !=

 

5.1 Fonction F() sur string

Les tableaux strings littéraux (string avec un s minuscule = tableau de caractères) comme "Bonjour !" sont créés dans la RAM qui n'est que 2 Ko dans l'UNO. Si on encadre le string par F(), comme ceci  F("Bonjour !") on utilise une macro qui va déplacer ce string dans la mémoire flash qui est atteint 32 Ko pour l'UNO. Faire son choix en fonction des places disponibles.

6 Les 2 routines systèmes

La routine void setup(){…} est exécuté une seule fois au démarrage de l'application, puis la routine loop() {…} est exécutée en boucle, sans fin. Si on veut faire faire une simple séquence d'opérations à l'Arduino, il suffit de la programmer entièrement dans la fonction setup(), et elle s'exécutera une fois. A contrario, on programmera dans loop() une séquence d'opérations à répéter indéfiniment.

7 Liaison série

Les liaisons séries communiquent par 2 broches RX et TX, avec un câble croisé : le Rx d'un appareil est connecté au TX et l'autre et réciproquement. On peut programmer des broches de données numériques en TX et RX pour effectuer une liaison série logicielle quand on n'a pas assez des liaisons matérielles existantes.

Arduino Uno : 1 seule liaison matérielle (Serial) par le connecteur USB qui est lié aux broches Rx = d0, TX = d1.

Arduino Mega : 4 liaisons matérielles

Broches utilisables en RX logiciel : 10, 11, 12, 13, 50, 51, 52, 53, A8 (62), A9 ( 63), A10 (64), A11 (65), A12 (66), A13 (67), A14 (68), A15 (69).

Pour le Leonardo, seuls les éléments suivants peuvent être utilisés en RX logiciel : 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI).

7.1 La liaison série/USB

Initialisation du port série USB (dans le setup en général) :

Serial.begin(9600); // 9600 bauds, cad bits/s en standard
while (!Serial) delay(1000); // Attendre la disponibilité de la connexion USB.

Sur le Uno, la liaison USB accapare les broches RX et TX (d0 et d1) qui ne sont plus disponibles pour un autre usage.

 

L'Arduino Mega a 4 ports séries :

void setup()

{

Serial.begin(9600);

Serial1.begin(38400);

Serial2.begin(19200);

Serial3.begin(4800);

Serial.println("Hello Computer");

Serial1.println("Hello Serial 1");

Serial2.println("Hello Serial 2");

Serial3.println("Hello Serial 3");

}

 

Sur le Uno la fonction Serial.end() arrête la liaison et rend disponibles les broches RX et TX pour des E/S générales.

7.2 Écriture sur une liaison série

Serial.print("Bonjour Michel !");

Serial.print(val);

Serial.print(val, format);

Le print ne prend qu'un argument, nombre ou string. Dans le cas d'un nombre entier on peut  mettre une 2ème argument qui spécifie le format parmi les suivants : BIN, DEC, OCT ou HEX.

Dans le cas d'un nombre flottant le nombre entier spécifie le nombre de décimales.

Idem avec insertion d'un retour à la ligne :

Serial.println("Bonjour Michel!");

Serial.print et Serial.println retournent le nombre de caractères écrits.

Serial.write  : Ecriture octet par octet :

Attention :

char c = 65; byte b = 65; int i = 65;

Serial.print(c) → A, Serial.write(c) → A,

Serial.print(b) → 65, Serial.write(b) → A,

Serial.print(i) → 65, Serial.write(i) → A.

 

Serial.print et Serial.write ne sont pas bloquant. Si on désire attendre la fin d'une sortie avant de passer à la suite, on utilise Serial.flush()qui met le programme en attente pendant le vidage du buffer sortant. Attention Serial.flush()n'a aucun effet sur les entrées !!! comme ce fut peut-être le cas sur les versions préliminaires. Pour vider le tampom d'entrée il suffit de faire : while(Serial.available()) Serial.read();

 

Le menu Outils/Moniteur série ouvre une console qui reçoit les messages envoyés par l'Arduino sur le liaison et permet, dans l'autre sens d'envoyer des messages à l'Arduino.

7.3 Lecture sur une liaison série

La fonction n = Serial.available() renvoi le nombre de caractères disponibles dans le buffer de réception et -1 quand il n'y a rien à lire. Les caractères présents dans ce buffer sont lus un par un en mode FIF0 (1er entré, 1er sorti) par la fonction c = Serial.read(). Exemple :
char c;
While(Serial.avalable() > 0) { c = Serial.read(); ... }

Plutôt que de boucler pour tester Serial.available() pour réceptionner les caractères, on peut utiliser une routine evènementielle qui est lancée avant chaque début de la routine loop() {..}, c'est la routine serialEvent(){..}.  Exemple :
void serialEvent()

{

int c;

  while((c = Serial.read()) != -1) { ... }

}

 

Pour vider le buffer de réception avant un autre read : while (Serial.read() ≥ 0);

Il existe des fonctions spécialisées pour la lecture des nombres, string et chaines :

int i = Serial.parsInt();  

float f = Serial.parseFloat();

Serial.readBytes(buffer, length);

Serial.readBytesUntil(character, buffer, length);

String s1 = Serial.readString();

qui lisent jusqu'au return ou au timeout qui est fixé par :

Serial.setTimeout(time_ms)

Attention :

Sur Arduino la fonction sscanf ne sait pas lire les flottants. Utiliser atof(). De même sprintf ne sait pas écrire les flottants. Utiliser dtostrf().

dtostrf (f, 10, 4, buf);  // number, width, decimal places, buffer

7.4 Liasons séries logicielles : SoftwareSerial

La librairie SoftwareSerial (#include <SoftwareSerial.h>) permet de configurer une paire de broches en broches RX/TX d'une liaison série, définie par le constructeur SoftwareSerial(Rx, Tx). Par exemple, si on utilise la broche d2 en Rx  (réception) et la broche d3 en Tx (transmission), on initialisera une liaison nommée ss (par exemple) par :

SoftwareSerial ss(2, 3);

placé avant le Setup(); Un troisième argument booleen (false par défaut) permet d'inverser les niveaux logiques sur les lignes (le haut devient 0 et le bas devient 1).

puis on l'initialisera dans le Setup(), par :

ss.begin(9600); // par exemple,

puis on communiquera sur cette liaison par ss.available(), ss.read(), ss.print()... tout comme sur la liaison Serial.

Si on utilise plusieurs liaisons série logicielles, une seule peut recevoir des données à la fois. C'est la liaison active. A l'origine c'est celle dont le begin() a été appelé le plus récemment. On rend la liaison xyz active en appelant sa méthode xyz.listen().

Lorsqu'on renvoie automatiquement une réponse sur une même ligne après réception d'un message, il faut laisser un petit délai avant de répondre sinon, ça ne marche pas très bien.

 

8 La gestion du temps

8.1 Temps écoulé

Le temps écoulé en millisecondes depuis le démarrage s'obtient par nbms = millis(); Cette fonction utilise un des timers de la carte : le timer0.

Il y a aussi l'instructions nmus = micros(); qui renvoi le même temps en microsecondes.

8.2 Pause

Une pause avant l'exécution de l'instruction suivante est obtenue par la fonction delay(n)n est en millisecondes.

8.3 Les timers

Voir : https://passionelectronique.fr/introduction-timer-arduino/

Les timers sont des registres du microprocesseur qui s’incrémente en fonction des impulsions d’horloge ou d’impulsions extérieures. Il est possible de les configurer pour modifier leur comportement. Le microprocesseur de l’Arduino UNO (ATmega328P) possède 3 timers:

  1. 1.timer0 (8 bits) compte de 0 à 255 et commande la PWM des broches 5 et 6. Il est aussi utilisé par les fonctions delay(), millis() et micros(). 

  2. 2. timer1 (16 bits) compte de 0 à 65535 et est utilisé pour la commande PWM des broches 9 et 10. Il est utilisé également par la libriaire Servo.h 

  3. 3.timer2 (8 bits) compte de 0 à 255. Il est utilisé par la fonction Tone() et la génération de la PWM sur les broches 3 et 11 du Uno. 

Le Mega en possède 8. Tous ces timers sont alimentés par l'horloge du microprocesseur qui tourne, de base à 16 Mhz.

8.3.1 Les valeurs des compteurs  TCNTx

On peut lire ou forcer le contenu des compteurs avec les variables TCNT0, TCNT1 et TCNT2. On peut également accéder aux poids forts et faibles de TCNT1 avec TCNT1H et TCNT1L.

8.3.2 Le Prescaler :  CLKPR

On peut à tout moment diviser la fréquence de base à l'aide du registre prescaler CLKPR (clock PRescaler), en founissant la valeur de division dans ses 4 bits de poids faible (CLKPS0 à CLKPS3), division par 1 à 256..

Pour modifier ce diviseur, il faut désactiver les interruptions, puis tout d’abord mettre à 1 le bit CLKPCE et tous les autres bits à 0 (en envoyant par exemple le nombre 0b10000000 dans le registre CLKPR) et ensuite, dans un délai maximal de 4 cycles d’horloge, de mettre à 0 le bit CLKPE, tout en spécifiant dans les 4 derniers bits le rapport de division de fréquence souhaitée (pour cela, il suffira donc d’envoyer le nombre 0b0000xxxx dans le registre CLKPR, en remplaçant xxxx par des valeurs 1 ou 0, selon le rapport de division que vous voulez, comme visible dans le tableau ci-dessus), puis réactiver les interruptions. Exemple :

cli();

CLKPR = 0b1000 0000;  // on souhaite changer de rapport de fréquence

CLKPR = 0b0000 0101;  // rapport voulu (ici 0101 => division par 32)

sei();

Remarque : Il vaut mieux ne pas toucher à cette fréquence car cela peut impacter le baudrate de la liaison série, etc...

8.3.3 Les prédiviseurs : TCCRxB

Chaque timer a en plus son propre prédiviseur. Le facteur de division est à indiquer dans les 3 bits de poids faible des registres TCCRxB avec x= 0,1 ou 2 pour le Uno (jusqu'à 8 pour le Mega).


On peut soit positionner d'un seul coup tous les bits d'un registre comme dans :

CLKPR = 0b1000 0000;

ou bien positionner bit par bit, comme par Exemple pour mettre CS10 à 1 dans le registre TCCR1B :

Solution 1 : bitSet(TCCR1B, CS10);

Solution 2 : TCCR1B |= (1<<CS10);

ou pour mettre CS12 à 0 dans le registre TCCR1B :

Solution 1 : bitClear(TCCR1B, CS12);

Solution 2 : TCCR1B &= ~(1<<CS12);

 

8.3.4 Mode de comptage : bits  WGMxy des registres TCCRxB

Nous avons déja vu l'utilisation des 3 bits de poids faible des registres TCCR0B, TCCR1B et TCCR2B pour fixer la valeur des prédiviseurs.

Les bits WGMxz permettent de définir le mode de comptage des timers :

WGM00, WGM01 dans TCCR0A et WGM02 dans  TCCR0B

WGM10, WGM11 dans TCCR1A,  et WGM12, WGM13 dans  TCCR1B

WGM20, WGM21 dans TCCR2A et WGM22 dans  TCCR2B

Pour le timer 1 :

8.3.5 Les registres drapeaux TIFRx

Leurs bits alertent sur le fait qu'un débordement est atteint (valeur max ) ou qu'une valeur de comparaison est atteinte. L'overflow est indiqué par le bit b0 : TOVx (x = 0, 1, 2) et l'égalité est indiquée par les bits b1 et b2 OCFxy

Attention : Si un drapeau est levé (valeur 1) pour le baisser il faut envoyer 1 à ce bit pour qu'il repasse à 0.

8.3.6 Les masques d'interruption TIMSKx

Chacun de ces registres contient des bits, qui, s’ils sont mis à 1, définissent dans quelle condition une interruption est déclenchée :

8.3.7 Les registres de comparaison OCRxy

Ils permettent de stocker des valeurs qui serviront à effectuer des tests d’égalité avec la valeur courant des timer. Ces valeurs sont stockées dans les registres suivants :

OCR0A et OCR0B, pour le masque d’interruption TIMSK0 (timer0 donc)

OCR1A et OCR1B, pour le masque d’interruption TIMSK1 (timer1 donc)

OCR2A et OCR2B, pour le masque d’interruption TIMSK2 (timer2 donc)

À noter que le timer1 est sur 16 bits au lieu de 8. Du coup, les registres huit bits de comparaison sont en fait OCR1AL, OCR1AH, OCR1BL, et OCR1BH. Par contre, au niveau de votre programme arduino, on peut directement entrer un nombre de 16 bits dans la variable OCR1x du code arduino, et le compilateur se chargera de répartir ces valeurs dans les deux registres 8 bits correspondants !

 

Exemple de configuration du timer2 :

   cli();                                                   // disable interrupts

   TCCR2A = (1<<WGM21)|(0<<WGM20);                 // Mode CTC

   TIMSK2 = (1<<OCIE2A);                                 // Local interruption OCIE2A

   TCCR2B = (0<<WGM22)|(1<<CS22)|(1<<CS21);         // Frequence 16Mhz/ 256 = 62500

   OCR2A = 250;                                               //250*125 = 31250 = 16Mhz/256/2

   sei();                                                     // enable interrupts

 

9 Les entrées/sorties numériques

Elles sont réalisées via le connecteur DIGITAL (PWM~) équipé des broches  0, 1, 2, ~3, 4, ~5, ~6, 7, 8, ~9, ~10, ~11, 12, 13, GND, AREF.

Comme les broches 0 à 13 fonctionnent dans les deux sens, ce denier doit être choisi avant l'utilisation de la broche.

Configuration de la broche d'E/S digitale numéro n, en entrée ou en sortie:

Constantes prédéfinies :

OUTPUT : Pour configurer l'E/S numérique en mode sortie (1 dans le cas de l'UNO).

INPUT : Pour configurer l'E/S numérique en mode entrée (0 dans le cas de l'UNO)

INPUT_PULLUP : Pour configurer l'E/S numérique en mode entrée avec une résistance de tirage interné reliée à l'alimentation (2 dans le cas de l'UNO).

LED_BUILTIN : Numéro de l'E/S numérique connectée à la LED interne (13 sur la plupart des cartes dont l'UNO).

9.1 Entrées numériques

La lecture d'un niveau sur une broche configurée en entrée se fait par digitalRead(n); ou n est le numéro de la broche lue. Cette fonction retourne les valeurs LOW ou HIGH.

En mode entrée pull_up une résistance interne de valeur comprise entre 20 et 50 k relie la patte au +5 V, ce qui fait qu'on peut la relier à un interrupteur poussoir dont l'autre patte est relié au 0V. A la lecture digitalRead(n); LOW correspond au circuit fermé (consommation environ 0.15 mA) et HIGH au circuit ouvert (consommation négligeable).

En mode entrée standard, pour détecter l'état d'un poussoir, on relie l'autre patte du poussoir au 5 V et on ajoute une résistance dite pull-down d'environ 5 à 10 kentre la patte d'E/S reliée au poussoir et le 0 V. Quand le poussoir est fermé on lit HIGH (consommation environ 0.7 mA) et quand il est ouvert on lit LOW ( consommation négligeable).

L'entrée pull_up est donc préférable.

Constantes prédéfinies :

LOW : (0 dans le cas de l'UNO)

en entrée : tension < 1.0 (carte 3.3V) ou < 1.5V (carte 5V) lue par digitalRead().

en sortie : tension = 0V.

HIGH : (1 dans le cas de l'UNO)

en entrée : tension > 2.0 (carte 3.3V) ou > 3.0V (carte 5V) lue par digitalRead().

en sortie : tension = 3.3 (carte 3.3V) ou = 5V (carte 5V)

9.2 Sorties numériques

Elles se font sur les broches d'E/S préalablement configurées en OUTPUT par les fonctions :

digitalWrite(pin, LOW);

ou

digitalWrite(pin, HIGH);

 

9.3 Sortie pseudo-analogique PWM

Les broches digitales du connecteur d'E/S numérique précédées d'un ~, à savoir les broches 3, 5, 6, 9, 10 et 11,  peuvent être programmées en PWM (Pulse Width Modulation) en faisant varier le rapport cyclique (duty cycle en anglais) entre les états de sortie HIGH et LOW, ce qui fournit l'équivalent d'un niveau analogique. Exemple :

analogWrite(11, val); ou val est le rapport cyclique compris entre 0 et 255. La valeur 0 fournit la tension LOW en permanence et la valeur 255 fournit la tension HIGH en continu.

La fréquence du cycle dépend du modèle d'Arduino et également des broches, mais seulement 2 fréquences sont utilisées : 490 ou 980 Hz.

Ne pas oublier de conditionner la broche en sortie : pinMode(11, OUTPUT);

On peut modifier la fréquence du cycle par programmation avec le code suivant :

// on définit une variable de type byte

// qui contiendra l'octet à donner au registre pour diviser la fréquence de la PWM

// division par : 1, 8, 64, 256, 1024

byte division_frequence=0x01;

// fréquence : 62500Hz, 7692Hz, ...

// temps de la période : 16µs, 130µs, ...

 

void setup()

{

    pinMode(6, OUTPUT); // broche de sortie

 

    // TCCR0B c'est le registre, on opère un masquage sur lui même

    TCCR0B = TCCR0B & 0b11111000 | division_frequence;

    // ce qui permet de modifier la fréquence de la PWM

}

 

void loop ()

{

    // on écrit simplement la valeur de 0 à 255 du rapport cyclique du signal

    analogWrite(6, 128);

    // qui est à la nouvelle fréquence choisit

}

TCCR0B est le nom du registre utilisé. Pour la variable division_frequence , on utilisera les valeurs hexadécimales suivantes :

0x01 // f = 62500Hz, f. max. possible (f. quartz / 256) divisée par 1

0x02 // f = 7692Hz, division par 8 de la fréquence maximale

0x03 // f = 976Hz, division par 64

0x04 // f = 244Hz, division par 256

0x05 // f = 61Hz, division par 1024

Génération d'une tension analogique à partir de la PWM

 

Avec les valeurs suivantes :

 

U=5V (ou 0 : sortie PWM

C=1000μF

Rcharge=1kΩ

Rdecharge=1kΩ

Constante de temps de charge et décharge : τ=R×C . Plus grand est  τ, meilleure est l'approximation, mais cela augment le temps d'établissement de la valeur. Si la fréquence de coupure 1/2πτ du filtre est 20 fois plus faible que la fréquence du cycle de la PWM, l'ondulation sera quasiment supprimée.

9.4 Sortie tone

Les broches digitales du connecteur d'E/S numérique  peuvent être programmées en tonalité à l'aide de la fonction : tone(pin, freq, nbms);

qui génère sur la broche pin, un signal carré  à la fréquence freq, pendant une durée nbms millisecondes. C'est en fait un signal entre LOW et HIGH de rapport cyclique 50% à la fréquence freq. Si nbms est absent, la durée est permanente jusqu'à un nouvel appel de la fonction ou jusqu'à l'appel de la fonction noTone(pin).

Les fréquences sont comprises entre 31 Hz et 65535 Hz

Remarque : si plusieurs notes sont jouées l'une après l'autre, il faut utiliser la fonction delay pour leur laisser le temps d’être exécutées :

    tone(8, 440, 1000); delay(1000);

    tone(8, 880, 2000); delay(2000);

    tone(8, 220, 1000); delay(1000);  

Pour tester cette fonction mettre une patte du buzzer à la terre et relier l'autre à la sortie numérique.

9.5 Conflits entre PWM et tone

Les librairies PWM et tone utilisent des timers pour générer les sorties, sans coordination entre elles, et comme ces timers sont en nombre limités il peut y avoir conflit, en particulier dans le cas du UNO l'utilisation de tone interfère avec analogWrite des broches 3 et 11.

10 Les entrées analogiques

Le connecteur ANALOG_IN comporte 6 entrées marquées A0, A1, … A5.

Lecture de la broche A0 : int v = analogRead(A0); tens = 5.*(v/1024.);

donne une valeur comprise entre 0 et 1023, image de la tension comprise entre 0 et 5 volts.

Remarque : Pour envoyer directement cette lecture vers une sortie pseudo-analogique (numérique en PWM), il suffit de diviser la valeur lue par 4 (pour la ramener entre 0 et 255).

Constantes prédéfinies : A0, A1, …, A5 = 14, 15, … 19 dans le cas de l'UNO.

11 Les interruptions

Seules certaines broches peuvent être utilisées pour envoyer des interruptions :

Uno, Nano, (chipset328) : d2, d3

Mega : d2, d3, d18 à d21

Due : Tous les dX

Micro, Leonardo (chipset 32u4) : d0 à d3 et d7

Zero : tous les dX sauf d4

MKR : d0, d1, d4 à d9, A1 et A2.

 

On attache une interruption par la fonction :

attachInterrupt(interrupt, callback, mode)

avec pour mode :

pour callback le nom de la fonction de rappel void callback();.

interrupt est le numéro de l'interruption donné par la fonction :

interrupt = digitalPinToInterrupt(pin);

en fonction du numero pin de la broche.

Attention, dans la callback, les fonctions delay() et millis() ne fonctionnent pas.

Les variables globales modifiées dans la callback doit être déclarée volatile (pour être sur que la modification soit effective).

 

On détache l'interruption par :

detachInterrupt(interrupt);

avec interrupt = digitalPinToInterrupt(pin);

 

12 Ecran lcd alphanumérique LiquidCrystal

L'écran LCD du starter kit Arduino à 2 lignes de 16 caractères. D'un point de vue logiciel il est régit par la bibliothèque LiquidCrystal à l'aide d'une classe LiquidCrystal dont les fonctions sont prototypées dans le fichier LiquidCrystal.h.

On doit connecter les broches suivantes du LCD :

soit 12 broches à brancher en tout et 4 (d0 à d3) facultatives.

Une instance de l'écran est créée par l'appel du constructeur :

LiquidCrystal(rs, en, d4, d5, d6, d7)

LiquidCrystal(rs, rw, en, d4, d5, d6, d7)

LiquidCrystal(rs, en, d0, d1, d2, d3, d4, d5, d6, d7)

LiquidCrystal(rs, rw, en, d0, d1, d2, d3, d4, d5, d6, d7)

Arguments :

rs: numéro de la broche Arduino connectée à la broche rS (n° 4) de l'écran LCD

rw: numéro de la broche Arduino connectée à la broche rw (n° 5) de l'écran LCD (optionnel, mettre à la masse en mode standard (lecture))

en: numéro de la broche Arduino connectée à la broche enable (n° 6) de l'écran LCD

d0, d1, d2, d3, d4, d5, d6, d7: les numéros des broches Arduino connectées aux broches de données correspondantes d0 (n°7) à d7 (n°14) de l'écran LCD (d0 à d3 sont facultatifs). Si on les omet, l'écran LCD sera contrôlé en utilisant uniquement les quatre lignes de données d4 à d7).

Exemple : LiquidCrystal lcd(12,11,5,4,3,2);

 crée une instance nommée lcd avec : rs = 12, en = 11, d4 = 5, .., d7 = 2.

Puis on doit initialiser l'écran par :

lcd.begin(nc, nl);  // où nl est le nombre de lignes de l'écran et nc le nombre de caractères par ligne.

 

Les méthodes les plus utiles sont :

lcd.clear(); // pour effacer

lcd.setCursor(c,l); pour positionner le curseur au caractère n°c de la ligne l.

lcd.home() lcd.setCursor(0,0);

lcd.print("Bonjour."); pour écrire à partir de la position du curseur, imprime un seul argument à la fois de type char, byte, int, long ou string. Dans le cas d'un nombre, un deuxième argument, pris parmi BIN, DEC, OCT ou HEX permet de spécifier la base (DEC par défaut).

Exemple de programme :

// include the library code:

#include <LiquidCrystal.h>

// Pour générations aléatoires

int aleat;

// description des branchements

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

 

void setup()

{

  // Nombre de colonnes et lignes du LCD

  lcd.begin(16, 2);

  // Message de bienvenue.

  lcd.print("Bonjour Michel");

  lcd.setCursor(0, 1); // curseur colonne 0, ligne 1

  lcd.print("Comment vas-tu ?");

}

 

void loop()

{

  delay(2000);

  aleat = random(32767);

  lcd.clear(); lcd.setCursor(0, 0);

  lcd.print("Tirage de "); lcd.print(aleat);

  lcd.setCursor(0, 1);

  switch (aleat%4) {

  case 0: lcd.print("0 modulo 4"); break;

  case 1: lcd.print("1 modulo 4"); break;

  case 2: lcd.print("2 modulo 4"); break;

  case 3: lcd.print("3 modulo 4"); break;

  }

}

13 Ecran OLED SSD 1306

Branchements pour Arduino Uno, Nano, Mega et Leonardo : informations tirées de https://randomnerdtutorials.com/guide-for-oled-display-with-arduino/

L'écran OLED (organic light-emitting diode) SSD1306 0.96 inch  I2C of128×64 pixels. Il n'utilise que 4 broches :

Oled

Uno/Nano

Méga/Léonardo

Vin

+5V

+5V

GND

GND

GND

SCL

A5

21

SDA

A4

20

 

Il faut télécharger les bibliothèques adafruit_SSD1306.h et adafruit_GFX.h (dans l'éditeur Arduino taper SSD1306 dans la fenêtre ouverte par le menu Sketch  >  Inclure la bibliothèque  >  Gérer les bibliothèques).

Documentation : https://learn.adafruit.com/adafruit-gfx-graphics-library/graphics-primitives

Fonctions utiles :

display.clearDisplay() – tous les pixels sont éteints

display.drawPixel(x,y, couleur) – tracer un pixel dans les coordonnées x,y

display.setTextSize(n) – définir la taille de la police, prend en charge les tailles de 1 à 8

display.setCursor(x,y) – définir les coordonnées pour commencer à écrire du texte

display.print ("message") – imprimer les caractères à l'emplacement x,y

display.display() – appelez cette méthode pour que les modifications prennent effet

 

Pour tester l'écran essayer l'exemple de la bibliothèque : menu Files/Examples/Adafruit SSD 1306/ ssd1306_128x64_i2c.

Si l'Oled n'a pas de broche RESET, il faut définir le OLED_RESET variable à -1 comme indiqué ci-dessous :

#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)

Adafruit Display(128, 64, &wire, OLED_RESET);

Le paramètre (-1) signifie que lécran OLED n'a pas de broche RESET. Si l'écran OLED a une broche RESET, il doit être connecté à un GPIO. Dans ce cas, il faut passer le numéro de la broche GPIO en paramètre.

 

Pour que ça marche j'ai modifié :

#define OLED_RESET 4 => -1

#define SCREEN_ADDRESS 0x3D => 0x3C

 

 

Si l'écran n'affiche rien, exécuter ce code :

/*********

  Rui Santos :Complete project details at https://randomnerdtutorials.com  

*********/

 

#include <Wire.h>

void setup() {

  Wire.begin();

  Serial.begin(115200);

  Serial.println("\nI2C Scanner");

}

void loop() {

  byte error, address;

  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;

  for(address = 1; address < 127; address++ ) {

    Wire.beginTransmission(address);

    error = Wire.endTransmission();

    if (error == 0) {

      Serial.print("I2C device found at address 0x");

      if (address<16) {

        Serial.print("0");

      }

      Serial.println(address,HEX);

      nDevices++;

    }

    else if (error==4) {

      Serial.print("Unknow error at address 0x");

      if (address<16) {

        Serial.print("0");

      }

      Serial.println(address,HEX);

    }    

  }

  if (nDevices == 0) {

    Serial.println("No I2C devices found\n");

  }

  else {

    Serial.println("done\n");

  }

  delay(5000);          

}

 

Vérifier l'adresse dans le moniteur série / résultat :

Scanning...

I2C device found at address 0x3C

done

et modifiez l'adresse en conséquence dans la ligne suivante :

if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {

adresse qui dans le cas présenté ci-dessus  était 0x3C.

 

Exemple "Hello world" :

/*********

  Rui Santos : Complete project details at https://randomnerdtutorials.com  

*********/

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED display height, in pixels

 

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

 

void setup() {

  Serial.begin(115200);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64

    Serial.println(F("SSD1306 allocation failed"));

    for(;;);

  }

  delay(2000);

  display.clearDisplay();

  display.setTextSize(1);

  display.setTextColor(WHITE);

  display.setCursor(0, 10);

  // Display static text

  display.println("Hello, world!");

  display.display();

}

void loop() {}

 

Les caractères s'écrivent sous la ligne x de setCursor(x,y).

La police de caractère par défaut en setTextSize(0 ou 1) a des caractères de 5x7 pixels avec en plus 1 pixel d'espacement en largeur (à droite) et en hauteur en dessous le caractère complet occupe  6x8 pixels ce qui fait qu'on peut écrire 8 lignes de 21 caractères en commençant en (0,0), (0,8), (0,16), (0,24), (0,32), (0,40), (0,48), et (0,56). Avec cette police display.println décale automatiquement de 8 pixels en hauteur.

On peut espacer les lignes davantage en gérant le nombre de pixels par ligne de caractères mais on ne pourra faire contenir que 7 lignes de 9 pixels de haut ou 6 de 10 ou 11 pixels de haut, etc.

On peut écrire avec des fontes plus élaborées, mais en perdant en nombre de caractères. Il faut à chaque fois inclure le .h correspondant, par exemple #include <Fonts/FreeSerif12pt7b.h> et charger la fonte par display.setFont(&FreeSerif9pt7b);

Les fontes suivantes sont disponibles :

FreeMono12pt7b.h                FreeSansBoldOblique12pt7b.h

FreeMono18pt7b.h                FreeSansBoldOblique18pt7b.h

FreeMono24pt7b.h                FreeSansBoldOblique24pt7b.h

FreeMono9pt7b.h                        FreeSansBoldOblique9pt7b.h

FreeMonoBold12pt7b.h                FreeSansOblique12pt7b.h

FreeMonoBold18pt7b.h                FreeSansOblique18pt7b.h

FreeMonoBold24pt7b.h                FreeSansOblique24pt7b.h

FreeMonoBold9pt7b.h                FreeSansOblique9pt7b.h

FreeMonoBoldOblique12pt7b.h        FreeSerif12pt7b.h

FreeMonoBoldOblique18pt7b.h        FreeSerif18pt7b.h

FreeMonoBoldOblique24pt7b.h        FreeSerif24pt7b.h

FreeMonoBoldOblique9pt7b.h        FreeSerif9pt7b.h

FreeMonoOblique12pt7b.h                FreeSerifBold12pt7b.h

FreeMonoOblique18pt7b.h                FreeSerifBold18pt7b.h

FreeMonoOblique24pt7b.h                FreeSerifBold24pt7b.h

FreeMonoOblique9pt7b.h                FreeSerifBold9pt7b.h

FreeSans12pt7b.h                FreeSerifBoldItalic12pt7b.h

FreeSans18pt7b.h                FreeSerifBoldItalic18pt7b.h

FreeSans24pt7b.h                FreeSerifBoldItalic24pt7b.h

FreeSans9pt7b.h                        FreeSerifBoldItalic9pt7b.h

FreeSansBold12pt7b.h                FreeSerifItalic12pt7b.h

FreeSansBold18pt7b.h                FreeSerifItalic18pt7b.h

FreeSansBold24pt7b.h                FreeSerifItalic24pt7b.h

FreeSansBold9pt7b.h                FreeSerifItalic9pt7b.h

Les 9 pt sont suffisamment grandes.

14 Keypad

14.1 Ancien soft

(Voir paragraphe suivant nouvelle librairie)

 
Les keypads 4x3 et 4x4 sont gérés par la librairie Keypad qui définit la classe Keypad. Pour l'utiliser : #include <Keypad.h>.

Liste des fonctions de la librairie Keypad ()

Keypad((char *)userKeymap, row[], col[], rows, cols)

begin()

getKey()

getState()

setHoldTime(unsigned int time)

setDebounceTime(unsigned int time)

addEventListener(keypadEvent)

 

Création d'un "objet clavier"

Pour créer un "objet clavier", il faut utiliser le constructeur suivant :

Keypad((char *) userKeymap, row[], col[], rows, cols)

avec :

userKeymap : tableau à 2 dimensions définissant les symboles des touches

row[] : tableau correspondant aux numéros des broches utilisées pour les lignes

col[] : tableau correspondant aux numéros dex broches utilisées pour les colonnes

rows : nombre de lignes

cols : nombre de colonnes

 

Exemple de création pour un clavier 4x3 (sans A,B,C,D)

const byte rows = 4; //four rows

const byte cols = 3; //three columns

char keys[rows][cols] = {

  {'1','2','3'},

  {'4','5','6'},

  {'7','8','9'},

  {'#','0','*'}

};

byte rowPins[rows] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad

byte colPins[cols] = {8, 7, 6}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad((char *) keys, rowPins, colPins, rows, cols );

 

Ce code crée un objet de type Keypad, appelé keypad, qui utilise les broches 5,4,3,2 pour les lignes et les broches 8,7,6 pour les colonnes. Ce clavier a 4 lignes et 3 colonnes , et a donc 12 touches.

 

Description des fonctions

void begin((char *)userKeymap)

Initialise toutes les variables. En fait le constructeur le fait déjà.

 

char getKey()

Renvoie la touche (sous forme caractère ASCII) qui est appuyée, si une l'a été.

 

KeypadState getState()

Renvoie l'état courant du clavier.

Les 4 états possibles sont IDLE, PRESSED, RELEASED et HOLD.

 

setHoldTime(unsigned int time)

Définit le nombre de millisecondes que l'utilisateur doit appuyer sur un bouton pour activer l'état HOLD.

 

setDebounceTime(unsigned int time)

Définit le nombre de millisecondes entre 2 appuis de touches. C'est une pause anti-rebond.

 

addEventListener(keypadEvent)

Crée un évènement si le clavier est utilisé. Vous pouvez regarder un exemple dans le logiciel Arduino dans "File -> Sketchbook -> Examples -> Library-Keypad -> EventSerialKeypad"

14.2 AdaFruit Keypad.

Nouvelle librairie du même clavier. Ci-après un exemple de mise en oeuvre.

#include "Adafruit_Keypad.h"

 

const byte ROWS = 4; // rows

const byte COLS = 4; // columns

//define the symbols on the buttons of the keypads

char keys[ROWS][COLS] = {

  {'1','2','3','A'},

  {'4','5','6','B'},

  {'7','8','9','C'},

  {'*','0','#','D'}

};

byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad

byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad

 

//initialize an instance of class NewKeypad

Adafruit_Keypad customKeypad = Adafruit_Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);

 

void setup() {

  Serial.begin(9600);

  customKeypad.begin();

  long n = getKBlong();

  Serial.print("Reçu la valeur "); Serial.println(n);

}

 

void loop() {

  // put your main code here, to run repeatedly:

  long n = getKBlong();

  Serial.print("Reçu la valeur "); Serial.println(n);  

  delay(10);

}

 

// Lecture d'un caractère avec attente maximale d'un certain delai.

char getKBcar(int attente_ms)

{

  long tdeb = millis();

  while (millis()-tdeb < attente_ms)

  {

    customKeypad.tick();

    while(customKeypad.available())

    {

      keypadEvent e = customKeypad.read();

      if(e.bit.EVENT == KEY_JUST_RELEASED) return (char) e.bit.KEY;

    }

    delay(10);

  }

  return '\0';

}

 

// Lecture d'un entier jusqu'au caractère non chiffre

char ligne[8];

long getKBlong()

{

  int i, n, c;

  ligne[0] = '0'; // Si on ne reçoit rien cette valeur est utilisée

  for (i = n = 0; i < 8; i++)

  {

    c = getKBcar(20000); if (c < 48 || c > 57) break;

    ligne[i] = c; n = i;

  }  

  long dix = 1, v = 0;

  for (i = n; i >= 0; i--)

  { v += (ligne[i] - 48)*dix;  dix *= 10;}

  return v;

}

15 Bluetooth

Les  modules les plus utilisés sont le HC-05 et le HC-06.

Le HC-05 peut fonctionner en maitre et esclave. Il est compatible +5V.

Le HC-06 ne fonctionne qu'en mode esclave et il vaut mieux limiter le voltage sur l'entrée RX à 3.3V par un pont diviseur 1kOhm--2kOhm.

 

Le module HC05, de dimensions 37,5 mm x 16,5 mm.Le module HC05, de dimensions 37,5 mm x 16,5 mm. Brochage du moduleBrochage du module

 

Le HC-06 a 4 broches en commun avec le HC-05 :
Vcc : entrée +5V,  Gnd : masse, Tx ( Transmit Data ou TXD)  et Rx (Receive Data ou RXD), à brancher à 2 broches Rx-Tx (en croisant) de l'Arduino.

15.1 Configuration interne : Commandes AT

Cette configuration interne n'est à faire que si on veut modifier le baudrate, parité, etc, le nom ou le mot de passe.

15.1.1 Configuration interne du HC-06

Quand il n'est pas encore appairé, la led du HC-06 est clignotante et les données que lui envoie l'Arduino sont interprétées comme des commandes AT (tableau de commandes non vérifié)

Commande AT HC-06

Signification

Réponse

AT

Test

OK

AT+VERSION

Version du module

linvorV1.5

AT+BAUDx

Changer la vitesse (1)

OKy

AT+NAMEnom

Changer le nom en nom

OKsetname

AT+PINnnnn

Changer le mot de passe

OKsetPIN

AT+PN, AT+PO, AT+PE

Changer la parité

OK None, OK Odd, OK Even

(1) x est l'index de la vitesse :1->1200, 2->2400, 3->4800, 4->9600, 5->19200, 6->38400, 7->57600 , 8->115200 et y est la valeur de la vitesse.

15.1.2 Configuration interne du HC-05

Le HC-05 a 2 broches supplémentaires :
- En ou Key que l'on n'utilise qu'en mode commande AT
- State que l'on ne connecte pas. State est connecté en interne à la LED du module
:

Pour modifier la configuration du HC-05 il faut le mettre en mode commande AT, ce qui est assez délicat : Il faut programmer la communication série interne entre l'Arduino et le HC-05 en 9600 ou 38400 exclusivement (pour cette com interne en mode AT). Par défaut elle se fait en 38400 (et je n'ai pas réussi en 9600). Suivant cette vitesse (9600 ou 38400) la broche Enable doit être portée à HIGH avant ou après la broche VCC (problématique). Le bouton poussoir du HC-05 simulerait la mise à HIGH de la broche Enable. Ce qui a marché en 38400, c'est programmer la broche En à High, et si la led ne clignotait pas lentement : débrancher la broche VCC du +5V, appuyer sur sur poussoir, puis rebrancher la broche VCC au +5V ce qui correspond au fait que la broche En est à HIGH (car toujours connectée) avant la broche VCC (que l'on rebranche).

HC-05 paramètres par défaut  :

 

Commande AT HC05.

 

Question

Commande

Réponse

AT

 

OK

AT+VERSION

 

+VERSION:2.0-20100601

AT+NAME

AT+NAME=nom

+NAME:DSD TECH HC-05

AT+PSWD

AT+PSWD=1234

+PSWD:1234

AT+ROLE

AT+ROLE=1 (maitre ou 0 slave)

+ROLE:0

AT+UART

AT+UART=57600,0,0

+UART:9600,0,0

 

Source du code testé :

/*

 * Lecture des paramètres du HC-05 en mode AT. La led doit clignoter très lentement, 1 fois

 * toutes les deux secondes environ. Si ce n'est pas le cas débrancher la broche d'alimentation

 * à Vcc (+5v), appuyer 1 à 2 secondes sur le bouton poussoir du HC-05 et rebrancher la broche.

 * Eventuellement débrancher aussi la broche Enable. Enfin, faites divers pour arriver à

 * obtenir ce clignotement LENT.

 * La vitesse de communication en modes Commande AT n'a rien à voir avec celle du mode données

 * qui est renseigné par la commande AT+UART. La vitesse en mode commande AT est soit de 9600

 * bauds, soit de 38400 bauds, suivant la séquence de tension au niveau des broches VCC et Enable.

 * Je n'ai pas réussi à le faire marcher en 9600. Ce fichier fonctionne bien en 38400. Et je

 * répète, cette vitesse n'a rien à voir avec celle qui sera utilisée pour la communication

 * bluetooth, renseignée ou fixée par la commande AT+UART.

 */

#include <SoftwareSerial.h>  //Software Serial Port  

#define RxArduino 3  // Tx HC-05  

#define TxArduino 2  // Rx HC-05

#define EnHC05 4 // Enable Hc-05

SoftwareSerial ss(RxArduino,TxArduino);  

 

void setup()  

{  

   Serial.begin(9600);

   delay(500);  

   // Configuration du bluetooth  

   pinMode(RxArduino, INPUT);  

   pinMode(TxArduino, OUTPUT);

   pinMode(EnHC05, OUTPUT);

   digitalWrite(EnHC05, HIGH); // Pour mode AT 9600

   ss.begin(38400);

   Serial.println("\n1:AT\n2:AT+VERSION\n3:AT+NAME\n4:AT+UART\n5:AT+ROLE\n6:AT+PSWD\n7:AT+NAME=HC-05-B");

}  

void loop()  

{  

   int cde = Serial.parseInt(); // Renvoi 0 si erreur => 0 n'est pris comme index de cde

   switch (cde)

   {

      case 1 :

      { Serial.println("Envoi commande AT"); ss.print("AT\r\n"); break;}

      case 2 :

      { Serial.println("Envoi commande AT+VERSION"); ss.print("AT+VERSION\r\n"); break;}

      case 3 :

      { Serial.println("Envoi commande AT+NAME"); ss.print("AT+NAME\r\n"); break;}  

      case 4 :

      { Serial.println("Envoi commande AT+UART"); ss.print("AT+UART\r\n"); break;}

      case 5 :

      { Serial.println("Envoi commande AT+ROLE"); ss.print("AT+ROLE\r\n"); break;}

      case 6 :

      { Serial.println("Envoi commande AT+PSWD"); ss.print("AT+PSWD\r\n"); break;}

      case 7 :

      { Serial.print("Envoi commande AT+NAME=HC-05-B"); ss.print("AT+NAME=HC-05-B\r\n"); break;}

   }

   while(ss.available()) {Serial.print((char) (ss.read()));}

}  

 

/* RESULTAT :

1:AT

2:AT+VERSION

3:AT+NAME

4:AT+UART

5:AT+ROLE

6:AT+PSWD

7:AT+NAME=HC-05-B

Envoi commande AT

OK

Envoi commande AT+VERSION

+VERSION:2.0-20100601

OK

Envoi commande AT+NAME

+NAME:DSD TECH HC-05

OK

Envoi commande AT+UART

+UART:9600,0,0

OK

Envoi commande AT+ROLE

+ROLE:0

OK

Envoi commande AT+PSWD

+PSWD:1234

OK

Envoi commande AT+NAME=HC-05-BOK

Envoi commande AT+NAME

+NAME:HC-05-B

OK

 */

 

15.2 Mode de communication bluetooth : Mode data

En utilisation normale bluetooth le circuit doit être en mode data. Pour cela il faut procéder à l'appariement entre ce circuit et l'organe éloigné avec lequel il va communiquer. Avant l'appariement la lumière du HC-05 clignote rapidement.

Pour faire l'appariement avec Windows 10 :

 

Dans le Gestionnaire de périphériques 2 nouvelles lignes apparaissent, intitulées Lien Série sur Bluetooth Standard. Un seul numéro de port COM va fonctionner avec Stellarium. Il faut l'identifier. Par un clic droit sur une des lignes on accède à la fenêtre des Propriétés.

Dans la fenêtre Propriétés, sélectionner l'onglet Détails et dans la liste déroulante Propriété chercher la rubrique Adresse du périphérique Bluetooth qui contient 00140305EF32 dans le cas du HC-05-B. Si cette rubrique n'est pas présente ce n'est pas le bon port COM.

 

Exemple de commmunication :

/* Test d'une liaison bluetooth avec le HC-05 ou HC-06 monté en SoftwareSerial sur le Uno  

   Apparier le bluetooth - Trouver son port COM - Ouvrir Termite en 9600 bauds sur ce port COM

   Avec Termite envoyer taper une ligne de caratères se terminant par # puis l'envoyer

   A sa réception l'Arduino l'affiche sur sa liaison série vers le moniteur série et

   la renvoie par bluetooth vers Termite qui doit l'afficher également.

   Envoyer une nouvelle ligne ....

*/

#include <SoftwareSerial.h>

#define NBMAXCHAR 80

char bufinput[NBMAXCHAR+1];

#define MITAD (NBMAXCHAR/2)

static int idx = 0;

SoftwareSerial ssBT(3, 2); // (Rx, Tx) coté Arduino, inverse cote Bluetooth

void setup() { Serial.begin(9600);  while (!Serial) ; ssBT.begin(9600);}

 

void loop()

{

bool isComplet = false;

char c;

int n = 0;

 

   // lecture bluetooth jusqu'à réception du #

   while (ssBT.available() && !isComplet)

   {

   c = (char) ssBT.read(); if (idx == 0 && c == '\n') continue;

   bufinput[idx ++] = c;

   if (c == '#') {isComplet = true; break;}

   // Si buffeur plein, on vidange la première moitié et on continue

   if (idx == NBMAXCHAR)

   { for (int i = 0; i < MITAD; i++){bufinput[i] = bufinput[i+MITAD];} idx = MITAD;}

   }

 

   if (isComplet) // Reçu un message terminé par #

   {

      bufinput[idx] = 0;

      // On le renvoie en bluetooth pour l'afficher dans Termite    

      ssBT.print("HC-05 a recu : <"); ssBT.print(bufinput); ssBT.println(">");

      delay(100);    

      // On le renvoie vers le Moniteur Série

      Serial.print("HC-05 a recu : <"); Serial.print(bufinput);Serial.println(">");

      idx = 0;  

   }

}

16 GPS

Les modules GPS les plus utilisés sont basés sur les puces neo-6 series de u-blox (https://www.u-blox.com/en/product/neo-6-series). Ils coûtent moins de 10€.

Le câblage standard (sans prise en compte du PPS) se limite à 4 fils de liaison entre le module GPS et la carte MEGA 2560 : a masse, le +5V et (à titre d'exemple) on relie RX/TX GPS à Serial2 du Mega :

- TX du module GPS à relier à RX2 broche 17 du Mega,

- RX à relier à TX2 broche 16  du Mega.

La LED du module GPS se met à clignoter, lorsqu'elle a réussi à acquérir la position. Cette led reflète le signal One PPS (un pulse par seconde) que certaines puces offrent sur une sortie. Le front de ce signal montant toute les secondes à quelques nanosecondes près, peut-être utilisé pour des mises à l'heur extrêment précises. L'heure TU de l'instant du front montant est fourni dans les trames envoyées à la suite de ce front.

Les trames envoyées commencent par $ et se terminennt par CR LF (Ox0D Ox0A).

Ensuite vient l'identifiant de l'équipement générateur de la trame :

Ensuite viennent les 3 caractères indiquant le type de la trame :

Exemple de sortie des trames fournies après chaque seconde entière par le Neo-6M, lorsque l'acquisition est bien établie

$GPRMC,104508.00,A,4331.52048,N,00134.38575,E,0.414,,081221,,,A*75

$GPVTG,,T,,M,0.414,N,0.768,K,A*2B

$GPGGA,104508.00,4331.52048,N,00134.38575,E,1,08,1.29,207.4,M,48.5,M,,*5A

$GPGSA,A,3,07,20,30,09,13,06,14,02,,,,,2.13,1.29,1.70*02

$GPGSV,3,1,11,02,35,241,29,05,39,308,16,06,14,193,27,07,61,063,17*7E

$GPGSV,3,2,11,09,28,076,27,11,38,226,31,13,26,268,17,14,11,153,26*7A

$GPGSV,3,3,11,16,00,021,,20,69,287,28,30,75,159,29*40

$GPGLL,4331.52048,N,00134.38575,E,104508.00,A,A*65

C'était le 8/12/21, date donnée par la trame $GPRMC. Il était 11h45mn08.00s TU, valeur donnée en premier par la trame $GPRMC, puis par les trames $GPGGA et $GPGLL. Longitude 43°31.52048'N et Latitude 1°34.38575'E donnée par la trame $GPRMC, puis par les trames $GPGGA et $GPGLL.

La trame $GPVTG donne des indications sur la route suivie (vitesse, angle de route, cap...).

La trame $GPGGA donne en plus le nombre de satellites utilisés : 08 et l'altitude : 207.4m.

La trame $GPGSA donne les numéros PRN1 des 8 satellites utilisés :  07,20,30,09,13,06,14,02 et des indications de précision.

Les trames $GPGSV redonnent ces numéros pour 11 satellites, les 8 utilisés (pas dans le même ordre) et 3 autres (soulignés), suivis de leur élévation, azimut et rapport signal/bruit.

On remarquera que seuls les satellites GPS sont utilisés.

 

Autre exemple de sortie fournie par un neo-M8N :

$GNRMC,093206.00,A,4331.51798,N,00134.36985,E,0.271,,081221,,,A*6C

$GNVTG,,T,,M,0.271,N,0.503,K,A*3F

$GNGGA,093206.00,4331.51798,N,00134.36985,E,1,04,4.50,209.9,M,48.5,M,,*42

$GNGSA,A,3,07,06,02,30,,,,,,,,,12.71,4.50,11.89*19

$GNGSA,A,3,,,,,,,,,,,,,12.71,4.50,11.89*19

$GPGSV,4,1,13,02,45,284,23,03,00,118,08,04,20,064,23,05,10,303,*70

$GPGSV,4,2,13,06,47,206,34,07,63,140,27,09,56,054,,11,54,273,*75

$GPGSV,4,3,13,13,02,247,,16,09,049,,20,39,306,19,29,04,326,*73

$GPGSV,4,4,13,30,41,183,34*40

$GLGSV,1,1,00*65

$GNGLL,4331.51798,N,00134.36985,E,093206.00,A,A*79

Le 8/12/21 à 9h32mn06.00s TU. Ici seuls 4 satellites sont utilisés sur les 13 satellites suivis. Ce sont  des satellites du mix GPS+GLONASS. Il semblerait que ce soient des GPS car 13 sont indiqués dans la trame $GPGSV et 0 dans la trame $GLGSV.

17 Centrale inertielle MPU6050

Trouvé de guide (non exploité cette trouvaille) : https://randomnerdtutorials.com/arduino-mpu-6050-accelerometer-gyroscope/

J'ai mis la doc et les programmes dans ces dossiers :

D:\MesProgs\arduino\documentation\MPU-6050

D:\MesProgs\arduino\libraries\MPU6050

Cette carte comporte 3 gyromètres et 3 accéléromètres. Sa liaison avec l'Arduino utilise le protocole I2C (bus informatique Inter-Integrated Circuit élaboré par Philips) qui passe par deux lignes :

sans oublier la masse commune aux équipements.

Ainis la connexion avec l'Arduino se fait par seulement par 5 fils :

Les  3 broches de la carte MPU6050 marquées XDA, XCL et AD0 ne sont pas utilisée dans l'exemple MPU6050_DMP6 décrit ci-après.

Pour communiquer avec le protocole I2C, Arduino utilise la librairie Wire qui dans le cas de la carte UNO suppose que les broches SCL et SDA de la carte MPU sont reliées au broches A5 et A4 de l'UNO.

En premier lieu, il faut inclure la définition :

#include "I2Cdev.h"

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE

#include "Wire.h"

#endif

Ensuite si on utilise le processeur de mouvement 3D interne au circuit MPU6050, on inclut :

#include "MPU6050_6Axis_MotionApps20.h"

sinon, on inclut seulement :

#include "MPU6050.h"

Attention : Le fichier MPU6050_6Axis_MotionApps20.h inclut le fichier helper_3dmath.h qui est une petite bibliothèque c++ d'outils géométriques et quaternion. Elle définit une classe VectorInt16 très mal conçue car sa méthode magnitude() est fausse si la longueur est > 256 et sa méthode normalize() n'a aucun sens car les composantes étant a priori inférieures à zéro, elle serait sensée rencvyer 0 sur toutes les composantes.

Puis on crée un objet MPU6050 :

MPU6050 mpu;

Le protocole I2C est initialisée par :

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE

    Wire.begin();

#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE

    Fastwire::setup(400, true);

#endif

On initialise la communication série entre l'Arduino et l'usager :

Serial.begin(38400); while (!Serial); // jusqu'à 115200 ou + ?

 

On initialise la carte MPU :

mpu.initialize();

et on teste la réussite (ou l'échec) de l'initialisation.

bool ok = mpu.testConnection();

Serial.println(ok ? "MPU6050 connection successful" : "MPU6050 connection failed");

Fonctions brutes (n'utilisant pas le Processeur de Mouvement Digital : DMP) :

On peut lire les offset des gyros et accéléros par les fonctions suivantes :

int16_t mpu.getXAccelOffset());

int16_t mpu.getYAccelOffset());

int16_t mpu.getZAccelOffset());

int8_t mpu.getXGyroOffset());

int8_t mpu.getYGyroOffset());

int8_t mpu.getZGyroOffset());

et les écrire par les suivantes

mpu.setXAccelOffset(int16_t);

mpu.setYAccelOffset(int16_t);

mpu.setZAccelOffset(int16_t);

mpu.setXGyroOffset(int8_t);

mpu.setYGyroOffset(int8_t);

mpu.setZGyroOffset(-nt8_t);

 

On peut lire les  valeurs des accéléros et gyros de plusieurs manières :

int16_t getAccelerationX ()

int16_t getAccelerationY ()

int16_t getAccelerationZ ()

void getAcceleration (int16_t *x, int16_t *y, int16_t *z)

int16_t getRotationX ()

int16_t getRotationY ()

int16_t getRotationZ ()

void getRotation (int16_t *x, int16_t *y, int16_t *z)

void getMotion6 (int16_t *ax, int16_t *ay, int16_t *az, int16_t *gx, int16_t *gy, int16_t *gz)

 

Fonctions utilisant le DMP (Processeur Nuumérique de Mouvement).

Initialisation de l'utilisation du DMP  dans le setup() :

devStatus = mpu.dmpInitialize();

// 0 : ok; 1 = initial memory load failed; 2 = DMP configuration updates failed

if (devStatus == 0) {

    mpu.setDMPEnabled(true);

    // enable Arduino interrupt detection : Arduino ext_interrupt 0

    attachInterrupt(0, dmpDataReady, RISING); // définit la callback

    mpuIntStatus = mpu.getIntStatus();

    dmpReady = true;

    packetSize = mpu.dmpGetFIFOPacketSize();

} else dmpReady = false; // Panique !!

 

La fonction attachInterrup déclare le nom de la callback dmpDataReady qui ne fait que positionner un booléen qui sera testé dans la loop() :

volatile bool mpuInterrupt = false;

void dmpDataReady() {

    mpuInterrupt = true;

}

 

Signification des bits du Status  qui est lu par mpu.getIntStatus():

#define MPU6050_INTERRUPT_FF_BIT            7
#define MPU6050_INTERRUPT_MOT_BIT           6
#define MPU6050_INTERRUPT_ZMOT_BIT          5
#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT    4 // 0x10 : Overflow de la pile
#define MPU6050_INTERRUPT_I2C_MST_INT_BIT   3
#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT   2
#define MPU6050_INTERRUPT_DMP_INT_BIT       1 // 0x02 : Données DMP pretes  
#define MPU6050_INTERRUPT_DATA_RDY_BIT      0 // Données brutes pretes

Il y a intérêt à lire les bits de status tous à la fois plutôt que un par un avec les fonctions spécifiques car chaque lecture remet tous les bits à zéro.

 

Utilisation dans loop() :

if (!dmpReady) return; // On ne fait rien s'il y a eu échec de l' ini du DMP

// Si des paquets pas deja prets dans la fifo, on attend l'interruption

while (fifoCount < packetSize && !mpuInterrupt) {;}  

// Reset de cette interruption et lecture infos pour savoir où on en est

mpuInterrupt = false;

mpuIntStatus = mpu.getIntStatus();

fifoCount = mpu.getFIFOCount();

// Vidange de la pile si overflow

if((mpuIntStatus & 0x10) || fifoCount == 1024) mpu.resetFIFO();

// Traitement des données si données DMP pretes

else if (mpuIntStatus & 0x02) {

  // Attente assez de données dans la pile

  while(fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

  // Lecture données Fifo et MAJour fifoCount

  mpu.getFIFOBytes(fifoBuffer, packetSize); fifoCount -= packetSize;

  // Transformation des données

  mpu.dmpGetQuaternion(&q, fifoBuffer); // fifo => quat

  mpu.dmpGetEuler(euler, &q);           // quat => Euler

  mpu.dmpGetGravity(&gravity, &q);      // quat => grav

  mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); // quat,grav => ypr

  mpu.dmpGetAccel(&aa, fifoBuffer);      // fifo => gam

  mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); // grav, gam = acl

}

REMARQUES : Voir sur MPU6050_6Axis_MotionApps20.h car il y a des version 16 et 32 bits qui sont différenciées par le type des arguments !!

 

Filtre Passe-bas :

set : mpu.setDLPFMode(uint8_t val); get : uint8_t mpu.getDLPFMode();

          |   ACCELEROMETER    |           GYROSCOPE

 DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate

 ---------+-----------+--------+-----------+--------+-------------

 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz

 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz

 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz

 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz

 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz

 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz

 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz

 7        |   -- Reserved --   |   -- Reserved --   | Reserved

Par défaut  DLPF_CFG est sur 3 : bande passante 43 Hz, (retard 5 ms) et freq. Ech. Gyro =  1 kHz

Filtre passe-haut :

set : mpu.setDHPFMode(uint8_t val); get : uint8_t mpu.getDHPFMode();

ACCEL_HPF | Filter Mode | Cut-off Frequency

 ----------+-------------+------------------

 0         | Reset       | None

 1         | On          | 5Hz

 2         | On          | 2.5Hz

 3         | On          | 1.25Hz

 4         | On          | 0.63Hz

 7         | Hold        | None

Par défaut c'est sur 0 : pas de coupure du continu.

Fréquence d'échantillonage d'accès aux mesures :

set : mpu.setRate(uint8_t val); get : uint8_t getRate();

La fréquence d'échantillonnage interne des gyros vaut 8 kHz quand le filtre passe-bas (DLPF) est inactif, et 1 kHz quand il est actif. La fréquences d'accès aux sorties est égale à celle des gyros divisée par   (1 + SMPLRT_DIV) ou  SMPLRT_DIV est positionné ou lu par setRate et getRate.

Toutefois, la fréquence maximale de génération des mesures accéléros est limitée à 1 kHz. Si on règle à une valeur plus élevée, les mêmes mesures sont repétées plusieurs fois.

Par défaut  SMPLRT_DIV = 0 => freq. Ech. Mesures = freq. Ech. Gyros = 1 kHz

 

Domaines de mesure des accéléros :

Les valeurs mesurées en entier sont sur 16 bits signés.

set : mpu.getFullScaleAccelRange(uint8_t val); get : uint8_t getFullScaleAccelRange();

 AFS_SEL | Full Scale Range | LSB Sensitivity

 --------+------------------+----------------

 0       | +/- 2g           | 8192 LSB/mg

 1       | +/- 4g           | 4096 LSB/mg

 2       | +/- 8g           | 2048 LSB/mg

 3       | +/- 16g          | 1024 LSB/mg

Par défaut +/- 2g = +/-32756 => g = 16384

 

Domaines de mesure des gyros :

Les valeurs mesurées en entier sont sur 16 bits signés.

set : mpu.getFullScaleGyroRange(uint8_t val); get : uint8_t getFullScaleGyroRange();

 FS_SEL | Full Scale Range   | LSB Sensitivity

 -------+--------------------+----------------

 0      | +/- 250 degrees/s  | 131 LSB/deg/s

 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s

 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s

 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s

Par défaut

 

18 Convertisseur série-usb FTDI

https://www.az-delivery.de/fr/products/ftdi-adapter-ft232rl

Permet d'envoyer sur un port usb les signaux de type série RS232 (RxD, TxD, CTS, DTR) directement avec les broches et certains des autres signaux (DCD, RSD,... ) en soudant aux points prévus à cet effet. Utilisé avec succès pour relier des composants GPS-Neo-6M et Neo-M8N dotés de la sortie One-PPS à un PC par USB.

Un câble pour ce circuit ? :

https://www.amazon.com.au/Converter-Terminated-Galileo-BeagleBone-Minnowboard/dp/B06ZYPLFNB

19 Convertisseur Max232

Circuit permettant de ramener les signaux série RS232 (qui peuvent atteindre ±12V et parfois ±24V) d'un fiche DB9 aux niveaux TTL et réciproquement. A l'arrière les broches marquées GND, TxD, RxD et VCC sont à brancher telles que à L'Arduino, sans croisement : Le RxD au Rx Arduino et le TxD au Tx Arduino.

19.1 Transmetteur/recepteur radio

Voir ce guide : https://randomnerdtutorials.com/arduino-mpu-6050-accelerometer-gyroscope/

20 Recepteur infra-rouge de télécommande

Voir ce guide : https://randomnerdtutorials.com/arduino-ir-remote-control/

21 Petits composants

21.1 Bouton poussoir

Ceux qui sont livrés avec l'Arduino sont doubles avec un interrupteur de chaque coté, mais commandés simultanément par un seul bouton poussoir.

 

 

Pour lire l'état de ce poussoir, relier une patte à une entrée numérique et à la masse via une résistance de 10 kW, et l'autre patte au +5V. La lecture de l'entrée numérique par un digitalRead(pin) fournira LOW si le poussoir est ouvert et HIGH s'il est fermé.

 

 

 

Pour se servir de ce poussoir en inverseur, on pourra utiliser le code suivant, qui commute l'inverseur uniquement à l'instant d'appui :

valeur = digitalRead(pin);

if (valeur == HIGH && oldvaleur != HIGH) sortie = !sortie;

oldvaleur = valeur;

Ce code est utilsé dans la classe Rupteur présentée ci-après.

Les boutons poussoirs présentant de très mauvais contacts, il est conseillé de lire leur état par le biais de la fonction debounce de la classe poussoir suivante :

// La classe Poussoir donne, à l'aide de la fonction "debounce()", la valeur de lecture de l'état du poussoir

// (HIGH ou LOW) qui ne change que lorsque la valeur est restée stable pendant au moins une certaine durée

class Poussoir

{

   int derniereMesure;

   unsigned long instantFront;

   unsigned long dureeCalme;

   int etatStabilise;

   int pinoche;

public :

   // Constructeur

   // pin : numéro broche de lecture du poussoir

   // duree : durée minimale (en ms) de stabilité de la valeur pour qu'elle soit prise en compte

   Poussoir(int pin, unsigned long duree)

   {

      pinoche = pin;

      derniereMesure = LOW;

      instantFront = 0;

      dureeCalme = duree;

      etatStabilise = LOW;

   }

   // Lecture valeur stabilisée

   int debounce()

   {

      int mesure = digitalRead(pinoche);

      int instantCourant = millis();

      if (mesure != derniereMesure) instantFront = instantCourant;

      if (instantCourant > instantFront + dureeCalme) etatStabilise = mesure;;

      derniereMesure = mesure;

      return etatStabilise;

   }

};  

 

La classe Rupteur, ci-dessous étend la classe Poussoir pour en faire un télérupteur fiable :

// La classe Rupteur donne à l'aide de la fonction "comut()" un bool qui est vrai si le pousoir a changé

// de valeur stabilisée. L'état du Rupteur est donnée accessible via la fonction etat().

class Rupteur : Poussoir

{

   int oldLecture;

   int etatCom;

public :

   // Constructeur (voir celui de Poussoir pou pin et duree)

   // etatIni : etat initial du Rupteur (LOW ou HIGH, au choix

   Rupteur(int pin, unsigned long duree, int etatIni) : Poussoir(pin, duree)

   {

      etatCom = etatIni;

      oldLecture = etatIni;

   }

 

   // Interrogation du rupteur : Retourne

   // vrai si l'état à commuté depuis le dernier appel et faux sinon

   bool comut()

   {

      bool sw = false;

      int lecture = debounce();

      if (lecture == HIGH && oldLecture != HIGH) { etatCom = !etatCom;  sw = true;}

      oldLecture = lecture;

      return sw;      

   }

 

   int etat() {return etatCom;}

};

 

Exemple de commutation de la led 13 de l'Uno avec l'entrée du poussoir sur pin n°2.

#include "poussoir.h" // Classes Poussoir et Rupteur

#define valIni LOW

Rupteur p(2, 20, valIni);

 

void setup() {

   pinMode(2, INPUT);

   pinMode(13, OUTPUT); // ledin

   digitalWrite(13, valIni);

}

 

void loop() {

   if (p.comut()) {digitalWrite(13, p.etat());}

}

 

 

21.2 Leds

Ce sont des diodes qui éclairent quand elles sonr parcourues (dans le bon sens) par un courant. Brancher la cathode (patte courte) via une résistance de 220 ohm à la masse, et pour l'allumer envoyer sur l'anode (patte longue représentée tordue) une tension positive,  par exemple via un digitalWrite(pin, HIGH).

 

 

21.3 Capteur de température TMP36

Pattes 1,2,3 de gauche à droite en regardant le coté plat qui est vers nous, le bombé étant de l'autre coté dans la direction du regard. Patte 1  au +5V, patte 3 à la masse et patte 2 (milieu) vers une entrée analogique (A0 à A5)

21.4 Interrupteur d'inclinaison

Il est allongé et a 4 pattes sur une des 2 petites faces. Quand il est disposé grandes faces horizontales, une bille est en équilibre et va se déplacer d'un coté ou de l'autre dès qu'une des 2 petite face est plus haute que l'autre. Sur la petite face opposée aux pattes , une flèche et un UP inscrit indique le haut et les bas. La grande face que l'on met en bas est rainurée. Les deux broches coté bas sont en circuit ouvert ou fermé suivant dès qu'on monte ou descend une petite face par rapport à l'autre. Pour lire son état, procéder comme pour un bouton poussoir (+5V sur une patte, l'autre vers une entrée numérique, reliée à la masse via 10 kW.

21.5 Buzzer

21.5.1 Montage en mode émetteur vibrations

Une broche à la masse et l'autre alimentée par une sortie digitale sur laquelle on envoie des commandes tone(pin, frqq, duree);

21.5.2 Montage en mode capteur vibrations

Une broche au +5v et l'autre reliée à la masse via une résistance de 1 MW. La tension variable (à priori faible de l'ordre de 0.1v à 1v) au niveau de cette dernière, envoyée sur une entrée analogique permet de détecter via un analogRead(pin) le niveau des vibrations subies par le buzzer.

 

21.6 Codeurs numériques rotatifs

Type : Encoder 600 P / R Photoelectric Incremental Rotary 5-24V AB Two Phases 6mm Shaft

Source de puissance: DC 5-24V

Arbre: 6*13mm

Dimension: 38*35.5mm

Sortie :circuit pulse orthogonaux rectangulaires 2 phases AB,  type NPN collecteur ouvert.

Vitesse maximale : 5000 tours / min

Réponse en fréquence : 0-20KHz

Longueur câble: 1.5 m

Note: La sortie 2 phases AB ne doit pas être directement connecté au VCC, cela brulerait la triode de sortie.  

Connexions :

Vert : phase A

Blanc : B phase,

Rouge :Vcc power +,

Noir = 0 V.

21.7 Servo-moteurs

Modèle SM-S2309S. Trois fils : Masse noire, 5V rouge  et commande blanche. Mettre un condensateur de découplage de 100 μF entre le 5 Volts et la masse pour atténuer les appels de courants.

#include <Servo.h>

Servo myServo; // déclaré en global par exemple

myServo.attach(9); // Dans le setup(), on déclare le numéro de la broche PWM (9 par exemple) qui commande le servo.

myServo.write(angle); // Dans loop() on commande un angle compris entre les entiers 0 à 179 au servo.

21.8 Moteur à courant continu et MOFSET

Le moteurs à courant continu fourni avec l'Arduino UNO est alimenté par 2 fils rouge et noir. L'Arduino n'ayant pas la puissance nécessaire pour alimenter ce moteur, le montage fait appel à une batterie supplémentaire pour apporter tension et puissance et à un transistor à effet de champ à grille isolée appelé MOSFET pour délivrer le courant. Ce mosfet (IRF520 Y56K BC ) est de type NPN dans la cas de l'exercice 9 du Arduino starter kit. Le fil rouge du moteur est directement relié au + 9V fourni par la batterie et le noir est relié à la masse par l'intermédiaire du mosfet qui va servir de robinet. Ainsi le fil noir du moteur est relié à la broche D (pour Drain) du mosfet, dont la broche S (pour Source) est reliée à la masse. La commande est effectuée par broche G (pour grille) du mosfet qui est reliée à une sortie numérique, sur laquelle on enverra digitalWrite(pin, LOW) pour bloquer le moteur et digitalWrite(pin, HIGH) pour le faire tourner.

 
Vu coté pattes, avec le radiateur au-dessus, la configuration de ces pattes est la suivante :

Source à gauche, drain à droite et grille à droite. (Attention la grille n'est pas au milieu !)

Remarque : Quand on envoie la commande arrêt, l'inertie de la charge fait que le moteur continue de tourner se comportant alors en génératrice qui à tendance à perpétuer le courant qui la traversait auparavant, courant qui peut abimer le mosfet. Pour éviter cela on met une diode en parallèle du moteur, dans un sens tel que le courant produit par le mosfet (qui fait débiter la batterie) ne traverse pas la diode (elle est donc mise avec la cathode vers le plus de la batterie).  Par contre le courant produit par le moteur, au lieu de descendre vers le mosfet pourra passer par cette diode.

21.9 Moteur à courant continu et pont en H

Pour fournir la puissance on utilise une pile de 9v dont la masse est reliée à celle de l'Arduino. Le circuit intégré réalisant le pont en H est mis en oeuvre dans l'exercice 09.

Ce circuit permet de faire tourner un moteur à courant continu dans les deux sens, à vitesse variable (en fait ce serait plutot à couple tension de commande variable). Il gère 4 canaux (1,2,3 et 4). Dans l'exercice seul les canaux 1 et 2 sont utilisés (pour faire tourner le moteur dans les 2 sens).

Le pont en H comporte (numéro des broches entre parenthèses) :

  • 2 broches Vcc : Vcc1 (16) est reliée ua +5v de l'Arduino et Vcc2 (8) qui est reliée au +9v de la pile. 

  • 4 broches masse et dissation de chaleur (4, 5, 12, 13). Dans l'exemple seules les broches 4 et 5 sont reliées à la masse, les broches 12 et 13 sont inutilsées. 

  • Une broche notée 1,2Enable (1) d'activation des canaux 1 et 2 (reliée à une sortie numérique pour gérer cette activation) 

  • Une broche notée 1,2Enable (9) d'activation des canaux 3 et 4, inutilisée. 

  • Deux broches de gestion du sens de rotation du moteur par les canaux 1 et 2 notées 1A (2) et 2A (7), reliées à des sorties digitales. L'envoi de 00 et 11 sur ces broches mettent le moteur à l'arrêt, 01 indique un sens et 10 l'autre. 

  • Deux broches de gestion du sens de rotation du moteur par les canaux 3 et 4 notées 3A (10) et 4A (15) inutilisées. 

  • Deux broches pour les sorties des commandes du moteur canaux 1 et 2 notées 1Y (3) et 2Y(6) sont reliées aux 2 poles du moteur. 

  • Deux broches pour les sorties des commandes du moteur canaux 3 et 4 notées 3Y (11) et 4Y(14) sont inutilisées. 

Principe du pont en H :

Si VA = 0 et VB = 5v, Q2 et Q4 sont bloqués et Q1 et Q3 conduisent. Le +5v traverse le moteur en passant par Q1, le moteur puis Q3, + coté A.

Si VA = 5v et VB = 0, Q1 et Q3 sont bloqués et Q2 et Q4 conduisent. Le +5v traverse le moteur en passant par Q4, le moteur puis Q2, + coté B.

Si VA = 0 et VB = 0, Q2 et Q3 sont bloqués et Q1 et Q4 conduisent. Le +5v arrive aux 2 bornes. Pas de ddp. Aucun courant ne passe.

Si VA = 5v et VB = 5v, Q1 et Q4 sont bloqués et Q2 et Q3 conduisent. Les 2 bornes sont à la masse. Pas de ddp. Aucun courant ne passe.

21.10 Transistor

Un transistor est un composant à 3 connexions qui s'appellent (standard / effet de champ):

  • l'émetteur (E) / la source (S) qui est traversée par l'ensemble du courant, et qui est symbolisé avec une flèche dans le sens du courant, 

  • la base (B) / la grille (G) qui commande le passage du courant, 

  • le collecteur (C) / le drain (D). 

Un transistor à deux jonction PN et NP consécutives (le courant conventionnel circule de P vers N). Il y a deux types :

  • le type NPN avec la zone P au centre. Le collecteur a une tension supérieure à celle de l'émetteur (Vc >> Ve). La flèche sort par l'émetteur, car le courant conventionnel va du collecteur vers l'émetteur. Le transistor conduit si Vb > Ve + 0.6V et la faible chute de tension totale Vce est de l'ordre de 0.1 à 2v suivant les modèles 

  • Le type PNP avec la zone N au centre. L'émetteur a une tension supérieure à celle du collecteur (Ve >> Vc). La flèche entre par l'émetteur, car le courant conventionnel va du collecteur vers l'émetteur.  Le transistor conduit si Vb < Ve – 0.6V et la faible chute de tension totale Vec est de l'ordre de 0.1 à 2v suivant les modèles (Vce de l'ordre de -0.1 à -2V). 

Dans les deux cas le transistor conduit quand la tension de la base se rapproche de celle du collecteur et se bloque quand la tension de la base se rapproche de celle de l'émetteur.

Le 1er schéma à gauche est utilisé lorsque les tensions sont plus grandes en haut qu'en bas. Il implique d'inverser la position des broches collecteur et émetteur.

Dans le 2ème schéma à droite, les collecteurs sont en haut et les émetteurs en bas. Dans ce cas la tension est plus grande en haut qu'en bas dans le cas du NPN (comme pour le 1er schéma), mais c'est l'inverse dans le cas du NPN.

 

Le transistor est un robinet fermé quand la tension de la base est voisine de celle de l'émetteur, et il s'ouvre quand elle se rapproche de celle du collecteur.

 

22 Annexe

22.1 Resets logiciels

22.1.1 Méthode brute

- Redémarrage logiciel par un jump à l'adresse 0, en appelant la routine suivante :

// Redémarre le programme depuis le début

void software_Reset()

{

  asm volatile ("  jmp 0");

}

mais ne remet pas à zéro les registres :  les états des pins (HIGH, LOW…) sont conservés et les shields externes ne sont pas redémarrés.

22.1.2 Méthode du Watchdog

Pour utiliser le watchdog, il faut d'inclure le fichier avr/wdt.h et appeler ensuite la fonction  wdt_enable().

La fonction wdt_enable accepte le temps à attendre avant de lancer un Reset automatique de la carte s'il n'y a pas d'autre appel au watchdog.

Constantes pour durées prédéfinies prédéfinies :

15mS    WDTO_15MS

30mS    WDTO_30MS

60mS    WDTO_60MS

120mS   WDTO_120MS

250mS   WDTO_250MS

500mS   WDTO_500MS

1S      WDTO_1S

2S      WDTO_2S

4S      WDTO_4S

8S      WDTO_8S

Pour forcer le reset de la carte, il suffit alors d'implémenter une courte boucle, le système reboot lorsque le temps choisi  expire (timeout).

L'exemple suivant utilise la plus petite valeur pour le timeout. Il suffit d'appeler la fonction software_Reboot pour rebooter la carte.

#include <avr/wdt.h>

void software_Reboot()

{

  wdt_enable(WDTO_15MS); while(1){}

}

22.1.3 Utilisation de la broche "Reset"

L'arduino possède une broche "Reset" (à coté du +3,3V sur le Uno"). Il suffit de raccorder une résistance de 1K entre la broche Reset et une broche digitale (ex: la pin 12).

Ensuite, il suffit d'utiliser la fonction suivante qui simule la pression du bouton Reset

void pushReset()

{

  int pin=12; pinMode(pin, OUTPUT);

  digitalWrite(pin, LOW);

}

22.2 Routines utilitaires

22.2.1 Générateur aléatoire

random(n) → entier aléatoire compris entre 0 et n.

22.2.2 Quatrième proportionnelle

 iy = map(ix, ix1, ix2, iy1, iy2);

version entière améliorée de iy = iy 1 + ( ix ix 1 ) × ( iy 2 iy 1 ) ( ix 2 ix 1 )

23 Les différentes cartes

  • Arduino Uno : La plus simple 

  • Arduino Leonardo : Evolution de l'Uno qui n'a pas eu de succès. 

  • Arduino Mega : La plus diffussée après la Uno. Mieux équipée et plus puissante. 

  • Arduino Mega ADK : idem Mega mais ouverte sur le monde Android. 

  • Arduino Due : La plus performante au niveau algorithmes (doubles en 64 bits) 

  • Arduino Nano : Une Uno miniaturisée. 

  • Arduino Yun : Orientée Linux dotée nativement d’un wifi intégré. 

 

 

Uno

Mega 2560

Due

Nano

µcontroleur

ATmega328P

ATmega2560

AT SAM3X8E

ATmega328

Flash

32 ko

256 ko

512 ko

32 ko

EEPROM

1 ko

4 ko

0

1 ko

SRAM

2 ko

8 ko

96 ko

2 ko

E/S Num

14

54

54

14

dont PWM

6

15

12

6

SPI

1

1

1

1

LED

1

1

1

1

TWI (I2C)

1:(A4-5)

1:(d20-21) +  ??

2

1:(A4-5)

Entrées Analogiques

6

16

12

8

Série (mat.)

1

4

4

1

Interrup. ext.

2

6

54

2

 

23.1 Connaitre la carte dans le code :

#if defined(TEENSYDUINO)

    //  --------------- Teensy -----------------

 

    #if defined(__AVR_ATmega32U4__)

        #define BOARD "Teensy 2.0"

    #elif defined(__AVR_AT90USB1286__)      

        #define BOARD "Teensy++ 2.0"

    #elif defined(__MK20DX128__)      

        #define BOARD "Teensy 3.0"

    #elif defined(__MK20DX256__)      

        #define BOARD "Teensy 3.2" // and Teensy 3.1 (obsolete)

    #elif defined(__MKL26Z64__)      

        #define BOARD "Teensy LC"

    #elif defined(__MK64FX512__)

        #define BOARD "Teensy 3.5"

    #elif defined(__MK66FX1M0__)

        #define BOARD "Teensy 3.6"

    #else

       #error "Unknown board"

    #endif

#else // --------------- Arduino ------------------

    #if   defined(ARDUINO_AVR_ADK)      

        #define BOARD "Mega Adk"

    #elif defined(ARDUINO_AVR_BT)    // Bluetooth

        #define BOARD "Bt"

    #elif defined(ARDUINO_AVR_DUEMILANOVE)      

        #define BOARD "Duemilanove"

    #elif defined(ARDUINO_AVR_ESPLORA)      

        #define BOARD "Esplora"

    #elif defined(ARDUINO_AVR_ETHERNET)      

        #define BOARD "Ethernet"

    #elif defined(ARDUINO_AVR_FIO)      

        #define BOARD "Fio"

    #elif defined(ARDUINO_AVR_GEMMA)

        #define BOARD "Gemma"

    #elif defined(ARDUINO_AVR_LEONARDO)      

        #define BOARD "Leonardo"

    #elif defined(ARDUINO_AVR_LILYPAD)

        #define BOARD "Lilypad"

    #elif defined(ARDUINO_AVR_LILYPAD_USB)

        #define BOARD "Lilypad Usb"

    #elif defined(ARDUINO_AVR_MEGA)      

        #define BOARD "Mega"

    #elif defined(ARDUINO_AVR_MEGA2560)      

        #define BOARD "Mega 2560"

    #elif defined(ARDUINO_AVR_MICRO)      

        #define BOARD "Micro"

    #elif defined(ARDUINO_AVR_MINI)      

        #define BOARD "Mini"

    #elif defined(ARDUINO_AVR_NANO)      

        #define BOARD "Nano"

    #elif defined(ARDUINO_AVR_NG)      

        #define BOARD "NG"

    #elif defined(ARDUINO_AVR_PRO)      

        #define BOARD "Pro"

    #elif defined(ARDUINO_AVR_ROBOT_CONTROL)      

        #define BOARD "Robot Ctrl"

    #elif defined(ARDUINO_AVR_ROBOT_MOTOR)      

        #define BOARD "Robot Motor"

    #elif defined(ARDUINO_AVR_UNO)      

        #define BOARD "Uno"

    #elif defined(ARDUINO_AVR_YUN)      

        #define BOARD "Yun"

    // These boards must be installed separately:

    #elif defined(ARDUINO_SAM_DUE)      

        #define BOARD "Due"

    #elif defined(ARDUINO_SAMD_ZERO)      

        #define BOARD "Zero"

    #elif defined(ARDUINO_ARC32_TOOLS)      

        #define BOARD "101"

    #else

       #error "Unknown board"

    #endif

23.2 Arduino Uno

Alimentation :

La carte peut être alimentée soit par le jack d'alimentation CC (7 - 12 V), le connecteur USB (5 V) ou la broche VIN de la carte (7-12 V) .

Les broches sortie d'alimentation sont les suivantes :

  • 5V : sortie 5V régulé du régulateur sur la carte. 

  • 3V3. sortie 3,3 volts régulé du régulateur sur la carte. Consommation maximale de 50 mA. 

  • GND. Broches de terre. 

  • IOREF. Cette broche sur la carte Arduino fournit la référence de tension avec laquelle fonctionne le microcontrôleur. Un blindage correctement configuré peut lire la tension de la broche IOREF.. 

Mémoire :

L'ATmega328 dispose de 32 Ko (dont 0,5 Ko occupé par le bootloader). Il possède également 2 Ko de SRAM et 1 Ko d'EEPROM (qui peuvent être lus et écrits avec la  bibliothèque EEPROM ).

 

Entrée-Sortie numériques :

- 14 broches numériques de l'Uno peut être utilisée comme entrée ou sortie, à l'aide des fonctions  pinMode() , digitalWrite() et  digitalRead()  . Elles fonctionnent sous 5 volts. Chaque broche peut fournir ou recevoir 20 mA selon les conditions de fonctionnement recommandées et possède une résistance de rappel interne (déconnectée par défaut) de 20 à 50 kohms. Un maximum de 40 mA est la valeur qui ne doit être dépassée sur aucune broche d'E/S .

- Fonstions spécialisées :

  • Série : 0 (RX) et 1 (TX). E/S série TTL. Ces broches sont connectées aux broches correspondantes de la puce série ATmega8U2 USB-to-TTL. 

  • Interruptions externes : 2 et 3. Ces broches peuvent être configurées par la fonction attachInterrupt(). 

  • PWM : 3, 5, 6, 9, 10 et 11. Fournissez une sortie PWM 8 bits avec la fonction analogWrite(). 

  • SPI : 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK). Ces broches prennent en charge la communication SPI à l'aide de la bibliothèque SPI. 

  • LED : 13. Il y a une LED intégrée pilotée par la broche numérique 13 (allumée si HIGH et éteinte si LOW). 

  • TWI : broche A4 ou SDA et broche A5 ou SCL. Prise en charge de la communication TWI à l'aide de la bibliothèque Wire. 

Entrées analogiques :

- 6 entrées analogiques, étiquetées A0 à A5, chacune fournissant 10 bits de résolution de 0 à 5 volts, mais il est possible de modifier l'extrémité supérieure de la plage à l'aide de la broche AREF et de la fonction analogReference().

- AREF. Tension de référence pour les entrées analogiques. Utilisé avec analogReference().

 

Autres :

- Reset. Mettre à LOW pour réinitialiser le microcontrôleur. Généralement utilisé lorsque le bouton de reset est rendu inaccessible par un montage annexe.

 

Communication

L'ATmega328 fournit une communication série UART TTL (5V), disponible sur les broches numériques 0 (RX) et 1 (TX). Un ATmega16U2 sur la carte canalise cette communication série via USB et apparaît comme un port de communication virtuel pour le logiciel sur l'ordinateur. Le micrologiciel 16U2 utilise les pilotes COM USB standard et aucun pilote externe n'est nécessaire. Cependant,  sous Windows, un fichier .inf est requis . Le logiciel Arduino (IDE) comprend un moniteur série qui permet d'envoyer des données textuelles simples vers et depuis la carte. Les LED RX et TX de la carte clignotent lorsque les données sont transmises via la puce USB-série et la connexion USB à l'ordinateur (mais pas pour la communication série sur les broches 0 et 1).

 

Une bibliothèque SoftwareSerial  permet la communication série sur n'importe laquelle des broches numériques de l'Uno.

 

L'ATmega328 prend également en charge les communications I2C (TWI) et SPI. Le logiciel Arduino (IDE) comprend une bibliothèque Wire pour simplifier l'utilisation du bus I2C ; Pour la communication SPI, utilisez la  bibliothèque SPI .

 

Reset Logiciel :

Une des lignes de contrôle de flux matériel (DTR) de l'ATmega8U2/16U2 est connectée à la ligne de réinitialisation de l'ATmega328 via un condensateur de 100 nanofarads ce qui permet à l'IDE de télécharger du code en appuyant simplement sur le bouton de téléchargement dans la barre d'outils de l'interface sans avoir à appyer sur le bouton reste de l'Arduino.

Cette configuration a d'autres implications. Lorsque l'Uno est connecté à un ordinateur exécutant Mac OS X ou Linux, il se réinitialise à chaque fois qu'une connexion est établie à partir d'un logiciel (via USB). Pendant environ la demi-seconde suivante, le chargeur de démarrage (bootloader) s'exécute sur l'Uno. Bien qu'il soit programmé pour ignorer les données malformées (c'est-à-dire tout autre chose qu'un téléchargement de nouveau code), il interceptera les premiers octets de données envoyés à la carte après l'ouverture d'une connexion. Si un sketch exécuté sur la carte reçoit une configuration unique ou d'autres données lors de son premier démarrage, assurez-vous que le logiciel avec lequel il communique attend une seconde après l'ouverture de la connexion et avant d'envoyer ces données.

23.3 Arduino Mega

 

- 4 liaisons séries matérielles
  • Serial : RX=0, TX=1 

  • Serial1 : RX=19, TX=18 

  • Serial2 : RX=17, TX=16 

  • Serial3 : RX=15, TX=14 

 

- 6 interruptions externes accessibles via l'instruction attachInterrupt(). Broches :

  • 2 (interrupt 0),  

  • 3 (interrupt 1),  

  • 18 (interrupt 5),  

  • 19 (interrupt 4),  

  • 20 (interrupt 3), 

  • 21 (interrupt 2). 

- PWM (largeur d'impulsion modulée) accessibles via l'instruction analogWrite():

  • Broches 0 à 13 

- SPI (Interface Série Périphérique): Broches 50 (MISO), 51 (MOSI), 52 (SCK), 53 (SS).

- I2C: Broches 20 (SDA) et 21 (SCL).

- LED incluse: Broche 13.

- Broches analogiques accessibles via l'instruction analoganalogRead()

  • 16 entrées analogiques (10 bits cad 0 à 1023) entre le 0V (valeur 0) et le 5V (valeur 1023) 

    Note : les broches analogiques peuvent être utilisées en tant que broches numériques.  

- AREF : Tension de référence pour les entrées analogiques (si différent du 5V). Utilisée avec l'instruction analogReference().

- Reset : Mettre cette broche au niveau BAS entraîne le redémarrage du microcontrôleur.

Attention :

Les port série/USB des cartes officielles utilise le chip FTDI qui est bien pris en charge par Windows 10 et des copies chinoises utilisent parfois le chip CH340 qui n'est pas pris en charge nativement et qui nécessite l'installation d'un driver (à télécharger ?).

 

23.4 Arduino Nano

Alimentation via port USB, ou 5 Vcc régulée sur broche 27, ou 6 à 20 V non régulée sur broche 30.

Mémoire

  • Atmega168 : flash: 16 ko, SRAM: 1 ko, EEPROM: 512 ko 

  • Atmega328 : flash: 32 ko, SRAM: 2 ko, EEPROM: 1 ko 

Cadencement: 16 MHz

01        TX1        D1        (E/S) Broche série TX

02        RX0         D0        (E/S) Broche série RX

03        RST                Reset

04        GND                 Masse d’alimentation

05        D2        D2        (E/S) et Envoi Int.

06        D3        D3        (E/S) et Envoi Int. et PWM

07        D4        D4        (E/S)

08        D5        D5         (E/S) et PWM

09         D6         D6         (E/S) et PWM

10         D7        D7         (E/S)

11         D8        D8         (E/S)

12         D9        D9         (E/S) et PWM

13         D10        D10         (E/S) et PWM

14         D11        D11        (E/S) et PWM

15         D12        D12        (E/S)

16         D13        D13        (E/S) – LED intégrée

17         3V3                 Sortie 3.3V

18         REF        AREF         Entrée         AREF

19         A0        A0        Entrée analogique 0

20         A1         A1        Entrée analogique 1

21         A2         A2        Entrée analogique 2

22         A3        A3        Entrée analogique 3

23         A4        A4        Entrée analogique 4

24         A5        A5        Entrée analogique 5

25         A6        A6        Entrée analogique 6

26         A7        A7        Entrée analogique 7

27         5V                 Entrée/Sortie 5V

28         RST                Reset

29         GND                 Masse d’alimentation

30         VIN                 Alimentation

 

AREF : Tension de référence pour les entrées analogiques (si différent du 5V). Utilisée avec l'instruction analogReference().

Reset : Mettre cette broche au niveau BAS entraîne le redémarrage du microcontrôleur.

 

Les 6 broches à l'opposé du port USB constituent un port ICSP (In Circuit Serial Programming, parfois noté ISCP) qui peut être utilisé pour flasher l'ATmega (méthode ??)

 

Liste par catégories (il y a des recoupements)

  • 14 broches digitales I/0 : broches 1 ,2,5,6,7,8,9,10,11,12,13,14,15,16. Voltage bas 0V, haut +5V, courant 40 mA.  

  • 6 broches PWM : broches 6 (D3), 8 (D5), 9 (D6), 12 (D9), 13 (D10), 14 (D11) 

  • 8 broches entrées analogiques : broches 18 à 26 

  • Communication série : broches 1(TX1 = D1), 0 (RX0 = D0) 

  • Seules les broches 5 (D2) et 6 (D3)  peuvent être utilisées pour envoyer des interruptions. 

Alimentation de la carte : 3 solutions :

  1. 1.Via le port USB 

  2. 2.Alim régulée 5V sur broche 5V (n° 27) 

  3. 3.Alim entre 7 et 12 v sur broche Vin (n° 30) 

 

23.5 Aduino Due

Contrairement aux autres cartes Arduino, l'Arduino Due fonctionne à 3.3 V au lieu des 5 V des autres cartes, de plus les réels "double" sont en 64 bits et toutes les broches numériques D peuvent envoyer des interruptions. La prise usb pour la programmation est celle qui est proche du jack d'alimentation.

  • Microcontrôleur: Atmel SAM3X8E ARM Cortex-M3 32 bits 84 Mhz 

  • Mémoires RAM: 96 Ko (répartis dans 2 banques de 64 Ko + 1 banque de 32 Ko) 

  • 2 microUSB: il en a 2 : Un pour la programmation (la plus proche de la prise d'alimentation) sélectionnée dans l'IDE par "ProgrammingPort" et un autre qui peut être utilisé en sélectionnant "NativeUSBPort". 

  • Flash: 512 Ko, tous disponibles au programme, 

  • Tension de fonctionnement: 3.3v (il y a une broche 5v pour les projets) 

  • Tension d'entrée (recommandée): 7-12v 

  • Tension d'entrée (limite maximale): 6-16v 

  • 54 Broches d'E/S numériques dont 12 PWM. 

  • 12 Broches d'entrée analogiques 

  • 2 Broches de sortie analogique (CNA) 

  • Intensité du courant par broche d'E / S: 130mAI 

  • Intensité du courant pour la broche 3.3v: 800mA 

  • Intensité du courant pour la broche 5v: 800mA 

 

Il y a un port USB OTG haute vitesse, 4 UART, un connecteur JTAG, un bouton de réinitialisation, un bouton de suppression, un connecteur SPI et 2 TWI avec broches SDA et SCL

  • Instruction IOREF qui permet à un bouclier d'adapter sa tension à celle de la plaque. 

  • Une broche non connectée Réservé pour une utilisation future. 

 

Arribution des broches :

  • Série 0: sur la broche 0 (RX) et la broche 1 (TX) 

  • Série 1: broche 19 (RX) et broche 18 (TX) 

  • Série 2: broche 17 (RX) et broche 16 (TX) 

  • Série 3: broche 15 (RX) et broche 14 (TX) 

  • PWM: passez des broches 2 à 13 pour fournir un PWM 8 bits. 

  • E/S numériques: de la broche 0 à 53 

  • Sorties analogiques: de la broche A0 à A11 

  • SPI: Tête SPI 

  • CAN: CANRX et CANTX pour la communication CAN 

  • DEL intégré inclus et connecté à la broche 13 

  • TWI 1: broche 20 (SDA) et broche 21 (SCL) 

  • TWI 2: marqué comme SDA1 SCL1 

  • DAC1 et DAC2 avec une résolution dans sa sortie de 12 bits (4096 niveaux) avec analogWrite () avec des tensions de 0.55v à 2.75v. 

  • AREF: une entrée analogique comme référence de tension. Utilisé avec la fonction analogReference () 

  • Réinit: si vous réglez cette ligne sur un niveau de tension bas ou bas, le microcontrôleur se réinitialise. 

 

Brochage :

Pour la programmation avec l'IDE, il faut choisir  la carte Arduino Due, dans les cartes ARM (32 bits) et non pas dans les cartes AVR (8 bits), celle via "Programming port" (celui qui est du coté du jack d'alimentation) et non l'autre (Native USB Port).

Réinitialisation automatique (logicielle)

Le microcontrôleur SAM3X diffère des microcontrôleurs AVR car la mémoire flash doit être effacée avant d'être reprogrammée. Une procédure manuelle impliquerait de maintenir enfoncé le bouton d'effacement pendant une seconde, d'appuyer sur le bouton de téléchargement dans l'IDE, puis sur le bouton de réinitialisation.

La procédure manuelle d'effacement-flash étant répétitive, elle est gérée automatiquement par les deux ports USB, de deux manières différentes :

Port natif

L'ouverture et la fermeture du port ''Natif' au débit en bauds de 1200bps déclenchent une procédure de "soft erase" : la mémoire flash est effacée et la carte est redémarrée avec le bootloader. Si, pour une raison quelconque, le MCU devait planter au cours de ce processus, il est probable que la procédure d'effacement en douceur ne fonctionnerait pas comme c'est le cas dans le logiciel du MCU lui-même.

L'ouverture et la fermeture du port natif à un débit en bauds autre que 1200bps ne réinitialisera pas le SAM3X. Pour utiliser le moniteur série et voir ce que fait votre sketch depuis le début, vous devrez ajouter quelques lignes de code dans le setup(). Cela garantira que le SAM3X attendra que le port SerialUSB s'ouvre avant d'exécuter l'esquisse :

while (!Serial) ; [Obtenir le code]

L'Appui sur le bouton Reset du Due provoque la réinitialisation du SAM3X ainsi que la communication USB. Cette interruption signifie que si le moniteur série est ouvert, il est nécessaire de le fermer et de le rouvrir pour redémarrer la communication.

Port de programmation

Le port de programmation utilise une puce USB-série connectée au premier UART du MCU (RX0 et TX0). La puce USB-série a deux broches connectées aux broches de réinitialisation et d'effacement du SAM3X. Lorsque vous ouvrez ce port série, l' USB-série active la séquence d'effacement et de réinitialisation avant de commencer à communiquer avec l'UART du SAM3X. Cette procédure est beaucoup plus fiable et devrait fonctionner même si le MCU principal est tombé en panne.

Pour communiquer en série avec le port de programmation, utilisez l'objet "Serial" dans l'IDE. Tous les croquis existants qui utilisent une communication série basée sur la carte Uno devraient fonctionner de la même manière. Le port de programmation se comporte comme le port série de l'Uno en ce sens que la puce USB-série réinitialise la carte chaque fois que vous ouvrez le moniteur série (ou toute autre communication série).

Le fait d'appuyer sur le bouton de réinitialisation pendant la communication via le port de programmation ne ferme pas la connexion USB avec l'ordinateur car seul le SAM3X est réinitialisé.

24 Différents types de mémoire

24.1 La RAM

Dans un Arduino c'est de la SRAM (pour Static Random Access Memory), qui est plus rapide mais aussi plus consommatrice en énergie que la RAM dynamique de ordinateurs. Elle est entièrement effacée lorsque l’alimentation de l’Arduino cesse.

24.2 L’EEPROM

L’EEPROM (Electrically Erasable Programmable Read-Only Memory) est capable de stocker des informations même lorsqu’elle n’est plus alimentée. La vitesse d’accès est moins élevée que la RAM et sa durée de vie (nombre de cycle d’écritures possible) est également plus faible.

 Pour pouvoir manipuler l’EEPROM, il faut dans un premier temps inclure la bibliothèque EEPROM.h. Une case mémoire qui n’a jamais été utilisée possède une valeur initiale de 255.

Enregistrer des données

La mémoire EEPROM est donc divisée en 1024 blocs de 8 bits. Pour écrire une donnée, il préciser dans quel bloc on veut l’enregistrer au moyen de la fonction EEPROM.write() qui prend comme arguments l’adresse (int entre 0 et 1023) et l’octet à enregistrer (unsigned char).

EEPROM.write(600, 42); //adresse = 600, valeur = 42

Lire des données

unsigned char donnee = EEPROM.read(600); //adresse = 600

//Ecriture d'un type int en mémoire EEPROM

void sauverInt(int adresse, int val)

{  

 

    unsigned char faible = val & 0x00FF;

    unsigned char fort = (val >> 8) & 0x00FF;

    EEPROM.write(adresse, fort) ;

    EEPROM.write(adresse+1, faible);

}

 

//lecture de l'int enregistrée par la fonction précédente

int lireInt(int adresse)

{

    int val = 0 ;

    unsigned char fort = EEPROM.read(adresse);

    unsigned char faible = EEPROM.read(adresse+1);

    val = fort ;

    val = val << 8 ;

    val = val | faible ;

    return val ;

}

24.3 La mémoire FLASH

Elle sert à stocker le programme téléchargé dans le microcontrôleur même lorsque l’alimentation est coupée et le bootloader. Ce dernier détecte au démarrage de l’Arduino si on tente de programmer la carte via la liaison série et le cas échéant il copie les données dans la mémoire FLASH. On n’y stocke pas de données pendant l’exécution du programme. En revanche, on peut y stocker des constantes afin de gagner un peu de place dans la RAM.

Avec la DUE il est en théorie possible d’écrire dans la mémoire Flash pendant l’exécution du programme, mais aucune bibliothèque dédiée n’existe pour le moment.

La "mémoire de programme" (ou encore "Progmem") sert d’ordinaire à stocker le code créé puis compilé. On ne peut enregistrer des données dedans qu’au moment du téléchargement du programme. Une fois le programme chargé, elle agit en lecture seule, si bien qu'on ne peut que récupérer des données injectées plus tôt.

Enregister des données dans la mémoir Flash

Les données que l'on peut enregistrer dans la mémoire Flash sont de char, int, long (unsigned ou signed).

On utilise la librairie avr/pgmspace.h et le modificateur PROGMEM lors de sa déclaration (tout en majuscule) :

#include <avr/pgmspace.h>

const int myint1 PROGMEM = 42; //ce int est enregistré en mémoire flash

const PROGMEM int myint2 = 42 ; //ce int est enregistré en mémoire flash

Le mot-clé PROGMEM ne doit pas être situé entre le type et le nom de la variable.

La lecture se fait à partir de l'adresse par

pgm_read_byte() -> pour lire un char

pgm_read_word() -> pour lire un int

pgm_read_dword() -> pour lire un long

Exemple :

#include <avr/pgmspace.h>

const unsigned char unChar PROGMEM = 42;

const unsigned int unInt PROGMEM = 1324;

const unsigned long unLong PROGMEM = 987654;

const char message[] PROGMEM = "Salut les gens !";

void setup()

{

    Serial.begin(9600);

    Serial.print("Mon char : ");

    Serial.println(pgm_read_byte(&unChar));

    Serial.print("Mon int : ");

    Serial.println(pgm_read_word(&unInt));

    Serial.print("Mon long : ");

    Serial.println(pgm_read_dword(&unLong));

    char temp = pgm_read_byte(message); //on récupère le premier caractère

    char i=0;

    while(temp != '\0')

    {

        Serial.print(temp);

        i++;

        temp = pgm_read_byte(message + i);

    }

    Serial.println();

    Serial.println(F("Encore plus simple !"));

}

Pour les chaines de caractères il y a plus simple avec la fonction F().

F("Chaine completement en flash !")

 

1le code PRN (Pseudo ramdom noise) est un numéro qui caractérise la fonction occupée par un satellite dans sa constellation