Se vuoi moltiplicare a virgola fissa, e hai a disposizione al massimo interi a 32 bit (uint32_t), e la frequenza massima che vuoi ottenere è di 50 MHz (50.000.000 Hz)... non puoi moltiplicarla per numeri maggiori di 85, altrimenti hai un overflow (il risultato supererebbe ).
Quindi non puoi moltiplicare 50.000.000 per 1527 e poi dividere per 64.
Però, se ti basta una granularità di regolazione di 100 Hz, puoi moltiplicare 500.000 per 1527, dividere per 64 e moltiplicare per 100, o più in generale:
Però la frazione si discosta da per 65 parti per milione.
Una frazione che la approssima a meno di 0,1 parti per milione è :
La routine della divisione intera (al posto dello shift a destra di 6 bit) non è poi così terribile. Si può anche eseguire. La precisione ottenibile è circa pari a quella dei float (a 32 bit), che hanno 7 cifre significative.
L'operazione dovrebbe risultare più veloce, e il programma più snello al non includere le routine di calcolo dei float.
Volendo arrotondare il risultato della divisione all'intero più vicino, anziché troncarlo, raddoppiamo numeratore e denominatore (riusciamo ancora a stare dentro i 32 bit), e aggiungiamo 1 al numeratore:
Magari potresti provare a fare una simulazione esaustiva su PC su tutte le frequenze da 100 Hz a 50 MHz, a passi da 100 Hz, e vedere che differenze ti danno il calcolo con i double, i float e quello con la frazione. Probabilmente sotto i 10 MHz i calcoli coincidono sempre. Bisogna anche vedere che precisione serve. Se andiamo oltre la precisione del quarzo che ti genera il clock, dovrebbe bastare.
Non ci sono i double nel compilatore che usi? O gli interi a 64 bit?
C'è un altro modo per fare le moltiplicazioni, spezzando moltiplicando e moltiplicatore in "parte alta" e "parte bassa" ed eseguendo quattro moltiplicazioni e tre somme:
Mi pare che così si riesca ad avere il prodotto su un numero doppio di bit (64 anziché 32 per esempio), ma non ricordo bene il procedimento.
AVR 8 bit: unsigned integer e FPU SW emulation
Moderatore: Paolino
48 messaggi
• Pagina 3 di 5 • 1, 2, 3, 4, 5
3
voti
Big fan of ⋮ƎlectroYou! Ausili per disabili e anziani su ⋮ƎlectroYou
Caratteri utili: À È É Ì Ò Ó Ù α β γ δ ε η θ λ μ π ρ σ τ φ ω Ω º ª ² ³ √ ∛ ∜ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ∃ ∄ ∆ ∈ ∉ ± ∓ ∾ ≃ ≈ ≠ ≤ ≥
Caratteri utili: À È É Ì Ò Ó Ù α β γ δ ε η θ λ μ π ρ σ τ φ ω Ω º ª ² ³ √ ∛ ∜ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ∃ ∄ ∆ ∈ ∉ ± ∓ ∾ ≃ ≈ ≠ ≤ ≥
1
voti
gvee ha scritto:
Il datasheet dice che è in MHz,
No, se esprimi fck in MHz ottieni fout in MHz, se lo esprimi in Hz ottieni four in Hz....
gvee ha scritto: ma facendo due calcoli con l'esempio di pag. 14 i conti non tornano. Secondo questo esempio, la FTW è:
FTW = 0x0e38e38e = 238609294 da cui = 10e6 (Hz) e non 10 (MHz), quindi nella formula è unsigned int.
Dal conto con quella Tuning Word è corretto 180*238609294/2^23=9,99999...
Ma con che risoluzione devi generare le frequenze?
1
voti
La notte porta consiglio, e mi sono reso conto che moltiplicare e dividere per 100, per frequenze basse introduce un errore ben più alto di 0,1 ppm.
Anche l'arrotondamento, richiedendo di dividere per un denominatore doppio, fa perdere un bit di risoluzione, quindi tanto vale evitarlo e tenersi quel bit di risoluzione in più.
Quindi riformulo la proposta così: fino alla frequenza di 1.192.053 Hz utilizzare la formula
Per più grandi, dividere per 2 (shift a destra) tante volte quante sono necessarie per rientrare nel limite di 1.192.053 Hz, effettuare il calcolo e poi moltiplicare (shift a sinistra) per lo stesso numero di volte.
Anche l'arrotondamento, richiedendo di dividere per un denominatore doppio, fa perdere un bit di risoluzione, quindi tanto vale evitarlo e tenersi quel bit di risoluzione in più.
Quindi riformulo la proposta così: fino alla frequenza di 1.192.053 Hz utilizzare la formula
Per più grandi, dividere per 2 (shift a destra) tante volte quante sono necessarie per rientrare nel limite di 1.192.053 Hz, effettuare il calcolo e poi moltiplicare (shift a sinistra) per lo stesso numero di volte.
Big fan of ⋮ƎlectroYou! Ausili per disabili e anziani su ⋮ƎlectroYou
Caratteri utili: À È É Ì Ò Ó Ù α β γ δ ε η θ λ μ π ρ σ τ φ ω Ω º ª ² ³ √ ∛ ∜ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ∃ ∄ ∆ ∈ ∉ ± ∓ ∾ ≃ ≈ ≠ ≤ ≥
Caratteri utili: À È É Ì Ò Ó Ù α β γ δ ε η θ λ μ π ρ σ τ φ ω Ω º ª ² ³ √ ∛ ∜ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ∃ ∄ ∆ ∈ ∉ ± ∓ ∾ ≃ ≈ ≠ ≤ ≥
0
voti
Ciao Guido,
No, ma teoricamente potrei prima dividere per 64 e poi moltiplicare per 1527 perché i risultati ci stanno in 32 bits.
Avevo intenzione di valutare oggi gli errori su tutto il range. Più tardi mi leggo il post con calma, intanto ti ringrazio.
Ops ! Avevo letto di fretta ! Quindi è una moltiplicazione tra float.
Avrei dovuto scrivere a destra.
GuidoB ha scritto:Quindi non puoi moltiplicare 50.000.000 per 1527 e poi dividere per 64.
No, ma teoricamente potrei prima dividere per 64 e poi moltiplicare per 1527 perché i risultati ci stanno in 32 bits.
Avevo intenzione di valutare oggi gli errori su tutto il range. Più tardi mi leggo il post con calma, intanto ti ringrazio.
GioArca67 ha scritto:No, se esprimi fck in MHz ottieni fout in MHz
Analog Devices ha scritto:System Clock = direct input reference clock (in MHz)
Ops ! Avevo letto di fretta ! Quindi è una moltiplicazione tra float.
gvee ha scritto:Avete ragione sul fatto di fare uno shift a sinistra, (...)
Avrei dovuto scrivere a destra.
0
voti
Ma insomma 'sti float si possono usare o no?
Se sì usiamoli, se no quello che ho scritto in [13] non mi pare tanto sballato (né tanto diverso da quanto letto).
Se sì usiamoli, se no quello che ho scritto in [13] non mi pare tanto sballato (né tanto diverso da quanto letto).
0
voti
EcoTan ha scritto:Ma insomma 'sti float si possono usare o no?
Secondo quanto detto da xyz direi di sì.
EcoTan ha scritto:Se sì usiamoli, se no quello che ho scritto in [13] non mi pare tanto sballato (né tanto diverso da quanto letto).
Ma quella non è la rappresentazione binaria secondo l'IEEE 754.
Comunque appena avró tempo farò qualche prova con un Arduino e avr-libc.
0
voti
gvee ha scritto:Ma quella non è la rappresentazione binaria secondo l'IEEE 754
non è float ma è pur sempre binaria, potrei chiamarla Integer se non fosse per la presenza della virgola.
0
voti
Per tenere conto della precisione totale dell' AD9851 0,04Hz circa (180MHz/2^32) un float non è sufficiente.
Ad es se in un float immagazzina fout maggiore di 33554432Hz non riesce ad avere una granularità migliore di 4 Hz, infatti il numero immediatamente successivo è 33554436 (che ottiene aggiungendo 1 ad una mantissa di tutti 0).
Ma se lavora con GCC per avr ha comunque i double.
Non ho forse ben capito il problema.
Ci sono vincoli di velocità nel calcolo? Occorre cioè velocità fra una impostazione e la successiva?
Ma comunque l'invio al DDS è limitato in velocità, servono almeno 18 cicli di SYSCLK, che a 180MHz sono circa 140 ns, 6 volte di più con CLK a 30MHz.
Ma cosa devo fare?
comunque il coefficiente non è 23,86, ma 23,8609294.
Occorre capire che risoluzione serva fra una frequenza e la successiva
Ad es se in un float immagazzina fout maggiore di 33554432Hz non riesce ad avere una granularità migliore di 4 Hz, infatti il numero immediatamente successivo è 33554436 (che ottiene aggiungendo 1 ad una mantissa di tutti 0).
Ma se lavora con GCC per avr ha comunque i double.
Non ho forse ben capito il problema.
Ci sono vincoli di velocità nel calcolo? Occorre cioè velocità fra una impostazione e la successiva?
Ma comunque l'invio al DDS è limitato in velocità, servono almeno 18 cicli di SYSCLK, che a 180MHz sono circa 140 ns, 6 volte di più con CLK a 30MHz.
Ma cosa devo fare?
comunque il coefficiente non è 23,86, ma 23,8609294.
Occorre capire che risoluzione serva fra una frequenza e la successiva
0
voti
La questione principale era se usando dati a virgola mobile (float o double, usando ovviamente le librerie avr-libc ed avr-gcc) ci fossero stati possibili problemi di risultati, p.e. valori completamente sbagliati etc..
Sì, era per arrotondare, ho già tenuto conto di questi errori di arrotondamento.
A parte le questioni teoriche che non fanno male ovviamente, i risultati finali, che si voglia o no, si vedono con una implementazione pratica di come avr-gcc con le avr-libc emula il floating point, singola precisione o doppia. Al momento non lo so con certezza, solo posso fare affidamento su quanto detto da xyz in [18].
Per questo farò qualche prova con un piccolo FW apposta usando Arduino, parcheggiato nel cassetto anche lui da qualche anno. La velocità di esecuzione/configurazione non è un problema, se poi vedo che divento vecchio durante i tempi di risposta allora ci ripenserò.
Ovviamente quanta più risoluzione riesca ad ottenere meglio è. Il circuito mi servirà per il mio laboratorio personale, tanto per uso professionale dove vada bene (in caso contrario ci sono gli strumenti professionali del laboratorio in azienda), como per uso hobbystico. Per il momento mi accontento un po' del meglio che riesco ad ottenere, altrimenti lo strumento lo compro e faccio prima.
GioArca67 ha scritto:comunque il coefficiente non è 23,86, ma 23,8609294
Sì, era per arrotondare, ho già tenuto conto di questi errori di arrotondamento.
A parte le questioni teoriche che non fanno male ovviamente, i risultati finali, che si voglia o no, si vedono con una implementazione pratica di come avr-gcc con le avr-libc emula il floating point, singola precisione o doppia. Al momento non lo so con certezza, solo posso fare affidamento su quanto detto da xyz in [18].
Per questo farò qualche prova con un piccolo FW apposta usando Arduino, parcheggiato nel cassetto anche lui da qualche anno. La velocità di esecuzione/configurazione non è un problema, se poi vedo che divento vecchio durante i tempi di risposta allora ci ripenserò.
Ovviamente quanta più risoluzione riesca ad ottenere meglio è. Il circuito mi servirà per il mio laboratorio personale, tanto per uso professionale dove vada bene (in caso contrario ci sono gli strumenti professionali del laboratorio in azienda), como per uso hobbystico. Per il momento mi accontento un po' del meglio che riesco ad ottenere, altrimenti lo strumento lo compro e faccio prima.
48 messaggi
• Pagina 3 di 5 • 1, 2, 3, 4, 5
Torna a Firmware e programmazione
Chi c’è in linea
Visitano il forum: Nessuno e 3 ospiti