MAX7219 con 4 display 7 segmenti

Buona giornata ragazzi
ho costruito un contattore con 4 display 7 segmenti con il max 7219 ed un Arduino nano il tutto e alimentato con alimentazione esterna,
utilizzo la libreria LedControl,

il tutto funziona,
pero vi chiedo cortesemente se potete spiegarmi due cose:

una e questo "difetto" se do tensione al tutto, si accendono i primi tre display non il quarto,
come inserisco l'usb al pc si accende il quarto,
non capisco come mai,

la seconda cosa riguarda il calcolo delle unita, decine, centinaia migliaia,
posto il codice

tmp = cunter;
  unita = tmp % 10;
  tmp = tmp / 10;
  decine = tmp % 10;
  tmp = tmp / 10;
  centinaia = tmp % 10;
  tmp = tmp / 10;
  migliaia = tmp % 10;
  tmp = tmp / 10;

mi sembra un po laborioso,
esiste un modo per renderlo più snello?

ringrazio anticipatamente chi mi può aiutare

per il problema display spento non saprei, forse vedendo tutto il programma
invece per le unità decine etc etc...
dovresti passare per un array e ciclarlo
una cosa del tipo

byte cifre[4];
.
.
.

tmp=counter;
for (byte i=0; i<4:i++)
{
   cifre[i]=tmp%10;
   tmp=tmp/10;
}

che se metti all'inizio una cosa un po' "fuori dalle righe" tipo questa:

#define unita cifre[0]
#define decine cifre[1]
#define centinaia cifre[2]
#define migliaia cifre[3]

nianche ti accorgi di usare un vettore
per curiosità, cosa stai facendo?

Ciao Standardoil grazie di avermi risposto,

ecco il programma per testare il MAX

#include "LedControl.h"
#define buton_1 2
#define buton_2 3

LedControl lc = LedControl(12, 11, 10, 1);

unsigned long delaytime = 250;
int cunter = 0;
int unita = 0;
int decine = 0;
int centinaia = 0;
int migliaia = 0;
int tmp = 0;

void setup() {
  Serial.begin(9600);

  lc.shutdown(0, false);
  lc.setIntensity(0, 10);
  lc.clearDisplay(0);

  pinMode(buton_1, INPUT_PULLUP);
  pinMode(buton_2, INPUT_PULLUP);
}

void loop() {

  if (digitalRead(buton_1) == 0) {
    cunter++;
  }
  else if (digitalRead(buton_2) == 0) {
    cunter--;
  }

  tmp = cunter;
  unita = tmp % 10;
  tmp = tmp / 10;
  decine = tmp % 10;
  tmp = tmp / 10;
  centinaia = tmp % 10;
  tmp = tmp / 10;
  migliaia = tmp % 10;
  tmp = tmp / 10;

  lc.setDigit(0, 3, (byte) migliaia, false);
  lc.setDigit(0, 2, (byte) centinaia, false);
  lc.setDigit(0, 1, (byte) decine, false);
  lc.setDigit(0, 0, (byte) unita, false);

  if (cunter > 9999) cunter = 0;
  delay(10);

}

grazie del consiglio per array,
non sono un esperto informatico ma ci provo poi ti so dire,

per curiosità, cosa stai facendo?

allora spiego cosa vorrei fare,
stampare su 3 display 7 segmenti la temperatura letta da un DS18B20,
oviamente c'è un problema "per me" che la temperatura e un float, mentre per stamare su display devo avere un int,

ora quello che so fare e,

int numero;
float reale;

reale = 47.19;
numero = (int)reale;

e fin qui credo vada bene, il problema e come prendere il decimale,
i tuoi consigli mi sarebbero moto preziosi

sarebbero preziosi anche un po'di accenti, ma vabbe'
ma cosa centrano i bottoni con la temperatura?
quello che hai mostrato qui è un contatore-decontatore
per i decimali, basta che decidi quante cifre vuoi avere dopo la virgola
e ragioni in decimi/centesimi/millesimi
per esempio se vuoi leggere i decimi moltiplichi la lettura per 10 e metti una virgola accesa fissa in seconda posizione
se ragioni in centesimo moltiplichi per cento e metti una virgola fissa in terza posizione
si chiama "aritmetica in virgola fissa", si contrappone alla "aritmetica in virgola mobile" dove mobile in inglese viene reso come "floating" (flottante) ecco quindi le variabili float
mah, un po' di teoria prima non farebbe male

Ciao ho seguito il tuo consiglio per le unità, decine ecc. logicamente funziona che e una meraviglia,

ma cosa centrano i bottoni con la temperatura?

niente, era solo per provare se il tutto funziona,

per i decimali forse non mi sono spiegato bene,

per leggere il DS18B20 la libreria mi da un dato float,
mentre la libreria LedControl accetta solo dati int,

allora se faccio un casting ottengo la parte intera senza il decimale,
ma per avere il decimale int non so come fare

milefori:
Ciao ho seguito il tuo consiglio per le unità, decine ecc. logicamente funziona che e una meraviglia,

per i decimali forse non mi sono spiegato bene,

punto 1) lo sapevo, grazie per il karma
Punto 2) ti sei spiegato benissimo, è leggere che non ti è uscito bene...

Scusami per il Karma, provvedo subito

milefori:
Ciao ho seguito il tuo consiglio per le unità, decine ecc. logicamente funziona che e una meraviglia,

ma cosa centrano i bottoni con la temperatura?

ma per avere il decimale int non so come fare

prima di spedire il tutto al display devi trasformare il numero in int moltiplicandolo per 100

poi lo processi con il solito sistema
questo puo andare

unita = tmp % 10;
tmp = tmp / 10;
decine = tmp % 10;
tmp = tmp / 10;
centinaia = tmp % 10;
tmp = tmp / 10;
migliaia = tmp % 10;

spedisci al display solo le tre cifre che ti interessano
e la cifra centrale deve sempre avere il punto acceso
qualcosa del genere

lc.setDigit(0,0,(byte)decine ,false),
lc.setDigit(0,1,(byte)centinaia ,true), // punto decimale acceso
lc.setDigit(0,2,(byte)migliaia ,false);

In effetti osservando il codice di quella libreria si nota come si preoccupa in modo essenziale di controllare uno più display tramite il MAX. Fornisce delle primitive essenziali che risultano poco pratiche, pertanto servirà creare delle funzioni ad hoc più pratiche da usare in base all'applicazione.

Per praticità si potrebbe iniziare a creare una funzione che visualizza il dato sul display.
dato sara un intero con o senza segno, se è con segno servirà accendere il - negativo sacrificando un display e non potendo visualizzare 9999 ma -999, solo tre cifre.

Stessa cosa andrebbe fatta per visualizzare un numero in virgola mobile:

X = digit spento, # digit

#  #  #   #  
X X  0.  1
X X  0.  2
X X  0.  3
ecc
9. 9  9   9
-   9. 9   9 
-   9  9.  9

Ciao.

elrospo:
prima di spedire il tutto al display devi trasformare il numero in int moltiplicandolo per 100

.
.
.

unita = tmp % 10;
tmp = tmp / 10;
decine = tmp % 10;
tmp = tmp / 10;
centinaia = tmp % 10;
tmp = tmp / 10;
migliaia = tmp % 10;

che è la stessa cosa che gli avevo detto io, con in meno la gestione di un array invece che 4 variabili slegate

La modalità di calcolo suggeritami da Standardoil mi piace e funziona,
ora approfitto della vostra disponibilità per chiedere due cose,

1°) sul MAX c'è un piedino siglato DP che presumo sia per pilotare il punto, non riesco a trovare in libreria la
funzione per portare alto quel piedino, cortesemente qualcuno sa come fare?
2°) mi rimane sempre quel problema del display collegato ad il pin DIG0 che all'avvio non si attiva, ma se inserisco l'usb di programmazione si attiva, oppure se premo un pulsante.

mille grazie a tutti per il vostro tempo che mi dedicate

1°) sul MAX c'è un piedino siglato DP che presumo sia per pilotare il punto, non riesco a trovare in libreria la
funzione per portare alto quel piedino, cortesemente qualcuno sa come fare?

Come ti hanno suggerito non funziona?

lc.setDigit(0, 2, (byte) centinaia, true);

2°) mi rimane sempre quel problema del display collegato ad il pin DIG0 che all'avvio non si attiva, ma se inserisco l'usb di programmazione si attiva, oppure se premo un pulsante.

Hai allegato schema?

Ciao Maurotec

Come ti hanno suggerito non funziona?

Si funziona bene, leggo il DS18B20 e stampo su tre display, il punto decimale per ora l'ho collegato con una resistenza da 330ohm a Vcc, perche non so come attivare il piedino DP del MAX,

allego lo schema

perche non so come attivare il piedino DP del MAX

Dallo schema il pin DP del MAX non è collegato ai 4 display per questo non si accende. Pertanto collega i 4 DP di ogni digit assieme e poi connettilo al DP del MAX. Ogni digit è composta da 7 segmenti per comporre il simbolo, più 1 per il punto, in totale 8 segmenti.

Dopo, il punto per ogni digit lo accendi con:

lc.setDigit(0, 2, (byte) centinaia, true);    // true accende DP sul digit 2

e lo spegni con:

lc.setDigit(0, 2, (byte) centinaia, false);    // false spegne DP sul digit 2

Rimane da capire come mai DIG0 lavora solo con USB.

beh, visto che dallo schema DG0 manco c'è...
sarebbe bene che lo OP, dopo aver magicamente messo a posto la sua ortografia mettesse a posto anche lo schema e ci desse l'ultima e aggiornata versione di schema e programma
così magari qualcosa si capisce

Bene ragazzi,
grazie al suggerimento di Maurotec, il punto decimale e ok,

lo schema che avevo postato era quello che avevo fatto le prove,
ora invece posto lo schema del MAX (se serve posto anche il resto) sul quale stampo la temperatura letta con il DS18B20,

il programma e questo

/************************************************************************
*leggo il sensore DS18B20 
*visualizzo la temperatura su 3 display a 7 segmenti
*utilizzo il draiver MAX7219
*
***********************************************************************/
#include "LedControl.h"
#include <OneWire.h>
#include <DallasTemperature.h>

/*********parte per leggere il sensoreDS**/
#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress tmp_address;
float temp0 = 0;
float temp = 0;
int gradi = 0;
int numberOfDevices;
/****************************************/
/////////////////////////(pin su arduino)
LedControl lc = LedControl(12, 11, 10, 1);//Pin del MAX (DIN, CLK, LOAD(CS), 1)

/**variabili e define per il calcolo del numero**/
//unsigned long delaytime = 250;
//int cunter = 0;
int tmp = 0; //variabile per il calcolo unita, decine, centinaia, migliaia
#define unita cifre[0]
#define decine cifre[1]
#define centinaia cifre[2]
byte cifre[3];
/*************************************/
void setup() {
//  Serial.begin(9600);

/**per display*************/
  lc.shutdown(0, false);
  lc.setIntensity(0, 10);
  lc.clearDisplay(0);

/*******per sensore**************/
  numberOfDevices = 1;
  sensors.begin();
  delay(1000);
}

void loop() {
sensors.requestTemperatures(); // Comando per leggere la temp.
temp0 = sensors.getTempCByIndex(0);
temp = temp0 * 10;
gradi = (int)temp;

  tmp = gradi;
for(byte i = 0; i < 3; i++){
  cifre[i] = tmp % 10;
  tmp = tmp /10;
}

  lc.setDigit(0, 2, (byte) centinaia, false);
  lc.setDigit(0, 1, (byte) decine, true);
  lc.setDigit(0, 0, (byte) unita, false);

  delay(50);

}

ora tutto funziona,
spero di non aver commesso errori
mille grazie a tutti voi

ora tutto funziona,
spero di non aver commesso errori
mille grazie a tutti voi

Ottimo, quindi hai anche risolto il problema con DIG0?

Ciao.

Ciao Maurotec

Ottimo, quindi hai anche risolto il problema con DIG0?

ora sto provando con il sensore, e il DIG0 funziona,

pero prima che provavo con due pulsanti e facevo un contattore up, down, non andava,
appena ho un po di tempo riprovo poi ti so dire,

Come promesso ho rifatto la prova,
chissà quale put... avevo fatto,
ora con questo programma va tutto bene, DIG0 e ok

#include "LedControl.h"

#define buton1 2
#define buton2 3


/////////////////////////(pin su arduino)
LedControl lc = LedControl(12, 11, 10, 1);//Pin del MAX (DIN, CLK, LOAD(CS), 1)

/**variabili e define per il calcolo del numero**/

int cunter = 0;
int tmp = 0; //variabile per il calcolo unita, decine, centinaia, migliaia
#define unita cifre[0]
#define decine cifre[1]
#define centinaia cifre[2]
byte cifre[3];
/*************************************/
void setup() {
//  Serial.begin(9600);

pinMode(buton1, INPUT_PULLUP);
pinMode(buton2, INPUT_PULLUP);

/**per display*************/
  lc.shutdown(0, false);
  lc.setIntensity(0, 10);
  lc.clearDisplay(0);
}

void loop() {
  if(digitalRead(buton1) == 0){
    cunter++;
  }
  else if(digitalRead(buton2) == 0){
    cunter--;
  }
  if(cunter == 999){
    cunter = 000;
  }

  tmp = cunter;
for(byte i = 0; i < 3; i++){
  cifre[i] = tmp % 10;
  tmp = tmp /10;
}

  lc.setDigit(0, 2, (byte) centinaia, false);
  lc.setDigit(0, 1, (byte) decine, false);
  lc.setDigit(0, 0, (byte) unita, false);

  delay(50);

}

mille grazie per il tuo interessamento