Aquila Reloaded – Chapitre 4 : Lire les valeurs des DIP Switchs avec un Arduino

Hello world !

Après la lecture et l’écriture de valeurs sur le bus DMX, on va passer à un chapitre qui parait très banal mais qui pourtant a toute son importance ! En effet, on va voir comment adresser et configurer notre équipement DMX512 à partir de DIP Switchs.

Utilisation des « boutons » : pas si trivial à cause du CMOS

« Facile, on relie le bouton à une entrée, et basta ! ». Eh bien, ce n’est pas si simple que cela 🙂 La première chose à savoir est qu’Arduino utilise la technologie CMOS. Cette technologie a une influence sur l’état des entrées :

  • Si la broche d’entrée est reliée au 5V, il s’agit d’un état haut (1)
  • Si la broche d’entrée est reliée à la masse, il s’agit d’un état bas (0)
  • Par contre, si la broche n’est pas reliée, l’état est inconnu et de surcroit instable !

Or, avec un bouton de type interrupteur ou bouton poussoir, il se peut que la broche soit reliée « dans le vide » lorsque le circuit est ouvert. Ce qui générera un état inconnu, alors que l’on s’attendrait à avoir un état bas. Comment faire pour malgré tout mettre notre broche à 0 ou 1 de façon fiable ?

Il existe une méthode simple : placer une résistance de type PULL UP ou PULL DOWN : on relie la broche à la masse (PULL DOWN) ou au 5V (PULL UP) à l’aide d’une résistance. Ainsi, lorsque le bouton ne sera pas pressé, la broche ne sera pas « à l’air », et lorsque le bouton sera pressé, la résistance sera reliée directement entre le 5V et la masse.

  • Sur un montage de type « Pull Down », l’entrée est à 0 lorsque le bouton n’est pas pressé, est à 1 lorsque le bouton est pressé.
  • A l’inverse, sur un montage « Pull up », l’entrée est à 1 lorsque le bouton n’est pas pressé, est à 0 lorsque le bouton est pressé, ce qui peut parfois être déconcertant mais très courant.

Cela veut dire qu’il faudra au moins une résistance par entrée. Cela peut vite générer de l’encombrement sur le circuit imprimé si on a beaucoup de boutons, ce qui sera le cas avec les DIP Switchs de l’Aquila, au nombre de 14. Heureusement, il faut le savoir, mais Arduino inclue pour chaque entrée une résistance interne de type PULL UP. Elle n’est pas active par défaut, il faudra l’activer logiciellement, mais cela simplifie grandement le montage !

Définir une entrée

Si on utilise une broche de l’Arduino exclusivement en entrée, il est nécessaire de configurer la broche en mode « INPUT ».

Pour ce faire, il suffit d’utiliser la fonction pinMode, idéalement dans la fonction de démarrage « setup() ». Exemple ci-dessous pour la broche 11 :

void setup() {
 pinMode(11, INPUT);
}

Si on veut utiliser la fonction Pull Up intégrée, il faut configurer l’entrée comme suit :

void setup() {
 pinMode(11, INPUT_PULLUP);
}

Ensuite, pour lire la valeur de l’entrée, il suffit d’utiliser la fonction

maVariable = digitalRead(11);

Cas pratique : comment adresser les canaux DMX avec nos DIP Switchs ?

Comme on l’a vu au chapitre précédent, le DMX nécessite un adressage de l’équipement. Dans notre cas on va le faire avec des DIP Switchs, en écrivant la valeur du canal en binaire. (DIP1 = 1 ; DIP2 = 2; DIP3 = 4 ; DIP4 = 8 ; … DIP9 = 256)

Pour adresser 512 canaux, il est nécessaire de lire la valeur de 9 DIP Switchs contigus.

Pour simplifier le câblage sur notre Arduino Nano, on va utiliser la résistance de Pull Up interne. On utilisera le plan suivant :

  • DIP1 = broche 3
  • DIP2 = broche 4
  • DIP9 = broche 11

Ce qui nous donne :

void setup() {
 pinMode(3, INPUT_PULLUP);
 pinMode(4, INPUT_PULLUP);
 pinMode(5, INPUT_PULLUP);
 pinMode(6, INPUT_PULLUP);
 pinMode(7, INPUT_PULLUP);
 pinMode(8, INPUT_PULLUP);
 pinMode(9, INPUT_PULLUP);
 pinMode(10, INPUT_PULLUP);
 pinMode(11, INPUT_PULLUP);
}

Ensuite, on va créer une fonction de lecture qui va lire, en binaire, les valeurs des 9 entrées. Attention, le fait d’utiliser une Pull Up implique que si l’interrupteur est sur « On », l’entrée associée retournera 0 (LOW), et par corollaire si l’interrupteur est sur « Off », l’entrée associée retournera 1 (HIGH).

A noter aussi que si notre équipement utilise plusieurs canaux contigus, la valeur du canal ne pourra pas dépasser « 512 – nombre de canaux a adresser ». Ainsi, pour un PAR RGB sur 3 canaux, la valeur maximale de l’adressage ne pourra excéder 512 – 3 = 509.

Ce qui nous donne le code suivant.

unsigned short readDipSwitches() {

 unsigned short dmxVal = 0;

 if(digitalRead(3) == LOW) dmxVal += 1;
 if(digitalRead(4) == LOW) dmxVal += 2;
 if(digitalRead(5) == LOW) dmxVal += 4;
 if(digitalRead(6) == LOW) dmxVal += 8;
 if(digitalRead(7) == LOW) dmxVal += 16;
 if(digitalRead(8) == LOW) dmxVal += 32;
 if(digitalRead(9) == LOW) dmxVal += 64;
 if(digitalRead(10) == LOW) dmxVal += 128;
 if(digitalRead(11) == LOW) dmxVal += 256;

 //Decrease value if value > (512 - 3 channels) = 509
 if(dmxVal > 509) dmxVal = 509;

 return dmxVal;
}

Enfin, pour pouvoir adresser le signal DMX en fonction des DIP Switchs, il suffira d’utiliser la fonction « readDipSwitches() ».

Voici un exemple reprenant celui du chapitre précédent :

#include <DMXSerial.h>
void setup() { 
 DMXSerial.init(DMXReceiver, 2); 
 pinMode(LED_BUILTIN, OUTPUT);
 pinMode(3, INPUT_PULLUP); 
 pinMode(4, INPUT_PULLUP); 
 pinMode(5, INPUT_PULLUP); 
 pinMode(6, INPUT_PULLUP); 
 pinMode(7, INPUT_PULLUP); 
 pinMode(8, INPUT_PULLUP); 
 pinMode(9, INPUT_PULLUP); 
 pinMode(10, INPUT_PULLUP); 
 pinMode(11, INPUT_PULLUP);
} 

unsigned short readDipSwitches() {
 //...
}

void loop() { 
 byte val1;
 byte val2;
 byte val3;
 val1 = DMXSerial.read(readDipSwitches());
 val2 = DMXSerial.read(readDipSwitches() + 1); 
 val3 = DMXSerial.read(readDipSwitches() + 2); 
 //Serial.println(val); 
 if(DMXSerial.noDataSince() > 3000) { 
  digitalWrite(LED_BUILTIN, LOW);
 } 
 else { 
  digitalWrite(LED_BUILTIN, HIGH); 
 } 
}

Astuce : utiliser un interrupt()

L’exécution d’un code Arduino se fait de façon séquentielle dans la fonction loop(). Il est cependant parfois nécessaire de détecter l’appui sur un bouton et de mettre en pause l’exécution du programme afin d’exécuter un autre morceau de code, plus prioritaire. Pour ce faire, Arduino permet à certaines entrées de faire appel à des « interrupt« .

Pour utiliser un interrupt, il faut d’abord définir une fonction qui correspond à notre « code prioritaire ». Par exemple, allumer ou éteindre la LED interne.

void changeLed() {
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}

Puis il faut définir notre interrupt, pour ce faire, il faut utiliser la fonction attachInterrupt().

attachInterrupt(digitalPinToInterrupt(**numero_pin**), **fonction**, **DECLENCHEUR**);

Le déclencheur peut être :

  • LOW : lorsque la broche est à l’état 0
  • HIGH : : lorsque la broche est à l’état 1
  • CHANGE : lorsque la broche change d’état (de 0 à 1, ou de 1 à 0)
  • RISING : lorsque la broche passe de l’état 0 à l’état 1
  • FALLING lorsque la broche passe de l’état 1 à l’état 1

Il va sans dire que les déclencheurs CHANGE, RISING et FALLING seront les plus utilisés.

Dans notre exemple sur Arduino Nano, nous allons utiliser la broche 2, ce qui nous donne :

attachInterrupt(digitalPinToInterrupt(2), changeLed, CHANGE);

Concrètement, cela donne :

void setup() { 
 pinMode(LED_BUILTIN, OUTPUT); 
 pinMode(2, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(2), changeLed, CHANGE);
}

void loop() {
 // Do what you want
}

void changeLed() {
 digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}

Attention toutefois à une chose ! Toutes les broches d’un Arduino ne sont pas compatibles avec les Interrupt !

  • Sur un Uno et un Nano, les broches compatibles sont : 2, 3
  • Sur un Mega, les broches compatibles sont : 2, 3, 18, 19, 20, 21

Il faudra donc veiller à sélectionner les bonnes entrées si vous les utilisez.

Et voila, vous savez maintenant lire la valeur d’une entrée sur un Arduino. Je reconnais que ce chapitre est plutôt simple comparé aux sujets que je traite d’habitude, mais il est important à mes yeux de bien rappeler les fondamentaux.

La suite au prochain épisode ! 🙂

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *