Coup de chaud sur Klipper : Comment l'ennui estival a fait clignoter ma Neptune 4 Max

Une idée née de la canicule : Par une après-midi de forte chaleur, l'ennui aidant, une question m'est venue en observant ma machine : comment prendre le contrôle total des LED de l'Elegoo Neptune 4 Max et les faire réagir à ma convenance ? Mon premier réflexe a été d'installer le célèbre plugin Led Effects pour Klipper dans l'espoir de générer des animations fluides et des clignotements complexes. C'était sans compter sur une réalité technique brute : les LED d'usine de la Neptune 4 Max ne disposent d'aucun microcontrôleur. Ce ne sont pas des LED RGB adressables, mais de simples bandes binaires. Elles ne connaissent que deux états : 1 ou 0, ON ou OFF. C'est en me plongeant directement dans l'analyse des macros natives qui gèrent l'allumage du cadre et de la tête d'impression que la solution pour contourner cette limitation est apparue comme une évidence...

L'art du détournement logique : Puisque le matériel refuse de faire varier son intensité ou ses couleurs, c'est au logiciel de simuler une animation dynamique. En manipulant le temps et les boucles de rétroaction de Klipper, on peut forcer un composant binaire à devenir un véritable outil de signalisation visuelle.

1. Première étape : Rompre la monotonie avec le clignotement simple

Pour s'affranchir de la rigidité du ON/OFF classique, la clé réside dans l'utilisation d'un [delayed_gcode]. Ce mécanisme permet à Klipper de créer une boucle infinie autonome qui change l'état de la broche toutes les 0,5 seconde, sans jamais bloquer le reste des calculs de l'imprimante.

Voici le bloc de code initial permettant d'activer cette routine de clignotement régulier (idéal pour signaler une phase de préchauffage ou une mise en garde mécanique) :

# --- VARIABLE STORAGE ---
[gcode_macro zew_led_settings]
variable_blinking_active: 0
variable_state: 0
gcode:
    # Dummy gcode block

# --- NATIVE BLINKING LOOP (HEATING/WARNING) ---
[delayed_gcode zew_led_blinking_loop]
gcode:
    {% set sv = printer["gcode_macro zew_led_settings"] %}
    {% if sv.blinking_active == 1 %}
        {% set next_state = 1 if sv.state == 0 else 0 %}
        SET_GCODE_VARIABLE MACRO=zew_led_settings VARIABLE=state VALUE={next_state}
        SET_PIN PIN=Frame_Light VALUE={next_state}
        UPDATE_DELAYED_GCODE ID=zew_led_blinking_loop DURATION=0.5
    {% endif %}

# --- CONTROLLER MACROS ---
[gcode_macro START_LED_BLINKING]
description: Start the native frame LED regular blink
gcode:
    SET_GCODE_VARIABLE MACRO=zew_led_settings VARIABLE=blinking_active VALUE=1
    SET_GCODE_VARIABLE MACRO=zew_led_settings VARIABLE=state VALUE=0
    UPDATE_DELAYED_GCODE ID=zew_led_blinking_loop DURATION=0.1

2. Pousser l'idée plus loin : Utilité et Code Morse

Une fois le clignotement de base maîtrisé, une nouvelle réflexion s'est imposée : comment transformer ce simple gadget visuel en une véritable fonction utile pour l'atelier ? Faire clignoter une lumière est une chose, mais lui faire transmettre un message d'erreur explicite en cas de défaillance critique (comme une coupure thermique ou un blocage d'axe) en est une autre.

C'est tout naturellement que l'idée de coder un **SOS universel en alphabet Morse** est apparue. Après plusieurs sessions d'expérimentations logiques et de tests de timing, le script de production complet sous forme de matrice temporelle a vu le jour.

La science du rythme : Le concept de Matrice

Le véritable défi du code Morse sur des LED binaires réside dans le strict respect des espacements. Sans un contrôle chirurgical des pauses, les éclairs lumineux s'enchaînent de manière brouillonne et le signal devient illisible. Pour régler ce problème, nous utilisons une matrice (un tableau indexé) où chaque élément représente une unité de temps fixe de 0,15 seconde :

  • Les points (S : . . .) : Sont codés par une alternance rapide de 1,0,1,0,1 (allumé brièvement, éteint brièvement).
  • Les traits (O : — — —) : Nécessitent une persistance lumineuse plus longue, codée par une succession de temps forts : 1,1,1,1,1.
  • Les silences inter-lettres : Pour séparer distinctement le "S" du "O", le script injecte une lourde pause d'extinction de six unités consécutives à zéro (0,0,0,0,0,0).
  • Le silence inter-mot : Avant de répéter la boucle de détresse, un grand vide temporel de quinze zéros est appliqué pour marquer la fin du mot SOS et permettre une lecture humaine parfaite.

3. Script de production complet : Lighting & Animation

Voici l'intégralité du module. Ce code fusionne le clignotement standard, la gestion millimétrée du SOS en Morse avec correction des espaces, et intègre le système d'interruption globale des effets :

#############################################################################
#############################################################################
# ZEW-Neptune4Max V1.0 | CUSTOM CORE COMPONENT
# -------------------------------------------------------------------------
# MODULE      : LIGHTING & ANIMATION CONFIGURATOR
# FUNCTION    : Frame-Only ON/OFF LED Signaling (Perfect Letter Spacing)
# DESIGNED BY : Frédéric IMBERT
# VERSION     : 1.4.6 (2026-07-01)
# STATUS      : PRODUCTION / CLEANED
#############################################################################
#############################################################################

# --- VARIABLE STORAGE ---
[gcode_macro zew_led_settings]
variable_blinking_active: 0
variable_sos_active: 0
variable_state: 0
variable_sos_step: 0
gcode:
    # Dummy gcode block

# --- NATIVE BLINKING LOOP (HEATING/WARNING) ---
[delayed_gcode zew_led_blinking_loop]
gcode:
    {% set sv = printer["gcode_macro zew_led_settings"] %}
    {% if sv.blinking_active == 1 %}
        {% set next_state = 1 if sv.state == 0 else 0 %}
        SET_GCODE_VARIABLE MACRO=zew_led_settings VARIABLE=state VALUE={next_state}
        SET_PIN PIN=Frame_Light VALUE={next_state}
        UPDATE_DELAYED_GCODE ID=zew_led_blinking_loop DURATION=0.5
    {% endif %}

# --- NATIVE MORSE SOS LOOP (ERROR) ---
[delayed_gcode zew_led_sos_loop]
gcode:
    {% set sv = printer["gcode_macro zew_led_settings"] %}
    {% if sv.sos_active == 1 %}
        {% set step = sv.sos_step %}
        
        # Perfect Morse Pattern with enhanced inter-letter and inter-word gaps
        # 1 = LED ON, 0 = LED OFF
        {% set sos_pattern = [
            1,0,1,0,1,                                         # S : . . . (Short flashes)
            0,0,0,0,0,0,                                       # Heavy Inter-letter pause (S -> O)
            1,1,1,1,1, 0,0,0,0, 1,1,1,1,1, 0,0,0,0, 1,1,1,1,1, # O : —   —   — (Long flashes)
            0,0,0,0,0,0,                                       # Heavy Inter-letter pause (O -> S)
            1,0,1,0,1,                                         # S : . . . (Short flashes)
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0                      # Extended Word pause before repeating SOS
        ] %}
        
        {% set pattern_length = sos_pattern|length %}
        {% set current_signal = sos_pattern[step] %}
        
        SET_PIN PIN=Frame_Light VALUE={current_signal}
        
        {% set next_step = step + 1 %}
        {% if next_step >= pattern_length %}
            {% set next_step = 0 %}
        {% endif %}
        
        SET_GCODE_VARIABLE MACRO=zew_led_settings VARIABLE=sos_step VALUE={next_step}
        # Step unit duration
        UPDATE_DELAYED_GCODE ID=zew_led_sos_loop DURATION=0.15
    {% endif %}

# --- CONTROLLER MACROS ---

[gcode_macro START_LED_BLINKING]
description: Start the native frame LED regular blink
gcode:
    STOP_ALL_LED_EFFECTS
    SET_GCODE_VARIABLE MACRO=zew_led_settings VARIABLE=blinking_active VALUE=1
    SET_GCODE_VARIABLE MACRO=zew_led_settings VARIABLE=state VALUE=0
    UPDATE_DELAYED_GCODE ID=zew_led_blinking_loop DURATION=0.1

[gcode_macro START_LED_SOS]
description: Start the frame-only High-Contrast Morse Code SOS
gcode:
    STOP_ALL_LED_EFFECTS
    SET_GCODE_VARIABLE MACRO=zew_led_settings VARIABLE=sos_active VALUE=1
    SET_GCODE_VARIABLE MACRO=zew_led_settings VARIABLE=sos_step VALUE=0
    UPDATE_DELAYED_GCODE ID=zew_led_sos_loop DURATION=0.1

[gcode_macro STOP_ALL_LED_EFFECTS]
description: Kill all active light loops and turn off frame LEDs
gcode:
    SET_GCODE_VARIABLE MACRO=zew_led_settings VARIABLE=blinking_active VALUE=0
    SET_GCODE_VARIABLE MACRO=zew_led_settings VARIABLE=sos_active VALUE=0
    UPDATE_DELAYED_GCODE ID=zew_led_blinking_loop DURATION=0
    UPDATE_DELAYED_GCODE ID=zew_led_sos_loop DURATION=0
    SET_PIN PIN=Frame_Light VALUE=0

Maintenant que ces principes de programmation et ce concept de gestion temporelle sont posés, le champ des possibles est immense. En vous basant sur cette logique de matrice, il devient extrêmement simple de modifier et d'adapter le code pour créer n'importe quel type de clignotement personnalisé, ajuster les cadences, ou même coder d'autres mots en morse (comme un signal spécifique pour la fin d'une impression ou un avertissement de changement de filament).

4. Intégration universelle dans votre printer.cfg

Que vous ayez adopté une architecture modulaire stricte ou que vous utilisiez encore l'arborescence de fichiers standard de Klipper, l'intégration de ce script reste à la portée de tous. Il suffit de créer un nouveau fichier de configuration (par exemple nommé zew_led_animations.cfg) et de l'appeler directement depuis votre fichier maître.

Ouvrez votre fichier printer.cfg principal et ajoutez simplement la directive d'inclusion suivante en adaptant le chemin selon l'emplacement choisi dans votre interface (Fluidd / Mainsail) :

# ===========================================================================
# INCLUSION DES SCRIPTS ET MACROS ADDITIONNELLES
# ===========================================================================

# Ajoutez cette ligne pour activer la gestion binaire des LED :
[include zew_led_animations.cfg]   # Active le clignotement natif et le SOS en Morse

# Note : Si vous placez le fichier dans un sous-dossier, spécifiez son chemin (ex: [include mon_dossier/zew_led_animations.cfg])

Rappel pour les systèmes Linux : Klipper respecte strictement la casse. Assurez-vous que le nom de votre fichier physique corrobore au caractère près (majuscules et minuscules) avec le nom renseigné dans votre directive [include] sous peine de bloquer l'initialisation du firmware au redémarrage.

En exploitant intelligemment la mémoire interne de Klipper et des tableaux de données temporels, nous viens de prouver qu'une simple contrainte matérielle peut se transformer en un atout de signalisation majeur. Dans un prochain article, nous verrons comment lier ces fonctions d'affichage à vos événements matériels pour automatiser les alertes de l'atelier. Restez connectés !

Choix utilisateur pour les Cookies
Nous utilisons des cookies afin de vous proposer les meilleurs services possibles. Si vous déclinez l'utilisation de ces cookies, le site web pourrait ne pas fonctionner correctement.
Tout accepter
Tout décliner
Analytique
Outils utilisés pour analyser les données de navigation et mesurer l'efficacité du site internet afin de comprendre son fonctionnement.
Google Analytics
Accepter
Décliner
Publicité
Si vous acceptez, les annonces présentes sur la page seront adaptées à vos préférences.
Publicité Google
Accepter
Décliner
Sauvegarder