Communiquer avec un ordinateur

De Wiki L.A.B
Aller à : navigation, rechercher

Communication IR

Matériel
  • 2 Arduino Uno
  • LED IR émittrice (exemple TSAL 6200)
  • KIT IR Réception (exemple SGK0002)
  • 2 résistances de 190 ohm (+/-)
  • APN avec déclenchement IR (Nikon D80 par exemple)
Principe

L'arduino couplé avec la LED IR va émettre en direction de l'arduino couplé avec le kit IR. Les exemples de code se basent sur la librairie IR REMOTE Cette librairie permet d’émettre et de recevoir via l’infrarouge; elle permet de gérer les protocoles NEC, Sony, Philips RC5/RC6 et le traitement de données brutes. La librairie comporte 2 fonctions essentielles, IRsend pour émettre un code et IRrecv pour recevoir un code. Article intéressant complémentaire : http://www.righto.com/2009/11/ir-bubbles-controlling-relay-with.html

Il est possible grâce à cette barrière IR de détecter qu'un objet la coupe par exemple et ainsi déclencher une action.

Montage
PARTIE RECEPTION

Recepteur-ir-fritz.jpg Recepteur-ir-photo2.jpeg

PARTIE EMISSION

Attention à bien utiliser le PIN 3 PWM

Emetteur-ir-fritz.jpg Emetteur-ir-photo.jpeg

Programme
PARTIE RECEPTION
#include <IRremote.h>

int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}
void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
}
PARTIE EMISSION

Il est nécessaire d'utiliser le PIN 3 PWM d'après la documentation de la librairie

#include <IRremote.h>
IRsend irsend;
void setup()
{
  Serial.begin(9600);
}
void loop() {
    for (int i = 0; i < 3; i++) {
      irsend.sendSony(0xa90, 12); // Sony TV power code
      delay(40);
    }
}

Déclenchement APN via IR

Matériel
  • 1 APN type reflex avec déclenchement par IR possible. Un Nikon D80 par exemple.
  • 1 Arduino UNO
  • LED IR émittrice (exemple TSAL 6200)
  • 1 résistances de 190 ohm (+/-)
  • 1 télécommande ML3 Nikon, optionnelle mais permet de valider l'ensemble
Principe

Le but est d'émuler la télécommande ML3 de Nikon pour déclencher une photo. Pour cela, nous utiliserons une librairie dédiée à cet usage :

http://sebastian.setz.name/arduino/my-libraries/multi-camera-ir-control/
Montage

Nikon-ml3.jpg

Programme
#include <multiCameraIrControl.h>
 
Nikon D80(9);
 
void setup(){
}
 
void loop(){
  D80.shutterNow();
  delay(5000);
}

Liaison Filaire Arduino<->PC

Matériel
  • 1 Arduino UNO
Principe

Le langage Arduino, issu de C/C++, intègre une API très facile à prendre en main pour la communication série. Elle contient les fonctions suivantes :

  • begin(): Fixe le débit en bits par secondes pour la transmission.
  • end(): désactive la communication série
  • available(): donne le nombre de bytes (caractères) disponible pour la lecture sur le port série.
  • read(): Lit le premier octet disponible sur le port série
  • flush(): Attend que toutes les données sortantes soient complètement envoyées
  • print(): Affiche les données sur le port série
  • println(): Affiche les données sur le port série, suivi d'un retour charriot (ASCII 13, or '\r') et d'une nouvelle ligne (ASCII 10, or '\n')
  • write(): écris les données sur le port série

Une description complète de ces fonctions n'est pas à l'ordre du jour d'autant que la documentation officielle est très bien faite.

Le but de ce chapitre est de vous familiariser avec l'échange via série à l'aide de deux exemple.

  1. Le premier cas montre comment communiquer entre un arduino et un langage type Python. Nous pourrons tout aussi bien ouvrir un terminal série pour écrire dedans ;-)
  2. Le second cas présente comment contrôler une arduino de manière plus précise à l'aide d'une grammaire maison :) Ca va faire hurler les théoriciens du langage de l'IUT
Programme

Nous allons commencer par faire un petit programme echo de base

/* une variable pour stocker l'information en provenance du port serie */
byte byteRead;

void setup() {                
  Serial.begin(9600);
}

void loop() {
   /*  On teste si de l'information est disponible */
  if (Serial.available()) {
    /* On lit l'octet disponible en premier */
    byteRead = Serial.read();
    /* On affiche sur le terminal en retour le caractère saisi */
    Serial.write(byteRead);
  }
}

On va apporter une petite modification en remplaçant Serial.write(byteRead) par Serial.println(byteRead) Désormais ce n'est plus un vrai écho dans le terminal. Le résultat affiché est désormais le code ASCII Ce table de conversion est bien utile pour comprendre les correspondances : http://www.ascii.cl/

/* une variable pour stocker l'information en provenance du port serie */
byte byteRead;

void setup() {                
  Serial.begin(9600);
}

void loop() {
   /*  On teste si de l'information est disponible */
  if (Serial.available()) {
    /* On lit l'octet disponible en premier */
    byteRead = Serial.read();
    /* On affiche sur le terminal en retour le caractère saisi */
    Serial.println(byteRead);
  }
}

Plus compliqué++ : ce programme ,très poli, vous donne le bonjour et vous invite à lui donner un chiffre. Il fera clignoter d'autant plus la mini led intégré à l'arduino sur le pin 13.

#define LED_PIN 13

void setup()
{
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
    Serial.println("Bonjour Sebastien, je suis Sarah le gluon de la LED13. Combien de fois dois je tilter ?");
    while(Serial.available()) {
         int chiffre = Serial.read() -'0';
        clignote(chiffre);
    }
    delay(1000);
}

void clignote(int chiffre)
{
  for (int i = 0; i < chiffre; i++)
  {
    digitalWrite(LED_PIN, HIGH);
    delay(1000);
    digitalWrite(LED_PIN, LOW);
    delay(1000);
  }
}

Passons au montage final désormais : envoyer une séquence dans le terminal pour modifier les couleurs d'une LED RGB

Montage

Nous reprenons un montage bien connu  :

Montage serie rgb.jpg

Montage LED RGB

int ledR = 6; // broche de la LED Rouge
int ledG = 5; // broche de la LED Verte
int ledB = 3; // broche de la LED Bleue

// valeur de l'intensite calcule à partir des infos reçues du port serie
unsigned int ledCurrent = 0;

// Octet courant lu
byte byteRead;

int i = 0; // variable de la boucle for

void setup() // setup est déroulé une seule fois après la remise à zéro
{
  pinMode(ledR, OUTPUT); // la broche led (3) est initialisée en sortie
  pinMode(ledG, OUTPUT); // la broche led (5) est initialisée en sortie
  pinMode(ledB, OUTPUT); // la broche led (6) est initialisée en sortie

  // ouverture du port serie
  Serial.begin(9600);
}

void loop() // loop est déroulé indéfiniment
{
  if (Serial.available())
  {
    byteRead = Serial.read();

    if (byteRead == 'R') {
      ledCurrent = ledR;
    } else if (byteRead == 'G') {
      ledCurrent = ledG;
    } else if (byteRead == 'B') {
      ledCurrent = ledB;
    }
    else if (byteRead == 'A')
    {
      digitalWrite (ledR,LOW);
      digitalWrite (ledG,LOW);
      digitalWrite (ledB,LOW);
      for (i = 0; i <= 255; i++) // i varie de 1 à 255
      {
        analogWrite(ledR, i); // génère une impulsion sur la broche de largeur i => la luminosité R augmente
        analogWrite(ledG, i); // génère une impulsion sur la broche de largeur i => la luminosité G augmente
        analogWrite(ledB, i); // génère une impulsion sur la broche de largeur i => la luminosité B augmente
        delay(20); // pause de 20 ms entre chaque pas
      }
    }
    allumer(ledCurrent);
  }
}

// Prend en parametre la LED à allumer
void allumer(int led)
{
  for (i = 0; i <= 255; i++) // i varie de 1 à 255
  {
    analogWrite(led, i); // génère une impulsion sur la broche de largeur i => la luminosité R augmente
    delay(20); // pause de 20 ms entre chaque pas
  }
  digitalWrite (led, LOW);
}
}

Liaison Filaire Arduino<->PC: Ethernet

Matériel
  • 1 Arduino UNO
  • 1 Shield Ethernet
Principe
Programme

Le premier exemple, est un client/serveur minimaliste de chat :

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1, 177);
IPAddress gateway(192,168,1, 1);
IPAddress subnet(255, 255, 0, 0);


// port telnet par défaut
EthernetServer server(23);
boolean alreadyConnected = false;

void setup() {
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
  Serial.begin(9600);
  Serial.print("Adresse du Chat:");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // attendre un nouveau client
  EthernetClient client = server.available();

  // quand le client commence à nous écrire dire "Hello"
  if (client) {
    if (!alreadyConnected) {
      client.flush();    
      Serial.println("Nous avons un nouveau client");
      client.println("Hello, client!");
      alreadyConnected = true;
    }

    if (client.available() > 0) {
      char thisChar = client.read();
      server.write(thisChar);
      Serial.write(thisChar);
    }
  }
}

Maintenant le client associé :

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEE };
IPAddress ip(192,168,1,178);

// IP de votre serveur de chat
IPAddress server(192,168,1,177);
EthernetClient client;

void setup() {
  Ethernet.begin(mac, ip);
  Serial.begin(9600);

  // delai d'initialisation du shield
  delay(1000);

  Serial.println("connexion...");

  if (client.connect(server, 23)) {
    Serial.println("connecté");
  }
  else {
    Serial.println("échec de connexion");
  }
}

void loop()
{
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  while (Serial.available() > 0) {
    char inChar = Serial.read();
    if (client.connected()) {
      client.print(inChar);
    }
  }

  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    while(true);
  }
}

Nous allons faire un petit programme qui va interroger un serveur HTTP et qui affiche la réponse sur le port série :

#include <SPI.h>
#include <Ethernet.h>

// Adresse MAC du shield Ethernet
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char server[] = "www.google.com";  

// Réglage de l'adresse de secours utilisée si le DHCP échoue
IPAddress ip(192,168,0,177);

EthernetClient client;

void setup() {
  Serial.begin(9600);
  // démarrage de la session Ethernet:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // En cas d'échec de l'allocation dynamique d'IP on configure manuellement
    Ethernet.begin(mac, ip);
  }
  // Laisser le temps au shield de terminer toutes ses initialisation.
  delay(1000);

  Serial.println("connexion...");

  if (client.connect(server, 80)) {
    Serial.println("connected");
    // Faire une requete HTTP
    client.println("GET /search?q=nedseb HTTP/1.1");
    client.println("Host: www.google.com");
    client.println("Connection: close");
    client.println();
  }
  else {
    Serial.println("échec de connexion");
  }
}

void loop()
{
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // Si l'on perd la connexion, les ressources du client sont libérées
  if (!client.connected()) {
    Serial.println();
    Serial.println("déconnexion.");
    client.stop();

    // Plus rien à faire
    while(true);
  }
}

L'exemple suivant créé un serveur HTTP affichant une page web donnant l'état des entrées analogiques

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};

IPAddress ip(192, 168, 0, 177);

//Créer un serveur en écoute sur le port 80 (celui utilisé par défaut pour les navigateurs Web)
EthernetServer server(80);

void setup() {
  Serial.begin(9600);


  // démarrage de la connexion et du serveur 
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("le serveur écoute sur l'adresse  ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // Écoute si un nouveau client est arrivé
  EthernetClient client = server.available();
  if (client) {
    Serial.println("nouveau client");
    // Une requête HTTP se termine par une ligne vide
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        if (c == '\n' && currentLineIsBlank) {
          // La requête est terminée, on envoie une réponse HTTP standard
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close"); 
          client.println("Refresh: 5");  // Rafraichir la page toute les 5 secondes
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          // afficher la valeur courante des entrées analogiques
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            int sensorReading = analogRead(analogChannel);
            client.print("L'entrée analogique ");
            client.print(analogChannel);
            client.print(" à pour valeur ");
            client.print(sensorReading);
            client.println("<br />");
          }
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
    Serial.println("client déconnecté");
  }
}


#include <SPI.h>
#include <Ethernet.h>

boolean incoming = 0;
char* etatLed;
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};

IPAddress ip(192, 168, 0, 177);

//Créer un serveur en écoute sur le port 80 (celui utilisé par défaut pour les navigateurs Web)
EthernetServer server(80);

void setup()
{
  pinMode(2, OUTPUT);
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.begin(9600);
}

void loop()
{
  EthernetClient client = server.available();
  if (client) {
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if(incoming && c == ' '){ 
          incoming = 0;
        }
        if(c == '$'){ 
          incoming = 1; 
        }
        
        //vérifier si l'URL contient $1 ou $2
        if(incoming == 1){
          Serial.println(c);
          
          if(c == '1'){
            etatLed = "ON";
            Serial.println("ON");
            digitalWrite(2, HIGH);
          }
          if(c == '2'){
            etatLed = "ON";
            Serial.println("OFF");
            digitalWrite(2, LOW);
          }
        }

        if (c == '\n' && currentLineIsBlank) {
          // La requête est terminée, on envoie une réponse HTTP standard
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close"); 
          client.println("Refresh: 5");  // Rafraichir la page toute les 5 secondes
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html><body>");
          client.print("<h1> Etat LED 2 : ");
          client.print("etatLed");
          client.print("</h1>");
          client.println("</body></html>");
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
    Serial.println("client déconnecté");
  }
}

Liaison Radio Arduino<->PC: XBee

Communication inter-composants : le bandeau de LED

Matériel
Principe

Le but est de manipuler la librairie neopixel fourni par Adafruit https://github.com/adafruit/Adafruit_NeoPixel en vue de la dernière journée pour la réalisation du module lightpainting. La première chose à faire est d'importer la librairie Neopixel dans Arduino et de redémarrez au besoin l'IDE.

Vous pouvez ajouter la dépendance de votre programme soit via l'IDE soit en ajoutant manuellement

#include <Adafruit_NeoPixel.h>

Avant de donner des instructions à la bande de Led, il est nécessaire de l'initialiser :

void setup() {
  strip.begin();
  strip.show(); 
}

La seconde ligne force les pixels à afficher leur couleur mais comme aucune n'a encore été défini, ceci met tout en off :)

Il existe deux façons de contrôler les pixels :

strip.setPixelColor(n, red, green, blue);

ou bien

uint32_t color = strip.Color(255, 0, 255); (magenta)
strip.setPixelColor(n, color);

Il est aussi possible de récupérer le nombre de pixels déclarés dans la bande

uint16_t n = strip.numPixels();

Et de jouer sur la luminosité

strip.setBrightness(64);

ATTENTION à bien appeler show après toutes ces méthodes comme pour setPixel sinon l'instruction n'est pas poussée vers la bande.

Montage

NeoPixel-UserGuide-Arduino-Brancher-01.png

Programme

Le but de ce programme est de faire un chenillard sur la bande de led.

// Simple NeoPixel test.  Lights just a few pixels at a time so a
// 1m strip can safely be powered from Arduino 5V pin.  Arduino
// may nonetheless hiccup when LEDs are first connected and not
// accept code.  So upload code first, unplug USB, connect pixels
// to GND FIRST, then +5V and digital pin 6, then re-plug USB.
// A working strip will show a few pixels moving down the line,
// cycling between red, green and blue.  If you get no response,
// might be connected to wrong end of strip (the end wires, if
// any, are no indication -- look instead for the data direction
// arrows printed on the strip).
 
#include <Adafruit_NeoPixel.h>
 
#define PIN      6
#define N_LEDS 144
 
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_LEDS, PIN, NEO_GRB + NEO_KHZ800);
 
void setup() {
  strip.begin();
}
 
void loop() {
  chase(strip.Color(255, 0, 0)); // Red
  chase(strip.Color(0, 255, 0)); // Green
  chase(strip.Color(0, 0, 255)); // Blue
}
 
static void chase(uint32_t c) {
  for(uint16_t i=0; i<strip.numPixels()+4; i++) {
      strip.setPixelColor(i  , c); // Draw new pixel
      strip.setPixelColor(i-4, 0); // Erase pixel a few steps back
      strip.show();
      delay(25);
  }
}