Aquila Reloaded – Chapitre 3 : Recevoir (et envoyer) des commandes DMX512 avec un Arduino

Hello world !

On continue sur nos tests unitaires sur notre Aquila Reloaded. On va voir comment lire des valeurs en DMX512.

Le DMX512, kézako ?

Le DMX512 est un protocole basé sur la norme de transmission RS485. Il s’agit d’une liaison série cadencée à 250k bauds sur laquelle sont transférées de façon cyclique un start byte suivi de 512 octets. Chaque octet transmis correspond à la valeur d’un canal (channel), dans l’ordre de diffusion. (Autrement dit, le premier octet définit le canal 1, le 2eme octet le canal 2, etc…).

Très utilisé dans le milieu de la scène et du spectacle, cette norme permet de piloter les équipements scéniques (éclairage, jeux de lumière, fumée, …) en utilisant un seul câble.

Tous les équipements sont reliés en série sur la même liaison RS485, et reçoivent tous, en même temps, les 512 canaux DMX. La liaison n’étant pas bidirectionnelle, il n’y a aucun retour d’état (même si on commence à voir apparaitre du retour d’état sur une nouvelle version de la norme, très peu utilisée).

Comment partager le bus DMX512 entre plusieurs équipements ?

Pour que les équipements puissent partager la liaison DMX, il est nécessaire de les adresser, c’est à dire de choisir quels sont les canaux que l’équipement va écouter. Prenons exemple sur un PAR à LED RGB : ce type d’équipement dispose souvent de 3 canaux : un pour l’intensité du rouge, un pour l’intensité du vert, et un pour le bleu. Si on adresse l’équipement sur le canal 14, il utilisera le canal 14 pour régler l’intensité du rouge, mais il se servira aussi des canaux 15 et 16 pour régler l’intensité du vert et du bleu. Il faut donc veiller à ce que les adressages DMX ne se chevauchent pas.

La configuration du canal peut se faire de deux manières :

  • Soit à l’aide de 9 « DIP Switchs », qui définissent la valeur à écouter en binaire. C’est la méthode utilisée par l’Aquila.
  • Soit à l’aide d’un écran (typiquement un 7 segments à 4 chiffres), sur lequel on choisi le numéro du premier canal adressé à l’aide de boutons poussoirs. C’est une méthode plus « user friendly » que l’on retrouve sur de plus en plus d’équipements.

Si vous voulez plus d’infos, vous pouvez lire ce document ainsi que cette page (crédit photos).

Comment relier un Arduino sur un bus DMX512

Comme indiqué précédemment, un bus DMX512 n’est ni plus ni moins qu’une liaison RS485. Ce type de liaison utilise 3 fils, un fil de masse, un fil diffusant la donnée (dit « point chaud ») et un fil diffusant l’opposition de la donnée (dit « point froid »). C’est ce qu’on appelle un signal symétrique : comme il y a toujours une différence de potentielle entre le point chaud et le point froid, la liaison est très peu sensible aux parasites.

Cependant, l’Arduino ne dispose pas d’entrée RS485, et de surcroit est limité à 5V. Il existe heureusement un composant permettant d’adapter le niveau de signal RS485 à un niveau de signal TTL (et inversement), il s’agit du RS485 développé par Maxim.Il existe une alternative équivalente SN75176 (utilisé sur l’Aquila). Je n’ai pas étudié la datasheet mais ce composant consomme un peu plus lorsqu’il est en veille, et supporte moins de débit que le MAX485 original. Toutefois il est amplement suffisant pour supporter le débit du DMX512. Il est possible d’utiliser aussi le MAX487, moins cher que le MAX485.

Voici ci-dessous un exemple de câblage relié à l’entrée RX de l’Arduino (réception DMX). Le 2 broches de sélection sont à l’état bas (masse).

NB : attention ce câblage peut perturber la programmation de l’Arduino. il est parfois nécessaire de déconnecter la liaison avec la broche RX.

Et voici ci-dessous un exemple de câblage relié à l’entrée TX. Le 2 broches de sélection sont à l’état haut (5V).

Et enfin, voici un cablage switchable avec une broche de contrôle émission / réception. J’ai volontairement ajouté des résistances sur les broches pour protéger l’Arduino suite à des problèmes de surchauffe / surintensités générés par le MAX485.

Fonctionnement logiciel

Au début, j’ai récupéré et adapté à ma sauce un code nommé « ArDMX ». Ce code nécessitant des modifications dans les librairies intégrés à l’Arduino, pour la gestion du bus série, j’ai fini par privilégier une autre librairie « prête à l’emploi » : DMXSerial.

Pour l’installer, rien de plus simple, il suffit d’ajouter la librairie via le menu idoine de l’Arduino.

Ensuite, pour l’utilisation, je vous conseille de regarder les codes donnés en exemple : DmxSerialRecv notamment. Il simule justement un PAR à LED RGB sur 3 canaux.

Voici comment l’utiliser simplement : tout d’abord il faut initialiser le bus DMX en mode « réception »

DMXSerial.init(DMXReceiver);

Attention ! Si on ne précise pas de sélecteur, le code utilise par défaut la broche 2 ! Il faudra en tenir compte pour vos programmes !

Dans le cas où l’on souhaite personnaliser le sélecteur, on peut préciser la broche à utiliser (dans cet exemple, la broche 5)

DMXSerial.init(DMXReceiver, 5);

Ensuite, pour lire les données, il faut utiliser la fonction read. L’exemple ci-dessous permet de lire le canal 42.

byte dmxval;
dmxval =  DMXSerial.read(42);

Il est possible de connaitre le délai écoulé depuis la réception des dernières trames. Cela peut être pratique, par exemple, pour savoir s’il y a interruption de signal.

DMXSerial.noDataSince(); //Retourne un unsigned long, en millisecondes

Voici un exemple de code, avec un voyant s’allumant en cas de réception d’un signal DMX.

#include <DMXSerial.h>

void setup() {
 DMXSerial.init(DMXReceiver, 2);
 pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
 byte val;
 val = DMXSerial.read(42);
 //Serial.println(val);
 if(DMXSerial.noDataSince() > 3000) {
  digitalWrite(LED_BUILTIN, LOW);
 }
 else {
  digitalWrite(LED_BUILTIN, HIGH);
 }
}

Si on souhaite effectuer de l’écriture sur le bus DMX, rien de plus simple, voici un exemple de code envoyant la valeur lue en analogique sur A0 sur le canal 42 :

#include <DMXSerial.h>

void setup() {
 DMXSerial.init(DMXController, 2);
 byte val;
}

void loop() {
 val = analogRead(0) / 4;
 DMXSerial.write(42, val);
}

Astuce pour utiliser un autre port série (sur Arduino Mega uniquement)

Si vous utilisez un Arduino Mega, ce dernier dispose de 5 ports série. Or, le code de la librairie DMXSerial utilise le port série par défaut. Or, comme je l’ai évoqué ci-dessus, si on cable un MAX485 sur la broche RX de l’Arduino, cela peut perturber la programmation via USB.

Si vous voulez utiliser le port série n°1 (a la place du 0), le développeur de la librairie a prévu un paramètre à modifier. Pour ce faire, il faut éditer le fichier DMXSerial.cpp, et décommenter la ligne define suivante :

#define DMX_USE_PORT1

Pensez à la commenter à nouveau si vous voulez réutiliser le port série 0 (ou un Arduino Uno/Nano).

Il n’est malheureusement pas possible d’utiliser un autre port série que le 0 ou le 1, car il semblerait que le développeur utilise les Interrupts. Or les Interrupts sont restreintes aux ports séries 0 et 1.

Voila, vous savez maintenant comment lire et écrire simplement sur un bus DMX512. Reste maintenant à voir comment lire la valeur du canal à partir de DIP Switchs. La suite au prochain épisode !

4 commentaires :

  1. Bonjour ,

    excellent document , un grand merci pour votre travail !
    je cherchais un moyen de controler du materiel DMX , c’est parfait , j’utilise principalement la bibliotheque en mode  »controle »
    cependant je ne comprends pas la notion  » Si on ne précise pas de sélecteur, le code utilise par défaut la broche 2 ! Il faudra en tenir compte pour vos programmes ! »
    les diff test que je réalise , j’ai branché DI sur TX de la carte , on peux changer ce PIN?
    merci d’avance pour votre réponse
    Cordialement
    MR moinet

  2. Bonjour,
    Je vous remercie pour le compliment 🙂
    En fait ce que j’appelle le « sélecteur », c’est la broche qui permet de passer d’un mode « contrôleur » à un mode « récepteur ». Par défaut il s’agit de la broche 2, mais on peut personnaliser en fonction de son câblage interne.
    Cette broche peut être pratique notamment si on développe un jeu de lumières disposant d’un mode autonome et d’un mode asservi : en mode « autonome » le scan peut envoyer des consignes DMX à d’autres scans identiques en mode « asservis » pour qu’ils aient le même effet de lumière en même temps.
    G-Rom

  3. Bonjour,
    Merci pour les explications. J’aurais aimé savoir si la commande en émission est sensible à une temporisation ?. Exemple si après avoir envoyé un signal DMX 155 sur le canal 3 (par exemple), je fais suivre d’une commande delay de quelques secondes, cela affecte le signal DMX ? Ou une fois la première commande envoyée, la trame se répète de toute façon (grâce à la librairie) jusqu’à ce qu’une nouvelle valeur dmx soit envoyé et ça même si une commande delay est utilisé dans le programme ?

    DMXSerial.init(DMXController, 2);

    DMXSerial.write(3,155);
    Delay (3000);
    …….;
    Affecte le signal dmx ?

  4. Bonjour,
    Désolé de la réponse (très) tardive.
    Si on met un delay dans le code, cela gèle l’envoi de données en DMX. Donc il ne faut pas faire de delay 🙂

    Il y a d’autres facons de faire un delay dans un morceau de code sans geler l’Arduino, par exemple en utilisant millis() qui retourne le nombre de ms écoulées depuis le début du programme.
    Exemple si on souhaite executer un code toutes les 3 secondes :
    En stockant dans une variable last_loop la valeur de millis(), il suffit de comparer :
    if (millis() – last_loop) > 3000 {
    last_loop = millis(); ==> On met à jour last_loop
    bout de code à executer toutes les 3 secondes;
    }

    on injecte ce bout de code dans loop(), on s’arrange pour que la librairie DMX soit executée à chaque tour de loop, et ainsi le tour est joué !

Laisser un commentaire

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