Arduino - Een 3 assige versnellingsmeter (ADXL345)

From SPAD-it Wiki
Jump to: navigation, search

De ADXL345 (of GY-291) is een chip die versnellingen kan meten in drie richtingen. Zoals gezegd meet de chip versnellingen, of meer precies: veranderingen van snelheid. De versnelling wordt uitgedrukt als de verandering van snelheid per seconde. Omdat snelheid wordt uitgedrukt als meter per seconde (m/s) wordt versnelling uitgedrukt als m/s2.

Het principe van deze metingen is dat binnen in de chip kleine mechanische onderdeeltjes zitten waarvan de beweging elektronisch wordt waargenomen. Bij een versnellingsmeting gaat het dan bijvoorbeeld om een gewichtje dat verend is opgehangen. De belasting van de veertjes wordt gemeten. De chip is daarmee een electro-mechanisch element. Dit soort elementen worden aangeduidt als MEMS - Micro-ElektroMechanisch Systeem. Als de chip versnelt, bewegen de verend opgehangen gewichtjes trager mee en zakken dus iets meer door in hun vering. Ook de zwaartekracht zelf heeft dit effect, zodat ook de zwaartekracht wordt gemeten als versnelling. Dit is niet zo vreemd omdat de zwaaartekracht door natuurkundigen ook wel de valversnelling wordt genoemd. De zwaartekracht zorgt voor een valversnelling van 9,8 m/s2.

Naast het meten van versnellingen in alle drie de richtingen, heeft de chip een aparte detector om vrije val te detecteren (wegvallen van de zwaartekracht - in feite alle krachten). Er zijn ook detectoren voor het meten van een klik en een dubbel-klik (zoals van een muis). Daarmee kun je bijvoorbeeld een auto laten starten en stoppen door er een keer op te tikken. Lichten kunnen dan aan en uit gaan door een korte dubbele tik.

De chip is zeer zuinig met energie (2,5V, 40μA). Zijn meetnauwkeurigheid is nagenoeg onafhankelijk van de grootte van het meetbereik: ongeveer 0.002 m/s2. Het kleinste meetbereik gaat tot 2G (tot 20 m/s2) en het grootste meetbereik is 16G (ongeveer 160 m/s2). Zoals gezegd leven we op Aarde continu met 1G. Een raket-auto die met 16G zou optrekken, zou van 0 tot 100km/h gaan in minder dan 0,2 seconde! De beste sportauto doet er tien keer langer over. Daarbij raken straaljagerpiloten bewusteloos als ze te scherpe bochten maken. Dat gevaar ontstaat vanaf ongeveer 5G. 16G is dus een behoorlijke range. De meetnauwkeurigheid van 0.002 m/s2 is ook mooi. Als je met zo'n snelheid "versnelt" duurt het meer dan 10 minuten voor je 5 km/h gaat.

Als je geintereseert bent in deze drie-assige versnellingsmeter, zijn er andere chips die je wellicht ook interesseren:

 ADXL335 (alternatieve versnellingsmeter)
 ITG3200/ITG3205, IDG500, MPU6050 (gyroscoop)
 HMC5883L (Aardmagneetveld)
 BMP280 (Barometrische luchtdruk = hoogtemeting)

Als je wat meer wilt lezen kun je hier eens kijken: https://www.sparkfun.com/pages/accel_gyro_guide. Merk wel op dat de hier aangeboden modules relatief duur zijn. Een ADXL345 module uit China kost minder dan €1,00 !


De schakeling

Extra benodigdheden:

  • 1 ADXL345 module
ADXL345.png
De schakeling voor de ADXL345; Groen=SDA en Oranje=SCL

Het programma

#include <Wire.h>
// Registers for ADXL345
#define ADXL345_ADDRESS (0xA6 >> 1)  // address for device is 8 bit but shift to the
                                     // right by 1 bit to make it 7 bit because the
                                     // wire library only takes in 7 bit addresses
#define ADXL345_REGISTER_XLSB (0x32)

int accelerometer_data[3];

// void because this only tells the chip to send data to its output register
// writes data to the slave's buffer
void i2c_write(int address, byte reg, byte data) {
  // Send output register address
  Wire.beginTransmission(address);
  // Connect to device
  Wire.write(reg);
  // Send data
  Wire.write(data); //low byte
  Wire.endTransmission();
}

// void because using pointers
// microcontroller reads data from the sensor's input register
void i2c_read(int address, byte reg, int count, byte* data) {
  // Used to read the number of data received
  int i = 0;
  // Send input register address
  Wire.beginTransmission(address);
  // Connect to device
  Wire.write(reg);
  Wire.endTransmission();

  // Connect to device
  Wire.beginTransmission(address);
  // Request data from slave
  // Count stands for number of bytes to request
  Wire.requestFrom(address, count);
  while(Wire.available()) // slave may send less than requested
  {
    char c = Wire.read(); // receive a byte as character
    data[i] = c;
    i++;
  }
  Wire.endTransmission();
}

void init_adxl345() {
  byte data = 0;

  i2c_write(ADXL345_ADDRESS, 0x31, 0x0B);   // 13-bit mode  +_ 16g
  i2c_write(ADXL345_ADDRESS, 0x2D, 0x08);   // Power register

  i2c_write(ADXL345_ADDRESS, 0x1E, 0x00);   // x
  i2c_write(ADXL345_ADDRESS, 0x1F, 0x00);   // Y
  i2c_write(ADXL345_ADDRESS, 0x20, 0x05);   // Z
 
  // Check to see if it worked!
  i2c_read(ADXL345_ADDRESS, 0X00, 1, &data);
  if(data==0xE5)
    Serial.println("it work Success");
  else
    Serial.println("it work Fail");
}

void read_adxl345() {
  byte bytes[6];
  memset(bytes,0,6);

  // Read 6 bytes from the ADXL345
  i2c_read(ADXL345_ADDRESS, ADXL345_REGISTER_XLSB, 6, bytes);
  // Unpack data
  for (int i=0;i<3;++i) {
    accelerometer_data[i] = (int)bytes[2*i] + (((int)bytes[2*i + 1]) << 8);
  }
}

void setup() {
  Wire.begin();                // start I2C communicatie
  Serial.begin(9600);          // start de seriele communicatie met de computer
  for(int i=0; i<3; ++i) {     // zet voor alle richtingen de buffer met meetdata op 0
    accelerometer_data[i] = 0;
  }
  init_adxl345();              // zie de void() functie hierboven
}

void loop() {
  read_adxl345();
  Serial.print("ACCEL: ");
  Serial.print(float(accelerometer_data[0])*3.9/1000);  //3.9mg/LSB scale factor in 13-bit mode
  Serial.print("\t");
  Serial.print(float(accelerometer_data[1])*3.9/1000);
  Serial.print("\t");
  Serial.print(float(accelerometer_data[2])*3.9/1000);
  Serial.print("\n");
  delay(100);
}

Uitleg

Beetje spelen

Een meting van versnelling kan natuurlijk gebruikt worden snelheid te berekenen, terwijl kennis van snelheid kan natuurlijk gebruikt worden om verplaatsing te berekenen. De formule die natuurkundigen daarvoor gebruiken is:

x = x0 + v0∙t + ½a∙t²

Hierin zijn x0 de beginafstand, v0 de beginsnelheid, a de versnelling en t de tijd. Helaas gaat deze formule ervan uit dat de versnelling constant is. In het algemeen is dat niet het geval. Om de snelheid te weten moeten we daarom versnellingen integreren. Dat werkt alsvolgt: Stel, je begint met snelheid 0 en meet 100 keer per seconde de versnelling. De eerste versnelling die je meet is, zeg, 2.0 m/s². Een positieve versnelling, dus de snelheid wordt hoger. Omdat je 100x per seconde meet, geldt deze versnelling maar voor 1/100ste van een seconde. Het is dus niet gek te denken dat de snelheid in die 1/100ste van een seconde met 2.0/100 m/s is toegenomen: 0 m/s + 0.02 m/s = 0.02 m/s. Als je daarna weer 2.0 m/s² meet, zal de snelheid verder toenemen. De snelheid was echter al 0.02 m/s en die wordt nu dus 0.04 m/s. De snelheid wordt dus bijgehouden door steeds de gemeten versnelling erbij op te tellen, maar dan wel gecorrigeerd voor de tijdsduur waarvoor de gemeten versnelling geldt. Omdat we 100x per seconde meten is die tijdsduur 0.01 seconde. Zo kun je ongeveer de snelheid bijhouden. Maar let op: elk foutje blijft doortellen. Naarmate je dit langer doet wordt de afwijking met de echte snelheid groter. Probeer dus altijd ijkpunten in te bouwen. Dan zullen dan met name momenten zijn waarop je apparaat stil staat.

Om ook de afstand te bepalen, moeten we de snelheid integreren. Laten we aannemen dat de afstand ook op 0 begint. De snelheid is in het begin ook 0. De eerste 1/100ste van een seconde gebeurt er dus nog niks. aarna is de snelheid 0.02m/s. De afstand die dan wordt afgelegd zal dus 0.02/100 meter zijn. Bij de tweede snelheidsmeting blijkt de snelheid 0.04 m/s te zijn. Ook dit geldt weer voor 1/100ste van een seconde. De afstand wordt dan dus 0.0002 + 0.04/100 = 0.0006 meter. Nog erg weinig natuurlijk, maar na honderd stapjes begint de snelheid op te lopen en gaat het ook met de afstand een stuk harder. Let op dat hierbij nog meer geldt dat onnauwkeurigheden zich opstapelen zodat je ook hier ijkpunten moet proberen in te bouwen.


Een voorwerp waarvan we continu de versnelling meten Als we beginnen met een afstand en snelheid van 0, dan vereenvoudigd de formule tot:

x = ½a∙t²

Navigatie