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 655
    J'aime reçus:
    37 937
    A peu près :D
     
    Moa Etctout et dawii aiment ça.
  2. dawii

    dawii membre

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

    Moa Etctout membre

    Inscrit:
    22 Septembre 2021
    Messages:
    1 555
    J'aime reçus:
    2 904
    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 888
    J'aime reçus:
    16 675
    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.

Partager cette page