Registre de décalage 74HC595

Bonjour à tous,

Je me suis récemment lancé dans quelques séances pratiques d'électronique, et j'en suis venu à affronter un composant avec un nom des plus barbares, le 74HC595.
Je pensais avoir compris son fonctionnement, j'ai donc fait le montage sur ma breadboard et ma carte UNO, en branchant une LED sur Qb et une sur Qe.

J'ai ensuite programmé le pavé suivant, qui je le sais manque de méthode, mais je ne comprends pas pourquoi cela ne fonctionne pas comme je le comprenais, tout de suite, le problème :

int SER = 4;
int VCC = 2;
int RCLK = 5;
int SRCLK = 6;

void setup() {
  // put your setup code here, to run once:
pinMode(SER,OUTPUT);
pinMode(VCC, OUTPUT);
pinMode(RCLK,OUTPUT);
pinMode(SRCLK,OUTPUT);
digitalWrite(VCC,HIGH);

}

void loop() {
  // put your main code here, to run repeatedly:
digitalWrite(SER,HIGH); //Envoi d'un signal dans Qa
digitalWrite(SER,LOW);  
digitalWrite(SRCLK,HIGH); //Décalage à droite dans Qb, ma première LED
digitalWrite(SRCLK,LOW);
digitalWrite(RCLK,HIGH); //Enregistrement du changement
digitalWrite(RCLK,LOW);
delay(500); //Délai pour voir la LED s'allumer
digitalWrite(SRCLK,HIGH); //Deux décalages à droite pour arriver à Qd
digitalWrite(SRCLK,LOW);
digitalWrite(SRCLK,HIGH);
digitalWrite(SRCLK,LOW);
digitalWrite(SER,HIGH); //Envoi d'un signal dans Qa
digitalWrite(SER,LOW);
digitalWrite(SRCLK,HIGH); // Deux décalages à droite, donc premier signal dans Qe, sur ma deuxième LED, et premier signal dans Qb, première LED.
digitalWrite(SRCLK,LOW);
digitalWrite(RCLK,HIGH);
digitalWrite(RCLK,LOW);
delay(1000);
}

Ci-joint une image du composant en question :

Donc quand je lance mon programme, je compte ici faire allumer ma première LED, puis que le "signal" de la première, en se décalant "à droite", se retrouve dans ma deuxième LED, en ayant au préalable relancé un autre signal, on aurait en quelque sorte à la suite: (Qa à Qh)
10000000 Rien
01000000 LED Allumée
00100000 Rien
00010000 Rien
10010000 LED 1 allumée
01001000 Deux LED allumées

Mon idée était ici que la première LED s'allume, puis les deux en même temps, puis la première, puis les deux en même temps etc

Or la première LED s'allume, puis s'éteint, puis la deuxième s'allume, puis s'éteint, et puis rien.

Si quelqu'un a une réponse à mon problème, toujours dans cet esprit de gérer "manuellement" (Je sais que mon code est pas terrible, mais je cherche à comprendre le mécanisme exacte de ce composant) les décalages, merci d'avance !

Vous avez mis des résistances de limitation de courant pour les LEDs? pourquoi alimentez vous le composant avec une des PINs? (leur capacité à fournir du courant est super limitée - faut pas dépasser 20mA même si la théorie dit 40)

(éventuellement faire aussi un clear, via la pin SRCLR en début de boucle pour partir d'un état "propre" à chaque fois)

Une maladresse de ma part en ce qui concerne l'alimentation sur la PIN, je change cela donc, sur la broche 5V je suppose ?
Oui j'ai placé des résistances de 330 Ohms devant chaque LED

ça vaut mieux effectivement de brancher directement sur le 5V

je suppose aussi que OE (Output Enable) est sur la masse (GND) ?

sinon quand vous faites

  digitalWrite(SER, HIGH); //Envoi d'un signal dans Qa 
  digitalWrite(SER, LOW);
  digitalWrite(SRCLK, HIGH); //Décalage à droite dans Qb, ma première LED

que pensez vous qu'il sera lu en entrée pour le prochain bit qui sera déplacé?

OE est bien sur le ground.

Votre question m'a fait changé de vision sur le mécanisme, je voyais cela comme une détection du "front montant" du pin SER, je pensais que quand SER passait à 1, le bit stocké dans Qa passait à 1, et donc que je devais repasser SER à LOW pour ensuite pouvoir remettre un 1 quand je le souhaite.
En fait en faisant

digitalWrite(SER,HIGH);
digitalWrite(SER,LOW);

Est-ce que je n'envoie pas 1 dans le Qb et 0 dans le Qa ? Dans ce cas le SRCLK n'est pas obligatoire pour décaler ? On pourrait aussi rentrer une autre valeur et cela décale automatiquement ?

Mauvaise compréhension du fonctionnement d'un registre à décalage.
SER c'est l'entrée de l'information
SRCLK rythme l'entrée de la donnée dans le registre. Sur le front montant de SRCLK, l'état de la donnée est échantillonné pour être transféré dans Qa, le contenu de Qa passe dans Qb, celui de Qb dans Qc et ainsi de suite.
Le résultat n'est visible en sortie que qu'après une transition montante sur RCLK.

en pratique vous avez quelques broches de contrôle qui sont décrites dans la doc

OE (Output Enable):

  • activer la sortie lorsqu’il est LOW, désactive en HIGH (sans perdre la mémoire)

SRCLR (Serial Clear):

  • vide complètement le Shift Register à LOW

RCLK (Register Clock):

  • RCLK à LOW aucune modification en sortie, on peut charger le registre avec 8 bits
  • RCLK à HIGH et le 74HC595 sort les modifications sur Qa…Qh

SRCLK (Serial Clock):

  • lors d'un front LOW - HIGH, décale le registre et lit SER pour le mettre dans Qa

SER (Serial):

  • valeur en entrée qui sera déplacée dans le registre au prochain front sur SRCLK

Donc la procédure classique est la suivante

RCLK à LOW // aucune modification en sortie, on charge le registre

on répète pour chaque bit à injecter

SRCLK à LOW // pour préparer le front montant de décalage
SER à LOW ou HIGH // en fonction du bit que l'on veut injecter
SRCLK à HIGH // pour déclencher le front montant, décaler les bits et enregistrer le bit SER dans Qa

RCLK à HIGH // on affiche le résultat

fdufnews:
Mauvaise compréhension du fonctionnement d'un registre à décalage.
SER c'est l'entrée de l'information
SRCLK rythme l'entrée de la donnée dans le registre. Sur le front montant de SRCLK, l'état de la donnée est échantillonné pour être transféré dans Qa, le contenu de Qa passe dans Qb, celui de Qb dans Qc et ainsi de suite.
Le résultat n'est visible en sortie que qu'après une transition montante sur RCLK.

J'en reviens donc à ma première version du fonctionnement d'un registre à décalage, pourtant mon code me prouve que je ne comprends pas non plus.
Je vois la chose comme tel :

Prenons le cas où je veux allumer une LED à la sortie de Qc, en état inital je suppose (hypothèse ?) que tous les Qi valent 0. (Faux ?)
Qa Qb Qc Qd Qe Qf Qg Qh
0 0 0 0 0 0 0 0

Je passe SER à HIGH :
Qa Qb Qc Qd Qe Qf Qg Qh
1 0 0 0 0 0 0 0

Je repasse SER à LOW pour pouvoir "refaire" un front montant après
Je passe SRCLK à HIGH :
Qa Qb Qc Qd Qe Qf Qg Qh
0 1 0 0 0 0 0 0

Je passe SRCLK à LOW, puis de nouveau à HIGH pour avoir un front montant :
Qa Qb Qc Qd Qe Qf Qg Qh
0 0 1 0 0 0 0 0

Je passe SRCLK à LOW
Je passe RCLK à HIGH pour valider ma "configuration"

Où est mon erreur de raisonnement ?

Après avoir lu vos messages et avoir utilisé deux ou trois neurones supplémentaires, voici mon bébé :

int SER = 4;
int RCLK = 5;
int SRCLK = 6;
void setup() {
  // put your setup code here, to run once:
pinMode(SER,OUTPUT);
pinMode(RCLK,OUTPUT);
pinMode(SRCLK,OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
digitalWrite(RCLK,LOW);
digitalWrite(SRCLK,LOW);
digitalWrite(SER,HIGH);
digitalWrite(SRCLK,HIGH);
digitalWrite(RCLK,HIGH);

digitalWrite(RCLK,LOW);
digitalWrite(SRCLK,LOW);
digitalWrite(SER,LOW);
digitalWrite(SRCLK,HIGH);
digitalWrite(RCLK,HIGH);

delay(10000);

digitalWrite(RCLK,LOW);
digitalWrite(SRCLK,LOW);
digitalWrite(SER,LOW);
digitalWrite(SRCLK,HIGH);
digitalWrite(RCLK,HIGH);

digitalWrite(RCLK,LOW);
digitalWrite(SRCLK,LOW);
digitalWrite(SER,LOW);
digitalWrite(SRCLK,HIGH);
digitalWrite(RCLK,HIGH);

digitalWrite(RCLK,LOW);
digitalWrite(SRCLK,LOW);
digitalWrite(SER,HIGH);
digitalWrite(SRCLK,HIGH);
digitalWrite(RCLK,HIGH);

delay(3000);

}

Et celui là fait bien ce que je veux, à savoir toujours allumer la première LED sur Qb, puis allumer les deux ensuite. J'avais mal compris le fait que le bit n'était pas stocké directement dans Qa au début, mais dans une "mini mémoire" à part à priori.

Un grand merci à tous !

L'objectif est maintenant le petit écran à 7 segments ! :slight_smile:

Je passe SER à HIGH :
Qa Qb Qc Qd Qe Qf Qg Qh
1 0 0 0 0 0 0 0

c'est là que vous avez faux.

Pour que Qa prenne la valeur de SER il faut faire

SRCLK à LOW
SER à HIGH
SRCLK à HIGH <-- c'est là que Qa prend la valeur de SER

là vous faites quelque chose "invisible" pour un humain car vous poussez des bits dans le registre et effectuez l'affichage mais comme vous n'avez pas de pause ça va défiler en quelques micro-secondes et la LED ne s'affichera pas vraiment

digitalWrite(RCLK,LOW);
digitalWrite(SRCLK,LOW);
digitalWrite(SER,LOW);
digitalWrite(SRCLK,HIGH);
digitalWrite(RCLK,HIGH);

digitalWrite(RCLK,LOW);
digitalWrite(SRCLK,LOW);
digitalWrite(SER,LOW);
digitalWrite(SRCLK,HIGH);
digitalWrite(RCLK,HIGH);

digitalWrite(RCLK,LOW);
digitalWrite(SRCLK,LOW);
digitalWrite(SER,HIGH);
digitalWrite(SRCLK,HIGH);
digitalWrite(RCLK,HIGH);

il faudrait simplement faire

digitalWrite(RCLK,LOW);

// injecte un LOW
digitalWrite(SRCLK,LOW);
digitalWrite(SER,LOW);
digitalWrite(SRCLK,HIGH);

// injecte un LOW
digitalWrite(SRCLK,LOW);
digitalWrite(SER,LOW);
digitalWrite(SRCLK,HIGH);

// injecte un HIGH
digitalWrite(SRCLK,LOW);
digitalWrite(SER,HIGH);
digitalWrite(SRCLK,HIGH);

// affiche le tout
digitalWrite(RCLK,HIGH);