Projet PLS : Programmable Lighting System

Discussion dans 'Discussion Technique' créé par sawblade, 9 Février 2026.

  1. fb11

    fb11 membre

    Inscrit:
    18 Octobre 2018
    Messages:
    16 904
    J'aime reçus:
    38 785
    A peu près :D
     
    Moa Etctout et dawii aiment ça.
  2. dawii

    dawii membre

    Inscrit:
    16 Octobre 2020
    Messages:
    8 966
    J'aime reçus:
    21 991
    de loin:p
     
    Moa Etctout apprécie ceci.
  3. Moa Etctout

    Moa Etctout membre

    Inscrit:
    22 Septembre 2021
    Messages:
    1 629
    J'aime reçus:
    3 100
    Alors, le principe, oui, comment, non
     
    sawblade et dawii aiment ça.
  4. sawblade

    sawblade membre
    Membre du personnel MODERATEUR

    Inscrit:
    7 Novembre 2009
    Messages:
    11 943
    J'aime reçus:
    16 869
    Allez, un premier essai pour variateur en mode crawler (freinage drag brake)
    On a :
    - feu stop au neutre pendant 5sec + feu stop 1seconde en cas de décélération brusque
    - feu de recul en marche arrière (pas pu vérifier, je crois que j'ai grillé ma led :mad:)
    - warning sur volant maintenu à gauche au neutre des gaz pendant 5sec (fonction impulsionnelle)
    - phares sur volant maintenu à droite au neutre des gaz pendant 5sec (fonction impulsionnelle)
    - sortie D4 en mode feu stop simple fonction
    - sortie D5 en mode feu arriere double fonction stop/position par PWM

    Câblage absolument identique à précédemment
    Tout ça sans utiliser un éventuel CH3. ça laisse donc la possibilité de réserver CH3 a un treuil par exemple (c'est mon cas). Mais ça peut aussi du coup focntioner sur des tx basiques à 2canaux

    #include <Servo.h>

    const byte ch2Pin = 2;
    const byte ch1Pin = 3;

    const byte outputD4 = 4;
    const byte outputD5 = 5;
    const byte outputD6 = 6;
    const byte D7_TOGGLE = 7;
    const byte outputD9 = 9;

    // ===============================
    // SEUILS CH2
    // ===============================

    const int NEUTRE_MIN = 1300;
    const int NEUTRE_MAX = 1600;

    // Hysteresis autour du neutre
    const int SORTIE_NEUTRE_ARRIERE = 1250;
    const int SORTIE_NEUTRE_AVANT = 1650;

    // Variation nécessaire pour déclencher un freinage rapide
    const int VARIATION_FREIN = 100;

    // Variation nécessaire pour réarmer le frein
    const int REMISE_GAZ = 50;

    // ===============================
    // TEMPORISATIONS
    // ===============================

    const unsigned long DUREE_FREIN_RAPIDE = 1000;
    const unsigned long DUREE_FREIN_NEUTRE = 5000;

    const unsigned long DUREE_MAINTIEN_TOGGLE = 5000;
    const unsigned long DUREE_CLIGNOTEMENT = 500;

    // ===============================
    // SEUILS CH1
    // ===============================

    const int CH1_GAUCHE = 1500;
    const int CH1_DROITE = 1300;

    // ===============================
    // PWM D5
    // ===============================

    const int PWM_D5_VEILLEUSE = 60;
    const int PWM_D5_STOP = 255;

    // ===============================
    // VARIABLES CH1 / CH2
    // ===============================

    int ch1 = 1500;
    int ch2 = 1500;

    int ch2Precedent = 1500;
    int referenceGaz = 1500;

    // ===============================
    // VARIABLES FREIN
    // ===============================

    bool freinActif = false;
    bool freinRapideActif = false;

    unsigned long debutFrein = 0;
    unsigned long debutNeutre = 0;

    bool etaitAuNeutre = false;
    bool freinArme = true;

    // ===============================
    // VARIABLES D6 WARNING
    // ===============================

    bool clignotementD6 = false;
    bool etatD6 = false;

    unsigned long debutMaintienD6 = 0;
    bool toggleD6DejaEffectue = false;
    unsigned long dernierChangementD6 = 0;

    // ===============================
    // VARIABLES D7
    // ===============================

    bool etatD7 = false;

    unsigned long debutMaintienD7 = 0;
    bool toggleD7DejaEffectue = false;

    // ===============================
    // GESTION D5
    // ===============================

    void mettreAJourD5()
    {
    if (freinActif)
    {
    // D4 ON = STOP
    // D5 à la puissance STOP
    analogWrite(outputD5, PWM_D5_STOP);
    }
    else if (etatD7)
    {
    // D7 ON sans frein
    // D5 en mode VEILLEUSE
    analogWrite(outputD5, PWM_D5_VEILLEUSE);
    }
    else
    {
    // D7 OFF et D4 OFF
    // D5 éteint
    analogWrite(outputD5, 0);
    }
    }

    // ===============================
    // ALLUMAGE FREIN
    // ===============================

    void allumerFrein()
    {
    digitalWrite(outputD4, HIGH);

    freinActif = true;

    mettreAJourD5();
    }

    // ===============================
    // EXTINCTION FREIN
    // ===============================

    void eteindreFrein()
    {
    digitalWrite(outputD4, LOW);

    freinActif = false;

    mettreAJourD5();
    }

    // ===============================
    // GESTION TOGGLE D6
    // CH1 GAUCHE + CH2 NEUTRE
    // MAINTIEN 5 SECONDES
    // ===============================

    void gererToggleD6(unsigned long maintenant, bool neutre)
    {
    bool ch1Gauche = (ch1 >= CH1_GAUCHE);

    if (ch1Gauche && neutre)
    {
    if (debutMaintienD6 == 0)
    {
    debutMaintienD6 = maintenant;

    Serial.println();
    Serial.println("D6 : CH1 GAUCHE + CH2 NEUTRE");
    Serial.println("MAINTIEN 5 SECONDES...");
    }

    if (!toggleD6DejaEffectue &&
    maintenant - debutMaintienD6 >= DUREE_MAINTIEN_TOGGLE)
    {
    toggleD6DejaEffectue = true;

    clignotementD6 = !clignotementD6;

    if (clignotementD6)
    {
    etatD6 = true;

    digitalWrite(outputD6, HIGH);

    dernierChangementD6 = maintenant;

    Serial.println("D6 : CLIGNOTEMENT ON");
    }
    else
    {
    etatD6 = false;

    digitalWrite(outputD6, LOW);

    Serial.println("D6 : CLIGNOTEMENT OFF");
    }
    }
    }
    else
    {
    debutMaintienD6 = 0;
    toggleD6DejaEffectue = false;
    }
    }

    // ===============================
    // CLIGNOTEMENT D6
    // ===============================

    void gererClignotementD6(unsigned long maintenant)
    {
    if (!clignotementD6)
    {
    digitalWrite(outputD6, LOW);
    etatD6 = false;

    return;
    }

    if (maintenant - dernierChangementD6 >= DUREE_CLIGNOTEMENT)
    {
    dernierChangementD6 = maintenant;

    etatD6 = !etatD6;

    digitalWrite(outputD6, etatD6 ? HIGH : LOW);
    }
    }

    // ===============================
    // GESTION TOGGLE D7
    // CH1 DROITE + CH2 NEUTRE
    // MAINTIEN 5 SECONDES
    // ===============================

    void gererToggleD7(unsigned long maintenant, bool neutre)
    {
    bool ch1Droite = (ch1 <= CH1_DROITE);

    if (ch1Droite && neutre)
    {
    if (debutMaintienD7 == 0)
    {
    debutMaintienD7 = maintenant;

    Serial.println();
    Serial.println("D7 : CH1 DROITE + CH2 NEUTRE");
    Serial.println("MAINTIEN 5 SECONDES...");
    }

    if (!toggleD7DejaEffectue &&
    maintenant - debutMaintienD7 >= DUREE_MAINTIEN_TOGGLE)
    {
    toggleD7DejaEffectue = true;

    etatD7 = !etatD7;

    digitalWrite(D7_TOGGLE, etatD7 ? HIGH : LOW);

    mettreAJourD5();

    if (etatD7)
    {
    Serial.println("D7 : ON");
    }
    else
    {
    Serial.println("D7 : OFF");
    }
    }
    }
    else
    {
    debutMaintienD7 = 0;
    toggleD7DejaEffectue = false;
    }
    }

    // ===============================
    // SETUP
    // ===============================

    void setup()
    {
    pinMode(ch2Pin, INPUT);
    pinMode(ch1Pin, INPUT);

    pinMode(outputD4, OUTPUT);
    pinMode(outputD5, OUTPUT);
    pinMode(outputD6, OUTPUT);
    pinMode(D7_TOGGLE, OUTPUT);
    pinMode(outputD9, OUTPUT);

    digitalWrite(outputD4, LOW);
    analogWrite(outputD5, 0);

    digitalWrite(outputD6, LOW);
    digitalWrite(D7_TOGGLE, LOW);
    digitalWrite(outputD9, LOW);

    Serial.begin(9600);

    Serial.println();
    Serial.println("=================================");
    Serial.println("FEUX STOP CRAWLER");
    Serial.println("TEST CH1 / CH2");
    Serial.println("=================================");
    }

    // ===============================
    // LOOP PRINCIPALE
    // ===============================

    void loop()
    {
    unsigned long maintenant = millis();

    // =============================
    // LECTURE CH2
    // =============================

    ch2 = pulseIn(ch2Pin, HIGH, 25000);

    if (ch2 == 0)
    {
    ch2 = ch2Precedent;
    }

    // =============================
    // LECTURE CH1
    // =============================

    ch1 = pulseIn(ch1Pin, HIGH, 25000);

    if (ch1 == 0)
    {
    ch1 = 1500;
    }

    // =============================
    // MONITEUR SERIE
    // =============================

    Serial.print("CH1 = ");
    Serial.print(ch1);

    Serial.print(" CH2 = ");
    Serial.println(ch2);

    // =============================
    // DETECTION NEUTRE
    // =============================

    bool neutre =
    (ch2 >= NEUTRE_MIN &&
    ch2 <= NEUTRE_MAX);

    // =============================
    // FEUX DE RECUL D9
    // CH2 < 1300
    // =============================

    if (ch2 < NEUTRE_MIN)
    {
    digitalWrite(outputD9, HIGH);
    }
    else
    {
    digitalWrite(outputD9, LOW);
    }

    // =============================
    // TOGGLE D6
    // =============================

    gererToggleD6(maintenant, neutre);

    // =============================
    // CLIGNOTEMENT D6
    // =============================

    gererClignotementD6(maintenant);

    // =============================
    // TOGGLE D7
    // =============================

    gererToggleD7(maintenant, neutre);

    // =============================
    // GESTION DU NEUTRE
    // =============================

    if (neutre)
    {
    if (!etaitAuNeutre)
    {
    etaitAuNeutre = true;

    debutNeutre = maintenant;

    allumerFrein();

    Serial.println("ENTREE AU NEUTRE : FREIN");
    }

    // Après 5 secondes au neutre,
    // extinction du frein
    if (maintenant - debutNeutre >= DUREE_FREIN_NEUTRE)
    {
    eteindreFrein();
    }

    ch2Precedent = ch2;

    delay(20);

    return;
    }

    // =============================
    // HYSTERESIS AUTOUR DU NEUTRE
    // =============================

    bool zoneHysteresis =
    (ch2 >= SORTIE_NEUTRE_ARRIERE &&
    ch2 <= SORTIE_NEUTRE_AVANT);

    if (etaitAuNeutre)
    {
    if (zoneHysteresis)
    {
    ch2Precedent = ch2;

    delay(20);

    return;
    }

    etaitAuNeutre = false;

    eteindreFrein();

    Serial.println("SORTIE REELLE DU NEUTRE");
    }

    // =============================
    // DIRECTION
    // =============================

    bool marcheAvant = (ch2 > NEUTRE_MAX);
    bool marcheArriere = (ch2 < NEUTRE_MIN);

    // =============================
    // FREINAGE RAPIDE
    // =============================

    if (freinArme)
    {
    // Freinage rapide en marche avant
    if (marcheAvant)
    {
    if (ch2Precedent - ch2 >= VARIATION_FREIN)
    {
    allumerFrein();

    freinRapideActif = true;
    debutFrein = maintenant;
    freinArme = false;

    Serial.println("FREINAGE RAPIDE AVANT");
    }
    }

    // Freinage rapide en marche arrière
    if (marcheArriere)
    {
    if (ch2 - ch2Precedent >= VARIATION_FREIN)
    {
    allumerFrein();

    freinRapideActif = true;
    debutFrein = maintenant;
    freinArme = false;

    Serial.println("FREINAGE RAPIDE ARRIERE");
    }
    }
    }

    // =============================
    // FIN DU FREINAGE RAPIDE
    // =============================

    if (freinRapideActif)
    {
    if (maintenant - debutFrein >= DUREE_FREIN_RAPIDE)
    {
    eteindreFrein();

    freinRapideActif = false;

    Serial.println("FIN FREINAGE RAPIDE");
    }
    }

    // =============================
    // REARMEMENT DU FREIN
    // =============================

    if (!freinArme && !freinRapideActif)
    {
    if (marcheAvant)
    {
    if (ch2 >= referenceGaz + REMISE_GAZ)
    {
    freinArme = true;

    referenceGaz = ch2;

    Serial.println("FREIN REARME AVANT");
    }
    }

    if (marcheArriere)
    {
    if (ch2 <= referenceGaz - REMISE_GAZ)
    {
    freinArme = true;

    referenceGaz = ch2;

    Serial.println("FREIN REARME ARRIERE");
    }
    }
    }

    // =============================
    // MEMORISATION CH2
    // =============================

    ch2Precedent = ch2;

    delay(20);
    }
     
    fb11 apprécie ceci.
  5. benjiv

    benjiv membre

    Inscrit:
    4 Janvier 2015
    Messages:
    5 740
    J'aime reçus:
    8 694
    Salut, question idiote : ça marche sur un ESP32-C3 Super mini ? J'en ai un en stock.
     
  6. sawblade

    sawblade membre
    Membre du personnel MODERATEUR

    Inscrit:
    7 Novembre 2009
    Messages:
    11 943
    J'aime reçus:
    16 869
    Tel quel, ca m'étonnerait. Les broches doivent etre différentes, la tension de fonctionnement n'est pas la même, et les bibliothèques sont sûrement différentes
    Mais en adaptant ca fonctionne forcément.
    Un coup de chatgpt et il te transforme ça

    Par contre, sur un arduino nano esp32 ca doit marcher à coup sûr. C'est d'ailleurs la dessus que je vais faire mes projets plus aboutis
     
    #66 sawblade, 9 Novembre 2026, à 20:13
    Dernière édition: 9 Novembre 2026, à 20:28

Partager cette page