Accelerometro MMA7361

Buon giorno.

Ho a disposizione Arduino Uno e questo accelerometro analogico: MMA7361

Sto utilizzando una libreria (Wiki) per poterlo far funzionare....vorrei realizzare un codice ad hoc senza passare per la libreria.

Visto che è possibile selezionare la sensibilità vorrei utilizzarlo ad 1.5g. I collegamenti sono realizzati come indicati da Wiki.

Collegamenti

Come posso scrivere lo sketch?

  1. studiando il datasheet e capendo come funziona

  2. studiano la libreria, ed i particolare i due files AcceleroMMA7361.cpp e AcceleroMMA7361.h per vedere ed imparare come l'autore di detta libreria si è interfacciato con l'accelerometro.

Detto tra noi, se quella libreria è scritta bene ... dubito che, facendo tu praticamnete le stesse cose, otterrai un aumento prestazionale visibile ... ::slight_smile:
Quel chip fornisce le accelerazioni in modo analogico ... quindi ... c'è poco da snellire ...

Guglielmo

Il discorso nasce dal fatto che io voglio essere certo che il mio sensore abbia una determinata frequenza di acquisizione.

Mi spiego meglio con un esempio tratto dalla libreria:

#include <AcceleroMMA7361.h>
AcceleroMMA7361 accelero;
int x;

void setup()
{
  Serial.begin(9600);
  
  
  accelero.begin(13, 12, 11, 10, A0, A1, A2);
  accelero.setARefVoltage(5); //sets the AREF voltage to 3.3V
  accelero.setSensitivity(HIGH); //sets the sensitivity to +/-6G
  accelero.calibrate();
}

void loop(){

x = accelero.getXAccel()+36;
  
delay(2); //make it readable 

}

Avendo un delay di 2 millisecondi la frequenza di campionamento dovrebbe essere di 500 Hz! Questo in teoria. E' così?

NI ... :smiley:

... primo nessuno ti garantisce che l'oscillatore della MCU viaggi esattamente a 16MHz e quindi che quei 2 millisecondi siano realmente 2 millisecondi (... anzi, sicuramente NON lo sono)

... secondo trascuri i tempi di esecuzione del programma (tra cui il tempo del ADC) che comunque, per quanto brevi, esistono

... terzo, hai tenuto conto del Bandwidth Response del chip? ... è limitato a 400Hz su X e Y e 300Hz su Z

Guglielmo

Grazie...
...sicuramente dovrò allontanarmi dai 2 millisecondi e quindi andare a campionare con una frequenza più bassa allontanandomi da quella critica.

Ora chiedo sarebbe possibile attraverso un qualsiasi metodo riuscire a risalire alla frequenza di campionamento così da capire "per un determinato sketch" con che frequenza sta campionando? Tenendo conto ovviamente di tutto quello che ci siamo detti circa i ritardi.

Grazie

Se ho capito bene la domanda ... puoi usare la micros() ... leggi il valore ad inizio ciclo, lo rileggi a fine ciclo, fai la differenza ed hai il tempo in microsecondi dal quale ricavi con che frequenza campioni realmente.

Guglielmo

Ci provo:

#include <AcceleroMMA7361.h>
AcceleroMMA7361 accelero;
int x;
int T1;
int T2;
int T;


void setup()
{
  Serial.begin(9600);
  accelero.begin(13, 12, 11, 10, A0, A1, A2);
  accelero.setARefVoltage(5); //sets the AREF voltage to 3.3V
  accelero.setSensitivity(HIGH); //sets the sensitivity to +/-6G
  accelero.calibrate();
 
}

void loop()

{
 
  T1=micros();   //leggo valore a inizio ciclo
  
  x=accelero.getXAccel()+36; //acquisisco il segnale
  delay(100);
  
  T2=micros()   //leggo valore a fine ciclo
  
  T=T2-T1;  // Differenza T2-T1
  
  Serial.println(T);
  
}

Esatto ... in questo modo hai il tempo in μSec della durata del singolo loop.

Guglielmo

P.S.: Non è applicabile qui, ma ricorda sempre che la micros() arriva al massimo a circa 70 minuti :wink:

Per intenderci:

Nel mio caso avendo un delay(100),teoricamente tra un ciclo loop e l'altro successivo dovrei avere un

100000=10^5 microsecondi. Ovviamente non sto considerando i ritardi!

Nella realtà, considerando i ritardi, la variabile T sarà maggiore di 10^5

Giusto?

Si, giusto ... precisione della millis() permettendo :smiley: :smiley: :smiley:

Guglielmo

Quindi anche in questo caso non dovrei avere un risultato veritiero?

Cosa si intende per precisione della millis()

Che millis(1) è CIRCA 1 millisecondo ... in funzione della vera frequenza di oscillazione del quarzo, della deriva termica, della stabilità della tensione di alimentazione, ecc. ecc.

Ti dico solo che con la millis() è impossibile fare un orologio ... hai un errore di decine di minuti nell'arco delle 24 ore ...
... questo ti dice quanto è aleatorio il valore.

Guglielmo

Chiaro....ho realizzato dei test e riporto i risultati:

1)Con delay(100) ho che T=T2-T1= -29200 ------>29,2 millisecondi----->34Hz
2)Con delay(50) ho che T=T2-T1= - 13700--------->13,7 millisecondi----->72Hz
3)Con delay(5) ho che T= T2-T1 = + 6780-------->6,7 millisecondi------148Hz

Da dire che le ultime cifre sono varibili in un certo range

Nei primi due test ho degli intervalli negativi, mentre nel terzo positivo.

Come è possibile che il Delta-Tempo nei primi due casi è più piccolo del delay?

Stranamente nell'ultimo caso sembra un Delta-Tempo ragionevole! Cioè leggermente superiore al delay.

Semplicemente perché ...
... hai sbagliato a dichiarare TUTTE le variabili relative al tempo (... non ci avevo fatto caso prima) ... ::slight_smile:

Quando tratti millis() e micros() devi usare unsigned long (4 bytes) NON int (2 bytes) !!!

Leggere SEMPRE il reference quando si usa una funzione per vedere che parametri vuole e che tipo ritorna !

Guglielmo

Ok in definitiva quindi dovrei avere:

#include <AcceleroMMA7361.h>
AcceleroMMA7361 accelero;
int x;
unsigned long T1;
unsigned long T2;
unsigned long T;


void setup()
{
  Serial.begin(9600);
  accelero.begin(13, 12, 11, 10, A0, A1, A2);
  accelero.setARefVoltage(5); //sets the AREF voltage to 3.3V
  accelero.setSensitivity(HIGH); //sets the sensitivity to +/-6G
  accelero.calibrate();
 
}

void loop()

{
 
  T1=micros();   //leggo valore a inizio ciclo
  
  x=accelero.getXAccel()+36; //acquisisco il segnale
  delay(100);
  
  T2=micros()   //leggo valore a fine ciclo
  
  T=T2-T1;  // Differenza T2-T1
  
  Serial.println(T);
  
}

Si, scusa, ma prima veramente non avevo fatto caso al tipo delle variabili :-[

Guglielmo

P.S.: Hai guardato il sorgente della libreria ? il metodo getXAccel() in realtà effettua la media di N letture (dove N, di default, mi pare valga 10), quindi, tienine conto.

Ah....

Come mai tale scelta? E' per la stabilità del dato fornito?

sossio89:
Come mai tale scelta? E' per la stabilità del dato fornito?

... suppongo, ma ... dovresti chiederlo all'autore della libreria :smiley: :smiley: :smiley:

Guglielmo

Allora credo che quella media sia necessaria in quanto da stabilità al valore letto. Dubito che andando a cambiare o eliminare quel valore di media avrei risultati migliori.

sono riuscito ad avere valori ragionevoli dell'intervallo di durata del loop. Grazie.