Torna indietro   BaroneRosso.it - Forum Modellismo > Elettronica > Circuiti Elettronici


Rispondi
 
Strumenti discussione Visualizzazione
Vecchio 16 novembre 18, 12:42   #1 (permalink)  Top
User
 
L'avatar di ElNonino
 
Data registr.: 06-05-2007
Residenza: Tre Ville (Preore)
Messaggi: 3.604
Invia un messaggio via MSN a ElNonino
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.

__________________
Peace & Love
Fate le cose nel modo più semplice possibile, ma senza semplificare. (A. Einstein)
ElNonino non è collegato   Rispondi citando
Vecchio 16 novembre 18, 13:35   #2 (permalink)  Top
User
 
L'avatar di Minestrone
 
Data registr.: 13-09-2012
Messaggi: 4.690
Citazione:
Originalmente inviato da ElNonino Visualizza messaggio
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.

Mah , proverò a fare delle altre prove avvitando il sensore al tavolo ed alzando la frequenza di campionamento dell'integrato (mi sembra di ricordare che ci sia un valore di registro per impostare la frequenza).
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
Minestrone non è collegato   Rispondi citando
Vecchio 29 novembre 18, 11:17   #3 (permalink)  Top
User
 
L'avatar di Minestrone
 
Data registr.: 13-09-2012
Messaggi: 4.690
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.
Minestrone non è collegato   Rispondi citando
Vecchio 29 novembre 18, 17:46   #4 (permalink)  Top
User
 
L'avatar di ElNonino
 
Data registr.: 06-05-2007
Residenza: Tre Ville (Preore)
Messaggi: 3.604
Invia un messaggio via MSN a ElNonino
Citazione:
Originalmente inviato da Minestrone Visualizza messaggio
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.
Stasera ti metto un pezzo di codice di come realizzo io i campionamenti e la media mobile.

__________________
Peace & Love
Fate le cose nel modo più semplice possibile, ma senza semplificare. (A. Einstein)
ElNonino non è collegato   Rispondi citando
Vecchio 29 novembre 18, 17:55   #5 (permalink)  Top
User
 
L'avatar di Minestrone
 
Data registr.: 13-09-2012
Messaggi: 4.690
Citazione:
Originalmente inviato da ElNonino Visualizza messaggio
Stasera ti metto un pezzo di codice di come realizzo io i campionamenti e la media mobile.

Molto gentile. Grazie.

Inviato dal mio Mi A1 utilizzando Tapatalk
Minestrone non è collegato   Rispondi citando
Vecchio 29 novembre 18, 22:01   #6 (permalink)  Top
User
 
L'avatar di ElNonino
 
Data registr.: 06-05-2007
Residenza: Tre Ville (Preore)
Messaggi: 3.604
Invia un messaggio via MSN a ElNonino
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
  while (1)
  {
  	switch(u8Tic & 7)
  	{
  		case 0:	//TASK 0
  						break;

  		case 1: //TASK 1
  						break;

  		case 2:	//TASK 2
  						break;

  		case 3:	//TASK 3
  						break;

  		case 4: //TASK 4
  						break;

  		case 5:	//TASK 5
  						break;

  		case 6: //TASK 6
  						break;

  		case 7: //TASK 7
  						break;
  	}
  	++u8Tic;
   	WaitMain();
	}

/*******************************************************************************|
| Function Name  : WaitMain                                                     |
| Description    : Routine di ritardo 12,5ms per RTOS.                          |
| Input          : None                                                         |
| Output         : None                                                         |
| Return         : None                                                         |
|*******************************************************************************/
void WaitMain(void)
{
  while(__HAL_TIM_GET_FLAG(&htim6,TIM_FLAG_UPDATE) == RESET);
  __HAL_TIM_CLEAR_FLAG(&htim6, TIM_FLAG_UPDATE);
}
/*-----------------------------------------------------------------------------*/

/******************************************************************************|
| Function Name  : Read_Voltage		                                       |
| Description    : Routine lettura tensioni alimentazione e temperatura PIC.   |
| Input          : None                                                        |
| Output         : None                                                        |
| Return         : None                                                        |
|******************************************************************************/      
void(Read_Voltage)(void)
{
  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;
  __delay_ms(10);
  
  u16App_ADC  = ADCC_GetSingleConversion(P_12V);          // Tensione 12V 
  u32Acc_12V = u32Acc_12V - u16Tab_12V[u8PunMMV] + u16App_ADC;
  u16Tab_12V[u8PunMMV] = u16App_ADC;
  u16P_12V = u32Acc_12V >> 4;
  __delay_ms(10);
  
  u16App_ADC =   ADCC_GetSingleConversion(P_5V);           // Tensione 5V
  u32Acc_5V = u32Acc_5V - u16Tab_5V[u8PunMMV] + u16App_ADC;
  u16Tab_5V[u8PunMMV] = u16App_ADC;
  u16P_5V = u32Acc_5V >> 4;
  __delay_ms(10);
  
  u16App_ADC =   ADCC_GetSingleConversion(P_3V);           // Tensione 3V
  u32Acc_3V = u32Acc_3V - u16Tab_3V[u8PunMMV] + u16App_ADC;
  u16Tab_3V[u8PunMMV] = u16App_ADC;
  u16P_3V = u32Acc_3V >> 4;
}
/*-----------------------------------------------------------------------------*/
Se hai dubbi chiedi pure.

__________________
Peace & Love
Fate le cose nel modo più semplice possibile, ma senza semplificare. (A. Einstein)

Ultima modifica di ElNonino : 29 novembre 18 alle ore 22:06
ElNonino non è collegato   Rispondi citando
Vecchio 29 novembre 18, 22:12   #7 (permalink)  Top
User
 
L'avatar di ElNonino
 
Data registr.: 06-05-2007
Residenza: Tre Ville (Preore)
Messaggi: 3.604
Invia un messaggio via MSN a ElNonino
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.

__________________
Peace & Love
Fate le cose nel modo più semplice possibile, ma senza semplificare. (A. Einstein)
ElNonino non è collegato   Rispondi citando
Rispondi

Bookmarks




Regole di scrittura
Non puoi creare nuove discussioni
Non puoi rispondere alle discussioni
Non puoi inserire allegati
Non puoi modificare i tuoi messaggi

BB code è Attivato
Le faccine sono Attivato
Il codice [IMG] è Attivato
Il codice HTML è Disattivato
Trackbacks è Disattivato
Pingbacks è Disattivato
Refbacks è Disattivato


Discussioni simili
Discussione Autore discussione Forum Commenti Ultimo Messaggio
Radiocomando 3 motori DC e 2 sensori di T con Arduino su trenino spraity Radiocomandi 3 09 febbraio 17 15:07



Tutti gli orari sono GMT +2. Adesso sono le 21:55.


Basato su: vBulletin versione 3.8.11
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
E' vietata la riproduzione, anche solo in parte, di contenuti e grafica. Copyright 1998/2026
www.baronerosso.it - www.toymagazine.it