Shift register 74HC165

Un saluto a tutti.
Sto cercando di capire per quale motivo il semplice circuito non si comporta come mi aspetto.
Il circuito è quello che vede il 74HC165 come stadio di ingresso che andrò a leggere con arduino uno.
lo schema e la base del codice è quello che viene presentato da Paolo Aliverti nel suo tutorial:

Il codice che io ho usato (solo la parte loop) è il seguente

void loop() {
  digitalWrite(REG_CK, HIGH); // segnale di clock pin 2 del 165
  digitalWrite(REG_SL, LOW);  // segnale di carico da parallelo a seriale pin 1 del 165
  digitalWrite(REG_SL, HIGH);  
  for (int i=0; i<16; i++) {
    bool n = digitalRead(REG_DI); // pin 8 del 165
    digitalWrite(REG_CK, LOW); // colpo di clock
    digitalWrite(REG_CK, HIGH);  
    Serial.print(n); // stampo il dato       
  }  
  Serial.println();
  delay(4000); 
}//loop

Il circuito funziona per visualizzare lo stato dei 16 ingressi discriminandoli correttamente quando questi sono tenuti allo stato alto per un tempo superiore al ciclo di loop.
Come vedete in fondo c’è un delay di 4 secondi, e vorrei che in questo tempo di attesa che non viene fatta alcuna lettura, gli ingressi del 165 memorizzino se uno dei pin sia passato nel frattempo allo stato alto (impulso in ingresso)
Invece sembra che viene visto lo stato alto di quella entrata soltanto quando avviene la lettura seriale o nello step precedente quando avviene il passaggio da basso ad alto del pin 1.
Dopo diverse prove sul pin 1 non sono riuscito ad ottenere questa memorizzazione del dato in attesa della lettura effettiva di arduino.
Dove sto sbagliando?
Grazie a tutti voi! :slight_smile:

L'HC165 non ha una "memoria" sugli ingressi ... e' il segnale basso sul pin uno che "carica" lo stato che gli ingressi hanno in quel momento nei flipflop ... ovviamente durante il delay arduino non fa nulla, quindi quello che succede li lo perdi ... solo nel momento in cui ridai l'impulso basso sul pin uno, lo stato dei registri interni si rimette "alla pari" con gli ingressi ...

Vedo solo tre possibilita', per fare quello che vuoi, e le prime due sono troppo complesse, secondo me, non impossibili da ottenere ma troppo complesse perche' ne valga la pena ...

o usare uno shift HC589 con latch sugli ingressi e costruirti un circuito che da un'impulso al latch ogni volta che un pin va alto (ma perderesti tutti quelli che nel frattempo tornano bassi, e ti devi costruire un circuito extra) ...

o costruirti un circuito simile per dare un'impulso di interrupt ad Arduino quando un'ingresso va alto per leggere gli shift in quel momento (ma avresti sempre la complicazione del circuito extra) ...

oppure continui a leggere gli ingressi senza delay, memorizzando via software quelli che vanno alti in un'array o simile, e leggi l'array ogni 4 secondi azzerandolo (in questo modo ogni volta che leggi l'array e lo azzeri hai tutti gli ingressi che sono andati alti nei 4 secondi in cui non li hai letti, ogni volta che lo leggi, e nel frattempo il micro puo fare anche altro)

Cosi al volo non mi viene in mente altro ...

Grazie, avevo cominciato a sospettare che fosse proprio così, quindi c'è poco da fare, a meno che non inserisco un elemento di "memoria" prima dell'ingresso, che viene resettato nel momento della lettura. Esiste una alternativa integrata eventualmente?

Scusa, ho editato mentre scrivevi ... la terza soluzione secondo me e' la piu semplice ... le altre due ti costringerebbero a costruire circuiti extra ... e non mi viene in mente nessuno shift che abbia integrato un'uscita per dare un'interrupt quando uno stato cambia ...

Esiste una alternativa integrata eventualmente?

Come shift register non saprei, però esistono dei GPIO extender, tipo l' MCP23017 , che offre due porte a 8 pin che puoi usari sia come input che come output. Ogni porta ha un pin di interrupt attivabile sui propri pin (se configurati come ingressi), e mantiene in memoria il pin di attivazione fino a quando non lo leggi.

Ciao, Ale.

Grazie Etemenanki, il polling permetterebbe di non usare un interrupt, e questo mi va bene, posso interrogare la periferica ogni 2-4 secondi! Stavo guardando il HC589 e da una prima lettura del datasheet sembrerebbe fare al caso mio, ora vedo se ci sono esempi su arduini!
Tank you!

ilguargua grazie

Anche questo sembra interessante, ma il problema che non ho evidenziato è che il segnale dovrebbe viaggiare lungo un cavo schermato di 30 metri a 5 poli, e non credo che la periferica I2C consenta di trasmettere dati a questa distanza. :confused:

l'HC589 farebbe al caso tuo solo se gli costruissi anche il circuito che da un'impulso al latch ogni volta che un'ingresso va alto ... la soluzione software, oppure il port expander con l'uscita per l'interrupt (che non avevo considerato, grazie ilguargua) sono le soluzioni migliori ...

Oppure si potrebbe anche programmare un secondo atmega328 standalone per fargli emulare uno shift register "intelligente" che avvisasse arduino ogni volta che un pin cambia stato ... sarebbe un po uno spreco di potenza di calcolo, ma costerebbe sempre molto meno di tutti gli integrati che ti servirebbero per creare il circuito per l'interrupt via hardware (in fondo i port expander sono una specie di micro-mcu con funzioni molto ridotte, alla fine :D)

Ora stavo guardando un CD4021 :roll_eyes:
Funziona come l'HC165 oppure tiene in memoria gli ingressi?

che il segnale dovrebbe viaggiare lungo un cavo schermato di 30 metri

...azz, sono tanti, forse anche per gli shift register. :slight_smile:

Ci sono dei repeater? expander? (non ricordo il termine giusto) per l'I2C che permettono distanze notevoli, mi pare Guglielmo ne avesse citato uno qualche tempo fa, ma non ricordo fino a che distanze possono coprire.
Sulle lunghe distnze comunque in genere è meglio usare un cavo twistato con collegamento sbilanciato, tipo l'RS485, RS422 (o il CAN in ultima analisi).

Ciao, Ale.

ilguargua:
... mi pare Guglielmo ne avesse citato uno qualche tempo fa

... eccoli QUI ... per le distanze, tocca mettersi la ed applicare le formule in funzione dei cavi ... comunque parlano di distanze anche di 50 mt. ... ::slight_smile:

Guglielmo

AndreaM:
Ora stavo guardando un CD4021
Funziona come l'HC165 oppure tiene in memoria gli ingressi?

Funziona come il 165, memorizza la foto degli ingressi con l'apposito impulso, ma non memorizza transizioni intermedie. Per quelle basta aggiungere dei flip-flop set/reset tra i segnali e gli ingressi dello shift register (esempio CD4043).

Salve a tutti e buona festa della Madonna.
Ho testato un'upgrade nell'uso del 165, ho applicato ai suoi ingressi le uscite del 4043. I vari FF fanno il loro dovere e tengono in memoria gli impulsi positivi in ingresso al SET. Ovviamente così rimangono fino a che non giunge un impulso positivo sull'ingresso RESET. Tutto funziona in effetti come mi aspetto. Viene fatta una lettura con arduino ogni 2 secondi, ed ho aggiunto anche delay di 10 millisecondi al clock per sicurezza. Ora bisogna inviare un segnale di RESET comune a tutti i FF, dopo che i dati sono stati caricati nei vari stadi del 165. Ho deciso di usare un semplice 555 con uscita ritardata. Il segnale PL (impulso basso) arriva in ingresso al 555 e la sua uscita al pin3 emette un impulso alto dopo un ritardo di alcuni millisecondi, tempo più che sufficiente per far acquisire i dati dal 165 prima che i FF vengano resettati.
Il progetto teorico sembra funzionare, ma nonostante abbia fatto diversi test variando il tempo di ritardo del 555 e verificando con uno oscilloscopio l'andamento del PL e del pin3 del 555... non funziona come mi aspetto.
Ho reso visibile lo stato delle linee con alcuni led per aiutarmi nella diagnosi, l'uscita del FF viene resettata dal 555, ma il dato di un FF allo stato alto non arriva ad arduino, i FF vengono visti sempre allo stato basso.
vi allego una parte di schema di come è realizzato il circuito.

Grazie per il vostro aiuto e per la vostra pazienza.

Ritengo che il problema sia il pin 1 dei 165 che non è sensibile ai fronti ma al livello. Finché rimane basso le variazioni degli ingressi continuano a propagarsi nei flip-flop interni. Probabilmente lo rialzi quando ormai il 555 ha resettato i 4043.

Quanto dura il tuo impulso di load che dai all'HC165 ? ... perche' se non dura a sufficenza per scaricare il condensatore, sara' difficile che il povero 555 riesca a generare un'impulso :wink:

In questi casi, le vecchie porte logiche possono tornare utili ... prova con un 4001 (o un 74hc02, che alla fine sempre 4 nor sono) ...

Normalmente il load e' ad 1, ed il circuito e' stabile con l'uscita a 0 ... nel passaggio del load da 1 a 0 non succede nulla, mentre nel ritorno da 0 ad 1 (dopo aver caricato i dati dei latch nello shift), genere un'impulso ad 1 per resettare i latch, poi torna a 0 ... ho disegnato solo una parte del circuito degli ingressi, per fare l'esempio, ed i valori dei componenti li decidi tu in base a quanto vuoi far durare l'impulso di reset ... :wink:

La durata dell'impulso di LOAD è sufficiente per far scattare il 555, ma forse il problema è che il mio reset di FF avviene quando PL è ancora basso, deduco quindi che i dati vengono acquisiti sul fronte di salita di PL. In sostanza resetto prima della fase di lettura? :confused:
Certo che il circuito alternativo di Etemenanki merita di essere considerato, i due condensatori c1 e c2 e le due resistenze r1 e r2 mi sembra che siano deputate al ritardo. Che valori consigli?
Ora vedo se ho il 4001.
Grazie mille!

L'HC165 carica con lo stato, non con la transizione ... finche il load e' basso, tutto quello che e' sugli ingressi passa ai registri, quindi anche le variazioni degli ingressi ... smette di caricare quando torna alto ... per cui se resetti gli ingressi prima che il load torni alto, leggi 0 ...

Il mio circuito l'ho disegnato perche' dia l'impulso solo dopo che il load e' tornato alto (cioe', in pratica nel momento in cui ci torna, piu il ritardo di propagazione del segnale e quello di attivazione del monostabile, che per quanto brevi dovrebbero essere sufficenti) ... il primo condensatore, quello dopo le due porte in parallelo, serve per dare un solo impulso di start al monostabile dopo che il load e' tornato alto (altrimenti l'uscita del monostabile rimarrebbe comunque sempre alta finche' ci rimane l'ingresso) ... il secondo determina la lunghezza dell'impulso all'uscita (giusto per fare in modo che siano sempre uguali - EDIT: tecnicamente parlando il secondo monostabile non sarebbe neppure servito, e' che cosi e' piu stabile e gli impulsi di uscita sono tutti uguali - ) ... puoi provare fra 100K e 220K per le resistenze e 22 o 33 nF per i condensatori, per stare su impulsi di pochi millisecondi ... che anche se a noi sembrano pochi, per delle porte logiche che viaggiano a poche manciate di nanosecondi come tempi di commutazione, dovrebbero essere piu che sufficenti ...

A proposito, non c'e' una specifica ragione per le due porte in parallelo, e' solo che ne restava una inutilizzata e mi scocciava lasciarla li abbandonata a se stessa, poverina ... :slight_smile: