From 507bf9e3cc64ed40775e8273c3c505db003c654c Mon Sep 17 00:00:00 2001 From: Davy39 Date: Tue, 2 Jan 2024 22:51:43 +0100 Subject: [PATCH] mide en forme dmx --- docs/projets/dmx/index.md | 297 ++++++++++++++++++++++---------------- 1 file changed, 169 insertions(+), 128 deletions(-) diff --git a/docs/projets/dmx/index.md b/docs/projets/dmx/index.md index 0cedf6c9c..e0f5a3d4e 100644 --- a/docs/projets/dmx/index.md +++ b/docs/projets/dmx/index.md @@ -5,190 +5,231 @@ Le **DMX512** (Digital Multiplexing) est une norme de transmission de données u Le projet est de fabriquer des contrôleurs DMX pour piloter nos lumières. +## Communications DMX -## Circuitpython +??? info "Protocole DMX512" -Circuitpython est un dérivé de micropython, adaptation de python pour les microcontroleurs. + Le protocole DMX512 est relativement simple à un **baudrate** de 250 kbit/s, soit un bit toute les 4 μs. -### Installation -L'installation se fait en copiant un fichier UF2 sur le microcontroleur démarrer en mode boot. + ``` + Idle | Break |MAB| Slot 0 | Slot 1 | + ------\ /---\ /-\ /--------\ + | | | | | | | + | | | | | | | + \-------------------/ \--------/ \-/ \--- - - - - - - + ``` -Télécharger l'UF2 : - - pour le [Raspberry Pico](https://circuitpython.org/board/raspberry_pi_pico/) + **Idle** : En l'absence de signal, la sortie digitale est à `1` . - - pour le [LOLIN S3](https://circuitpython.org/board/lolin_s3/) + **Break** : Pur prévenir l'arrivée du signal, il faut commencer par envoyer un signal à ``0`` pendant environ 100 μs. + **MAB** : Le Mark After Break (MAB) est un signal de 12 μs à `1` qui suit le **break**. -### Utilisation + **Slots** : Les slots correspondent a un signal de départ (un octet à `0`), suivi des octets qui correspondent au valeurs de chaque canaux DMX (512 au maximum). -!!! note "Remarque" - L'IDE [mu-editor](https://codewith.mu/en/) est prévue spécifiquement pour interfacer les boards CIRCUITPY. Une extension Circuitpython est également disponible dans **VScode**. + Exemple d'un slot à une valeur de 152 (`0b10011000`). -- Créer simplement un fichier nommé `code.py` à la racine du système de fichier CIRCUITPY. + ``` + S 0 1 2 3 4 5 6 7 E E + \ /-\ /---\ /-- + | | | | | | + | | | | | | + \-/ \---/ \------/ + ``` + Chaque octet doit être précédé d'un start à `0` (S), et de 2 stops à `1` (E). +??? info "Cablage" -### Ajout de librairies + Le protocole DMX512 utilise un protocole de type **RS-485** qui permet des communications sur des plus longues distances par le recours à un signal symétrisé (2 pins A + B, plus le GND). -- Créer un dossier `lib` qui contiendra les librairies supplémentaires. + La puce **MAX485** permet de convertir un signal tx habituel en un signal rs-485. -!!! note "Remarque" - De nombreuses librairies sont diffusées dans les [bundle](https://circuitpython.org/libraries) officiels et communautaires. D'autres se trouvent sur github. Pour un gain de place et de ressources du microcontrolleur, elles sont précompilées dans un format `mpy`. -- Pour les installer facilement, installer l'outil `circup` -```bash -pip install circup -``` + ![](http://hobbycomponents.com/images/forum/RS485_Module_HCMODU0081_Diagram.png) -Une fois votre board CIRCUITPY connectée, l'installation d'une librairie se fait en une commande. + **Mode Émission** -Par exemple, pour installer la librairie `adafruit_ble_radio` : + - RE & DE -> Gnd -```bash -circup install adafruit_ble_radio -``` + - RO -> RX -## Communications DMX -### Cablage + **Mode Transmission** -Le protocole DMX512 utilise un protocole de type RS-485 qui permet des communications sur des plus longues distances par le recours à un signal symétrisé (2 pins A + B, plus le GND). + - RE & DE -> 5V -La puce **MAX485** permet de convertir un signal tx habituel en un signal rs-485 + - DI -> TX -![](http://hobbycomponents.com/images/forum/RS485_Module_HCMODU0081_Diagram.png) +## Programmation d'un signal DMX -**Mode Emmission** -> RE & DE -> Gnd -> RO -> RX +### Circuitpython -**Mode Transmission** -> RE & DE -> 5V -> DI -> TX +Circuitpython est un dérivé de micropython, adaptation de python pour les microcontroleurs. -### Librairie dmx_transmitter +??? info "Installation" + L'installation se fait en copiant un fichier UF2 sur le microcontroleur démarrer en mode boot. -Une librairie, uniquement valable pour le Raspberry Pico est en cours de développement sur [github](https://github.com/mydana/CircuitPython_DMX_Transmitter) + Télécharger l'UF2 : -- Cloner le dépot et copier le dossier `dmx_transmitter` dans le dossier `lib` + - pour le [Raspberry Pico](https://circuitpython.org/board/raspberry_pi_pico/) + + - pour le [LOLIN S3](https://circuitpython.org/board/lolin_s3/) + + +??? info "Utilisation" + !!! note "Remarque" + L'IDE [mu-editor](https://codewith.mu/en/) est prévue spécifiquement pour interfacer les boards CIRCUITPY. Une extension Circuitpython est également disponible dans **VScode**. -#### Exemple d'utilisation + - Créer simplement un fichier nommé `code.py` à la racine du système de fichier CIRCUITPY. -```python -"Exemple de clignottement d'une lampe DMX." -import time -import board -from dmx_transmitter import dmx_transmitter -# Piloter le module RS485 avec GP0 -DMX_PIN = board.GP0 -# Instantiation du DMX -dmx = dmx_transmitter.DMXTransmitter(first_out_pin=DMX_PIN) -# Clignottement + ??? info "Ajout de librairies" -while True: - # Eteint les lampes - dmx.clear() - dmx.show() - # Attend 1 seconde - time.sleep(1) - # Allume la lampe. Canaux DMX : 1, 2, 3 - dmx[0:3] = 255 - dmx.show() - # Attend 1 seconde - time.sleep(1) -``` + - Créer un dossier `lib` qui contiendra les librairies supplémentaires. + !!! note "Remarque" + De nombreuses librairies sont diffusées dans les [bundle](https://circuitpython.org/libraries) officiels et communautaires. D'autres se trouvent sur github. Pour un gain de place et de ressources du microcontrolleur, elles sont précompilées dans un format `mpy`. -## Périphériques d'entrée + - Pour les installer facilement, installer l'outil `circup` + ```bash + pip install circup + ``` -### Joystics analogique à 2 axes + Une fois votre board CIRCUITPY connectée, l'installation d'une librairie se fait en une commande. + Par exemple, pour installer la librairie `adafruit_ble_radio` : -```python -import time -import analogio -ax = analogio.AnalogIn(board.A0) -ay = analogio.AnalogIn(board.A1) + ```bash + circup install adafruit_ble_radio + ``` -def range_map(x, in_min, in_max, out_min, out_max): +### Librairie dmx_transmitter + +Une librairie, uniquement valable pour le Raspberry Pico est en cours de développement sur [github](https://github.com/mydana/CircuitPython_DMX_Transmitter) + +- Cloner le dépot et copier le dossier `dmx_transmitter` dans le dossier `lib` + + +!!! python "Exemple d'utilisation" + + ```python + "Exemple de clignottement d'une lampe DMX." + import time + import board + from dmx_transmitter import dmx_transmitter + # Piloter le module RS485 avec GP0 + DMX_PIN = board.GP0 + # Instantiation du DMX + dmx = dmx_transmitter.DMXTransmitter(first_out_pin=DMX_PIN) + # Clignottement + + while True: + # Eteint les lampes + dmx.clear() + dmx.show() + # Attend 1 seconde + time.sleep(1) + # Allume la lampe. Canaux DMX : 1, 2, 3 + dmx[0:3] = 255 + dmx.show() + # Attend 1 seconde + time.sleep(1) + ``` + + +### Périphériques d'entrée + +??? note "Joystics analogique à 2 axes" + + ```python + import time + import analogio + ax = analogio.AnalogIn(board.A0) + ay = analogio.AnalogIn(board.A1) + + def range_map(x, in_min, in_max, out_min, out_max): return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min -while True: + while True: x=range_map(ax.value, 0, 4095, -127, 127) y=range_map(ay.value, 0, 4095, -127, 127) print("x", x, "y", y) time.sleep(0.1) -``` + ``` -!!! note "Remarque" + !!! note "Remarque" Il n'y a que 4 Analog In avec le RP2040. Il peut être utile d'utiliser un multiplexeur comme le module hc4067. -### Encodeurs rotatifs - -Contrairement aux potentiomètres et faders, les encodeurs rotatifs permettrons de changer dynamiquement les canaux DMX, en passant d'un preset à l'autre, et sont minis d'une fonction bouton (pour enregistrer la valeur dans le preset ?). +??? note "Encodeurs rotatifs" -![](https://cdn-learn.adafruit.com/assets/assets/000/044/661/original/rotary_encoder_bb.png?1486239862) + Contrairement aux potentiomètres et faders, les encodeurs rotatifs permettrons de changer dynamiquement les canaux DMX, en passant d'un preset à l'autre, et sont minis d'une fonction bouton (pour enregistrer la valeur dans le preset ?). -Leur utilisation avec circuitpython est détaillée [ici](https://learn.adafruit.com/rotary-encoder/hardware) + ![](https://cdn-learn.adafruit.com/assets/assets/000/044/661/original/rotary_encoder_bb.png?1486239862) -#### Exemple d'utilisation -```python -import rotaryio #pour l'ncodeur rotatif -import digitalio #pour le bouton -import board + Leur utilisation avec circuitpython est détaillée [ici](https://learn.adafruit.com/rotary-encoder/hardware) -encoder = rotaryio.IncrementalEncoder(board.D10, board.D9) + !!! python "Exemple d'utilisation" + ```python + import rotaryio #pour l'ncodeur rotatif + import digitalio #pour le bouton + import board -button = digitalio.DigitalInOut(board.D12) -button.direction = digitalio.Direction.INPUT -button.pull = digitalio.Pull.UP + encoder = rotaryio.IncrementalEncoder(board.D10, board.D9) -button_state = None -last_position = None + button = digitalio.DigitalInOut(board.D12) + button.direction = digitalio.Direction.INPUT + button.pull = digitalio.Pull.UP -while True: - position = encoder.position - if last_position is None or position != last_position: - print(position) - last_position = position - if not button.value and button_state is None: - button_state = "pressed" - if button.value and button_state == "pressed": - print("Appui sur le bouton.") button_state = None -``` -### Ecran SSD1306 - -#### Exemple d'utilisation -```python -import displayio -import terminalio -import adafruit_displayio_ssd1306 - -# On efface le contenu de l'écran -displayio.release_displays() - -# On déclare un port I2C sur les pins PG0 et GP0 -i2c = busio.I2C(scl=board.GP1, sda=board.GP0) - -# On déclare notre écran de 128x32 pixels sur l'I2C à l'addresse 0x3C -display_bus = displayio.I2CDisplay(i2c, device_address=0x3C) -display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=32) -# On gère l'affichage du texte sur l'écran -text_group = displayio.Group(max_size=5) -# On écrit sur un ligne située à 3 pixel du haut -text_area = label.Label(terminalio.FONT, text="Mon texte", color=0xFFFFFF, x=0, y=3) -text_group.append(text_area) -# On écrit sur un ligne située à 14 pixel du haut -text_area = label.Label(terminalio.FONT, text="Mon 2ème texte", color=0xFFFFFF, x=0, y=14) -text_group.append(text_area) -# On écrit sur une ligne située à 25 pixel du haut -text_area = label.Label(terminalio.FONT, text="Ma 3ème ligne", color=0xFFFFFF, x=0, y=25) -text_group.append(text_area) -display.show(text_group) -``` \ No newline at end of file + last_position = None + + while True: + position = encoder.position + if last_position is None or position != last_position: + print(position) + last_position = position + if not button.value and button_state is None: + button_state = "pressed" + if button.value and button_state == "pressed": + print("Appui sur le bouton.") + button_state = None + ``` +### Périphérique de sortie + +On peut utiliser un écran pour afficher les valeurs des canaux DMX, et le numéro des présets. + +??? note "Ecran SSD1306" + + ```python + import displayio + import terminalio + import adafruit_displayio_ssd1306 + from adafruit_display_text import label + + # On efface le contenu de l'écran + displayio.release_displays() + + # On déclare un port I2C sur les pins PG0 et GP0 + i2c = busio.I2C(scl=board.GP1, sda=board.GP0) + + # On déclare notre écran de 128x32 pixels sur l'I2C à l'addresse 0x3C + display_bus = displayio.I2CDisplay(i2c, device_address=0x3C) + display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=32) + # On gère l'affichage du texte sur l'écran + text_group = displayio.Group(max_size=5) + # On écrit sur un ligne située à 3 pixel du haut + text_area = label.Label(terminalio.FONT, text="Mon texte", color=0xFFFFFF, x=0, y=3) + text_group.append(text_area) + # On écrit sur un ligne située à 14 pixel du haut + text_area = label.Label(terminalio.FONT, text="Mon 2ème texte", color=0xFFFFFF, x=0, y=14) + text_group.append(text_area) + # On écrit sur une ligne située à 25 pixel du haut + text_area = label.Label(terminalio.FONT, text="Ma 3ème ligne", color=0xFFFFFF, x=0, y=25) + text_group.append(text_area) + display.show(text_group) + ``` \ No newline at end of file