/*
***********************************************
* Gestion de feux tricolores routier *
* version 20241221 *
* pour arduino Nano ou Tiny84 *
***********************************************
Version commune corrigée pour adaptation aux nouveaux PCB avec utilisation du pullup à la place du pulldown
ATtiny84 - Feux tricolores_20241222.dip
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Ce code est distribué gratuitement sous licence !
! Creativ Commons CC-BY-NC-ND 3.0 !
! !
! Cette licence permet à d'autres utilisateurs d'utiliser ce code !
! à des fins non commerciales, dans la mesure où le nom de l'auteur est !
! mentionné. Toute modification du code devra être soumise à !
! l'autorisation expresse de l'auteur. !
! Tests sur https://wokwi.com/projects/417801740642996225 !
! auteur Philippe GUENET - [email protected] - https://wgnt-train.fr !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
VCC * * GND
PB0 * * PA0/ADC0/INT0
PB1 * * PA1/ADC1/INT1
PB3 * * PA2/ADC2
PB2 * * PA3/ADC3
ADC7/PA7 * * PA4/ADC4
ADC6/PA6 * * PA5/ADC5
Envisager la possibilité d'utiliser les sorties analogiques pour un allumage/extinction progressives des leds.
*/
// A commenter si on n'utilise pas l'allumage/extinction progressifs
#define IsProgressif
//#define IsATtiny84
// Identification de la carte
#if defined(IsATtiny84)
#if defined(IsProgressif)
const byte pinFeu_A_Vert = A1; // Analogique
const byte pinFeu_A_Rouge = A2; // Analogique
const byte pinFeu_A_Orange = A4; // Analogique
const byte pinFeu_B_Vert = A3; // Analogique
const byte pinFeu_B_Rouge = A0; // Analogique
const byte pinFeu_B_Orange = A5; // Analogique
#else
const byte pinFeu_A_Vert = PA1;
const byte pinFeu_A_Rouge = PA2;
const byte pinFeu_A_Orange = PA4;
const byte pinFeu_B_Vert = PA3;
const byte pinFeu_B_Rouge = PA0;
const byte pinFeu_B_Orange = PA5;
#endif
#else
const byte pinFeu_A_Vert = A1; // Analogique
const byte pinFeu_A_Rouge = A2; // Analogique
const byte pinFeu_A_Orange = A4; // Analogique
const byte pinFeu_B_Vert = A3; // Analogique
const byte pinFeu_B_Rouge = A0; // Analogique
const byte pinFeu_B_Orange = A5; // Analogique
const byte pinPotentiometre = A7;
#endif
long tempoLed = 3000; // temps de base (ms)
// Durées associées aux états
long etatDurations[6];
// État courant
byte currentState = 0;
// Gestion du temps
unsigned long previousMillis = 0;
int step = 0; // Pas pour le progressif
void setup() {
#if !defined(IsATtiny84)
Serial.begin(9600);
#endif
pinMode(pinFeu_A_Vert, OUTPUT);
pinMode(pinFeu_A_Rouge, OUTPUT);
pinMode(pinFeu_A_Orange, OUTPUT);
pinMode(pinFeu_B_Vert, OUTPUT);
pinMode(pinFeu_B_Rouge, OUTPUT);
pinMode(pinFeu_B_Orange, OUTPUT);
pinMode(pinPotentiometre, INPUT);
// Test des connexions
digitalWrite(pinFeu_A_Vert, HIGH);
digitalWrite(pinFeu_A_Rouge, HIGH);
digitalWrite(pinFeu_A_Orange, HIGH);
digitalWrite(pinFeu_B_Vert, HIGH);
digitalWrite(pinFeu_B_Rouge, HIGH);
digitalWrite(pinFeu_B_Orange, HIGH);
delay(1000);
digitalWrite(pinFeu_A_Vert, LOW);
digitalWrite(pinFeu_A_Rouge, LOW);
digitalWrite(pinFeu_A_Orange, LOW);
digitalWrite(pinFeu_B_Vert, LOW);
digitalWrite(pinFeu_B_Rouge, LOW);
digitalWrite(pinFeu_B_Orange, LOW);
// Lecture initiale du potentiomètre pour configurer tempoLed
tempoLed = map(analogRead(pinPotentiometre), 0, 1023, 1000, 10000);
#if !defined(IsATtiny84)
Serial.print(F("tempoLed = ")); Serial.println(tempoLed );
#endif
// Initialisation des durées des états en fonction de tempoLed
recalculerEtatDurations();
// Initialisation : Feu Vert A, Rouge B
initialiserEtat(0);
} // Fin de setup()
void loop() {
unsigned long currentMillis = millis();
// Mise à jour de tempoLed si le potentiomètre est modifié
static long previousTempoLed = tempoLed;
tempoLed = map(analogRead(pinPotentiometre), 0, 1023, 1000, 10000);
if (abs(tempoLed - previousTempoLed) > 100) {
previousTempoLed = tempoLed;
#if !defined(IsATtiny84)
Serial.println(tempoLed);
#endif
// Recalculer les durées des états après changement de tempoLed
recalculerEtatDurations();
} // Fin de if (tempoLed != previousTempoLed)
// Vérification si le temps écoulé dépasse la durée de l'état
if (currentMillis - previousMillis >= etatDurations[currentState]) {
previousMillis = currentMillis; // Mise à jour du temps de référence
currentState = (currentState + 1) % 6; // Passage à l'état suivant avec RAZ à 0 si currentState = 6
initialiserEtat(currentState); // Configuration des feux pour le nouvel état
} // Fin de if (currentMillis - previousMillis >= etatDurations[currentState])
} // Fin de loop()
// Fonction pour recalculer les durées des états en fonction de tempoLed
void recalculerEtatDurations() {
etatDurations[0] = 4 * tempoLed;
etatDurations[1] = 2 * tempoLed;
etatDurations[2] = tempoLed / 2;
etatDurations[3] = 4 * tempoLed;
etatDurations[4] = 2 * tempoLed;
etatDurations[5] = tempoLed / 2;
}
// Fonction pour initialiser un état
void initialiserEtat(byte etat) {
// Suppression de eteindreFeux() systématique
// Nouvelle logique : n'éteindre que les feux concernés
switch (etat) {
case 0: // Vert A, Rouge B
activerFeu(pinFeu_A_Vert);
activerFeu(pinFeu_B_Rouge);
eteindreFeu(pinFeu_A_Rouge);
eteindreFeu(pinFeu_A_Orange);
eteindreFeu(pinFeu_B_Vert);
eteindreFeu(pinFeu_B_Orange);
break;
case 1: // Orange A, Rouge B
activerFeu(pinFeu_A_Orange);
activerFeu(pinFeu_B_Rouge);
eteindreFeu(pinFeu_A_Vert);
eteindreFeu(pinFeu_A_Rouge);
eteindreFeu(pinFeu_B_Vert);
eteindreFeu(pinFeu_B_Orange);
break;
case 2: // Rouge A, Rouge B
activerFeu(pinFeu_A_Rouge);
activerFeu(pinFeu_B_Rouge);
eteindreFeu(pinFeu_A_Vert);
eteindreFeu(pinFeu_A_Orange);
eteindreFeu(pinFeu_B_Vert);
eteindreFeu(pinFeu_B_Orange);
break;
case 3: // Rouge A, Vert B
activerFeu(pinFeu_A_Rouge);
activerFeu(pinFeu_B_Vert);
eteindreFeu(pinFeu_A_Vert);
eteindreFeu(pinFeu_A_Orange);
eteindreFeu(pinFeu_B_Rouge);
eteindreFeu(pinFeu_B_Orange);
break;
case 4: // Rouge A, Orange B
activerFeu(pinFeu_A_Rouge);
activerFeu(pinFeu_B_Orange);
eteindreFeu(pinFeu_A_Vert);
eteindreFeu(pinFeu_A_Orange);
eteindreFeu(pinFeu_B_Rouge);
eteindreFeu(pinFeu_B_Vert);
break;
case 5: // Rouge A, Rouge B
activerFeu(pinFeu_A_Rouge);
activerFeu(pinFeu_B_Rouge);
eteindreFeu(pinFeu_A_Vert);
eteindreFeu(pinFeu_A_Orange);
eteindreFeu(pinFeu_B_Vert);
eteindreFeu(pinFeu_B_Orange);
break;
}
} // Fin de initialiserEtat(byte etat)
// Fonction pour éteindre un feu spécifique
void eteindreFeu(byte pin) {
digitalWrite(pin, LOW);
} // Fin de eteindreFeu(byte pin)
// Fonction pour allumer un feu spécifique
void activerFeu(byte pin) {
digitalWrite(pin, HIGH);
} // Fin de activerFeu(byte pin)