Un altro post che non so se mettere in HW o in SW... scusate ![]()
Vediamo se ho fatto le cose per bene.
partiamo dal datasheet: http://invensense.com/mems/gyro/itg3200.html
apprendiamo che è un giroscopio 3 assi I2C, al massimo campiona a 8kHz e con filtro passa basso a 256Hz.
Un ADC interno a 16 bit è molto, ma il range della velocità angolare non è regolabile.
Partiamo subito con il codice, che ci permetti di campionare a 188Hz o a 255Hz, inviando i dati via seriale in modo BINARIO (per risparmiare banda sulla seriale e stare nei baudrate più bassi)
notare che è anche implementato un low pass filter digitale
#include <Wire.h> //I2C Arduino Library
#define address 0x68 //0011110b, I2C 7bit address of ITG3200
#define FAST true // true = 8kHz sample rate for 256Hz output, else 1kHz for 188Hz putput
void setup(){
//Initialize Serial and I2C communications
Serial.begin(19200);
delay(1000);
Wire.begin();
Serial.print("START ");
Wire.beginTransmission(address);
Wire.write(0x3E);
Wire.write(0x80); //send a reset to the device
Wire.endTransmission(); //end transmission
//SETTING SAMPLE RATE DIVER
Wire.beginTransmission(address);
Wire.write( 0x15 );
Wire.write( byte(0x00) ); //sample rate divider to 0
Wire.endTransmission(); //end transmission
//SETTING FULL SCALE RANGE AND LOW PASS FILTER
Wire.beginTransmission(address);
Wire.write(0x16);
if (FAST){
Wire.write(0x18); // ±2000 degrees/s 8kHz sample rate for 256Hz output(default value)
}
else{
Wire.write(0x19); // ±2000 degrees/s 1kHz sample rate for 188Hz output(default value)
}
Wire.endTransmission(); //end transmission
while(Serial.available()<10){
delay(1000);
continue;
}
}
int x,y,z, count=0, countX=0, countY=0, countZ=0; //triple axis data
int Filtered_ValueX=0, Filtered_ValueY=0, Filtered_ValueZ=0;
unsigned long SumX =0, SumY=0, SumZ=0;
int filtro = 3;
void loop(){
Wire.beginTransmission(address);
Wire.write(0x1D); //select register 3, X MSB register
Wire.endTransmission();
Wire.requestFrom(address, 6);
while(Wire.available()<6){
continue;//wait for data
}
Serial.flush();
x = Wire.read()<<8; //X msb
x |= Wire.read(); //X lsb
z = Wire.read()<<8; //Z msb
z |= Wire.read(); //Z lsb
y = Wire.read()<<8; //Y msb
y |= Wire.read(); //Y lsb
SumX = SumX - Filtered_ValueX + x;
Filtered_ValueX = (SumX+(1<<(filtro - 1)))>>filtro;
SumY= SumY - Filtered_ValueY + y;
Filtered_ValueY = (SumY+(1<<(filtro - 1)))>>filtro;
SumZ = SumZ - Filtered_ValueZ + z;
Filtered_ValueZ = (SumZ+(1<<(filtro - 1)))>>filtro;
Serial.write(Filtered_ValueX>>8);
Serial.write(Filtered_ValueX);
Serial.write(Filtered_ValueY>>8);
Serial.write(Filtered_ValueY);
Serial.write(Filtered_ValueZ>>8);
Serial.write(Filtered_ValueZ);
if (FAST){
delayMicroseconds(3910);//~250Hz
}
else{
delayMicroseconds(5320);//~188Hz
}
}
passiamo all'analisi dei dati raccolti. prima di tutto il grafico (gnuplot) di x, y, e z da sensore fermo mostra come dallo 0 reale si scenda subito ad un -23 +- 1 circa, dove però rimane stabile (merito del filtro SW, prima leggevo variazioni di +-15)
poi un'alalisi delle frequenze (baudline) del sensore in movimento; mostra un solo asse, sulla destra il suo andamento, e sulla sinista l'analisi delle frequenze.

