generare una sequenza di bit a frequenza variabile

menniti:
dopo il 30mo impulso devo però bloccare il loop, non potrei mettere il code sotto SETUP invece che sotto loop? In questo modo potrei tenere ENABLE a 0 per l'intera durata del ciclo oppure funziona su fronte e quindi serve proprio l'impulso?

Sarà che oggi ho la testa un pochino sconfusionata da un bel raffreddore, ma non ti seguo :slight_smile:
Il software su Arduino deve seguire una logica di questo tipo:
Nel setup inizializzi tutti i vari pin come serve.
All'interno del loop dovrai attendere un evento che causa il cambio sequenza, dato che non hai specificato come questo avviene posso solo ipotizzare che lo fai a intervalli fissi di tempo oppure tramite uno specifico comando premendo un pulsante o un carattere che arriva dalla seriale.
Comunque sia non devi fare altro che aspettare l'evento, cioè inserisci un controllo, e quando questo avviene chiami la funzione che genera l'eventuale sequenza random, oppure specifichi un array precaricato in memoria che contiene la sequenza, oppure la ricevi dalla porta seriale, dopo di che chiami la funzione che la carica nello shift register.
La funzione che carica la sequenza non deve fare altro che eseguire queste operazioni partendo dal presupposto che le tre linee di controllo, ENABLE, DATA, CLOCK, si trovano tutte quante 1 logico durante il normale funzionamento dello shift register:

  1. portare ENABLE a 0 logico
  2. mettere su DATA il valore caricare prelevandolo dall'array che contiene la sequenza.
  3. Portare CLOCK da 1 a 0
  4. Attendere 10us
  5. Portare CLOCK da 0 a 1
  6. Ripetere dal punto 2 per tante volte quanti sono i bit da caricare.
  7. Riportare DATA, CLOCK, ENABLE a 1 logico per riavviare lo shift register.

In pratica nella funzione che carica la sequenza usi una for(i=0;i<n;i++) ove n è il numero dei bit da caricare.

Con questa tipologia di schema posso decidere di variare i bit della sequenza (avendo necessità di un range 25-32) semplicemente scegliendo una delle uscite Q1 (4) ÷ Q8 (11)? Potrei usare un dip commutando un solo pin per volta verso l'OUT.

Si, in teoria puoi avere da 2 a 32 bit, basta che cambi il bit usato per il ricircolo e per l'out.

Infine, per fare alcune prove oggi, dispongo di due comunissimi cd4094, di un cd4011 (nand, anche se con pinatura delle porte leggermente diversa), di un generatore di funzioni a 10MHz (ma penso che i CMOS non reggano questa frequenza, potrei provare a 1MHz)

Direi che hai tutto quello che serve, la massima frequenza di lavoro dipende dalla serie, se sono i vecchi CD4xxx sarà difficile che arrivi oltre i 5 MHz, però per provare va bene lo stesso.

il dubbio che ho è se questi componenti possono andar bene per una simulazione con sequenza a 16 bit (o meno) e se i livelli logici dell'Arduino vengono riconosciuti dalle porte CMOS.

Anche se le soglie di tensione per 1 e 0 sono leggermente diverse tra l'ATmega e i CMOS della serie CD4xxx non dovrebbero esserci problemi.

Non è il raffreddore, sono io...
Dunque la parte elettronica ora mi è chiara. I problemi sono sulla parte Arduino (ancora non ci ho capito molto, come ben vedi!)
Il mio sistema deve funzionare in modo semplice e manuale:
Carico il code su Arduino, lo invio al tuo circuito, stop, a quel punto il tuo circuito dovrebbe vivere di vita propria e l'altro che ho realizzato (il riconoscitore di sequenze) legge i dati provenienti da esso e mi avvisa quando riconosce una delle sequenze che sto cercando; quindi non ho comandi automatici da mandare o controllare; la sequenza la imposto su Arduino e mi vale per tutta la sperimentazione; se decido di cambiarla semplicemente rimando il code ad Arduino e tutto ricomincia daccapo. Spero di essere stato più chiaro così. :astonished:
Ho provato a tradurre le tue indicazioni

#define DATA 12
#define ENABLE 13
#define CLOCK 7
byte sequenza[] = {
  1, 1, 1, 0, 1, 1, 0, 0};

void setup() {                
  pinMode(DATA, OUTPUT);  // attivo le uscite
  pinMode(ENABLE, OUTPUT);
  pinMode (CLOCK, OUTPUT);
  digitalWrite(ENABLE, LOW); //blocco tutto
  digitalWrite(DATA, LOW);
  digitalWrite(CLOCK, LOW);
}

void loop() 
{
  for(int i=0; i<8; i++)  //ciclo per 8 bit
  {
    digitalWrite(ENABLE, LOW); 
    digitalWrite(DATA, sequenza[i]);
    digitalWrite(CLOCK, LOW);
    delay (10);
    digitalWrite(CLOCK, HIGH);
  }
  digitalWrite(ENABLE, HIGH); //riavvio tutto
  digitalWrite(DATA, HIGH);
  digitalWrite(CLOCK, HIGH);
}

Il mio dubbio è che in questo stesso thread mi hano spiegato che ciò che è nella sezione loop si ripete all'infinito, ma questo mi creerebbe problemi; io vorrei eseguire tutto una sola volta in modo da non "disturbare" più il tuo circuito. Mi spieghi come fare e soprattutto se quando ho postato è corretto?

Meglio così :slight_smile:

#define DATA 12
#define ENABLE 13
#define CLOCK 7
byte sequenza[] = {
  1, 1, 1, 0, 1, 1, 0, 0};

void setup() {                
  pinMode(DATA, OUTPUT);  // attivo le uscite
  pinMode(ENABLE, OUTPUT);
  pinMode (CLOCK, OUTPUT);
  digitalWrite(ENABLE, LOW); //blocco tutto
  digitalWrite(DATA, HIGH);
  digitalWrite(CLOCK, HIGH);
}

void loop() 
{
  digitalWrite(ENABLE, LOW); // fermi ciclo shift
 
 for(int i=0; i<8; i++)  //ciclo per 8 bit
  {
    digitalWrite(DATA, sequenza[i]);
    digitalWrite(CLOCK, LOW);
    delay (10);
    digitalWrite(CLOCK, HIGH);
  }

  digitalWrite(ENABLE, HIGH); //riavvio tutto
  digitalWrite(DATA, HIGH);
  digitalWrite(CLOCK, HIGH);

  while(1);  // loop infinito e blocca il ciclo.

}

Naturalmente....
Grazie di tutto, ormai devo lasciare il mio angolo di pace (ho un piccolo lab fuori casa :D) e tornare alla cruda realtà (moglie, mutuo, ecc =(), posso continuare a gironzolare sul forum, ma per le prove ormai se ne parla nei prox giorni; naturalmente appena ho finito il mini-circuito posto i risultati, poi realizzerò quello completo con i componenti che mi hai indicato. Siete stati tutti davvero molto disponibili, a te un ringraziamento particolare per non avermi mandato un virus della rabbia invece del circuito...mi armerò della tua pazienza prima di rientrare :wink:

Carissimo Astrobeed,
funziona alla grande! Per il momento ho testato con due soli cd4094 e un cd4011, in configurazione "full", cioè sfruttando tutti i 16 bit, in quanto prelevo dal pin 9 del secondo Shift; in effetti la frequenza max è di 3MHz, ma dipende dai cmos, come prevedibile.
Confermando quanto dicevi lo stato dei bit è invertito, poiché non ho porte disponibili mi "secca" mettere un inverter nel circuito finale, poiché mi viene scomodo "ragionare" al contrario per inserire la sequenza, ho pensato di invertirla via soft; mi sembrava una cosa facile :astonished: col seguente codice:

for(int k=0; k<16; k++)
{ if (sequenza [k] == 0)
(sequenza [k] = 1);
else
(sequenza [k] = 0);
}

invece non funziona per niente :. mi trasforma la sequenza in un'altra che non c'entra niente, ho fatto decine di prove (ho provato a metterla sia in setup che in loop ma non cambia nulla); comunque se non riesco metto l'inverter, però mi pare davvero una cosa banale, dove sbaglio?
In ogni caso moltissime grazie, già solo questo problema risolto mi vale l'acquisto dell'Arduino.

Anche se hai scelto il modo più "macchinoso" per farlo mi sembra corretto, prova a inserire queste righe di codice in setup:

for(int k=0; k<16; k++)
   {
      sequenza[i] ^= 1;
   }

Eseguire l'Xor con 1 di un valore logico lo inverte e viene usata una singola istruzione assembler.

Ciao, al momento sono senza PC nel lab e non posso provare, in ogni caso ho realizzato l'oscillatore a 10MHz con 3 nand, uso il 4° per invertire il segnale, ma comunque voglio risolverlo il problema, ti faccio sapere al più presto.
Intanto ho serie difficoltà a trovare il 5/74hc4094, hai un riferimenti in italia? mi pare eccessivo ordinare all'estero; a questo punto integrerei con altro materiale.
In alternativa potrei usare il più semplice (anche se concuma un po' più corrente) 74ls91 o altro similare? non ha le uscite parallele, ma a questo punto a me basta il dip per selezionare 8-16-24 bit.
Vorrei inoltre sapere se, una volta inviata la sequenza e caricati gli shift, è possibile memorizzare lo status in modo da non perdere tutto allo spegnimento. L'idea è questa: collego lo schedino (già realizzato) all'Arduino, lo programmo con la sequenza che mi serve, memorizzo la stato dei bit, spengo tutto e mi porto il solo schedino, senza necessità di pc e arduino.
Forse potrei mettere proprio il micro di Arduino, ma non so se sia conveniente e se sia fattibile senza tutta la circuiteria dell'ArduinoUno.
Peraltro ho fatto finalmente un po' di prove sul campo ed in realtà con 24 bit ce la faccio, infatti ho previsto 3 shift.
Potresti aiutarmi ancora, sempre che la cosa non ti faccia perdere troppo tempo?
Grazie

Io i componenti elettronici li compro solo da Digikey o da Mouser, hanno praticamente tutto a stock, prezzi ottimi, spedizione gratuita se si acquista più di 70 Euro, magazzini in Europa quindi niente sorprese di dogana e lunghe attese, di solito la merce arriva dopo 2-3 giorni lavorativi dall'ordine.
Non è possibile memorizzare la sequenza sugli shift register, se togli l'alimentazione va persa, una alternativa è realizzare un sistema totalmente stand alone, sullo stesso pcb metti anche un ATmega 328 col relativo quarzo, ogni volta che accendi il tutto come prima cosa carica la sequenza, volendo puoi usare dei dip switch per impostarne un certo numero a scelta, 8 dip switch ti permettono di selezionare fino a 256 diverse sequenze.
Il cambio di sequenza lo puoi fare quando ti pare, imposti il nuovo valore e premi reset, oppure temporizzato, ogni tot secondi/minuti la sequenza cambia da sola.
Per cambiare le sequenze memorizzate basta riprogrammare l'ATmega.
Una curiosità, a cosa ti serve questa sequenza ad una frequenza così elevata ?

Ho cercato di capire come funziona il quote, non ho idea di quale sia il risultato, speriamo bene... :blush:

Io i componenti elettronici li compro solo da Digikey o da Mouser, hanno praticamente tutto a stock, prezzi ottimi, spedizione gratuita se si acquista più di 70 Euro, magazzini in Europa quindi niente sorprese di dogana e lunghe attese, di solito la merce arriva dopo 2-3 giorni lavorativi dall'ordine.

Allora stasera mi metto alla ricerca di queste Aziende, ma una spesa di 70 euro non saprei davvero come raggiungerla e se è inferiore mi sa che mi costa più il trasporto del poco che mi serve. Ho a disposizione questi TTL della serie 74LS: 91 (ma solo 1pz), 164, 299; pensavo di poter usare uno di questi tipi al posto del 4094, ma non capisco se c'è o meno corrispondenza di logica. :~

Non è possibile memorizzare la sequenza sugli shift register, se togli l'alimentazione va persa, una alternativa è realizzare un sistema totalmente stand alone, sullo stesso pcb metti anche un ATmega 328 col relativo quarzo, ogni volta che accendi il tutto come prima cosa carica la sequenza, volendo puoi usare dei dip switch per impostarne un certo numero a scelta, 8 dip switch ti permettono di selezionare fino a 256 diverse sequenze.
Il cambio di sequenza lo puoi fare quando ti pare, imposti il nuovo valore e premi reset, oppure temporizzato, ogni tot secondi/minuti la sequenza cambia da sola.
Per cambiare le sequenze memorizzate basta riprogrammare l'ATmega.

Quello che intendevo dire era memorizzare gli stati degli shift su qualcosa tipo una o più prom da aggiungere al circuito, ma penso sia complicato. Mi pare molto più semplice l'idea dell'ATmega 328 + quarzo + pulsante reset; invece la programmazione la farei sempre da Arduino (immagino mettendo l'ATMega al posto di quello di serie), il cambio sequenza devo farlo periodicamente e non frequentemente. Ma tecnicamente mi basta aggiungere l'AT, collegare il quarzo, un pulsante reset, l'alimentazione ed i pin che mi servono ed è fatta? in caso contrario potresti darmi un chiarimento maggiore? :~

Una curiosità, a cosa ti serve questa sequenza ad una frequenza così elevata ?

All'Università abbiamo un macchinario in laboratorio che legge dei dati cerebrali e li manda sotto forma numerica o grafica ad un PC, ha inoltre la possibilità di inviarli sotto forma di lunghissime sequenze binarie, lavora a circa 10MHz in uscita; parte del nostro lavoro consiste nel verificare la periodicità di dati che non sempre conosciamo a priori. Ho realizzato diversi riconoscitori di sequenze base, ma probabilmente ricorrerò ad Arduino anche per questa operazione. Mi serve simulare in modo più realistico possibile questa uscita per fare le prove nel mio piccolo lab, tutto qui. Come vedi stai rendendo un servizio alla Scienza :), naturalmente si opera a livello gratuito, purtroppo, ma con la scusa unisco lavoro e passione per l'elettronica (ma a livello di logica digitale di base, come avrai ormai capito, oltre ci siete tu e gli altri "mostri" di questo forum :D)
Un'ultima cosa: ma c'è modo di allargare questo quadro dei post che mi fa impazzire :0 ogni volta che scrivo troppo, o è fatto apposta? :~
Grazie per il grande aiuto, fino a qualche giorno fa mi sembravaimpossibile fare questa cosa....

ciao menniti

Altri fornitori veloci, ma non sempre a miglior prezzo sono distrele.it e it.rs-online.com e sono sicuro che forniscono anche a privati. Distrelec e RS forniscono su specificazione anche materiale di cataloghi di altri paesi. (RS c'é in tantissimi paesi. distrelec anche in Germania o Austria con una gamma di prodotti maggiori.
Altro fornitore, ma Ti serve partita IVA é farnell.it

Non Ti ho piú risposto perché astrobeed Ti ha fornito uno schema funzionante simile a quello che pensavo di fare io.

Ciao Uwe

Ciao uwe, avevo intanto trovato rs components ed ho inviato l'ordine, naturalmente approfittando per prendere un po' di cosette sempre utili; rispetto ai due negozi della mia città i prezzi sono comunque ottimi ed in ogni caso ho trovato roba che qui non ti portano nemmeno su ordinazione.
Non devi affatto giustificarti, ci mancherebbe! Nessuno è tenuto a fare nulla, io ero sicuro che mi avresti mandato lo schema, poi una volta arrivato quello di astrobeed non aveva più significato, però stiamo continuando la discussione tecnica sul circuito, se hai dritte sono accettatissime.
Grazie di tutto.
menniti

Avevo fatto una promessa e é giusto che mi scuso se non la tengo. Senó hai ragione, nessuno è tenuto a fare nulla, ma una promessa cambia le cose.
Aiuteró volentieri.
Ciao Uwe

Buongiorno,
allora, la situazione è questa: ho reperito i 74HC4094 presso RS, arriveranno, quindi inutile perdere tempo a valutare i TTL che avevo indicato (anche se una risposta sul piano teorico mi farebbe piacere averla); oggi spero di riavere il mio pc di lab per poter provare il code di astrobeed riguardo l'inversione della sequenza ma non mi accanirò più di tanto in quanto mi avanza una nand dall'HC00 che ho usato per l'oscillatore a 10MHz, quindi nel caso risolvo via hardware.
A questo punto mi serve solo avere le idee più chiare sullo stand alone. Ho letto un trhead riguardo la creazione di AT con bootloader; avendo un "UNO" ho capito che mi conviene continuare a comprare il chip precaricato, non devo realizzare nulla di industriale; vorrei però capire:
1 - quali componenti (oltre al chip ed al quarzo da 16MHz) devo montare sul mio schedino?
2 - dove posso trovare le connessioni da replicare ed i pin da collegare (alimentazione, uscite 13, 12, 8,...)?
3 - il quarzo dell'AT è solo per il clock del chip o lo stesso chip lo riporta su qualche pin? potrei "dividerlo" ed ottenere direttamente da lì i miei 10MHz, invece di ricorrere ad un circuito aggiuntivo.
Grazie ancora.

Per la versione stand alone ha varie opzioni possibili, la più semplice è usare uno dei tanti pcb/schede commerciali dove trovi già tutto il necessario per far funzionare l'ATmega.
L'alternativa è montare l'ATmega direttamente sulla stessa scheda dove metti gli shift register, ti serve un ATmega 328 già programmato col bootloader, un quarzo da 16 MHz, due condensatori da 22 pf, una resistenza da 10k.
Non puoi usare il quarzo dell'ATmega per ricavare i 10 MHz, anche perché non è semplice ottenere tale frequenza partendo da 16 MHz senza usare un prescaler e un PLL.
Però puoi dare il clock all'ATmega tramite l'oscillatore dei 10 MHz, risulterà il 40% più lento nell'eseguire il programma, e non puoi programmarlo mentre si trova sulla scheda, ma non è certo un problema vista l'applicazione.

Ciao, in commercio ho trovato delle "protopcb" che replicano i contatti dell'Arduino ma non prevedono direttamente l'ATmega, e poi sono troppo piccole per mettere 5-6 IC, come nel mio caso, forse quelle buone sono quelle previste per Arduino Mega, ma credo sia inutile per me; mi pare più facile montare questi 5 componenti sui miei schedini.
Questa idea dell'oscillatore a 10MHz mi piace, almeno per questo progetto a cui stiamo lavorando con te :), non credo che userò sempre oscillatori quarzati, ma non si sa mai; in questo caso dovrei collegare l'uscita dell'oscillatore anche all'ATmega, forse è meglio se la "separo" usando l'altro NAND? (in questo caso però devo assolutamente risolvere l'inversione via software!) o posso applicarla in parallelo al clock degli shift register? In ogni caso uno dei due pin dell'ATmega andrebbe a massa, quale deve essere?
Il fatto che rallenti l'ATmega non mi crea difficoltà, tanto deve solo caricare la sequenza degli shift, quindi qualche istante in più per questa operazione non mi farebbe alcun danno.
Per regolarmi sulle connessioni mi serve uno schema, ho trovato quello della duemilanove, le connessioni sono uguali alla UNO? Mi confermi che devo collegare solo: i due pin dell'oscillazione, Vcc e massa, i 3 pin abilitati per gestire gli shift?
Nel caso invece volessi "caricarlo" sullo schedino stesso mi basta collegare (altre a mettere il clock a 16MHz) anche tx-rx o serve altro.
Se ti sto complecando la vita con tutte queste richieste ignorale tranquillamente, magari facciamo un passo per volta.
A presto.

Hai provato a prendere in considerazione l'uso di un Arduino nano ?
Risolvi tutti i problemi con un minimo impegno di spazio, la schedina è grande quanto un IC a 28 pin con passo 2.54, è dotato del chip USB, quindi facilmente riprogrammabile, lo installi sulla scheda con gli shift register tramite uno zoccolo per IC e puoi usarlo pure come alimentatore tramite USB o tramite una batteria esterna, sopra c'è anche il regolatore a 5V.

Dimenticavo, c'è anche ArduinoMini, ancora più piccolo e meno costoso, per contro non c'è la parte USB.

C'avevo pensato e lo stavo pure ordinando stanotte :blush: ma poi ho visto che costa 50 euro (la versione col 328), cioè l'equivalente di 7 chip precaricati. Certo le funzionalità sono eccezionali e tutto in uno spazio di un chip, ma devo usare solo 3 pin, certamente varrà la pena per qualcosa in cui si usi intensamente l'intera struttura dell'Arduino, che ne pensi?
Invece Arduino mini potrebbe fare al mio caso, 23 euro da Futura, però già cloccato e tutti i pin pronti per la connessione. Se ho ben capito per programmarlo dovrei togliere il chip dal mio UNO e collegare quei 4-5 fili come nelle imagini.
E' una buona idea, ma naturalmente voglio anche sperimentare il solo chip, mi lancio e spero di non fare danni con le connessioni. Se trovi qualche minuto puoi darmi un minimo di chiarimenti sulle domande che ti ho posto prima?
Comunque grazie davvero, mi si sta aprendo un mondo affascinante davanti, questo forum, grazie alla vostra disponibilità, è una fonte inesauribile.
Ciao.

Ma di quanta memoria hai bisogno?
Perché altrimenti ci sono anche gli Attiny2313: lavorano a 10 MHz, hanno 2 kB di Flash, sono DIP20.

astrobeed:
Dimenticavo, c'è anche ArduinoMini, ancora più piccolo e meno costoso, per contro non c'è la parte USB.

Anch' io volevo suggerire un arduino mini o pro mini al posto di mettere un ATmega sulla scheda dei 4094. (astrobeed era piú veloce =( )
Il vantaggio é che si ha un Arduino siccuramente funzionante senza dover preocuparsi della sua costruzione.
Per caricare il programma sul mini o mini pro é necessario un interfaccia USB-seriale TTl oppure un arduino 2009 o UNO dove togli il ATmega.

Consiglio di comprare un oscillatore da 10 Mhz al posto di farlo con uno quarzo e delle porte logiche. È piú sicuro dal punto di vista del funzionamento.

Sappi anche che l'Arduino a 10Mhz avrá i tempi di delay millis() ecc sbagliati.

Ciao Uwe