Tu tentes un copié /collé ? Je commence aussi à réfléchir a une version pour crawler (beaucoup plus compliqué à cause du drag brake automatique !)
non pas du tout, juste impressionné par les lignes de code, 'suis vite largué en electro bien que ça soit très interressant Bonne continuation
oui ou si peu Mais quand on est une buse en electro, bref Rien à voir... Après quelques épisodes Initial D, cet été en train de refaire la saga des Fast and furious (sur netflix), ça fait drôle de revoir 20 ans après, une autre époque, tout à fond! il y a quand même de superbes prises de vue ..Ta voiture est clairement dans cet état d'esprit
J'ai aussi essayé vite fait de faire une évocation du flame spiting au relâché des gaz ou lors de l'antilag. J'ai pas passé trop de temps à affiner, ce ne sera pas prioritaire. J'ai quand même fait en sorte que ce ne soit pas trop régulier lors de l'antilag L'essai est fait avec la led de clignotant, l'idée serait d'insérer une toute petite led dans des sorties d'échappement en tube métallique : - Allumage lors du bang ( relâché d'accélérateur plein gaz) - Allumage lors de l'activation de l'antilag (gaz maintenu a fond) Je trouve ça très rigolo meme si c'est pas parfait
Rlaarlo l’a fait sur la Mitsu EVO 6 au 1/7 qui vient de sortir . J’aurais pas la patience de faire ce que tu fais, ni les compétences
Je ferai un recap a la fin, vous verrez la facilité avec laquelle on peut arriver a ce résultat Le gros morceau à venir, ca va etre l'agencement propre de l'ensemble du câblage. La place étant comptée, je pense me passer de toute connectique
En attendant, je colle ici la dernière version du code. J'ai rajouté la distinction Feu Stop / Feu de Recul sur le deuxième appui en arrière de la gâchette. J'ai rajouté aussi un brouillon d'une fonction "surprise", qui fonctionne mais ne donne pas encore le rendu espéré... Les plus curieux la trouveront peut-etre dans le code. N'hésitez pas a chercher, les annotations au milieu des lignes de code donne un aspect plus lisible. C'est parti: #include <Servo.h> //===================================================== // ENTREES //===================================================== const byte ch2Pin = 2; const byte ch1Pin = 3; //===================================================== // SORTIES //===================================================== const byte outputD4 = 4; // Feux stop const byte outputD6 = 6; const byte outputD7 = 7; const byte servoPin = 8; // Servo const byte outputD9 = 9; // Feux de recul const byte outputD10 = 10; // Fonction D10 Servo servo; //===================================================== // CH2 //===================================================== // Marche arrière / frein const int SEUIL_BAS = 1300; // Zone neutre const int NEUTRE_MIN = 1300; const int NEUTRE_MAX = 1600; // Plein gaz const int PLEIN_GAZ = 1960; //===================================================== // D6 / D7 //===================================================== const unsigned long TEMPS_TOGGLE = 3000; const unsigned long TEMPS_CLIGNOT = 500; //===================================================== // FREIN / MARCHE ARRIERE //===================================================== const unsigned long TEMPS_NEUTRE = 100; //===================================================== // D10 //===================================================== // Impulsion lors de : // PLEIN GAZ -> NEUTRE const unsigned long D10_IMPULSION = 100; // Temps de plein gaz avant clignotement const unsigned long D10_DELAI = 2000; // Clignotement irrégulier rapide const unsigned long D10_ON_MIN = 50; const unsigned long D10_ON_MAX = 100; const unsigned long D10_OFF_MIN = 120; const unsigned long D10_OFF_MAX = 280; //===================================================== // SERVO //===================================================== const int SERVO_POSITION_0 = 2000; const int SERVO_POSITION_100 = 1000; //===================================================== // FREIN / MARCHE ARRIERE //===================================================== enum EtatGachette { AVANT, FREIN, NEUTRE_APRES_FREIN, MARCHE_ARRIERE }; EtatGachette etatGachette = AVANT; unsigned long neutreTimer = 0; //===================================================== // D6 //===================================================== bool d6Enable = false; bool d6State = false; unsigned long d6Timer = 0; unsigned long d6Blink = 0; bool d6WaitingRelease = false; //===================================================== // D7 / SERVO //===================================================== bool d78Enable = false; unsigned long d78Timer = 0; bool d78WaitingRelease = false; //===================================================== // D10 //===================================================== // A-t-on déjà vu le plein gaz ? bool d10PleinGazVu = false; // Timer du plein gaz unsigned long d10GazTimer = 0; // Clignotement actif bool d10Repeat = false; // Etat actuel de D10 bool d10State = false; // Timer de l'état actuel unsigned long d10Timer = 0; // Durée actuelle ON ou OFF unsigned long d10Duree = 0; //===================================================== // SETUP //===================================================== void setup() { pinMode(ch1Pin, INPUT); pinMode(ch2Pin, INPUT); pinMode(outputD4, OUTPUT); pinMode(outputD6, OUTPUT); pinMode(outputD7, OUTPUT); pinMode(outputD9, OUTPUT); pinMode(outputD10, OUTPUT); digitalWrite(outputD4, LOW); digitalWrite(outputD6, LOW); digitalWrite(outputD7, LOW); digitalWrite(outputD9, LOW); digitalWrite(outputD10, LOW); //------------------------------------------------- // Servo //------------------------------------------------- servo.attach(servoPin); servo.writeMicroseconds(SERVO_POSITION_0); //------------------------------------------------- // Aléatoire //------------------------------------------------- randomSeed(analogRead(A0)); //------------------------------------------------- // Série //------------------------------------------------- Serial.begin(115200); Serial.println("===== DEMARRAGE ====="); } //===================================================== // LOOP //===================================================== void loop() { unsigned long now = millis(); //================================================= // LECTURE RADIO //================================================= unsigned long ch2 = pulseIn(ch2Pin, HIGH, 25000); unsigned long ch1 = pulseIn(ch1Pin, HIGH, 25000); //================================================= // POSITION CH2 //================================================= bool gazArriere = (ch2 > 0 && ch2 < SEUIL_BAS); bool gazNeutre = (ch2 >= NEUTRE_MIN && ch2 <= NEUTRE_MAX); bool gazAvant = (ch2 > NEUTRE_MAX); bool pleinGaz = (ch2 >= PLEIN_GAZ); //================================================= // FREIN / MARCHE ARRIERE //================================================= //------------------------------------------------- // AVANT //------------------------------------------------- if (etatGachette == AVANT) { digitalWrite(outputD4, LOW); digitalWrite(outputD9, LOW); if (gazArriere) { etatGachette = FREIN; } } //------------------------------------------------- // FREIN //------------------------------------------------- else if (etatGachette == FREIN) { digitalWrite(outputD4, HIGH); digitalWrite(outputD9, LOW); if (!gazArriere) { neutreTimer = now; etatGachette = NEUTRE_APRES_FREIN; } } //------------------------------------------------- // NEUTRE APRES FREIN //------------------------------------------------- else if (etatGachette == NEUTRE_APRES_FREIN) { digitalWrite(outputD4, LOW); digitalWrite(outputD9, LOW); if (gazAvant) { etatGachette = AVANT; } else if (gazNeutre) { // Attente } else if (gazArriere) { if (now - neutreTimer >= TEMPS_NEUTRE) { etatGachette = MARCHE_ARRIERE; } } } //------------------------------------------------- // MARCHE ARRIERE //------------------------------------------------- else if (etatGachette == MARCHE_ARRIERE) { digitalWrite(outputD4, LOW); digitalWrite(outputD9, HIGH); if (gazNeutre) { digitalWrite(outputD4, LOW); digitalWrite(outputD9, LOW); neutreTimer = now; etatGachette = NEUTRE_APRES_FREIN; } else if (gazAvant) { digitalWrite(outputD4, LOW); digitalWrite(outputD9, LOW); etatGachette = AVANT; } } //================================================= // D6 //================================================= if (ch2 > 0 && ch1 > 0 && ch2 < SEUIL_BAS && ch1 < SEUIL_BAS) { if (d6Timer == 0) d6Timer = now; if (!d6WaitingRelease && now - d6Timer >= TEMPS_TOGGLE) { d6Enable = !d6Enable; d6WaitingRelease = true; } } else { d6Timer = 0; } //------------------------------------------------- // Réarmement D6 //------------------------------------------------- if (ch2 > SEUIL_BAS && ch1 > SEUIL_BAS) { d6WaitingRelease = false; } //================================================= // CLIGNOTEMENT D6 //================================================= if (d6Enable) { if (now - d6Blink >= TEMPS_CLIGNOT) { d6Blink = now; d6State = !d6State; digitalWrite(outputD6, d6State); } } else { d6State = false; digitalWrite(outputD6, LOW); } //================================================= // D7 + SERVO //================================================= if (ch2 > 0 && ch2 < SEUIL_BAS && ch1 == 0) { if (d78Timer == 0) d78Timer = now; if (!d78WaitingRelease && now - d78Timer >= TEMPS_TOGGLE) { d78Enable = !d78Enable; d78WaitingRelease = true; } } else { d78Timer = 0; } //------------------------------------------------- // Réarmement //------------------------------------------------- if (!(ch2 > 0 && ch2 < SEUIL_BAS && ch1 == 0)) { d78WaitingRelease = false; } //================================================= // SERVO + D7 //================================================= if (d78Enable) { digitalWrite(outputD7, HIGH); servo.writeMicroseconds(SERVO_POSITION_100); } else { digitalWrite(outputD7, LOW); servo.writeMicroseconds(SERVO_POSITION_0); } //================================================= // D10 //================================================= //------------------------------------------------- // 1. DETECTION DU PLEIN GAZ //------------------------------------------------- if (pleinGaz) { //------------------------------------------------- // Premier passage à plein gaz //------------------------------------------------- if (!d10PleinGazVu) { d10PleinGazVu = true; d10GazTimer = now; d10Repeat = false; } //------------------------------------------------- // Plein gaz maintenu > 1 seconde //------------------------------------------------- if (!d10Repeat && now - d10GazTimer >= D10_DELAI) { d10Repeat = true; d10State = true; digitalWrite(outputD10, HIGH); d10Timer = now; d10Duree = random(D10_ON_MIN, D10_ON_MAX + 1); } } //================================================= // 2. RETOUR DU PLEIN GAZ VERS LE NEUTRE //================================================= if (d10PleinGazVu && gazNeutre) { //------------------------------------------------- // Impulsion unique de 200 ms //------------------------------------------------- d10State = true; d10Repeat = false; digitalWrite(outputD10, HIGH); d10Timer = now; d10Duree = D10_IMPULSION; //------------------------------------------------- // On désarme //------------------------------------------------- d10PleinGazVu = false; } //================================================= // 3. SORTIE DU PLEIN GAZ //================================================= /* Si on quitte le plein gaz sans passer immédiatement par le neutre, on arrête le clignotement répétitif. MAIS on conserve d10PleinGazVu afin que le passage suivant dans la zone neutre puisse déclencher l'impulsion. */ if (!pleinGaz) { d10Repeat = false; } //================================================= // 4. GESTION D10 //================================================= if (d10State) { //------------------------------------------------- // D10 allumé //------------------------------------------------- if (now - d10Timer >= d10Duree) { d10State = false; digitalWrite(outputD10, LOW); d10Timer = now; //------------------------------------------------- // Si répétition active : // choisir durée OFF //------------------------------------------------- if (d10Repeat) { d10Duree = random(D10_OFF_MIN, D10_OFF_MAX + 1); } } } else if (d10Repeat) { //------------------------------------------------- // D10 éteint //------------------------------------------------- if (now - d10Timer >= d10Duree) { d10State = true; digitalWrite(outputD10, HIGH); d10Timer = now; //------------------------------------------------- // Nouvelle durée ON //------------------------------------------------- d10Duree = random(D10_ON_MIN, D10_ON_MAX + 1); } } //================================================= // SECURITE D10 //================================================= /* Si aucune fonction D10 n'est active, D10 doit être éteint. Cette partie évite qu'une ancienne impulsion puisse rester active. */ if (!d10State && !d10Repeat) { digitalWrite(outputD10, LOW); } //================================================= // MONITEUR SERIE //================================================= static unsigned long lastPrint = 0; if (now - lastPrint >= 250) { lastPrint = now; Serial.print("D2="); Serial.print(ch2); Serial.print(" D3="); Serial.print(ch1); Serial.print(" D4="); Serial.print(digitalRead(outputD4)); Serial.print(" D6="); Serial.print(digitalRead(outputD6)); Serial.print(" D7="); Serial.print(digitalRead(outputD7)); Serial.print(" D9="); Serial.print(digitalRead(outputD9)); Serial.print(" D10="); Serial.print(digitalRead(outputD10)); Serial.print(" Servo="); Serial.print(d78Enable ? "100%" : "0%"); Serial.print(" D10PG="); Serial.print(d10PleinGazVu); Serial.print(" D10REP="); Serial.print(d10Repeat); Serial.print(" Etat="); switch (etatGachette) { case AVANT: Serial.print("AVANT"); break; case FREIN: Serial.print("FREIN"); break; case NEUTRE_APRES_FREIN: Serial.print("NEUTRE_APRES_FREIN"); break; case MARCHE_ARRIERE: Serial.print("MARCHE_ARRIERE"); break; } Serial.print(" PleinGaz="); Serial.println(pleinGaz); } }
Modification du jour: ajout d'une fonction feux arrières double fonction (position et stop) sur la borne D5 (la borne D4 reste en feu STOP classique, pour cabler des feux stop arrieres séparés des feux de position, ou pour un éventuel 3eme feu stop ) Ci joint le nouveau code (j'ai aussi modifé quelques commentaires, pour que ce soit plus explicite): #include <Servo.h> //===================================================== // ENTREES //===================================================== const byte ch2Pin = 2; const byte ch1Pin = 3; //===================================================== // SORTIES //===================================================== const byte outputD4 = 4; // Feux stop const byte outputD5 = 5; // Feu arrière double intensité PWM const byte outputD6 = 6; // Warning const byte outputD7 = 7; // Phares const byte servoPin = 8; // Servo const byte outputD9 = 9; // Feux de recul const byte outputD10 = 10; // Echappement Servo servo; //===================================================== // CH2 //===================================================== // Marche arrière / frein const int SEUIL_BAS = 1300; // ZONE NEUTRE const int NEUTRE_MIN = 1300; const int NEUTRE_MAX = 1600; // PLEIN GAZ const int PLEIN_GAZ = 1960; //===================================================== // CLIGNOTANTS / PHARES //===================================================== const unsigned long TEMPS_TOGGLE = 3000; const unsigned long TEMPS_CLIGNOT = 500; //===================================================== // FREIN / MARCHE ARRIERE //===================================================== const unsigned long TEMPS_NEUTRE = 100; //===================================================== // FEU ARRIERE D5 //===================================================== // Intensité feu arrière avec phares allumés const byte D5_INTENSITE_VEILLEUSE = 70; // Intensité feu stop const byte D5_INTENSITE_STOP = 255; // Valeur PWM actuellement envoyée à D5 byte d5PWM = 0; //===================================================== // ECHAPPEMENT //===================================================== // Impulsion lors de : // PLEIN GAZ -> NEUTRE const unsigned long D10_IMPULSION = 100; // Temps de plein gaz avant clignotement const unsigned long D10_DELAI = 2000; // Clignotement irrégulier rapide const unsigned long D10_ON_MIN = 50; const unsigned long D10_ON_MAX = 100; const unsigned long D10_OFF_MIN = 120; const unsigned long D10_OFF_MAX = 280; //===================================================== // SERVO //===================================================== const int SERVO_POSITION_0 = 2000; const int SERVO_POSITION_100 = 1000; //===================================================== // FREIN / MARCHE ARRIERE //===================================================== enum EtatGachette { AVANT, FREIN, NEUTRE_APRES_FREIN, MARCHE_ARRIERE }; EtatGachette etatGachette = AVANT; unsigned long neutreTimer = 0; //===================================================== // WARNING //===================================================== bool d6Enable = false; bool d6State = false; unsigned long d6Timer = 0; unsigned long d6Blink = 0; bool d6WaitingRelease = false; //===================================================== // PHARES / SERVO //===================================================== bool d78Enable = false; unsigned long d78Timer = 0; bool d78WaitingRelease = false; //===================================================== // ECHAPPEMENT //===================================================== // A-t-on déjà vu le plein gaz ? bool d10PleinGazVu = false; // Timer du plein gaz unsigned long d10GazTimer = 0; // Clignotement actif bool d10Repeat = false; // Etat actuel de D10 bool d10State = false; // Timer de l'état actuel unsigned long d10Timer = 0; // Durée actuelle ON ou OFF unsigned long d10Duree = 0; //===================================================== // SETUP //===================================================== void setup() { pinMode(ch1Pin, INPUT); pinMode(ch2Pin, INPUT); pinMode(outputD4, OUTPUT); pinMode(outputD5, OUTPUT); pinMode(outputD6, OUTPUT); pinMode(outputD7, OUTPUT); pinMode(outputD9, OUTPUT); pinMode(outputD10, OUTPUT); digitalWrite(outputD4, LOW); analogWrite(outputD5, 0); digitalWrite(outputD6, LOW); digitalWrite(outputD7, LOW); digitalWrite(outputD9, LOW); digitalWrite(outputD10, LOW); //------------------------------------------------- // Servo //------------------------------------------------- servo.attach(servoPin); servo.writeMicroseconds(SERVO_POSITION_0); //------------------------------------------------- // Aléatoire //------------------------------------------------- randomSeed(analogRead(A0)); //------------------------------------------------- // Série //------------------------------------------------- Serial.begin(115200); Serial.println("===== DEMARRAGE ====="); } //===================================================== // LOOP //===================================================== void loop() { unsigned long now = millis(); //================================================= // LECTURE RADIO //================================================= unsigned long ch2 = pulseIn(ch2Pin, HIGH, 25000); unsigned long ch1 = pulseIn(ch1Pin, HIGH, 25000); //================================================= // POSITION CH2 //================================================= bool gazArriere = (ch2 > 0 && ch2 < SEUIL_BAS); bool gazNeutre = (ch2 >= NEUTRE_MIN && ch2 <= NEUTRE_MAX); bool gazAvant = (ch2 > NEUTRE_MAX); bool pleinGaz = (ch2 >= PLEIN_GAZ); //================================================= // FREIN / MARCHE ARRIERE //================================================= //------------------------------------------------- // AVANT //------------------------------------------------- if (etatGachette == AVANT) { digitalWrite(outputD4, LOW); digitalWrite(outputD9, LOW); if (gazArriere) { etatGachette = FREIN; } } //------------------------------------------------- // FREIN //------------------------------------------------- else if (etatGachette == FREIN) { digitalWrite(outputD4, HIGH); digitalWrite(outputD9, LOW); if (!gazArriere) { neutreTimer = now; etatGachette = NEUTRE_APRES_FREIN; } } //------------------------------------------------- // NEUTRE APRES FREIN //------------------------------------------------- else if (etatGachette == NEUTRE_APRES_FREIN) { digitalWrite(outputD4, LOW); digitalWrite(outputD9, LOW); if (gazAvant) { etatGachette = AVANT; } else if (gazNeutre) { // Attente } else if (gazArriere) { if (now - neutreTimer >= TEMPS_NEUTRE) { etatGachette = MARCHE_ARRIERE; } } } //------------------------------------------------- // MARCHE ARRIERE //------------------------------------------------- else if (etatGachette == MARCHE_ARRIERE) { digitalWrite(outputD4, LOW); digitalWrite(outputD9, HIGH); if (gazNeutre) { digitalWrite(outputD4, LOW); digitalWrite(outputD9, LOW); neutreTimer = now; etatGachette = NEUTRE_APRES_FREIN; } else if (gazAvant) { digitalWrite(outputD4, LOW); digitalWrite(outputD9, LOW); etatGachette = AVANT; } } //================================================= // WARNING //================================================= if (ch2 > 0 && ch1 > 0 && ch2 < SEUIL_BAS && ch1 < SEUIL_BAS) { if (d6Timer == 0) d6Timer = now; if (!d6WaitingRelease && now - d6Timer >= TEMPS_TOGGLE) { d6Enable = !d6Enable; d6WaitingRelease = true; } } else { d6Timer = 0; } //------------------------------------------------- // Réarmement WARNING //------------------------------------------------- if (ch2 > SEUIL_BAS && ch1 > SEUIL_BAS) { d6WaitingRelease = false; } //================================================= // CLIGNOTEMENT WARNING //================================================= if (d6Enable) { if (now - d6Blink >= TEMPS_CLIGNOT) { d6Blink = now; d6State = !d6State; digitalWrite(outputD6, d6State); } } else { d6State = false; digitalWrite(outputD6, LOW); } //================================================= // Déclenchement PHARES + SERVO //================================================= if (ch2 > 0 && ch2 < SEUIL_BAS && ch1 == 0) { if (d78Timer == 0) d78Timer = now; if (!d78WaitingRelease && now - d78Timer >= TEMPS_TOGGLE) { d78Enable = !d78Enable; d78WaitingRelease = true; } } else { d78Timer = 0; } //------------------------------------------------- // Réarmement //------------------------------------------------- if (!(ch2 > 0 && ch2 < SEUIL_BAS && ch1 == 0)) { d78WaitingRelease = false; } //================================================= // PHARES D7 + SERVO //================================================= if (d78Enable) { digitalWrite(outputD7, HIGH); servo.writeMicroseconds(SERVO_POSITION_100); } else { digitalWrite(outputD7, LOW); servo.writeMicroseconds(SERVO_POSITION_0); } //================================================= // FEU ARRIERE DOUBLE FONCTION D5 //================================================= /* LOGIQUE D5 : D7 OFF + FREIN OFF = 0 % D7 OFF + FREIN ON = 100 % D7 ON + FREIN OFF = 50 % D7 ON + FREIN ON = 100 % Le frein est prioritaire sur les phares. */ if (etatGachette == FREIN) { // FREIN : pleine intensité d5PWM = D5_INTENSITE_STOP; } else if (d78Enable) { // PHARES : intensité réduite d5PWM = D5_INTENSITE_VEILLEUSE; } else { // PHARES OFF + pas de frein d5PWM = 0; } // Envoi du PWM sur D5 analogWrite(outputD5, d5PWM); //================================================= // ECHAPPEMENT //================================================= //------------------------------------------------- // 1. DETECTION DU PLEIN GAZ //------------------------------------------------- if (pleinGaz) { //------------------------------------------------- // Premier passage à plein gaz //------------------------------------------------- if (!d10PleinGazVu) { d10PleinGazVu = true; d10GazTimer = now; d10Repeat = false; } //------------------------------------------------- // PLEIN GAZ maintenu > D10_DELAI //------------------------------------------------- if (!d10Repeat && now - d10GazTimer >= D10_DELAI) { d10Repeat = true; d10State = true; digitalWrite(outputD10, HIGH); d10Timer = now; d10Duree = random(D10_ON_MIN, D10_ON_MAX + 1); } } //================================================= // 2. RETOUR DU PLEIN GAZ VERS LE NEUTRE //================================================= if (d10PleinGazVu && gazNeutre) { //------------------------------------------------- // Impulsion unique //------------------------------------------------- d10State = true; d10Repeat = false; digitalWrite(outputD10, HIGH); d10Timer = now; d10Duree = D10_IMPULSION; //------------------------------------------------- // On désarme //------------------------------------------------- d10PleinGazVu = false; } //================================================= // 3. SORTIE DU PLEIN GAZ //================================================= /* Si on quitte le plein gaz sans passer immédiatement par le neutre, on arrête le clignotement répétitif. MAIS on conserve d10PleinGazVu afin que le passage suivant dans la zone neutre puisse déclencher l'impulsion. */ if (!pleinGaz) { d10Repeat = false; } //================================================= // 4. ANTILAG sur ECHAPPEMENT //================================================= if (d10State) { //------------------------------------------------- // D10 allumé //------------------------------------------------- if (now - d10Timer >= d10Duree) { d10State = false; digitalWrite(outputD10, LOW); d10Timer = now; //------------------------------------------------- // Si répétition active : // choisir durée OFF //------------------------------------------------- if (d10Repeat) { d10Duree = random(D10_OFF_MIN, D10_OFF_MAX + 1); } } } else if (d10Repeat) { //------------------------------------------------- // D10 éteint //------------------------------------------------- if (now - d10Timer >= d10Duree) { d10State = true; digitalWrite(outputD10, HIGH); d10Timer = now; //------------------------------------------------- // Nouvelle durée ON //------------------------------------------------- d10Duree = random(D10_ON_MIN, D10_ON_MAX + 1); } } //================================================= // SECURITE D10 //================================================= /* Si aucune fonction D10 n'est active, D10 doit être éteint. */ if (!d10State && !d10Repeat) { digitalWrite(outputD10, LOW); } //================================================= // MONITEUR SERIE //================================================= static unsigned long lastPrint = 0; if (now - lastPrint >= 250) { lastPrint = now; Serial.print("D2="); Serial.print(ch2); Serial.print(" D3="); Serial.print(ch1); Serial.print(" D4="); Serial.print(digitalRead(outputD4)); // IMPORTANT : // Affiche maintenant le PWM réellement envoyé à D5 Serial.print(" D5_PWM="); Serial.print(d5PWM); Serial.print(" D6="); Serial.print(digitalRead(outputD6)); Serial.print(" D7="); Serial.print(digitalRead(outputD7)); Serial.print(" D9="); Serial.print(digitalRead(outputD9)); Serial.print(" D10="); Serial.print(digitalRead(outputD10)); Serial.print(" Servo="); Serial.print(d78Enable ? "100%" : "0%"); Serial.print(" D10PG="); Serial.print(d10PleinGazVu); Serial.print(" D10REP="); Serial.print(d10Repeat); Serial.print(" Etat="); switch (etatGachette) { case AVANT: Serial.print("AVANT"); break; case FREIN: Serial.print("FREIN"); break; case NEUTRE_APRES_FREIN: Serial.print("NEUTRE_APRES_FREIN"); break; case MARCHE_ARRIERE: Serial.print("MARCHE_ARRIERE"); break; } Serial.print(" PleinGaz="); Serial.println(pleinGaz); } }
J'ai vite fait un schema de mon système. Comme vous pouvez le constater, niveau électronique, il n'y a pas grand chose ! Même pas une résistance : pour gérer les 2 niveaux d'intensité lumineuse des Feux STOP / POSITION , car j'utilise un signal PWM (comme si c'était un signal moteur émis par un variateur, en gros) à 2 fréquences distinctes ! En gros, on soude les fils d'éclairage du véhicule, et c'est tout... C'était aussi le but du projet, que ce soit le plus épuré possible. Et aussi que ce soit le plus abordable possible, même pour quelqu'un qui n'a aucune notion d'électronique. Les fins observateurs remarqueront peut-être qu'il reste un couple de broches de libre sur l'ULN2803A (1B et 1C). Si vous pensez à une fonction, je suis preneur d'idée Attention toutefois au fait que la contrainte est de n'utiliser que les canaux CH1 et CH2 du récepteur (ou des combinaisons) , car sur le CH3 j'ai mon gyroscope...
@sawblade , j'ai pensé à un truc pour la gestion de ton allumage de feux stop avec le drag brake: plutôt que de chercher une solution pour l'allumer, si tu voyais plutôt une solution pour l'éteindre: je m'explique, par défaut, les avoir allumés et lorsque tu appuies sur la gâchette ( dans le sens avant ou arrière) ça l'éteint. Ça marcherait pas comme ça ?
En principe de base de fonctionnement oui, mais je voudrais essayer de reproduire un truc plus réaliste, comme : - rajouter un delai d'allumage a l'arrêt (au bout d'un moment, les feux stop s'éteignent) - creer un allumage sur drag brake violent sans que le véhicule s'arrête Histoire d'obtenir un truc plus vivant. Mais tu as raison, la logique de départ du système, c'est bien "feux stop allumés au neutre"
Sur le système Lane Boy RC, tu as une variable qui gère la valeur de la commande des gaz autour du neutre pour laquelle les feux stop vont se couper. Elle est aléatoire mais comprise entre 2 valeurs données. Il y a une seconde variable qui donne le temps où les feux stop restent allumé à l’arrêt avant de se couper (quand le véhicule reste à l'arrêt). Celle ci aussi est aléatoire mais comprise entre 2 valeurs prédéfinies. Ca rend le fonctionnement très réaliste parce qu'à chaque fois où les feux stop se coupent, se sera légèrement différent de la fois d'avant. Il y a plein de variable de ce genre sur ce système. Sur le feux de recul par exemple. Il y en a une qui donne le temps où il reste allumé après une marche arrière puis un retour au neutre. Ca rend le fonctionnement plus "humain".
Gemini me dit ça (a adapter avec tes valeurs et impossible a vérifier pour moi qui suis une quiche en programmation): // --- PINOUT --- const int PIN_GAZ = 2; // Entrée signal RC Gaz (PWM voie 2) const int PIN_STOP = 9; // Sortie LED Feux Stop // --- PARAMÈTRES RÉGLABLES --- const int NEUTRE_CENTRE = 1500; // Signal neutre en microsecondes (µs) const int ZONE_MORTE = 40; // Plage neutre (+/- 40µs) const unsigned long TIMEOUT_STOP = 3000; // Extinction auto des stop après 3 sec au neutre (ms) const int SEUIL_DRAG_BRAKE_SEVERE = 120; // Variation brutale minimale des gaz pour déclencher le stop // --- VARIABLES INTERNES --- int gazActuel = NEUTRE_CENTRE; int gazPrecedent = NEUTRE_CENTRE; unsigned long tempsDebutNeutre = 0; bool auNeutre = false; bool feuxStopActifs = false; void setup() { pinMode(PIN_GAZ, INPUT); pinMode(PIN_STOP, OUTPUT); } void loop() { unsigned long tempsActuel = millis(); // 1. Lecture de la voie des gaz gazActuel = pulseIn(PIN_GAZ, HIGH, 25000); if (gazActuel == 0) gazActuel = NEUTRE_CENTRE; // Sécurité si perte de signal // 2. Vérification de la zone morte (Véhicule au neutre) bool maintenantAuNeutre = (gazActuel >= (NEUTRE_CENTRE - ZONE_MORTE)) && (gazActuel <= (NEUTRE_CENTRE + ZONE_MORTE)); // 3. Calcul de la décélération rapide (Drag Brake violent en mouvement) // Delta positif lors d'un lâcher de gaz en marche avant int deltaGaz = gazPrecedent - gazActuel; // --- LOGIQUE DES FEUX STOP --- // CAS A : Déclenchement sur Drag Brake violent (même en mouvement) if (gazPrecedent > (NEUTRE_CENTRE + ZONE_MORTE) && deltaGaz > SEUIL_DRAG_BRAKE_SEVERE) { feuxStopActifs = true; } // CAS B : Gestion de l'arrêt au neutre avec temporisation if (maintenantAuNeutre) { if (!auNeutre) { // Transition vers le neutre : activation initiale et démarrage du timer auNeutre = true; feuxStopActifs = true; tempsDebutNeutre = tempsActuel; } else { // Si on reste au neutre, vérifier le délai d'extinction if (tempsActuel - tempsDebutNeutre >= TIMEOUT_STOP) { feuxStopActifs = false; // Extinction après timeout } } } else { // Si on accélère à nouveau (marche avant ou arrière volontaire) auNeutre = false; // Si l'accélération est stabilisée ou en hausse, éteindre le stop if (deltaGaz <= 0) { feuxStopActifs = false; } } // 4. Application de l'état sur la LED digitalWrite(PIN_STOP, feuxStopActifs ? HIGH : LOW); // Mémorisation de la position pour le prochain cycle gazPrecedent = gazActuel; delay(20); // Petite pause pour stabiliser les mesures (~50 Hz) }
Et avec un temps aléatoire ( ici entre 3 et 10 secondes, ça donnerai ça : // --- PINOUT --- const int PIN_GAZ = 2; // Entrée signal RC Gaz (PWM voie 2) const int PIN_STOP = 9; // Sortie LED Feux Stop // --- PARAMÈTRES RÉGLABLES --- const int NEUTRE_CENTRE = 1500; // Signal neutre en microsecondes (µs) const int ZONE_MORTE = 40; // Plage neutre (+/- 40µs) const int SEUIL_DRAG_BRAKE_SEVERE = 120; // Variation brutale minimale des gaz pour déclencher le stop // Plage du délai aléatoire à l'arrêt (en millisecondes) const unsigned long DELAI_STOP_MIN = 3000; // 3 secondes const unsigned long DELAI_STOP_MAX = 10000; // 10 secondes // --- VARIABLES INTERNES --- int gazActuel = NEUTRE_CENTRE; int gazPrecedent = NEUTRE_CENTRE; unsigned long tempsDebutNeutre = 0; unsigned long delaiExtinctionStop = 3000; // Stockera le délai tiré au sort bool auNeutre = false; bool feuxStopActifs = false; void setup() { pinMode(PIN_GAZ, INPUT); pinMode(PIN_STOP, OUTPUT); // Initialise le générateur aléatoire à partir du bruit électrique d'une broche analogique libre randomSeed(analogRead(A0)); } void loop() { unsigned long tempsActuel = millis(); // 1. Lecture de la voie des gaz gazActuel = pulseIn(PIN_GAZ, HIGH, 25000); if (gazActuel == 0) gazActuel = NEUTRE_CENTRE; // Sécurité si perte de signal // 2. Vérification de la zone morte (Véhicule au neutre) bool maintenantAuNeutre = (gazActuel >= (NEUTRE_CENTRE - ZONE_MORTE)) && (gazActuel <= (NEUTRE_CENTRE + ZONE_MORTE)); // 3. Calcul de la décélération rapide (Drag Brake violent) int deltaGaz = gazPrecedent - gazActuel; // --- LOGIQUE DES FEUX STOP --- // CAS A : Déclenchement sur Drag Brake violent (même en mouvement) if (gazPrecedent > (NEUTRE_CENTRE + ZONE_MORTE) && deltaGaz > SEUIL_DRAG_BRAKE_SEVERE) { feuxStopActifs = true; } // CAS B : Gestion de l'arrêt au neutre avec temporisation aléatoire if (maintenantAuNeutre) { if (!auNeutre) { // Transition vers le neutre : auNeutre = true; feuxStopActifs = true; tempsDebutNeutre = tempsActuel; // Tirage au sort d'une durée aléatoire entre 3 et 10 secondes delaiExtinctionStop = random(DELAI_STOP_MIN, DELAI_STOP_MAX + 1); } else { // Si on reste au neutre, vérifier si le délai tiré au sort est dépassé if (tempsActuel - tempsDebutNeutre >= delaiExtinctionStop) { feuxStopActifs = false; // Extinction après le délai aléatoire } } } else { // Si le véhicule réaccélère (marche avant ou arrière) auNeutre = false; // Si l'accélération est stabilisée ou en hausse, éteindre les feux stop if (deltaGaz <= 0) { feuxStopActifs = false; } } // 4. Application de l'état sur la LED digitalWrite(PIN_STOP, feuxStopActifs ? HIGH : LOW); // Mémorisation de la position pour le prochain cycle gazPrecedent = gazActuel; delay(20); // Petite pause pour stabiliser la boucle (~50 Hz) }