Communiquer avec un ordinateur
Sommaire
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
PARTIE EMISSION
Attention à bien utiliser le PIN 3 PWM
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
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.
- 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 ;-)
- 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 :
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
- 1 Arduino Uno
- 1 BANDE LED Adressable (http://www.adafruit.com/product/1506)
- 1 Alimentation 5V/3A ou DC
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
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);
}
}