74hc164ad + 2 display7 segmenti 4 caretteri + 4 led+ 4 tasti

mi ritrovo questo circuito gia bello, montato e ordinato, con pazienza ho ricavato anche tutti i collegamenti e li ho disegnati con kicad anche se un po disordinati, secondo voi con arduino si riesce a farlo funzionare di nuovo??

i display hanno 12 piedini e dallo shift registrer arrivano 4 pin che alimentano i pin 1-4-5-7 dei display, credo che i 4pin siano l'anodo o il cadoto comune di ogni carattere e i restanti 8 siano i led di ogni singola parte dei caratteri


Sarebbe da capire col tester quali pin sono i anodi e catodi, quale pin corrisponde a quale segmento e se i display sono a anodo comune o a catodo comune.

Pernso che si puó utilizzare con Arduino.

Ciao Uwe

Allora controllato con due pile stilo e i display sono ad anodo comune. Quindi per accendersi devono chiudere a massa e ogni uscita del 74hc164 attiva un carattere

allora internamente i display sono come in questa immane, il secondo schema

ragionando se voglio visualizzare per esempio 1234 mi ritrovo un 8888, come faccio a ovviare a questo problema?? da come ho capito devono chiudere a massa attraverso i pin digitali di arduino, giusto?? è possibile che si deve visualizzare un numero alla volta ma ad una frequenza elevata?? cioè come in figura??

è possibile che si deve visualizzare un numero alla volta ma ad una frequenza elevata?? cioè come in figura??

Esatto. Mandi una cifra,mettendo a LOW i pin della schedina dove ci sono le resistenze.
e poi abiliti una porta dello shift register
Cambi cifra e abilti la porta successiva dello shift register
e via cosi', fino alla quarta cifra( o ottava )
poi rincominci da capo

Quindi Arduino e il 74hc164 devono essere sincronizzati attraverso il pin clock??

puoi prendere degli spunti da qui

mi è venuto un dubbio, se imposto un pin digitale come input, in parallelo a questo pin ci va una resistenza di pul down che chiude a massa??

come questo??

o collego i pin dei catodi dei segmenti direttamente ai pin digitali??

mi è venuto un dubbio, se imposto un pin digitale come input, in parallelo a questo pin ci va una resistenza di pul down che chiude a massa??

si, altrimenti a pulsante aperto il Pin rimane fluttuante
Quindi o resistenza di PullDown ( se il pulsante e' collegato al positivo ) o PullUp ( se il pulsante e' collegato al negativo )

o collego i pin dei catodi dei segmenti direttamente ai pin digitali??

Non capisco che c'entri questo con quello detto sopra
Per pilotare i segmenti devi mettere il pin come Output e collegare le resistenze sui catodi direttamente ai pin digitali

brunello:
Non capisco che c'entri questo con quello detto sopra
Per pilotare i segmenti devi mettere il pin come Output e collegare le resistenze sui catodi direttamente ai pin digitali

le resistenze IN SERIE ai segmenti gia ci sono e sono montate direttamente sulla schedina e sono da 330ohm, ora per farli condurre sui pin digitali li devo mettere come OUTPUT LOW in modo che questi siano a bassa impedenza??

cioè cosi??

#define data 11
#define clock 12
#define segA 2
#define segB 3
#define segC 4
#define segD 5
#define segH 6
#define segG 7
#define segF 8
#define segE 9

void setup()
{
  pinMode(clock, OUTPUT); 
  pinMode(data , OUTPUT); 
  pinMode(segA , OUTPUT);
  digitalWrite(segA, LOW);
  pinMode(segB , OUTPUT);
  digitalWrite(segB, LOW);
  pinMode(segC , OUTPUT);
  digitalWrite(segC, LOW);
  pinMode(segD , OUTPUT);
  digitalWrite(segD, LOW);
  pinMode(segH , OUTPUT);
  digitalWrite(segH, LOW);
  pinMode(segG , OUTPUT);
  digitalWrite(segG, LOW);
  pinMode(segF , OUTPUT);
  digitalWrite(segF, LOW);
  pinMode(segE , OUTPUT);
  digitalWrite(segE, LOW); 
  
  
}

Non mi convince l'affermazione "sono ad anodo comune", principalmente perchè non mi spiego come deve funzionare la scansione dei 4 pulsanti tattili.

Non mi convince neanche il fatto che quelli sui pulsanti siano diodi zener, penso invece siano semplici diodi 1N4148, 1N914 ecc. Anche perchè non essendoci il valore di tensione dello zener mi riesce difficile capire cosa dovrebbe accadere.

Se il comune dei pulsanti è collegato ad una pull-up e ad un pin di ingresso di Arduino "kxin" allora da Q0 a Q3 ci saranno 3 uscite alte e una bassa, ciò che "shifta" è l'uscita bassa.

Piagiando il pulsante su Q0 kxin da alto (tenuto alto dalla pull-up) diventa basso, quando Q0 è basso. Al prossimo passo Q0 High e Q1 low, se il pulsante su Q1 è premuto l'uscita kxin è low.

Comunque il sistema di pilotaggio è quello ipotizzato da te, e si chiama genericamente multiplex.

Se invece il display è come hai detto ad anodo comune, da Q0 a Q3 ci saranno tre uscite low ed una alta ed quella alta a "shiftare", ma in tal caso non mi torna il funzionamento dei pulsanti tattili.

Ciao.

per il momento i pulsanti non li sto prendendo in considerazione ma mi sa che hai ragione che non sono dei zener perché sono come questi

anche perché ancora non ho capito a cosa servono quei diodi. l'obbiettivo finale è quello di visualizzare sui display 2 parametri da due sensori

Non basta quel codice per far funzionare il display devi anche inviare il dato e il clock, altrimenti i il catodo comune o anodo comune non si trovano alimentati e alimentando solo a, b, c ecc non si accende nulla.

Metti un segmento alto o basso e prova ad inviare dati e clock al 74.

Ciao.

infatti mentre mangiavo pensavo a come far accendere un carattere alla volta, e siccome sono 8 pin sullo shift register da far accendere ho pernsato di inviare 00000001 poi 00000010 e ancora 00000100 e così via per far accendere i singoli caratteri, ho finito di scrivere il codice così

#define data 11
#define clock 12
#define segA 2
#define segB 3
#define segC 4
#define segD 5
#define segH 6
#define segG 7
#define segF 8
#define segE 9
byte car1  = B00000001;
byte car2  = B00000010;
byte car3  = B00000100;
byte car4 = B00001000;
byte car11  = B00010000;
byte car12 = B00100000;
byte car13 = B01000000;
byte car14 = B10000000;



void setup()
{
  pinMode(clock, OUTPUT); 
  pinMode(data , OUTPUT); 
  pinMode(segA , OUTPUT);
  digitalWrite(segA, LOW);
  pinMode(segB , OUTPUT);
  digitalWrite(segB, LOW);
  pinMode(segC , OUTPUT);
  digitalWrite(segC, LOW);
  pinMode(segD , OUTPUT);
  digitalWrite(segD, LOW);
  pinMode(segH , OUTPUT);
  digitalWrite(segH, LOW);
  pinMode(segG , OUTPUT);
  digitalWrite(segG, LOW);
  pinMode(segF , OUTPUT);
  digitalWrite(segF, LOW);
  pinMode(segE , OUTPUT);
  digitalWrite(segE, LOW); 
  
  
}

void loop()
{
    shiftOut(data, clock, LSBFIRST, car1);
    delay(1);
    shiftOut(data, clock, LSBFIRST, car2);
    delay(1);
    shiftOut(data, clock, LSBFIRST, car3);
    delay(1);
    shiftOut(data, clock, LSBFIRST, car4);
    delay(1);
    shiftOut(data, clock, LSBFIRST, car11);
    delay(1);
    shiftOut(data, clock, LSBFIRST, car12);
    delay(1);
    shiftOut(data, clock, LSBFIRST, car13);
    delay(1);
    shiftOut(data, clock, LSBFIRST, car14);
    delay(1);
   
}

se aumento il delay vedo che si accende un carattere alla volta, metto su HIGH uno dei segmenti vedo che si spegne il segmento che voglio. ora devo capire come far visualizzare i valori dei sensori

allora mi sono impantanato, come faccio a visualizzare sul display un valore letto sui pin analogici?? devo fare una conversione da decimale a BCD?? non esiste una libreria per un'applicazione come la mia??

Io ho usato del codice specifico, però il codice è molto frammentato e postarlo tutto è impossibile, ma quello che posto ti permette di prendere spunto.

Considera che io uso display a catodo comune.

#define CHAR0               0x3f
#define CHAR1               0x06
#define CHAR2               0x5b
#define CHAR3               0x4f
#define CHAR4               0x66
#define CHAR5               0x6d
#define CHAR6               0x7d
#define CHAR7               0x07
#define CHAR8               0x7f
#define CHAR9               0x6f

#define CHARa               0x5f
#define CHARA               0x77
#define CHARb               0x7c
#define CHARc               0x58
#define CHARC               0x39
#define CHARd               0x5e
#define CHARe               0x7b
#define CHARE               0x79
#define CHARF               0x71
#define CHARH               0x76
#define CHARi               0x04
#define CHARJ               0x0e
#define CHARL               0x38
#define CHARn               0x54
#define CHARo               0x5c
#define CHARP               0x73
#define CHARq               0x67
#define CHARS               0x6d
#define CHARt               0x78


#define CHARu               0x1c
#define CHARU               0x3e
#define CHARy               0x6e
#define CHARdot             0x80
#define CHARminus           0x40
#define CHARspace           0x00

#define CATODO_NIBBLE       4

FILE _dled_stream;

int dled_put_char(char c, FILE *stream)
{
    char cc = 0;
    if (c == 'A')
        cc = CHARA;
    else if (c == 'a')
        cc = CHARa;
    else if (c == 'b')
        cc = CHARb;
    else if (c == 'C')
        cc = CHARC;
    else if (c == 'c')
        cc = CHARc;
    else if (c == 'd')
        cc = CHARd;
    else if (c == 'e')
        cc = CHARe;
    else if (c == 'E')
        cc = CHARE;
    else if (c == 'F')
        cc = CHARF;
    else if (c == 'H')
        cc = CHARH;
    else if (c == 'i')
        cc = CHARi;
    else if (c == 'J')
        cc = CHARJ;
    else if (c == 'L')
        cc = CHARL;
    else if (c == 'n')
        cc = CHARn;
    else if (c == 'o')
        cc = CHARo;
    else if (c == 'P')
        cc = CHARP;
    else if (c == 'q')
        cc = CHARq;
    else if (c == 'S')
        cc = CHARS;
    else if (c == 't')
        cc = CHARt;
    else if (c == 'u')
        cc = CHARu;
    else if (c == 'U')
        cc = CHARU;
    else if (c == 'y')
        cc = CHARy;
    else if (c == '0' )
        cc = CHAR0;
    else if (c == '1' )
        cc = CHAR1;
    else if (c == '2' )
        cc = CHAR2;
    else if (c == '3' )
        cc = CHAR3;
    else if (c == '4' )
        cc = CHAR4;
    else if (c == '5' )
        cc = CHAR5;
    else if (c == '6' )
        cc = CHAR6;
    else if (c == '7' )
        cc = CHAR7;
    else if (c == '8' )
        cc = CHAR8;
    else if (c == '9' )
        cc = CHAR9;
    else if (c == '.' )
        cc = CHARdot;
    else if (c == '-' )
        cc = CHARminus;
    else if (c == ' ')
        cc = CHARspace;
    else
        return 0;

    if (cc == CHARdot) {
        if (current_column == 1) {
            ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
                bit_buff[3] |= _BV(7);
            }
        } else {
            ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
                bit_buff[current_column-1] |= _BV(7);
            }
        }
    } else {
        if (current_column > n_max_columns-1)
            return 0;

        ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
            if (current_column > 0)
                bit_buff[current_column] = cc;
            else
                bit_buff[current_column] |= _BV(PB6);
        }
        ++current_column;
    }

    return 0;
}

void dled_initialize()
{
    if (!n_max_columns)
        n_max_columns = _dled_n_columns;
    if (n_max_columns <=0)
        n_max_columns = 1;
    if (!bit_buff)
        bit_buff = _dled_bit_buff;

    dled_stream = &_dled_stream;
    fdev_setup_stream(dled_stream, dled_put_char, NULL, _FDEV_SETUP_WRITE);
    DDRC &= ~_BV(PC3);
    PORTC &= ~_BV(PC3);
}

// chiama questa funzione periodicamente almeno ogni 4ms
// per esempio si può usare un task di leOS da eseguire ogni 4ms
// bit_buff contiene i caratteri da stampare
// Su PORTB ci sono i segmenti a, b, c ecc
// Sui 4 bit più significativi di PORTC ci sono i catodi.
void dled_update()
{
    static uint8_t idx = 0;

    PORTC &= ~0xf0;
    if (idx > n_max_columns-1)
        idx = 0;
    PORTB = bit_buff[idx];
    PORTC |= _BV( idx + CATODO_NIBBLE);
    idx++;
}

Per scrivere basta usare fprintf(dled_stream, “%s”, “stringa (o numero convertito in string) da visualizzare” );

Vedi se ti può essere utile e se vuoi chiarimenti in merito al codice posta pure.

Ciao.

allora se ho capito, per visualizzare i numeri sul display devo definire, nello sketch, ogni carattere. per visualizzare un carattere ci vogliono 8bit, un bit per ogni segmento, 7 per il carattere + 1 per il punto. quindi per visualizzare, per esempio, 3472 perché questo lo ottengo in qualche moto dai pin analogici devo scomporre prima il 3

edit by mod: link all'immagine rimossa perché il server di destinazione non accetta link diretti

quindi devo mettere a LOW i pin ABCDG e i restanti metterli in HIGH il che guardando come sono collegati su arduino ho che il pin 2=A 3=B 4=C 5=D 6=H 7=G 8=F 9=E e 1=high e 0=low quindi per ABCDG devo shiftare e contemporaneamente avere 00001011 poi per il 4 shiftare e 10011001 poi per il 7 shiftare e 00011101 poi per il 2 shiftare e 00101010 e così ho scritto 3274, ma c'è un però siccome i display sono due e dopo che il 74 ha finito di shiftare con il primo display deve comunque passare al secondo display e li deve scrivere comunque qualcosa. è una trasmisione seriale-parallela sincronizzata! ora tornando al suggerimento di MauroTec perché quando hai definito lo 0 "#define CHAR0 0x3f" hai dado un HEX che indica il 6? :relaxed:? cioè quando hai definito i caratteri non hai dato a nessuno il valore reale, perché?? lo so che sono una scarpa da ginnastica puzzolente ma cerco di diventare uno stivale di cuoio luccicante!

lo so che sono una scarpa da ginnastica puzzolente ma cerco di diventare uno stivale di cuoio luccicante!

questa mi piace

ma c'è un però siccome i display sono due e dopo che il 74 ha finito di shiftare con il primo display deve comunque passare al secondo display e li deve scrivere comunque qualcosa

e perche' ? se nel tuo esempio meti nel loop solo

    shiftOut(data, clock, LSBFIRST, car1);
    delay(1);
    shiftOut(data, clock, LSBFIRST, car2);
    delay(1);
    shiftOut(data, clock, LSBFIRST, car3);
    delay(1);
    shiftOut(data, clock, LSBFIRST, car4);
    delay(1);

lavori solamente con un display

Studia questo esempio, capisci bene come funziona il multiplexer e come inviare un numero.
con pochi adattamenti fa' al caso tuo

ora tornando al suggerimento di MauroTec perché quando hai definito lo 0 "#define CHAR0 0x3f" hai dado un HEX che indica il 6? smiley-slim? cioè quando hai definito i caratteri non hai dato a nessuno il valore reale, perché??

Intanto nel codice che ho postato ci può essere un errore, io l'ho postato solo per prendere spunto.
Ma non è questo il caso. Io uso un microcontroller ATmega644A che più pin rispetto al 328 montato sulla 2009/UNO, Per questo ho potuto usare una intera porta connessa ai segmenti e 4 bit di un'altra porta per i catodi. Ovviamente il segmento 'a' è connesso al bit 0, il 'c' al bit 1 e così via fino al segmento dp (punto).
Accendendo f, e, d, c, b, a sul display compare lo zero, quindi il valore da attribuire alla porta è 0011 1111 che in esadecimale si esprime 0x3f. ** Ripeto il mio display è a catodo comune e non uso il 74164.

Lo zero nel caso di display ad anodo comune è il not di 0011 1111, cioè 1100 0000, quindi i codici definiti da me possono essere usati sia per anodo comune che per catodo comune, semplicemente invertendo il valore prima di usarlo PORTC = ~CHAR0;

Ti consiglio di studiare il datasheet del 74164, fino ad avere ben chiaro come funziona, così da sapere nel dettaglio cosa e come devi inviargli i dati.

Scrivi codice di test impostando i segmenti per formulare lo zero e accendi l'anodo del primo display, spegnilo e accendi l'anodo del secondo display ecc. Nel tuo caso hai 8 display, si potrebbe pensare di fare uno shift da 0 a 7, ma nulla toglie che lo shift sia "1000 1000", "0100 0100", "0010 0010" ecc, che poi è come inviare in sequenza 0x88, 0x44, 0x22, 0x11.

Ciao.