Bargraph qui pose des problèmes

Bonsoir,

Je me suis lancé dans la réalisation d'un indicateur de niveau constitué d'un bargraph de 12 segments bicolores et géré par un MAX 7219, tout ça avec une Nano.

Je me suis inspiré du tuto suivant :

les exemples fournis fonctionnent à merveille, ce qui me laisse penser que mon câblage est ok.

Le code suivant :

#include <SPI.h>

#define LOAD          10   // Entrée LOAD du MAX72219
#define DISPLAY_TEST  0x0F // Registre Display-Test
#define SHUTDOWN      0x0C // Registre Shutdown
#define DECODE_MODE   0x09 // Registre Decode-mode
#define SCAN_LIMIT    0x0B // Registre Scan-limit
#define INTENSITY     0x0A // Registre Intensity
#define DIGIT0        0x01 // Registre Digit 0
#define DIGIT1        0x02 // Registre Digit 1
#define DIGIT2        0x03 // Registre Digit 2
const int m = 2000;

void setup() {
  pinMode(LOAD, OUTPUT);
  digitalWrite(LOAD, HIGH);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST); /* bits de poids fort en premier */
  
  writeRegister(DISPLAY_TEST, 0x00); /* Normal operation */
  writeRegister(DECODE_MODE, 0x00);  /* No decode */
  writeRegister(SCAN_LIMIT, 0x02);   /* Display digits 0, 1, 2 */
  writeRegister(INTENSITY, 0x04);    /* LED brightness, max=0x0F */
  writeRegister(SHUTDOWN, 0x01);     /* Normal operation */
  
}
void writeRegister(byte thisRegister, byte thisValue) // Écrire dans un registre du MAX7219
{
  // Mettre l'entrée LOAD à l'état bas
  digitalWrite(LOAD, LOW);

  SPI.transfer(thisRegister); // Adresse du registre
  SPI.transfer(thisValue); // Contenu du registre

  // Basculer l'entrée LOAD à l'état haut pour verrouiller et transférer les données
  digitalWrite(LOAD, HIGH);
}

/*void niveau1() {
  byte red = 0x00;
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0x00); // 0000 0000
  writeRegister(DIGIT2, 0x00); // 0000 0000

  for (int i = 0; i < 4; i++) {
    red |= (1 << i);
    writeRegister(DIGIT0, red); // scan du premier digit en rouge
    delay(500);
  }
  for (int i = 0; i < 5; i++) {
    writeRegister(DIGIT0, 0x0F);
    delay(100);
    writeRegister(DIGIT0, 0x00);
    delay(100);
  }
}*/

void niveau2() {
  writeRegister(DIGIT0, 0xCF); // 1100 1111
  writeRegister(DIGIT1, 0xF0); // 1111 0000
  writeRegister(DIGIT2, 0xF0); // 1111 0000
}

void niveau3() {
  writeRegister(DIGIT0, 0xCE); // 1100 1110
  writeRegister(DIGIT1, 0xF0); // 1111 0000
  writeRegister(DIGIT2, 0xF0); // 1111 0000
}
void niveau4() {
  writeRegister(DIGIT0, 0xCC); // 1100 1100
  writeRegister(DIGIT1, 0xF0); // 1111 0000
  writeRegister(DIGIT2, 0xF0); // 1111 0000
}
void niveau5() {
  writeRegister(DIGIT0, 0x88); // 1000 1000
  writeRegister(DIGIT1, 0xF0); // 1111 0000
  writeRegister(DIGIT2, 0xF0); // 1111 0000
}
void niveau6() {
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0xF0); // 1111 0000
  writeRegister(DIGIT2, 0xF0); // 1111 0000
}
void niveau7() {
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0xE0); // 1110 0000
  writeRegister(DIGIT2, 0xF0); // 1111 0000
}
void niveau8() {
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0xC0); // 1100 0000
  writeRegister(DIGIT2, 0xFF); // 1111 1111
}
void niveau9() {
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0x80); // 1000 0000
  writeRegister(DIGIT2, 0x7F); // 0111 1111
}
void niveau10() {
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0x00); // 0000 0000
  writeRegister(DIGIT2, 0x2E); // 0010 1110
}
void niveau11() {
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0x00); // 0000 0000
  writeRegister(DIGIT2, 0x0C); // 0000 1100
}
void niveau12() {
  writeRegister(DIGIT0, 0xCF); // 1100 1111
  writeRegister(DIGIT1, 0xF0); // 1111 0000
  writeRegister(DIGIT2, 0xF0); // 1111 0000
}

void loop()

{
//  niveau1();  delay(m);
  niveau2();  delay(m);
  niveau3();  delay(m);
  niveau4();  delay(m);
  niveau5();  delay(m);
  niveau6();  delay(m);
  niveau7();  delay(m);
  niveau8();  delay(m);
  niveau9();  delay(m);
  niveau10();  delay(m);
  niveau11();  delay(m);
  niveau12();  delay(m);
  }

que j'ai créé en m'inspirant des exemples ne fonctionne pas correctement.

De "niveau2()" à "6", les segments s'éteignent ou changent de couleur selon mon code mais à la fonction "niveau7()", tout s'éteint sans tenir compte des autres niveaux et le code cesse de fonctionner.

La loop ne redémarre plus.

je ne trouve pas de quoi ça vient.

Merci d'avance pour votre aide.

si vous mettez dans niveau7() le code de niveau6() - que se passe-t-il?

quelle R avez vous mis sur ISET de votre MAX7219? correspond-elle bien aux specifications de vos LEDs?

Pour R, j'ai au max 10 leds vertes et 4 rouges allumées en même temps (2 rouges, 2 oranges et 8 vertes), j'ai donc mis une R de 22.9K (27+2.2).

J'avais mis en commentaires les lignes des niveaux 8 à 12 mais ça changeait rien.

Pour les inversions de fonction, je testerais demain.

Bonjour,

Bon voilà, j'ai fait mes tests :

Cà fonctionne y compris le niveau 7. La loop fait son job. :slight_smile:

J'ai remplacé les instructions des niveaux 8 et 9 par celles des 6 et 5 et là Miracle ça fonctionne.

J'ai donc ré-écrit les instructions qui posent problèmes (on ne sait jamais : une faute de frappe qui passe inaperçue) mais ça change rien. Ca bloque tout.

Je suis donc coincé.....

Et franchement, je ne vois pas ce qui bloque (à part mon incapacité)

Merci de m'aider

essayez d'isoler en mettant 1 fois dans le setup le code de chacune des fonctions pour voir ce qu'il se passe...

J'ai testé chaque fonction individuellement et pour les fonctions niveau 8 et 9, ça ne marche pas.

J'ai ensuite essayé de niveau 2 à 7 : c'est bon, de niveau 10 à 12 c'est bon, de niveau 2 à 7 puis 10 à 12 ça marche toujours mais dès que j'inclue dans la boucle les niveaux 8 et 9 là c'est mort.

C'est donc bien le code de ces fonctions qui ne fonctionne pas.

Mais ou est l'erreur ....... ? :o

Je vais les reprendre dans le détail. Je crois que ça sera mieux.

mais si vous ne mettez que le code de 8 et 9, pas dans la boucle mais dans le setup (avec la pause) - ça fait quoi ?

si vous conservez tout le code et mettez le code de la fonction 6 dans 8 et 9 (juste pour voir), ça fait quoi ?

Sans rien dans la loop et si dans le setup je mets le code d'une fonction autre que 8 et 9, ça fonctionne et si je mets le code de la 8 et/ou 9, ça compile mais rien ne se passe......

Si je remplace les codes des 8 et 9 par le code de la 6 ou une autre, ça fonctionne.

les fonctions 8 et 9 sont les seules qui utilisent plus de 7 lignes de data à 1 dans la commande ==> problème de puissance ?

La nano à son alim et le bargraph à une alim 5V 2A. Les GND sont reliés. C'est le niveau 2 qui consomme le + avec 14 leds allumées en meme temps

c'est louche... vous avez essayé d'inverser des pins ?

Non, si j'inverse des pins ça ne pilotera plus les bons segments.

Et puis comme ça marche pour les autres niveaux et les exemples du tuto , le câblage semble bon

je veux dire complètement inverser - changer la pin 3 des 2 côtés- juste pour éliminer un soucis hardware avec une pin ?

Ok je vais voir de ce côté la

Merci de me consacrer du temps

essayez en remplaçant le setup et la fonction par ceci:

void setup()
{
  pinMode(LOAD, OUTPUT);
  digitalWrite(LOAD, HIGH);
  SPI.begin();

  writeRegister(DISPLAY_TEST, 0x00); /* Normal operation */
  writeRegister(DECODE_MODE, 0x00);  /* No decode */
  writeRegister(SCAN_LIMIT, 0x02);   /* Display digits 0, 1, 2 */
  writeRegister(INTENSITY, 0x04);    /* LED brightness, max=0x0F */
  writeRegister(SHUTDOWN, 0x01);     /* Normal operation */

}

void writeRegister(byte thisRegister, byte thisValue) // Écrire dans un registre du MAX7219
{
  SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0))
  // Mettre l'entrée LOAD à l'état bas
  digitalWrite(LOAD, LOW);

  SPI.transfer(thisRegister); // Adresse du registre
  SPI.transfer(thisValue); // Contenu du registre

  // Basculer l'entrée LOAD à l'état haut pour verrouiller et transférer les données
  digitalWrite(LOAD, HIGH);
  SPI.endTransaction();
}

il manqueait la gestion des transaction SPI dans writeRegister(), vous êtes peut-être victime d'une interruption inadéquate

j'ai modifié le setup mais ça n'a pas résolu le problème.

En faisant des tests, beaucoup de tests, et encore des tests ..... j'ai constaté que si j'avais plusieurs leds oranges sur les segment de 5 à 12 du bargraphe ça mettait le bord.. et ça bloquait tout.

Pourquoi , ça je ne sais pas, je ne suis pas assez calé dans le domaine.

J'ai donc modifié mes couleurs de bargraphe à partir du niveau 8 et c'est bon ça fonctionne. je sais c'est une solution pour contourner le problème mais bon faut bien tricher des fois :slight_smile:

Voici le code modifié :

#include <SPI.h>

#define LOAD          10   // Entrée LOAD du MAX72219
#define DISPLAY_TEST  0x0F // Registre Display-Test
#define SHUTDOWN      0x0C // Registre Shutdown
#define DECODE_MODE   0x09 // Registre Decode-mode
#define SCAN_LIMIT    0x0B // Registre Scan-limit
#define INTENSITY     0x0A // Registre Intensity
#define DIGIT0        0x01 // Registre Digit 0
#define DIGIT1        0x02 // Registre Digit 1
#define DIGIT2        0x03 // Registre Digit 2
const int m = 1000;

void setup() {
  pinMode(LOAD, OUTPUT);
  digitalWrite(LOAD, HIGH);
  SPI.begin();
  
  writeRegister(DISPLAY_TEST, 0x00); /* Normal operation */
  writeRegister(DECODE_MODE, 0x00);  /* No decode */
  writeRegister(SCAN_LIMIT, 0x02);   /* Display digits 0, 1, 2 */
  writeRegister(INTENSITY, 0x04);    /* LED brightness, max=0x0F */
  writeRegister(SHUTDOWN, 0x01);     /* Normal operation */
  delay(500);
}

void writeRegister(byte thisRegister, byte thisValue) // Écrire dans un registre du MAX7219
{
  SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0));
  // Mettre l'entrée LOAD à l'état bas
  digitalWrite(LOAD, LOW);

  SPI.transfer(thisRegister); // Adresse du registre
  SPI.transfer(thisValue); // Contenu du registre

  // Basculer l'entrée LOAD à l'état haut pour verrouiller et transférer les données
  digitalWrite(LOAD, HIGH);
  SPI.endTransaction();
}

void niveau1() {
  byte red = 0x00;
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0x00); // 0000 0000
  writeRegister(DIGIT2, 0x00); // 0000 0000

  for (int i = 0; i < 4; i++) {
    red |= (1 << i);
    writeRegister(DIGIT0, red); // scan du premier digit en rouge
    delay(500);
  }
  for (int i = 0; i < 5; i++) {
    writeRegister(DIGIT0, 0x0F);
    delay(100);
    writeRegister(DIGIT0, 0x00);
    delay(100);
  }
}

void niveau2() {
  writeRegister(DIGIT0, 0xCF); // 1100 1111
  writeRegister(DIGIT1, 0xF0); // 1111 0000
  writeRegister(DIGIT2, 0xF0); // 1111 0000
}

void niveau3() {
  writeRegister(DIGIT0, 0xCE); // 1100 1110
  writeRegister(DIGIT1, 0xF0); // 1111 0000
  writeRegister(DIGIT2, 0xF0); // 1111 0000
}
void niveau4() {
  writeRegister(DIGIT0, 0xCC); // 1100 1100
  writeRegister(DIGIT1, 0xF0); // 1111 0000
  writeRegister(DIGIT2, 0xF0); // 1111 0000
}
void niveau5() {
  writeRegister(DIGIT0, 0x88); // 1000 1000
  writeRegister(DIGIT1, 0xF0); // 1111 0000
  writeRegister(DIGIT2, 0xF0); // 1111 0000
}
void niveau6() {
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0xF0); // 1111 0000
  writeRegister(DIGIT2, 0xF0); // 1111 0000
}
void niveau7() {
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0xE0); // 0000 1110
  writeRegister(DIGIT2, 0xF8); // 1111 1000
}
void niveau8() {
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0xC0); // 1100 0000
  writeRegister(DIGIT2, 0x7E); // 0111 1110
}
void niveau9() {
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0x80); // 1000 0000
  writeRegister(DIGIT2, 0x1F); // 0001 1111
}
void niveau10() {
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0x00); // 0000 0000
  writeRegister(DIGIT2, 0x0E); // 0000 1110
}

void niveau11() {
  writeRegister(DIGIT0, 0x00); // 0000 0000
  writeRegister(DIGIT1, 0x00); // 0000 0000
  writeRegister(DIGIT2, 0x0C); // 0000 1100
}

void niveau12() {
  writeRegister(DIGIT0, 0x10); // 0001 0000
  writeRegister(DIGIT1, 0x00); // 0000 0000
  writeRegister(DIGIT2, 0x0C); // 0000 1000
}

void loop()

{
  niveau1();  delay(m);
  niveau2();  delay(m);
  niveau3();  delay(m);
  niveau4();  delay(m);
  niveau5();  delay(m);
  niveau6();  delay(m);
  niveau7();  delay(m);
  niveau8();  delay(m);
  niveau9();  delay(m);
  niveau10();  delay(m);
  niveau11();  delay(m);
  niveau12();  delay(m);
}

@ J-M-L

Un grand merci pour l'aide apportée. la modif du setup améliore l'exécution de la boucle.

Je pense que c’est aussi le SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0)); et le SPI.endTransaction(); qui manquaient plus que le setup()

Bonjour

. j'ai constaté que si j'avais plusieurs leds oranges sur les segment de 5 à 12 du bargraphe ça mettait le bord.. et ça bloquait tout.

Une led 'orange' compte pour 2, cette couleur est obtenue en allumant deux leds.

Il semble donc que la piste de la consommation excessive soit à conserver en compte vu les symptomes.

Bonjour,

@ J-M-L

oui effectivement, encore merci.

@alfch

Une led 'orange' compte pour 2, cette couleur est obtenue en allumant deux leds.

C'est donc pour ça que ne trouve pas de led orange dans le bargraph :slight_smile: :slight_smile: :slight_smile:

La consommation a déjà été évoquée par JML. L'ensemble bargraph est alimenté par du 5V (stable) 2A.

j'ai constaté que si j'avais plusieurs leds oranges sur les segment de 5 à 12 du bargraphe

Je dis bien "5 à 12".

Quand je code 12 leds oranges (donc 12 vertes et 12 rouges :slight_smile: ) ça fonctionne.

L'alimentation n'est, enfin je crois, pas en cause.

EGT59:
C'est donc pour ça que ne trouve pas de led orange dans le bargraph :slight_smile: :slight_smile: :slight_smile:

oui si vous suivez le tuto que vous avez pointé il a de jolis dessins qui expliquent comment allumer le vert et rouge et donc obtenir du orange.

EGT59:
La consommation a déjà été évoquée par JML. L'ensemble bargraph est alimenté par du 5V (stable) 2A.
L'alimentation n'est, enfin je crois, pas en cause.

En pratique sur la consommation énergétique, avec la technique du multiplexage seulement huit LED au maximum seront allumées simultanément.

La encore dans le tuto c'est expliqué:

Le courant maximal traversant chaque LED étant fixé grâce à la résistance RSET, et sachant que dans le fonctionnement multiplexé seules huit LED peuvent être allumées simultanément : 8 x 20 = 160 mA, auxquels on rajoute environ 10 mA consommés par le MAX7219, soit environ 170 mA. Si on prend en compte la consommation propre de la carte Arduino, environ 40 mA, l'alimentation générale de votre dispositif doit pouvoir fournir jusqu'à 210 mA pour fonctionner correctement.

==> Le soucis n'est pas la capacité de votre alimentation à fournir assez de courant pour cela, avec 5V 2A vous êtes largement tranquille

2 questions:

Vous dites

Pour R, j'ai au max 10 leds vertes et 4 rouges allumées en même temps (2 rouges, 2 oranges et 8 vertes), j'ai donc mis une R de 22.9K (27+2.2).

Votre calcul sur le nombre de LED n'est pas correct mais c'est pas très grave :slight_smile: la résistance que vous prenez sert à définir le courant max fourni par le MAX7219 (à mettre entre ISET et V+). comme expliqué dans le tuto la résistance à prendre dépend des caractéristiques des LED rouge et verte du bargraphe. Avez vous vérifié que vos LEDs ont les même caractéristiques que celles du tuto?

Autre question: votre alimentation 5V 2A, où est elle branchée sur votre arduino Nano (Vin ou 5V) ? et avez vous aussi le câble Mini-B USB branché ?