Pages: 1 2 [3] 4 5 6   Go Down
Author Topic: generare una sequenza di bit a frequenza variabile  (Read 5702 times)
0 Members and 1 Guest are viewing this topic.
Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 501
Posts: 12307
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@ astrobed:
sei un pozzo di scienza! mi sono riguardato quest'argomento su un testo di calcolatori, giusto per "fissarlo" con qualche esempio, spieghi meglio tu di Bucci!
@ lesto e leo72:
grazie per la soluzione ed i ragguagli: oggi la provo, riguardo la precisione, non devo realizzare uno strumento di lettura, bensì convertire il periodo in frequenza, in realtà mi basterebbero addirittura i soli interi (11364 (Hz), p.es., se poi ottengo un valore con 3 cifre decimali, e mi dite che sono abbastanza significative, ho fatto molto più di quanto mi serve. Vi ricordo che alla fine devo solo capire con che frequenza "indicativa" si ripete la sequenza che sto generando.
Certo questa disquisizione tornerà utilissima quando sarà necessaria, in altri casi, una lettura precisa, ma un buon frequenzimetro di rado mostra oltre le 5 cifre decimali, quindi hai voglia ad accontentarsi!
Infine mi sono reso conto di un errore a monte: per ottenere la frequenza in Hz devo prima rapportare i µs in s, quindi devo dividere seq_time per 1000000, poiché stiamo parlando di KHz, in realtà mi basta rapportarli a ms, dividendo per 1000. Pensavo quindi di fare:
Serial.println((float)1)/seq_time/1000;
il dubbio che ho: il solo float iniziale mi rende tutta l'espressione in virgola mobile? Inoltre vorrei far uscire tutto sulla stessa riga con l'indicazione della parola "frequenza" e l'unità di misura, penso mi basti "giocare" con , e ;
Proverò oggi e vi faccio sapere come va a finire. Intanto inizio a fare qualche prova con uno shift da 8 bit ed un dip, in attesa dell'uovo di pasqua di uwe smiley
Grazie a tutti.
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9158
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Premesso che l'unico modo semplice per ottenere quello che desideri è usare degli shift register con ingresso seriale e uscita sia seriale che parallela (SIPO shift register) per ottenere un ring shift register della desiderata dimensione, però c'è un punto oscuro da risolvere prima di disegnare lo schema.
La frequenza di 10 MHz è riferita al singolo bit del pacchetto che devi trasmettere oppure è la frequenza di ripetizione di tutto il pacchetto ?
Logged

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 501
Posts: 12307
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

In effetti c'era confusione su questa cosa, poi mi sono chiarito le idee, e da lì è nata la discussione sulla misura della frequenza. I 10MHz riguardano la velocità alla quale devono essere "sparati" i singoli bit in seriale, considerando che sono una trentina (circa, come ho già spiegato) credo che l'intera sequenza si ripeta ogni 300-350KHz, quindi il clock sarà di 10MHz. Poiché carichiamo in seriale ad una velocità decisamente inferiore, bisognerebbe prima caricare lo shift e poi renderlo circolare (serve a questo la sezione parallela?), l'eventuale cambio sequenza per me rappresenta una prova ex novo.
Aspetto aiuti. Grazie.
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

0
Offline Offline
Shannon Member
****
Karma: 129
Posts: 10447
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Serial.println((float)1)/seq_time/1000;
a parte che è sbagliata per via della parentesi del println che si chiude prima delle divisioni (quindi in pratica stampi 1 in float e poi provi a dividere una funzione, credo che il compilatore si incavoli un pò smiley

al solito... se non erro il compilatore, in caso di pari priorità degli operatori, parte da DESTRA.
quindi prima fa seq_time/1000
e poi 1/quelchel'è
come vedi però hai perso precisione per la storia degli interi nella /1000, quindi o usi i cast o fai 1000.0

per evitare mille parentesi e cast inutili (che vengono fatti a runtime, se non erro, facendo perdere qualche ciclo CPU) fai:
Serial.println( 1.0/seq_time/1000.0 );
e vai sicuro
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 501
Posts: 12307
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ho risolto così:
Serial.print("Tempo della sequenza: ");
  Serial.print(seq_time);
  Serial.print("Frequenza (KHz): ");
  Serial.println(1.0/(seq_time/1000.0));
quindi l'operazione viene fatta regolarmente da sx verso dx (se non metto le () alla 2a divisione mi dà 0.
Ma il risultato è con 2 decimali, ne volevo almeno 3, probabilmente non ho capito qualcosa nella discussione precedente.  smiley-confuse
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9158
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I due decimali sono un limite della serial.println, in realtà il numero ha tutti i decimali del caso, per vederne di più  moltiplica il valore per 10-100-1000 e poi fai la serial.println, ovviamente dovrai riposizionare mentalmente la virgola.
Esempio pratico se faccio 7/3 ottengo 2.33 se moltiplico per 1000 la variabile che contiene il risultato ottengo 2333.33

Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9158
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Come non detto, mi sono appena ricordato che basta specificare dopo la virgola il numero dei decimali desiderati, se scrivo Serial.println(a,4) e a contiene 32.12345 mi viene inviato 32.1234.
Logged

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 501
Posts: 12307
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Perfetto, ora funziona bene; speriamo che troviate anche il tempo di aiutarmi col circuito esterno.
Grazie
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9158
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Per il momento prendilo come schema di principio, è una cosa che ho buttato giù al volo, ma dovrebbe andare bene.
Le tre linee in ingresso se lasciate a 1 logico fanno funzionare lo ring shift register come serve a te, portando Enable a 0 logico viene bloccato sia il clock a 10 MHz che il ricircolo dei dati, ogni volta che mandi un impulso negativo sulla linea clock il valore presente su DATA viene trasferito all'interno dello shift register, attenzione che vengono negati quindi o lo prevedi da software oppure aggiungi un inverter.
Fornendo 30 impulsi sul clock carichi completamente lo shift register, è possibile variare la lunghezza del pacchetto modificando l'out per il ricircolo dati.
Gli shift register sono dei 54HC4094 (oppure 74HC4094) da 8 bit l'uno, le porte logiche sono contenute in un singolo 54HC00, l'oscillatore è del tipo quarzato ibrido, ma puoi metterci quello che ti pare.

« Last Edit: March 06, 2011, 10:59:15 am by astrobeed » Logged

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 501
Posts: 12307
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

WOW! alla faccia del "volo"!
Allora alcuni chiarimenti: per caricare lo shift con i miei 30 impulsi da Arduino, visto che devo farne passare uno per volta, mi conviene abilitare un altro pin che porto a 0 prima di ogni bit della sequenza, e che collego all'ENABLE, dopo lo porto a 1, e così via; 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?
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.
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); 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.
Che dici?
Grazie di tutto, mi hai fatto davvero un grande regalo!
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9158
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley
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.
2) Portare CLOCK da 1 a 0
3) Attendere 10us
4) Portare CLOCK da 0 a 1
5) Ripetere dal punto 2 per tante volte quanti sono i bit da caricare.
6) 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.

Quote
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.

Quote
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.

Quote
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.
Logged

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 501
Posts: 12307
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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ì. smiley-eek
Ho provato a tradurre le tue indicazioni
Code:
#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?
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9158
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Meglio così  smiley

Code:
#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.

}
Logged

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 501
Posts: 12307
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Naturalmente....
Grazie di tutto, ormai devo lasciare il mio angolo di pace (ho un piccolo lab fuori casa smiley-grin) e tornare alla cruda realtà (moglie, mutuo, ecc  smiley-cry), 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  smiley-wink
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 501
Posts: 12307
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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  smiley-eek 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 smiley-small 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.
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Pages: 1 2 [3] 4 5 6   Go Up
Jump to: