![]() |
Arduino e sensori accelerometri Premesso che sono molto, ma molto, nubbio in elettronica, vorrei realizzare un circuito con degli accelerometri. Ho trovato in rete un progettino liberamente scaricabile e molto simile al mio che utilizza due Adafruit MMA8451 facendo largo uso di librerie preconfezionate. Gli MMA8451 però li ho trovati abbastanza costosi. Siccome ho trovato sensori GY 520 con MPU-6050 molto più economici, vorrei chiedervi che differenze ci sono tra gli uni e gli altri e se l'utilizzo, dal punto di vista del codice, cambia molto oppure no. Grazie tante a tutti. |
Citazione:
|
Citazione:
ps. sono queste? https://github.com/jarzebski/Arduino-MPU6050 |
Citazione:
comunque se devi fare un inclinometro di alta performance ti conviene fare la sensor fusion tra accelerometri e gyro. oppure piu semplice puoi sfruttare il sw interno di mpu6050 che fa gia la sensor fusion... certo ti togli il gusto di capirci qualcosa... importante procurarsi la mappa dei registri... la trovi facilmente su internet digitando su google register map mu6050 pdf |
Citazione:
A questo punto metterò in pausa perché questo mese non ho molto tempo ma tra un paio di settimane lo farò.... Intanto comincio a studiare perché non ne so nulla. Se avessi qualche link da cui partire te ne sarei grato. Intanto grazie delle info. Inviato dal mio Mi A1 utilizzando Tapatalk |
Citazione:
da questo link raggiungi una grande quantità di altri link... c'è di tutto e di più .. |
Grazie molte Inviato dal mio Mi A1 utilizzando Tapatalk |
una piccola imbeccata Ormai è quasi una settimana che smanetto con i sensori e l'arduino. Ho letto molto in merito ed ho trovato una infinità di librerie. Purtroppo sono al punto in cui mi sono sturato di informazioni e ho confusione. La lettura dei dati raw e la loro elaborazione non è un problema (ci sono riuscito senza librerie) però mi sembra che i valori siano molto sporchi e molto variabili. Quello che voglio realizzare è un incidenziometro e, calcolando l'angolo rispetto alla verticale sfruttando solo gli accelerometri, trovo che il dato mi varia di parecchi decimi di grado. So che i dati provenienti dagli accelerometri sono rumorosi di natura e pertanto ho capito che devo filtrare i dati e combinarli con l'angolo ottenuto integrando i valori dei giroscopi. Qui mi sto trovando in difficoltà. Qualcuno sa darmi un'imbeccata su come applicare un filtro Kalman o, ancora meglio, complementare e come combinare i dati dei giroscopi con quelli degli accelerometri per ottenere dei dati che mi permettano di arrivare a capire l'angolo rispetto alla verticale? Ho capito che questi calcoli li potrebbe fare il DMP integrato nella scheda ma non ho trovato alcuna informazione su come usarlo. |
Citazione:
qui trovi comi utilizzare dmp https://maker.pro/arduino/tutorial/h...pu-6050-sensor |
Non conosco direttamente la MPU in oggetto però per lavoro ho utilizzato accelerometri per leggere un'inclinazione sul piano, alcuni analogici altri con uscita digitale e DSP interni. Per misurare un'inclinazione in regime statico come è la lettura dell'incidenza di ali, piani di coda o pale di elicottero basta un accelerometro, il giroscopio è inutile, il problema degli accelerometri analogici è che l'uscita non era lineare rispetto all'angolo d'inclinazione ma bensì ha un andamento sinusoidale che va compensato tramite algoritmi di fusione dei dati di almeno due assi e poi ulteriormente linearizzato con una tabella appositamente creata. Uso un solo accelerometro analogico da oltre 10 anni per leggere l'inclinazione verticale dei pannelli FV installati in baita sul mio sistema di inseguimento solare senza alcun problema, utilizzo solo gli assi X ed Y in quanto l'asse Z è sempre parallelo al suolo e la velocità di rotazione è estremamente bassa quindi non ho necessità di effettuare ulteriori compensazioni. Indipendentemente dal tipo di sensore usato è comunque necessario filtrare molto bene il segnale, sia attraverso reti RC passa basso + algoritmi digitali nel caso di analogico che filtri digitali + DSP in quelli puramente digitali, mi ricordo di aver disquisito di ciò sul Barone in un'altra discussione (forse in elicotteri o multirotori) Comunque una soluzione semplicissima (ma non di soddisfazione) per realizzare un incidenziometro è quella di acquistare un inclinometro digitale e fissarlo su opportuni supporti, cosa che ho fatto io per le pale dei miei elicootteri RC. Se servono info a disposizione. :yeah: |
Grazie a tutti delle preziose informazioni. Sto sbattendo la testa per la prima volta con questi sensori e sto cercando a fatica di capire. Oramai ho capito come lavorare sul registro dell'integrato e mi sento già un passo avanti. Purtroppo non riesco più a stare alzato fino a tardi come qualche anno fa e la mia attività modellistica ne sta risentendo. Ora sto rifinendo il mio sketch che, al momento, fa uso di due soli assi dell'accelerometro. Devo inserire la calibrazione e registrare il valore nel registro dell'integrato. Per adesso non sto usando né DMP né librerie. Per quanto riguarda il giroscopio, da quello che ho capito e da quello che sto osservando nelle mie prove, il problema è che l'accelerometro è molto rumoroso e il filtro complementare (o altri) mixano i valori del gyro e dell'accelerometro per ottenere un dato pulito. Devo ancora implementare la lettura e la determinazione dell'angolo con il gyro, fatto quello potrò scoprire se il filtro funziona. Per adesso ho detto valori molto sporchi e variabili. Ho provato ad applicare un filtro passa basso con la libreria filter senza ottenerne nulla, probabilmente la frequenza di campionamento dell'integrato è troppo bassa. Sto facendo la media delle letture con calcolo della media ogni mezzo secondo ma i risultati sono ancora sporchissimi. Inviato dal mio Mi A1 utilizzando Tapatalk |
Citazione:
la sensor fusion con il gyro serve per migliorare la risposta in frequenza... se la misura è lenta allora la soluzione diventa banale e basta filtrare potentemente con filtro IIR le componeti del vettore accelerazione |
Citazione:
:yeah: |
Citazione:
Comunque stasera ho fatto diverse prove. Il filtro passabasso non mi ha portato a nessun miglioramento significativo, ho provato diverse frequenze ma il risultato non cambiava molto; forse ho sbagliato qualcosa. Facendo la media aritmetica dei campionamenti raccolti in un mezzo secondo il risultato si stabilizza molto anche se ci sono ancora oscillazioni alla seconda cifra decimale (se riuscissi ad avere una buona pulizia alla prima cifra decimale sarei parecchio contento). Avevo scelto di fare una media del genere perchè ho pensato di fare il refresh del display ogni mezzo secondo. Facendo una media in virgola mobile naturalmente il risultato migliora perchè perde gli scalini e gli sbalzi di una media aggiornata ogni 500millisecondi, però per poter ottenere un risultato decente ho usato degli array con 64 valori. Dovendo calcolare la media mobile su 3 array con 64 valori credo proprio che non potrò usare un algoritmo grezzo, altrimenti occupo il processore con il solo calcolo della media. |
Citazione:
Bah... Alla notte dovrei dormire, non calcolare le medie.. Inviato dal mio Mi A1 utilizzando Tapatalk |
Ho dato un'occhiata al datasheet della MCU e mi pare che non abbia un filtro passa basso sull'accelerometro ma solo sul giroscopio, quindi necessita sicuramente filtrare il segnale nel microprocessore anche perchè questa MCU è indicata per giocattoli od applicazioni in cui non è richiesta molta precisione. Quando fai le prove controlla che la MCU non abbia vibrazioni, sia ben fissata ed usa i canali X ed Y non lo Z; poi controlla con un break point quali sono i valori nei due array per vedere se ci sono picchi od anomalie. La media mobile comporta solo pochissimi calcoli, in pratica una sottrazione, una somma ed un right shift quindi può essere chiamata spesso senza appesantire la CPU, un buon filtraggio lo puoi anche ottenere usando due medie mobili in cascata, comunque scordati di ottenere l'accuratezza di 1/100 di grado e sopratutto che con quella MCU sia affidabile nel tempo. Verifica anche che non ci siano perdite di dati nella comunicazione I2C o SPI. :yeah: |
Citazione:
Nelle prove che ho fatto non c'era NESSUNA differenza tra i valori filtrati e quelli non filtrati. Che frequenza di filtro mi consigli? Per la precisione credo che un decimo di grado sia più che sufficiente, per l'affidabilità metterò un algoritmo di calibrazione da richiamare ogni tanto. Se poi funziona bene posso anche pensare di trasformare il tutto per un sensore più preciso. Stasera devo mettere mano al minikosmo, che è più importante, domani vedo di andare avanti. Intanto grazie dell'interessamento. Inviato dal mio Mi A1 utilizzando Tapatalk |
Sto andando avanti con il mio progettino ma ho un problemino con la gestione della media in virgola mobile. In pratica il risultato della media impiega parecchi secondi a stabilizzarsi ad ogni movimento del sensore. Non capisco perchè, sarà sicuramente una stupidata ma io non la vedo. Se posso approfitto della vostra competenza e vi allego il codice del loop per cercare di capire cosa non va. Considerate che la maggior parte del codice risiede nel void setup, compresa la parte della calibrazione che comprende la maggioranza delle righe di codice, ma non credo che quella interessi. Vi posto il codice note: tempodiciclo è impostato a 500millisecondi ( const int tempodiciclo=500; ) k è la dimensione dell'array per il calcolo della virgola mobile e vale 64 ( const int k=64; ) void loop(){ letturaMPU_0(); //funzione che riceve dati dal sensore MPU_0 e li memorizza nelle variabili // MPU_0_AcX, MPU_0_AcY e MPU_0_GyZ (i primi due sono accelerazioni, //l'ultimo e un dato di gyroscopio.) sommadegMPU_0-=degMPU_0[i]; degMPU_0[i] = ((atan2(MPU_0_AcY, MPU_0_AcX )) * 180.0) / PI; //calcolo tramite accelerometro sommadegMPU_0+=degMPU_0[i]; i++; if (i==k) {i=0;} tempodiciclo = millis()-startMillis; startMillis = millis(); //reset timer ciclorefresh+=tempodiciclo; deggyroMPU_0=deggyroMPU_0+(((MPU_0_GyZ/131)*tempodiciclo)/1000);//calcolo tramite gyro if(ciclorefresh >= lcdRefreshRate){ mediadegMPU_0 = sommadegMPU_0 / k ; ciclorefresh=0; } //fine if #ifdef debug {stampadebug(); #endif} //se il debug è acceso chiama la funzione per la stampa seriale dei valori } Ovviamente il valore dell'angolo calcolato tramite accelerometro cambia ogni 500 millisecondi sullo schermo del pc perchè così è impostato, però ad ogni movimento il valore impiega 4 o 5 secondi a raggiungere il valore reale. il tempo di ciclo lo stampo a video per vedere quanto vale ed è attorno agli 83 millisecondi. Ho scoperto che il tempo di ciclo varia in funzione di come modifico la funzione stampadebug() , evidentemente la stampa a video di valori e stringhe tramite Serial.print() richiede molto tempo. Stampando un pochino di valori per avere un'idea di come varino le variabili sono arrivato ad avere tempi di ciclo sui 250ms. |
Citazione:
:yeah: |
Citazione:
Inviato dal mio Mi A1 utilizzando Tapatalk |
Prima del listato devo anticiparti che io da tempo uso un semplicissimo RTOS che a dire il vero è uno schedulatore a bassissima latenza, cioè ogni funzione viene eseguita ad intervalli regolari di x tempo, questo perchè in genere ho bisogno di precisione nel timing di misure od altro, anche eventuali routine di interrupt non creano problemi perchè vengono eseguite sempre in tempi ridottissimi. Il codice è in ANSI C e molto portatile, purtroppo uso pochissimo Arduino quindi quello che segue è per ARM o PIC. Codice: // Loop RTOS 12,5ms task, 100ms loop:yeah: |
Dimenticavo, la media mobile che ho lincato include un ritardo di 10ms fra i vari canali perchè era per un applicazione assai lenta, togliendo i ritardi viene eseguita tutta in pochi ms (5ms per tutti i canali) con un PICF18..... con clock a 48MHz. Con un STM32F030... sempre a 48MHZ una media mobile su 8 campionamenti di un Array a 16 biti di dimensioni 2x8 impiega 2ms. :yeah: |
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. |
Citazione:
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. :yeah: |
Citazione:
|
Ok, penso di aver capito anche l'uso che fai di &. Veramente interessante Inviato dal mio Mi A1 utilizzando Tapatalk |
Allora per il punto #def k 180.0 è perchè in genere una costante (k) il compilatore la alloca in memoria statica e quando viene utilizzata viene richiamata in un solo ciclo, invece usare 180.0 obbliga il compilatore ad usare più cicli. Per le operazioni binarie devi sapere che un x >>1 equivale a dividere per 2 il valore di x ed un x <<2 equivale a moltiplicare per due, ora nella maggior parte dei compilatori questa operazione comporta un solo ciclo di clock, una / molti di più. Il tuo tempo di stabilizzazione può essere corretto, nel senso che se hai un ciclo di 80ms ed un array di 64 valori 0,08s x 64 = 5,12s contando che per avere un valore stabile all'accensione servono almeno due serie di campionamenti completi siamo sui 10,24s, decisamente lento. Io direi che se usi un array di 2 x 16 valori in cui inserisci le letture di X ed Y dell'accelerometro e calcoli l'angolo una sola volta a ciclo usando la media dei due canali velocizzi di molto il tempo di ciclo. Poi per il printf di float ci sono trucchetti semplici che lo velocizzano molto. Se hai un oscilloscopio, anche economicissimo, ti consiglierei di utilizzarlo per misurare con precisione il tempo impiegato da operazioni, funzioni, routine o loop: imposti un pin digitale come output e ti crei due macro in define che settino o resettino il pin e le chiami TEST_ON e TEST_OFF poi TEST_ON ...... ..... ..... TEST_OFF e sull'oscilloscopio vedrai esattamente la durata delle operazioni comprese far ON ed OFF, è un sistema che ho sempre usato in fase di scrittura e test di programmi time critical per microprocessori embedded. :yeah: |
Farò tesoro dei consigli. Per quanto riguarda la misura del tempo di ciclo un oscilloscopio rudimentale ce l'ho, però ho sempre fatto misurare il tempo di ciclo tramite la funzione millis() e facendo stampare a video il risultato; certamente il tempo di ciclo è sovrastimato, però credo che con buona approssimazione possa andare, o no? Inviato dal mio Mi A1 utilizzando Tapatalk |
Io non fido troppo delle misure sui tempi d'esecuzione ottenute dallo stesso micro su cui gira il programma, preferisco andare alla vecchia con l'oscilloscopio, l'unico errore introdotto dallo strumento è quello del tempo di salita e discesa dei fronti dell'impulso che in genere è di pochissimi ns. :yeah: |
Citazione:
Inviato dal mio Mi A1 utilizzando Tapatalk |
| Tutti gli orari sono GMT +2. Adesso sono le 09:21. |
Basato su: vBulletin versione 3.8.11
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
E' vietata la riproduzione, anche solo in parte, di contenuti e grafica. Copyright 1998/2019 - K-Bits P.I. 09395831002