Salve ho realizzato un frequenzimetro con ARDUINODUE fatto con il seguente codice Libero - Community - I siti personali
L'ho adattato per funzionare con 6 display sette seg. col seguente codice modificato da me.
Ho notato nel codice originale che ci sono degli errori nell' algoritmo riscontrato caricando e mandando in esecuzione il codice.
Ad esempio la riga "if (pulseCount == 1000)" si trova dentro a loop(){} ed invece dovrebbe trovarsi dentro ad una chiamata ogni 1msec altrimenti non si dovrebbe visualizzare la frequenza.
Con la modifica apportata nel mio codice ho constatato che non visualizzo un bel niente.
Per favore aiutatemi.
Vero. Sei sicuro venga chiamata ?
Hai provato a levare un pò di codice e nella chiama a fare solo una semplice serial.print ?
Inoltre, di solito il codice di una routine interrupt dovrebbe essere il più breve possibile. Tu in quella millisec fai conversioni/scritture su pin/etc molto dispendiose.
Comunque il codice a quel primo tuo post, su digilander, perchè dici che non dovrebbe funzionare ? Lo hai provato ? proprio la pulseCount che arriva a 1000 è la base del conteggio
Si ho provato la millisec() solo con la funzione converti().
Nella mia versione c'è solo converti() che visualizza le cifre.
Mi succcede che se metto solo conveverti() con prima la formula di conversione per ottenere la "frequency" ottengo
un countdown da un valore molto alto fino alla frequenza del generatore di funzioni ossia in questo caso 32Hz ed una volta
arrivato a quel valore riparte al valore molto alto per ritornare a fare il coutdown.
Ciò succede solo con pulseCount = 0 ed alert = 0 nella funzione loop(){}.
Inoltre, tutto il codice mi sembra pesante... I pin andrebbero scelti sapientemente, per sfruttare porte intere. In questo modo, ad esempio, con Arduino Uno (328p) ho fatto la conversione a 7 segmenti semplicemente così:
void displ()
{
switch(n) // Anodo comune
// D 76543210
{ // dpGFEDCBA (0: segmento acceso)
case 0: {PORTD|=0b01000000; // Spegne i segmenti a 1
PORTD&=0b11000000;} // Accende i segmenti a 0
break;
case 1: {PORTD|=0b01111001;
PORTD&=0b11111001;}
break;
case 2: {PORTD|=0b00100100;
PORTD&=0b10100100;}
break;
case 3: {PORTD|=0b00110000;
PORTD&=0b10110000;}
break;
case 4: {PORTD|=0b00011001;
PORTD&=0b10011001;}
break;
case 5: {PORTD|=0b00010010;
PORTD&=0b10010010;}
break;
case 6: {PORTD|=0b00000010;
PORTD&=0b10000010;}
break;
case 7: {PORTD|=0b01111000;
PORTD&=0b11111000;}
break;
case 8: {PORTD|=0b00000000;
PORTD&=0b10000000;}
break;
case 9: {PORTD|=0b00010000;
PORTD&=0b10010000;}
break;
}
}
Considera, poi, che i valori che scriviamo vengono già convertiti in binario! Scrivendo, ad esempio, 9 sulla porta D con PORTD&=9+0xF0; PORTD|=9; già hai scritto 9 in binario sui 4 LSB (bit 0, 1, 2, 3).
PORTD&=9+0xF0: moltiplico bit per bit il contenuto della porta D con 11110000 (0xF0: 1111=F e 0000=0) più 9, che è il valore che mi interessa. In questo modo, i bit a 0 del valore 9 andranno a 0, mentre gli altri resteranno invariati.
PORT|=9: sommo bit per bit il contenuto della porta D con il valore 9. In questo modo, i bit a 1 del valore 9 verranno posti a 1.
Datman:
Inoltre, tutto il codice mi sembra pesante... I pin andrebbero scelti sapientemente, per sfruttare porte intere. In questo modo, ad esempio, con Arduino Uno ...
Guarda che su Arduino DUE (SAM) la cosa è piuttosto più complessa e NON così banale come è su MCU AVR !
... ohi, nulla di impossibile eh, ma sicuramente più articolato ...
There are 5 ports, A/B/C/D/E, each 32 bit, mapped to the pins as documented in variant.cpp.
There are several registers for each port that read and write it, and each pin can
be updated atomically so no special interrupt handling is needed:
PIO_PER - write 1's here to override other peripherals and allow GPIO use for pins
PIO_OER - write 1's here to set pins as OUTPUT
PIO_ODR - write 1's here to set pins as INPUT
PIO_SODR - write 1's here to set output pins HIGH
PIO_CODR - write 1's here to set output pins LOW
PIO_PDSR - read's actual state of the pins on the port.
PIO_PUDR - write 1's here to switch off internal pull-up for pins
PIO_PUER - write 1's here to switch on internal pull-up for pins
There are other registers to do with input filtering, interrupts, etc etc,
but these are the main ones.
Altro suggerimento che si trova è:
In fact to ensure the port(s) is enabled its simplest to call pinMode() for each pin you want to directly manipulate, otherwise you have to configure the PIO
controller in more detail which isn't needed once pinMode() has done its thing.
Non c'entra nulla con il problema del OP, ma è sempre bene ricordare che sulla DUE c'è anche il problema della corrente fornibile da ogni singolo pin, che varia per gruppi di pin ... per alcuni gruppi massimo 3mA e per altri massimo 15mA ... valori ben lontani dalle MCU AVR.
QUESTA bella chart in formato A4 aiuta a riconoscere i suddetti pin
Ho aggiunto pure la formula per ottenere la frequenza partendo da t1 e t2 ossia frequenza=1/(t1+t2); poi aggiungo la converti(frequenza); e mi da tutti i display spenti.
Perchè?
Che portata ha questo frequenzimetro?
Ho messo converti frequenza nel loop, e sempre nel loop ho messo il serial.print, funzionicchia, ma da valori sballati di circa un 10%, sbaglio qualcosa?
Grazie
Ecco di seguito il mio sorgente modificato io al posto della funzione per scrivere nella seriale che invia i dati a
monitor ho utilizzato la converti(freq) che invia i dato ad un display 7 seg.
Mi succede che con questo codice visualizzo una serie ci cifre senza significato che lampeggiano ad alta velocita'.
Cosa ho sbagliato?
come prima cosa ti suggerirei di rallentare un pelo la scrittura sui display, la fai ad ogni iterazione del loop.
Anche solo con i 50Hz la faresti 50 volte al secondo che sarebbe velocissimo per avere senso su un display.
poi potresti calcolare una media in un certo lasso di tempo e magari stampare solo quella, diciamo una volta al secondo.
E tenere traccia dei tempi min e max per vedere se all'interno del tempo di campionamento c'è stata una grossa variazione della frequenza. Magari è normale, magari hai captato dei disturbi...