[Programmation] fonctionnement 74154
Répondre à la discussion
Affichage des résultats 1 à 7 sur 7

fonctionnement 74154



  1. #1
    Blaise032

    Question fonctionnement 74154


    ------

    Le même carrefour qu vu précédemment, mais remplacement du MCP23107 par un 74154.

    Je pensais que cela allait aller tout seul... mais non, toutes les LED restent allumées

    Nom : 2023.05.24 11.390001.png
Affichages : 144
Taille : 48,1 Ko
    Code:
    /////////////////////////////////////////////////////////////////////////////////////////
    // Pour le 74154
    const int A_PIN = 7;
    const int B_PIN = 8;
    const int C_PIN = 9;
    const int D_PIN = 10;
    const int E1_PIN = 11;
    const int E2_PIN = 12;
    /////////////////////////////////////////////////////////////////////////////////////////
    
    #include <TM1637Display.h>  // gestion de 4 digits 7 segments
    
    // Module connection pins (Digital Pins)
    #define CLK 5
    #define DIO 6
    TM1637Display display(CLK, DIO);
    
    
    const int UT = 2;  // Durée de l'unité de temps en secondes (ou plutôt en nbre de compteurs)
    int t1, t2;
    const byte interruptPin_A = 2;
    const byte interruptPin_B = 3;
    const byte pinMaintenace = 4;
    bool fBP;   // mémorise si les boutons pbA ou pbB ont été enclenchés
    
    int compteur = 0;  // Le nombre d'unités de temps (secondes) écoulés
    unsigned long long next_seconde = 0;
    bool bSens = true;  // si true A = Vert, sinon B = Vert
    //char cSens[2]; // contiendra 'A' et 'B'
    char message[50]; // Attention : pas trop peu, sinon plantage sans erreur
    
    // pour la maintenance
    bool bEtatOrange = false;
    bool bInitMaintenance = false; //pour le 1er passage
    unsigned long long nextOrange = 0 ; // gestion des temps
    
    /*
        valeurs et tableaux pour mieux comprendre les messages
        À terme, ils pourront disparaitrent
    */
    enum {RED, ORANGE, GREEN}; //0, 1 et 2
    const char* tColors[] = {
      "Rouge",
      "Orange",
      "Vert"
    };
    const char* tState[] = {
      "LOW",  // pour 0 (on pourrait aussi mettre "Off"
      "HIGH" // pour 1 (on  pourrait aussi mettre "On"
    };
    
    char cSens[2]; // sera rempli dans le setup
    
    struct ST_FEU {
      int sens;     // 0/1  false/true
      int couleur;  // 0 1 2  RED ORANGE GREEN | voir emum ci-dessus
      int broche;   // broche mcp
      int etat;     // 0/1  LOW/HIGH
    };
    
    /*
        Les 10 feux avec leurs broches (mcp) respectives.
        Seule le dèrnière dimension (etat) changera : LOW / HIGH
    */
    ST_FEU feuxVoitures[6] = {
      {1, 0, 0, 0}, // Feu voiture A - rouge - broche - LOW
      {1, 1, 1, 0}, // Feu voiture A - orange - broche - LOW
      {1, 2, 2, 0}, // Feu voiture A - vert - broche - LOW
      {0, 0, 3, 0}, // Feu voiture B - rouge - broche - LOW
      {0, 1, 4, 0}, // Feu voiture B - orange - broche - LOW
      {0, 2, 5, 0}  // Feu voiture B - vert - broche - LOW
    };
    
    ST_FEU feuxPietons[4] = {
      {1, 0, 6, 0}, // Feu piéton A - rouge - broche - LOW
      {1, 2, 7, 0}, // Feu piéton A - vert - broche - LOW
      {0, 0, 8, 0}, // Feu piéton B - rouge - broche - LOW
      {0, 2, 9, 0}  // Feu piéton B - vert - broche - LOW
    };
    
    void gere(int nombre) {
      // Éteignez toutes les broches
      digitalWrite(A_PIN, LOW);
      digitalWrite(B_PIN, LOW);
      digitalWrite(C_PIN, LOW);
      digitalWrite(D_PIN, LOW);
    
      // Vérifiez si le nombre est dans la plage valide (1-16)
      if (nombre >= 1 && nombre <= 16) {
        // Convertissez le nombre décimal en binaire
        int binaire[4];
        for (int i = 0; i < 4; i++) {
          binaire[i] = nombre % 2;
          nombre /= 2;
        }
    
        // Configurez les broches A_PIN à D_PIN en fonction du nombre binaire
        digitalWrite(A_PIN, binaire[0]);
        digitalWrite(B_PIN, binaire[1]);
        digitalWrite(C_PIN, binaire[2]);
        digitalWrite(D_PIN, binaire[3]);
      }
    }
    
    
    void majVoitures(bool way, int color, int state) {
      Serial.println();
      sprintf(message, "feux voiture voie %c couleur %s etat %s", cSens[way], tColors[color], tState[state]);
      Serial.print(message);
      Serial.print(" ");
      for (int i = 0; i <= 5; i += 1) {
        if (feuxVoitures[i].sens == way) { // tous les feux de sens à LOW
          feuxVoitures[i].etat = LOW;
          if (feuxVoitures[i].couleur == color) { // traitement de ce feu particulier (LOW ou HIGH)
            feuxVoitures[i].etat = state;
          }
        }
        //mcp.digitalWrite(feuxVoitures[i].broche, feuxPietons[i].etat);
        gere(feuxVoitures[i].broche); //, feuxVoitures[i].etat);
      }
    }
    
    void majPietons(bool way, int color, int state) {
      Serial.println();
      sprintf(message, "feux pietons voie %c couleur %s etat %s", cSens[way], tColors[color], tState[state]);
      Serial.print(message);
      Serial.print(" ");
      for (int i = 0; i <= 3; i += 1) {
        if (feuxPietons[i].sens == way ) { // tous les feux de sens à LOW
          feuxPietons[i].etat = LOW;
          if (feuxPietons[i].couleur == color) { // traitement de ce feu particulier (LOW ou HIGH)
            feuxPietons[i].etat = state;
          }
        }
        //mcp.digitalWrite(feuxPietons[i].broche, feuxPietons[i].etat);
        gere(feuxPietons[i].broche);
      }
    }
    
    void init_timer() {
      // initialise t1 et t2 selon UT
      t2 = 2 * UT;
      t1 = 6 * t2;
    }
    
    void event_bp_A() {
      if (bSens && digitalRead(pinMaintenace) == HIGH) {  //sens VERT hors maintenance pour A (on accepte l'appui)
    
        fBP = true;
        Serial.print("* ");
      }
    }
    
    void event_bp_B() {
      if (!bSens && digitalRead(pinMaintenace) == HIGH) {  //sens VERT hors maintenance pour B (on accepte l'appui)
        fBP = true;
        Serial.print("* ");
      }
    }
    
    int Affichage() {
      /*
         le temps restant est t1+t2 - compteur
         le sens est connu avec bSens
      */
      int digit = bSens * 2;
      display.showNumberDec(t1 + t2 - compteur, false, 2, digit);
    
      digit = !bSens * 2;
      display.showNumberDec(0, false, 2, digit);
    
      return compteur;
    
    } // fin affichage
    
    void setup() {
      Serial.begin(9600);
      Serial.println();
      Serial.println(__FILE__);
      Serial.println();
      cSens[0] = 'B';  // si false
      cSens[1] = 'A';  // si true
      compteur = 0;
      init_timer();  // t1 et t2
      pinMode(interruptPin_A, INPUT_PULLUP);
      pinMode(interruptPin_B, INPUT_PULLUP);
      pinMode(pinMaintenace, INPUT_PULLUP);
      attachInterrupt(digitalPinToInterrupt(interruptPin_A), event_bp_A, LOW );
      attachInterrupt(digitalPinToInterrupt(interruptPin_B), event_bp_B, LOW );
      fBP = false;
    
      pinMode(A_PIN, OUTPUT);
      pinMode(B_PIN, OUTPUT);
      pinMode(C_PIN, OUTPUT);
      pinMode(D_PIN, OUTPUT);
      pinMode(E1_PIN, OUTPUT);
      pinMode(E2_PIN, OUTPUT);
      digitalWrite(E1_PIN, LOW);  // Activer les sorties du décodeur
      digitalWrite(E2_PIN, LOW);  // Activer les sorties du décodeur
      display.setBrightness(5); // de 0 à 8
    
      display.clear();
    }
    
    void loop() {
      Serial.print(Affichage());
      Serial.print(" ");
    
      if (compteur >= (t1 + t2)) {
        // Changement de sens de circulation à la fin du cycle t1+t2. compteur à 0
        Serial.println("T1+T2 ");
        bSens = !bSens;
        compteur = 0;
        // urgence maintenance
        while (digitalRead(pinMaintenace) == LOW) { // tant que le bouton Maintenance est actionné
          if (!bInitMaintenance) { // 1er passage
            /*
               Éteindre les feux piétons
               =========================
               if suffit d'un mettre 1 à LOW dans les 2 sens pour qu'ils soient tous à LOW
            */
            majPietons(bSens, GREEN, LOW);
            majPietons(!bSens, GREEN, LOW);
            /*
               Définir les temps
               =================
               HIGH 750 millisecondes
               LOW 250 millis
            */
            bEtatOrange = false; // je les décare éteins pour les allumer juste après
            bInitMaintenance = true; // fin du 1er passage, on y repassera plus
          } // fin 1er passage (nextOrange = 0)
    
          if (nextOrange < superMillis()) { //temps écoulé, échange true/false donc HIGH/LOW
            bEtatOrange = !bEtatOrange;
            majVoitures(bSens, ORANGE, bEtatOrange);
            majVoitures(!bSens, ORANGE, bEtatOrange);
            if (bEtatOrange) { // Orange allumé pendant ...
              nextOrange = superMillis() + 750;
            } else { // temps éteind pendant ...
              nextOrange = superMillis() + 250;
            }
          } // fin du test/bascule clignotemant
    
        } // fin de l'urgenece
        bInitMaintenance = false;
      } // fin compteur >= (t1 + t2)
    
      if (compteur == 0) {  // début
        init_timer();  // s'il a été modifié ou pas, recalcul t1
    
        majVoitures(bSens, GREEN, HIGH);
        majVoitures(!bSens, RED, HIGH);
    
        majPietons(bSens, RED, HIGH);
        majPietons(!bSens, GREEN, HIGH);
      } // fin compteur == 0
    
      if (compteur == t1) {  // Préparation du changement de sens : orange pour le sens en cours, rouge pour le reste
        Serial.print("_T1_ ");
        majVoitures(bSens, ORANGE, HIGH);
        majVoitures(!bSens, RED, HIGH);
    
        majPietons(bSens, RED, HIGH);
        majPietons(!bSens, RED, HIGH);
      } // fin compteur == t1
    
      /*
         le reste du temps, attend 1 seconde
         on n'utilise pas delay pour que les interruptions fonctionnent
      */
      while (superMillis() <= next_seconde) {
        /*
           si un Bouton Piéton a été appuyé (même avant t1/2
           et que l'on est dans la tranche horaire (compteur) entre t1/2 et T1
           on raccourci t1 au compteur actuel (+ 1 seconde)
        */
        if (fBP && compteur >= (t1 / 2) && compteur < t1)  {
          t1 = compteur + 1;
          fBP = false;
        }
      }
      next_seconde = 500 + superMillis(); // dans la version définitive, remplacer  par 1000
      compteur += 1;
    }
    
    
    unsigned long long superMillis() {
      //https://www.carnetdumaker.net/snippets/8/
      /**
         Retourne le nombre de millisecondes depuis le démarrage du programme
         sous la forme d'un nombre entier sur 64 bits (unsigned long long).
         anti bug de l'overflow des 32 bits qui repasse à zéro tous les moins de 50 jours
         Là, ce sera l'overflow toutes les 584.542.046 années
      */
      static unsigned long nbRollover = 0;
      static unsigned long previousMillis = 0;
      unsigned long currentMillis = millis();
      if (currentMillis < previousMillis) {
        nbRollover++;
      }
      previousMillis = currentMillis;
      unsigned long long finalMillis = nbRollover;
      finalMillis <<= 32;
      finalMillis += currentMillis;
      return finalMillis;
    }

    -----

  2. #2
    jiherve

    Re : fonctionnement 74154

    bonjour
    un 74154 fonctionne en logique inverse , les sorties sont à l’état '1' par défaut il faut donc inverser le branchement des leds, accessoirement le simulateur est foireux car l’état haut garanti ne peut fournir que 800 µA.
    toujours lire les datasheet!
    JR
    l'électronique c'est pas du vaudou!

  3. #3
    Blaise032

    Re : fonctionnement 74154

    Ok. Existe-t'il un circuit qui inverse ces états tout en délivrant + de puissance ?

  4. #4
    jiherve

    Re : fonctionnement 74154

    re
    oui n'importe quel inverseur collecteur ouvert fera le boulot, mais il est plus simple d'inverser les Leds en les branchant au +5; En TTL il faut toujours utiliser le niveau bas pour tirer une charge.
    JR
    l'électronique c'est pas du vaudou!

  5. A voir en vidéo sur Futura
  6. #5
    Blaise032

    Re : fonctionnement 74154

    Bien, c'est comme je pensais. Mais je n'ai pas trouvé de moyen pour inverser les LED dans Proteus... C'est du boulot !

  7. #6
    Pascal071

    Re : fonctionnement 74154

    bonjour

    oui, communs Led au +5v

    je n'ai pas épluché le code, mais les Leds sont multiplexées?
    car le 74154 ne fait que décoder, donc 1 seule sortie active suivant le code BCD en entrée.
    de plus il consomme 50mA au repos ( TTL)

    avec un UNO, tu as assez des sorties pour piloter 10 Leds, avec un driver ULN2803 pour booster les sorties (500mA max) Leds commun au +5

    utilises les entrées analogiques pour les switches maintenance, BPA, BPB
    Dernière modification par Pascal071 ; 24/05/2023 à 14h43.

  8. #7
    polo974

    Re : fonctionnement 74154

    Ça existe encore le TTL pur et dur?
    Même pas en LS?

    Allez, soyons fou, en HC ou HCT...

    Mais en fait, avec 2 74xyz595 (par ex), c'est pas plus simple (si on cherche à économiser les pins du uc)???

    Heuu, sinon, les 220 ohm en série avec les led, ça donne du 10 mA par led, grosse louche. Et 2 leds par sortie, ça va chauffer... Là aussi, il y a eu certains progrès...
    Dernière modification par polo974 ; 24/05/2023 à 19h16.
    Jusqu'ici tout va bien...

Discussions similaires

  1. Fonctionnement générateur et Fonctionnement récepteur
    Par invite1518322a dans le forum Chimie
    Réponses: 4
    Dernier message: 19/10/2020, 10h40
  2. Fonctionnement PAC air/air
    Par xavierb15 dans le forum Habitat bioclimatique, isolation et chauffage
    Réponses: 6
    Dernier message: 25/03/2018, 20h07
  3. sn 74154 ainsi uqe cd4017 et relais
    Par invite60c4c75a dans le forum Électronique
    Réponses: 12
    Dernier message: 09/03/2013, 23h08
  4. Fonctionnement du LHC
    Par invited8d2faee dans le forum Physique
    Réponses: 1
    Dernier message: 24/05/2009, 21h42
  5. fonctionnement fax
    Par nanard dans le forum Technologies
    Réponses: 3
    Dernier message: 07/07/2006, 10h28
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...