Citazione:
Originalmente inviato da Minestrone Ciao ElNonino. Effettivamente ho diversi dubbi, ci sono delle parti del tuo codice che non so decifrare. Però mi sembra di capire che la porzione del codice che mi interessa, ovvero quella della virgola mobile, sia questa (per un canale):
u8PunMMV = (++u8PunMMV & 15);
u16App_ADC = ADCC_GetSingleConversion(channel_Temp); // Temperatura PIC
u32Acc_P_T = u32Acc_P_T - u16Tab_P_T[u8PunMMV] + u16App_ADC;
u16Tab_P_T[u8PunMMV] = u16App_ADC;
u16P_T = u32Acc_P_T >> 4;
Mi sembra uguale alla mia:
sommadegMPU_0-=degMPU_0[i];
degMPU_0[i] = ((atan2(MPU_0_AcY, MPU_0_AcX )) * 180.0) / PI;
sommadegMPU_0+=degMPU_0[i];
i++;
if (i==k) {i=0;}
poi, ogni 500 millisecondi eseguo:
mediadegMPU_0 = sommadegMPU_0 / k
dove k è la dimensione del vettore contenente l'angolo ricavato
in pratica la variabile sommadegMPU_0 contiene la somma di tutti i valori delle letture che concorrono al calcolo della virgola mobile, tali valori sono contenuti nell'array degMPU_0[] e i è l'incremento che mi dice quale elemento del vettore degMPU_0[] devo sostituire. mediadegMPU_0 è la media. |
ci sono alcune differenze fra i due sistemi, la principale è che io uso una variabile u32Acc_P_T che è un accumulatore, cioè contiene ad ogni loop la somma attuale degli n valori compionati ed inseriti nell' array, e quando viene divisa per 16 in u16P_T mi trovo aggiornata ad ogni loop la media reale.
Poi ti spiego alcuni trucchi:
- usare una variabile di appoggio (u16App_ADC) dove memorizzare la lettura del sensore aiuta molto nel debug e velocizza il loop,
- usare "u8PunMMV = (++u8PunMMV & 15)" anzichè "i++; if (i==k) {i=0;}" è più veloce, un & richiede in genere un solo ciclo di clock un if ne usa di più. quando un contatore incrementale ad 8 bit super 255 ritorna a 0 quindi con un & adatto ottieni automaticamente i valori da 0 a n. Chiaramente funziona se la dimensione dell'array è potenza di 2, cosa peraltro assai consigliabile.
- il motivo per cui la tua routine è lenta e sicuramente occupa anche tanta memoria è che usi tutto in floating point e se il micro non ha una FPU ci mette un secolo a fare quei calcoli, inoltre per la velocità sarebbe meglio usare un #def 180 180.0 perchè il compilatore ne è felice...
Se tu lavorassi con interi poi potresti usare un >> per la divisione (sempre se con esponenti di 2) che è enormemente più veloce di un / fra floating.
In ultimo se usi una printf per stampare (o mettere in una stringa) un valore floating un micro ad 8 bit ci passa la notte....
Vedo di riesumare la mia routine per leggere l'elevazione dei pannelli FV completa di tabella di linearizzazione e poi la pubblico, girava su un PIC16F877 .
Nei sistemi embedded è una regola d'oro usare sempre interi e convertirli in floating una sola volta, se possibile.