Première connexion au PC

Installer le logiciel (IDE).

Ar_Pgm_downloadAller sur la page de téléchargement du logiciel Arduino et télécharger. S’il existe une version « Installer » et une version « ZIP file » alors la plus simple est « Installer » car il suffit de double-cliquer pour installer le programme.

Ar_Pgm_disquedurLe programme fait plus de 50 Mo car il contient tous les outils qui permettront de fonctionner sans aucun autre programme, ainsi qu’une bibliothèque d’exemples et les drivers !

Une fois le téléchargement terminé, installer alors cet IDE.

Connecter la carte.

Ar_Pgm_led_alimentation

Ar_Pr_cableUSB_typeAB

Avec un câble USB (type A / type B), relier la carte à votre ordinateur sur le port USB …  la carte devrait s’installer toute seule.

L’USB alimente alors la carte et une petite LED verte devrait s’allumer (et un clignotement de la LED du pin 13).

La carte est alors reconnue comme un nouveau port série (un port COM). Cependant, contrairement aux apparences, il ne s’agit pas d’une véritable connexion USB, mais d’une émulation du port USB en port série !

0_ambulance Si problème : Sachez que les pilotes Windows de la carte sont inclus dans le logiciel Arduino téléchargé juste au-dessus, donc si besoin, on peut indiquer à Windows de chercher les drivers dans ce répertoire. Pour faire cela :Ar_Pgm_periph_inconnu

  • On va dans le gestionnaire de périphériques en faisant : panneau de configuration > système  > gestionnaire de périphériques (sur le panneau gauche).
  • Une fois gestionnaire de périphériques ouvert, vous devriez voir un périphérique mal-installé (avec un panneau « attention » jaune), clic droit > Mettre à jour les pilotes > Rechercher le pilote moi-même, puis sélectionner le répertoire du logiciel Arduino puis son dossier drivers.

Régler :  type de carte et port COM.

IDE : Menu Outils

Ensuite il faut indiquer au logiciel Arduino le type de carte Arduino utilisée (Uno, Duemilanove, Mega …) et aussi le numéro du port série sur lequel est connectée la carte :

  • Type de carte : menu  Outils > Type de carte et choisir Uno.
  • n° du port COM : menu  Outils > Port série et choisir parmi : COM1, COM2, … et pour ne pas se tromper, lisez ce qui suit.

Comment trouver le n° de port COM.

Il suffit de comparer la liste des ports COM proposés par l’IDE lorsque la carte est connectée ou pas. On procède ainsi :

  • Connecter la carte Arduino et observer la liste des ports COM dans  le menu :  Outils > Port série.
  • Déconnecter la carte Arduino et observer à nouveau la liste des ports COM (Outils > Port série) . Le port COM qui a disparu est celui de votre carte !!
  • Rebrancher la carte (sur le même port USB que précédemment .. évidemment ! ) et régler l’IDE sur le port COM en question.

Test : 1er programme.

Ecrire le code

Ar_pgm_blink

L’IDE contient un bon nombre de programmes déjà écrits, ils se trouvent dans : menu  Fichier > Exemples.

Exemple : Prenons le programme qui consiste à faire clignoter la LED, se nomme Blink , il se trouve dans la catégorie Basics  :  Fichier > Exemples > 01.Basics > Blink.

Une nouvelle fenêtre s’ouvre avec le code de Blink. Régler l’IDE sur le bon type de carte et le port COM. (Vous pouvez fermer l’ancienne fenêtre.)

Téléverser le code

Pour téléverser :  clic sur Ar_Pr_Btn_upload   ou   menu  Fichier > Téléverser.

NB : « téléverser » (upload) consiste à envoyer le code dans la mémoire de la carte Arduino (son contraire est télécharger, c’est-à-dire recevoir des données).

0_ambulance  Si problème :

  • Vérifier le type de carte : menu  Outils > Type de carte  (la petite carte bleu est la UNO).
  • Vérifier le port COM : menu  Outils > Port série.
  • Téléverser à nouveau le programme (cette étape peut être capricieuse et bugger de temps en temps).

0_ambulance  Erreur  avrdude: stk500_recv() et avrdude: stk500_getsync() :

  • changer de câble USB (sur mes 3 câbles, un seul fonctionne).
  • appuyer sur le RESET de la carte au moment précis où commence le téléversement :
    • Mettre les préférences du logiciel sur téléversement détaillé : Fichier > Préférences > 'Afficher les résultats détaillés pendant :' cocher 'téléversement'
    • Lancer le téléversement, et dès que te taux apparaît (le nombre de bauds), appuyer sur RESET (sur la carte).

Variante : On peut aussi rester appuyé sur RESET puis ne relâcher qu’à l’apparition du taux de transfert.
        

Les principales instructions

Règle n°1 : Toute instruction se termine par un point-virgule.

Règle n°2 : Les 5 fonctions incontournables pour programmer votre Arduino :

  • digitalWrite(pin,etat) sur pin Digital : digitalWrite sert à envoyer du courant positif (HIGH donc +5v ) ou négatif (LOW donc GND) dans la broche Digitale indiquée.
    void setup() {
      pinMode(13, OUTPUT);   // met la digital pin 13 en mode "sortie". Rappel : pin 13 est relié à la LED
    }
    
    void loop() {
      digitalWrite(13, HIGH);  // allume la LED (on envoie une tension)
      delay(1000);             // on attend 1 seconde (1000 ms)
      digitalWrite(13, LOW);   // éteint la LED (on met la tension à 0)
      delay(1000);             // on attend 1 seconde (1000 ms)
    }
    

  • analogWrite(pin,valeur) sur pin PWM : analogWrite sert à envoyer un courant plus ou moins puissant, compris entre 0 et 255 dans la broche PWM indiquée (digitale). Rappel : PWM = pin 3, 5, 6, 9, 10, 11.
    NB : Il est inutile de mettre la broche en mode « sortie » (pas besoin de pinMode(pin, OUTPUT) ).
    NB : analogWrite ne se comporte pas du tout comme analogRead.

    void setup() { }
    
    void loop() {
      analogWrite(13, 211);  // envoie le signal 211 dans la broche PWM 11
    }
    

  • analogRead(pin) sur pin Analogique : analogRead permet de connaître le courant circulant au niveau du pin Analogique concerné. analogRead retourne une valeur comprise entre 0 et 1023.
    NB : Il est inutile de mettre la broche en mode « entrée » (pas besoin de pinMode(pin, INPUT) ) car toutes les broches analogiques sont des « entrées » !!
    NB : analogRead ne se comporte pas du tout comme analogWrite.

    int valeur = 0;        // déclaration de "valeur" : une variable qui contiendra un entier (de type int) 
    
    void setup() {
      Serial.begin(9600);  // ouvre une connexion série (avec le PC) de débit 9600 bps (9600 bits par seconde) 
    }
    
    void loop() {
      valeur = analogRead(3);  // analyse le potentiel de la broche A3 et le stocke dans la variable "valeur"
      Serial.println(valeur);  // affiche cette valeur dans la console (pour débogage)
    }
    

  • digitalRead(pin) sur pin Digital : digitalRead permet de savoir si le courant circule dans le pin digital concerné. digitalRead retourne que deux valeurs possibles : 0 ou 1.
    int s;  // on déclare une variable "s" de type entier (int)
    
    void setup() {
      pinMode(7, INPUT);    // met la broche digitale 7 en mode "entrée"
    }
    
    void loop() {
      s = digitalRead(7);   // renvoie 0 ou 1 selon le signal de la broche 7 et l'affecte à la variable s
    }
    

  • delay(valeur) : delay met en pause le programme pendant le temps indiqué, en millisecondes. Cette instruction est très utile (ex : pour faire clignoter une led, ou pour laisser le temps au robot d’avancer avant de passer à la suite du programme ..).
    delay(2000);   // attend 2 secondes (avant de passer à l'instruction suivante) 
    

Les commentaires

Utilité des commentaires

Les commentaires permettent d’annoter un programme : expliquer un bout de code, indiquer un bug … ils ne servent donc à rien pour la carte mais ils sont fondamentaux pour la personne qui s’impliquera dans votre projet (votre collègue, votre professeur …) ! Et bien entendu, il faut commenter au fur et à mesure de l’avancement du programme, il ne s’agit pas d’attendre la fin du projet pour mettre les commentaires !

Commentaire ligne  :  //

Ar_Ins_commentaireDans les programmes précédents,  // indique un commentaire-ligne. C’est simplement une ligne que le compilateur ne doit pas prendre en compte.
Le commentaire commence par // et se termine à la fin de la ligne.

Commentaire bloc  :   /*   ……   */

On peut également mettre un paragraphes (donc plusieurs lignes) en commentaire ; pour cela il suffit de placer  /* au début et */ à la fin.

Les variables

Utilisation : déclaration et affectation

Pour se représenter une variable, il faut imaginer que la mémoire de l’ordinateur est composée d’une multitude de petites boîtes. Chacune de ces boîtes porte un nom et ne peut contenir qu’une valeur. Changer cette valeur signifie qu’on perd la valeur précédente (on dit qu’on écrase l’ancienne valeur).

0_case_variable

Pour utiliser une variable, il faut :

  • commencer par indiquer son type (entier, nombre à virgule, booléen, caractère …) : c’est la déclaration d’une variable.
  • puis lui donner une valeur : c’est l’affectation.

Ces deux étapes peuvent être faîtes en 1 instruction :

int s = analogRead(15); // déclaration et affectation de la variable s

Ou en 2 instructions :

int s; //déclaration variable entière "s"
s = analogRead(15); // affectation de la variable s

Ensuite, l’intérêt des variables est d’effectuer :

  • des calculs : addition (+), multiplication (*), …
  • des tests : if (s > 11) { digitalWrite(12,LOW); }
  • des boucles : for (s = 1 ; s<11 ; s++) { digitalWrite(13, 2*s); }

Types de variables

Les types de variables les plus utilisés en Arduino :

  • int :  pour stocker un nombre entier (integer).
  • float :  pour stocker un nombre à virgule (un flottant).
  • boolean :  pour stocker un état « tout ou rien ». Il n’y a que 2 valeurs booléennes :  TRUE et FALSE.

NB : L’avantage des booléens est qu’ils ne prennent que 1 bit en mémoire …

boolean clignote = TRUE;
float angleDeRotation = 10.54;
int duree_en_ms = 2000;

Nom de variable

Le nom de variable accepte quasiment tous les caractères sauf les : point, virgule, lettre accentuée, espace ..
En revanche, il accepte l’underscore « _ » et les majuscules. D’ailleurs, on les utilise souvent pour distinguer les mots : angleDeRotation ou duree_en_ms.

En principe, un nom de variable entièrement en majuscule symbolise plutôt une constante dans le programme. Exemple :

int PIN_MOTEUR_A = 13;
int PIN_MOTEUR_B = 14;
float PI = 3.14;

void setup(){}
void loop(){}

Les caractéristiques de l’UNO

Ar_Pr_carte_perspective_legende

  • Taille : 5,5 cm x 7 cm  (épaisseur = 1.5 cm)
  • Microcontroleur : ATmega328P cadencé à une fréquence de 16 Mhz.
  • Mémoire flash : 32 ko pour stocker le programme Arduino.
  • Mémoire vive : 2 ko de SRAM
  • Mémoire morte : 1 ko d’EEPROM destinée aux données.
  • Des broches : utilisant un courant de 40 mA pour une tension de 5 V.

Alimenter de la carte en courant

Ar_Pr_alim_jack

Il y a 3 façons d’alimenter la carte  :

  • par un câble USB relié à un ordinateur ou une batterie.
  • par câble jack à une pile 9V (ou plus généralement une batterie entre 7 V et 12 V) … mais la polarité est importante, il faut le + au centre du jack.
  • par le biais des 2 broches « Vin » et « GND ». « Vin » est connecté au pôle « + » d’une pile 9V de la pile et GNG connecté au pôle « – » (ou une batterie entre 7 V et 12 V en respectant la polarité).

Attention : les broches 3,3 V et 5 V ne sont pas des entrées d’alimentation pour la carte mais des sorties, cela signifie qu’elles peuvent servir pour alimenter d’autres périphériques (des cartes shield comme carte de contrôle moteur … ).

14 broches digitales (entrée ou sortie)

Ar_Pr_carte_face_legende

La particularité d’Arduino est de mettre à votre disposition un ensemble de broches et c’est à vous de les configurer (via le programme). Les 14 broches digitales peuvent être configurées comme entrée ou sortie, par exemple : 7 entrées/7 sorties, ou 10 entrées/4 sorties, … Comme elles sont « digitales » alors  elles ne permettent que 2 valeurs : le 0 ou le 1 … c’est du « tout ou rien » !! Par exemple, une LED connectée sur une sortie digitale n’a que 2 états « allumée » ou « éteinte » … pas d’éclairage à 75%  (à moins d’utiliser le PWM – expliqué plus bas)  !

Comment une broche exprime-t-elle un 0 ou un 1 ?

En fait, c’est le potentiel de la broche qui est interprété par un 0 ou un 1 !

En mode « sortie » : le 0 logique met le potentiel du pin sur 0V et le 1 logique le met sur  5V.

En mode « entrée » : si le pin reçoit entre 0V et 2,5V alors cette tension est traduite en un 0 logique ; s’il reçoit entre 2,5V et 5V alors ce sera le 1 logique.

Qu’est-ce que le PWM ?

Ar_Pr_pwm

La bonne nouvelle est que, parmi les broches digitales, 6 sont capables de produire du PWM (pins 3, 5, 6, 9, 10, 11), c’est à dire se comporter comme une sortie analogique et par exemple régler la luminosité d’une LED à 75%  ! En réalité, c’est un trompe l’œil, le signal n’est pas une ligne à 75% mais un signal carré, c’est à dire une succession très rapide de 0 et 1 (PWM : ~ 500 Hz) donc cela produit un clignotement permanent de la LED à 500 Hz … imperceptible par l’œil donc vu comme un éclairage à 75% (fréquence de l’œil : ~ 70 Hz) !

Broches digitales particulières (PWM, RX, TX, LED 13)

Parmi ces 14 pins, il y a :

  • pins 0 et 1 : RX et TX  : réservés à la communication de données en entrée et sortie.
  • pin 13 : elle est reliée à une LED en série ; donc permet de mieux visualiser le signal.
  • pins 3, 5, 6, 9, 10, 11 : ces 6 broches peuvent générer des sorties PWM (Pulse Width Modulation ou Modulation de largeur d’impulsion) c’est à dire 0 pendant une durée puis 1 pendant une autre durée, et cela périodiquement.

6 broches analogiques (des entrées)

Les 6 entrées analogiques (pins A0 à A5) convertissent une tension de 0 à 5V en un nombre de 0 à 1023 (sur 10 bits). Les entrées analogiques permettent donc une grande diversité de valeurs (contrairement aux digitales).

Les cartes filles (shield).

Ar_Pr_avecMotorShieldPour que la carte soit intéressante, il faut rajouter des accessoires plus concrets (une diode, une sonde de température, un module bluetooth …) pour interagir avec l’extérieur. Cet accessoire peut aussi être une autre carte qui s’emboîte sur la carte bleue (on peut en empiler plusieurs). Par exemple, ça peut être une carte de contrôle de moteur pour diriger les roues d’un robot. Il existe une multitude de cartes shield (carte Ethernet, carte wifi, …).

On trouve des alcootests, des cubes de LED, des systèmes de domotique, des afficheurs Twitter et même des kits d’analyse ADN basés sur Arduino.

Les autres cartes Arduino

Il existe plusieurs modèles de cartes Arduino, la plus petite est la UNO (c’est la moins chère).

Il en existe d’autres possédant davantage d’entrées / sorties, de mémoires et doté d’un meilleur microcontroleur … (elles sont plus onéreuses) : Mega, Due … et plus anciennement : Leonardo, Duemilanove !

Ar_Pr_autreCartesArduino

Le logiciel (IDE)

L’IDE (environnement de développement) est libre et gratuit ; il est distribué sur le site d’Arduino (compatible Windows, Linux et Mac)  https://arduino.cc/en/main/software Ar_Pr_IDE

 

Le langage impose une structure particulière :

  • setup()  est une fonction qui contient les initialisations. Ce sont les opérations nécessaires à la configuration de la carte (directions des entrées sorties, débits de communications série, etc.).
  • loop() est une fonction exécutée en boucle après l’exécution de la fonction setup(). Elle continuera de boucler tant que la carte n’est pas mise hors tension ou redémarrée par le bouton Reset. On peut aussi téléverser le programme minimum c’est à dire :
     
    void setup() {}
    void loop() {}
    

Ar_Pr_Btn_verify Verify : pour vérifier que le programme compile correctement.
Ar_Pr_Btn_upload Upload : pour téléverser le programme dans la carte.
Ar_Pr_Btn_new New : pour créer un nouveau programme (appelé « Sketch »).
Ar_Pr_Btn_open Open : pour ouvrir un programme existant .. ou par le menu déroulant :  File > Open
Ar_Pr_Btn_save Save : pour sauvegarder le programme. Mais pour le sauvegarder sous un autre nom, passer le menu : File > Save as
Ar_Pr_Btn_serial Serial Monitor : pour ouvrir la fenêtre qui permet de visualiser les données transmises par le port série de la carte Arduino (très pratique pour chercher une erreur : le débogage ! )

Vidéo du projet de 2 élèves : controler la direction d’un robot par liaison Bluetooth (avec une appli Android gratuite) + 1 capteur de distance Ultra-Son à l’avant qui prévient d’obstacle + 1 lance-missile.

Application Androïd = Arduino Car Control

Cover art    Arduino Car Control – Capture d'écran

#define PIN_MISSILE 8
#define pwm_a 3   //vitesse moteur A (pin 3) (PWM)
#define pwm_b 11  //vitesse moteur B (pin 11)(PWM)
#define dir_b 13  //direction du moteur B : horaire/anti-horaire
#define dir_a 12  //direction du moteur A : horaire/anti-horaire
#define HOR  LOW
#define AHOR HIGH
#define COEF_B 0.89
#define AFOND 200

//Librairie Software Serial Port + initialise le BT
#include <SoftwareSerial.h>
#define RxD 9
#define TxD 10
SoftwareSerial btSerial(TxD, RxD);
String readString; //commande envoyée par l'app Android (en bluetooth)(1 mot)

//Librairie NewPing (pour l'UltraSon) + initialise UltraSon
#include <NewPing.h>
#define TRIGGER_PIN 7 //pin émetteur de l'Ultra-Son (mode OUTPUT)
#define ECHO_PIN 6    //pin récepteur de l'Ultra-Son (mode INPUT)
#define MAX_DISTANCE 200 // distance max (en cm) qu'on veut "pinger" (portée max = 400-500cm)
#define PING_INTERVAL 50 // tps d'attente entre 2 pings. 50 ms = 20 pings/seconde.
#define DANGER 25
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup (pins & max distance)
unsigned int distance;
unsigned long pingTimer;


void setup() { 
  btSerial.begin(9600); // Ouvre une communication Série avec le HC-06
  initMissile();
  initMoteur();
  Serial.begin(115200); //démarre la liaison "série" avec l'IDE
  pingTimer = millis() + 100; // millis() = tps écoulé en ms depuis début du pgm
}

void loop() {
  while (btSerial.available()) { // the code here is for bluetooth
    delay(3);
    char c = btSerial.read();
    readString += c;
  }

  // si temps écoulé depuis dernier "ping", on fait à nouveau un "ping".
  if (millis() > pingTimer) { // NB : no delay => multi-task
    pingTimer += PING_INTERVAL;  // temps pour déclenchement du prochain "ping"
    
    sonar.ping_timer(echoCheck); // envoie 1ping + appel echocheck() par intermitence(24us)
   }

  if (readString.length() > 0) { // when a certain button is pressed the reaction will be...
    Serial.println(readString);
    if (readString == "Forward") { forward(); }
    if (readString == "Back")    { back();    }
    if (readString == "Left")    { left();    }
    if (readString == "Right")   { right();   }
    if (readString == "Stop")    { stopped(); }
    if (readString == "Car on")  { }
    if (readString == "Car off") { }
    if (readString == "Far on")  { missile();  }
    if (readString == "Far off") { rafaleMissile();}
  }
  readString = "";
}


//----- Fonctions
void echoCheck() { // sous-programme d'interruption 
  if (sonar.check_timer()) { // si le ping est complet 
    distance = sonar.ping_result / US_ROUNDTRIP_CM;
    Serial.print("Ping: ");
    Serial.print(distance);
    Serial.println("cm");
    //Vérification du danger
    if ((distance > 0) && (distance < DANGER)) { stopped(); delay(400); }
  }
}

void missile() {
  digitalWrite(PIN_MISSILE, HIGH);
  delay(120); // 120 ms = 1 fléchette
  digitalWrite(PIN_MISSILE, LOW);
}

void rafaleMissile() {
  digitalWrite(PIN_MISSILE, HIGH);
  delay(400); // 400 ms = 5/6 fléchettes
  digitalWrite(PIN_MISSILE, LOW);
}

void forward() {
  digitalWrite(dir_a, HIGH);
  digitalWrite(dir_b, LOW);
  analogWrite(pwm_a, 255);
  analogWrite(pwm_b, 255);
}

void right() {
  digitalWrite(dir_a, HIGH);
  digitalWrite(dir_b, HIGH);
  analogWrite(pwm_a, 100);
  analogWrite(pwm_b, 100);
}

void back() {
  digitalWrite(dir_a, LOW);
  digitalWrite(dir_b, HIGH);
  analogWrite(pwm_a, 255);
  analogWrite(pwm_b, 255);
}

void left() {
  digitalWrite(dir_a, LOW);
  digitalWrite(dir_b, LOW);
    analogWrite(pwm_a, 255);
    analogWrite(pwm_b, 255);
}

void stopped() {
  digitalWrite(dir_a, LOW);
  digitalWrite(dir_b, LOW);
  analogWrite(pwm_a, 0);
  analogWrite(pwm_b, 0);
}

void initMissile() {
  pinMode(PIN_MISSILE, OUTPUT);
  digitalWrite(PIN_MISSILE, LOW);
}

void initMoteur() {
  pinMode(pwm_a, OUTPUT); //on met les 4 broches en mode "sortie"
  pinMode(pwm_b, OUTPUT);
  pinMode(dir_a, OUTPUT);
  pinMode(dir_b, OUTPUT);
}