Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Oriëntatie volgen met Arduino en ADXL345 Accelerometer

In deze tutorial leren we hoe we de hoek en de oriëntatie van het spoor kunnen meten met behulp van de Arduino en de ADXL345 Accelerometer-sensor. Je kunt de volgende video bekijken of de schriftelijke tutorial hieronder lezen voor meer details.

Overzicht

Eerst zal ik uitleggen hoe de sensor werkt en hoe de gegevens eruit kunnen worden gelezen, en vervolgens zullen we met behulp van de ontwikkelomgeving Processing een 3D-visualisatie maken van de oriëntatie van de versnellingsmeter.

Hoe ADXL345-versnellingsmeter werkt

Laten we om te beginnen eens kijken hoe de ADXL345-sensor werkt. Dit is een 3-assige versnellingsmeter die zowel statische als dynamische versnellingskrachten kan meten. De zwaartekracht van de aarde is een typisch voorbeeld van statische kracht, terwijl dynamische krachten kunnen worden veroorzaakt door trillingen, bewegingen enzovoort.

De maateenheid voor versnelling is meter per seconde kwadraat (m/s^2). Versnellingsmetersensoren drukken de metingen echter meestal uit in "g" of zwaartekracht. Eén "g" is de waarde van de zwaartekracht van de aarde die gelijk is aan 9,8 meter per seconde in het kwadraat.

Dus als we een accelerometer plat hebben gepositioneerd, met de Z-as naar boven gericht, tegengesteld aan de zwaartekracht, zal de Z-as output van de sensor 1g zijn. Aan de andere kant zullen de X- en Y-uitgangen nul zijn, omdat de zwaartekracht loodrecht op deze assen staat en ze helemaal niet beïnvloedt.

Als we de sensor ondersteboven draaien, is de uitvoer op de Z-as -1 g. Dit betekent dat de output van de sensor vanwege zijn oriëntatie op de zwaartekracht kan variëren van -1g tot +1g.

Dus volgens deze gegevens en met behulp van wat trigonometrische wiskunde, kunnen we de hoek berekenen waaronder de sensor is geplaatst.

ADXL345-versnellingsmetergegevens lezen met Arduino

Oké, laten we nu eens kijken hoe we de ADXL345-versnellingsmetergegevens kunnen lezen met behulp van de Arduino. Deze sensor gebruikt het I2C-protocol voor communicatie met de Arduino, dus we hebben slechts twee draden nodig om hem aan te sluiten, plus de twee draden om hem van stroom te voorzien.

U kunt de benodigde componenten voor deze Arduino-zelfstudie verkrijgen via de onderstaande links:

  • ADXL345 Versnellingsmeter ………………. Amazon / Banggood / AliExpress
  • Arduino-bord ………………………….. 
  • Broodplank en springdraden ………… 

ADXL345 Accelerometer Arduino-code

Hier is de Arduino-code voor het lezen van de ADXL345-versnellingsmetergegevens.

/*
    Arduino and ADXL345 Accelerometer Tutorial
     by Dejan, https://howtomechatronics.com
*/

#include <Wire.h>  // Wire library - used for I2C communication

int ADXL345 = 0x53; // The ADXL345 sensor I2C address

float X_out, Y_out, Z_out;  // Outputs

void setup() {
  Serial.begin(9600); // Initiate serial communication for printing the results on the Serial monitor
  Wire.begin(); // Initiate the Wire library
  // Set ADXL345 in measuring mode
  Wire.beginTransmission(ADXL345); // Start communicating with the device 
  Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D
  // Enable measurement
  Wire.write(8); // (8dec -> 0000 1000 binary) Bit D3 High for measuring enable 
  Wire.endTransmission();
  delay(10);
}

void loop() {
  // === Read acceleromter data === //
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  X_out = ( Wire.read()| Wire.read() << 8); // X-axis value
  X_out = X_out/256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet
  Y_out = ( Wire.read()| Wire.read() << 8); // Y-axis value
  Y_out = Y_out/256;
  Z_out = ( Wire.read()| Wire.read() << 8); // Z-axis value
  Z_out = Z_out/256;

  Serial.print("Xa= ");
  Serial.print(X_out);
  Serial.print("   Ya= ");
  Serial.print(Y_out);
  Serial.print("   Za= ");
  Serial.println(Z_out);
}Code language: Arduino (arduino)

Beschrijving: Dus eerst moeten we de Wire.h-bibliotheek opnemen die wordt gebruikt voor de I2C-communicatie. Als je meer wilt weten over hoe de I2C-communicatie werkt en hoe je deze met Arduino kunt gebruiken, kun je mijn andere gedetailleerde tutorial erover raadplegen.

Elk apparaat dat de I2C-communicatie gebruikt, heeft een uniek I2C-adres en dit adres is te vinden in de datasheet van de sensor (ADXL345 Datasheet). Dus, zodra we het adres en de variabelen voor de drie uitgangen hebben gedefinieerd, in de setup-sectie, moeten we eerst de draadbibliotheek initialiseren en vervolgens de accelerometer in de meetmodus zetten. Om dat te doen, kunnen we, als we de datasheet nog eens bekijken, zien dat we bit D3 van het POWER_CTL-register op HOOG moeten zetten.

Dus, met behulp van de functie beginTransmission() starten we de communicatie, vervolgens met behulp van de functie write() vertellen we tot welk register we toegang willen hebben, en opnieuw met de functie write() stellen we de D3-bit HOOG in, door het getal 8 in te schrijven in decimaal die overeenkomen met het instellen van de bit D3 HOOG.

// Set ADXL345 in measuring mode
  Wire.beginTransmission(ADXL345); // Start communicating with the device 
  Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D
  // Enable measurement
  Wire.write(8); // (8dec -> 0000 1000 binary) Bit D3 High for measuring enable 
  Wire.endTransmission();Code language: Arduino (arduino)

In het lusgedeelte lezen we nu de gegevens van de sensor. De gegevens voor elke as worden opgeslagen in twee bytes of registers. We kunnen de adressen van deze registers zien in de datasheet.

Om ze allemaal te lezen, beginnen we met het eerste register, en met behulp van de requestionFrom() functie vragen we om de 6 registers te lezen. Vervolgens gebruiken we de functie read() om de gegevens van elk register te lezen en omdat de uitvoer twee complementen zijn, combineren we ze op de juiste manier om de juiste waarden te krijgen.

// === Read acceleromter data === //
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  X_out = ( Wire.read()| Wire.read() << 8); // X-axis value
  X_out = X_out/256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet
  Y_out = ( Wire.read()| Wire.read() << 8); // Y-axis value
  Y_out = Y_out/256;
  Z_out = ( Wire.read()| Wire.read() << 8); // Z-axis value
  Z_out = Z_out/256;Code language: Arduino (arduino)

De uitgangswaarden van de sensor zijn eigenlijk afhankelijk van de geselecteerde gevoeligheid, die kan variëren van +- 2g tot +-16g. De standaardgevoeligheid is +-2g, daarom moeten we de output delen door 256 om waarden van -1 tot +1g te krijgen. De 256 LSB/g betekent dat we 256 tellingen per g hebben.

Afhankelijk van de toepassing kunnen we de juiste gevoeligheid selecteren. In dit geval is een gevoeligheid van +-2g prima, maar voor toepassingen waarbij we een hogere versnellingskracht moeten voelen, zoals plotselinge bewegingen, schokken enzovoort, kunnen we enkele van de andere gevoeligheidsbereiken kiezen met behulp van het DATA_FORMAT-register en zijn D1- en D0-bits.

ADXL345 Accelerometer-kalibratie

Desalniettemin, als we de gegevens eenmaal hebben gelezen, kunnen we deze eenvoudig op de seriële monitor afdrukken om te controleren of de waarden zijn zoals verwacht. In mijn geval waren de waarden die ik kreeg niet precies zoals ze zouden moeten zijn, vooral de Z-as met een merkbare fout van 0,1 g.

Om dit probleem op te lossen, moeten we de versnellingsmeter kalibreren met behulp van de 3 offset-kalibratieregisters, en hier is hoe we dat kunnen doen. We moeten de sensor dus plat positioneren en de RAW-waarden afdrukken zonder ze door 256 te delen.

Vanaf hier kunnen we nu zien hoeveel de uitgangen zijn uitgeschakeld, in mijn geval was de Z-uitgang ongeveer 283. Dat is een verschil van 27 in positief. Nu moeten we deze waarde delen door 4, en dat geeft het nummer dat we naar het Z-as offset register moeten schrijven. Als we de code nu uploaden, is de uitvoer op de Z-as precies 256, of 1g zoals het hoort.

// This code goes in the SETUP section
// Off-set Calibration
  //X-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1E);  // X-axis offset register
  Wire.write(1);
  Wire.endTransmission();
  delay(10);
  //Y-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1F); // Y-axis offset register
  Wire.write(-2);
  Wire.endTransmission();
  delay(10);
  
  //Z-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x20); // Z-axis offset register
  Wire.write(-7);
  Wire.endTransmission();
  delay(10);Code language: Arduino (arduino)

Indien nodig moeten we de andere as met dezelfde methode kalibreren. En even een snelle opmerking dat deze kalibratie niet permanent naar de registers wordt geschreven. We moeten deze waarden bij elke opstart van de sensor naar de registers schrijven.

Als we klaar zijn met de kalibratie, kunnen we nu eindelijk de Roll and Pitch berekenen, of de rotatie rond de X-as en de rotatie rond de Y-as in graden, met behulp van deze twee formules.

// Calculate Roll and Pitch (rotation around X-axis, rotation around Y-axis)
  roll = atan(Y_out / sqrt(pow(X_out, 2) + pow(Z_out, 2))) * 180 / PI;
  pitch = atan(-1 * X_out / sqrt(pow(Y_out, 2) + pow(Z_out, 2))) * 180 / PI;Code language: Arduino (arduino)

Voor meer details over hoe deze formules werken, kunt u deze toepassingsnotitie van Freescale Semiconductor raadplegen.

Arduino en ADXL345 Accelerometer Orientation Tracking – 3D-visualisatie

Oké, laten we nu het 3D-visualisatievoorbeeld van de accelerometer maken.

We gebruiken dus dezelfde code die de Roll- en Pitch-waarden via de seriële poort stuurt. Hier is de volledige Arduino-code:

/*
    Arduino and ADXL345 Accelerometer - 3D Visualization Example 
     by Dejan, https://howtomechatronics.com
*/
#include <Wire.h>  // Wire library - used for I2C communication

int ADXL345 = 0x53; // The ADXL345 sensor I2C address

float X_out, Y_out, Z_out;  // Outputs
float roll,pitch,rollF,pitchF=0;

void setup() {
  Serial.begin(9600); // Initiate serial communication for printing the results on the Serial monitor
 
  Wire.begin(); // Initiate the Wire library
  // Set ADXL345 in measuring mode
  Wire.beginTransmission(ADXL345); // Start communicating with the device
  Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D
  // Enable measurement
  Wire.write(8); // Bit D3 High for measuring enable (8dec -> 0000 1000 binary)
  Wire.endTransmission();
  delay(10);

  //Off-set Calibration
  //X-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1E);
  Wire.write(1);
  Wire.endTransmission();
  delay(10);
  //Y-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1F);
  Wire.write(-2);
  Wire.endTransmission();
  delay(10);

  //Z-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x20);
  Wire.write(-9);
  Wire.endTransmission();
  delay(10);
}

void loop() {
  // === Read acceleromter data === //
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  X_out = ( Wire.read() | Wire.read() << 8); // X-axis value
  X_out = X_out / 256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet
  Y_out = ( Wire.read() | Wire.read() << 8); // Y-axis value
  Y_out = Y_out / 256;
  Z_out = ( Wire.read() | Wire.read() << 8); // Z-axis value
  Z_out = Z_out / 256;

  // Calculate Roll and Pitch (rotation around X-axis, rotation around Y-axis)
  roll = atan(Y_out / sqrt(pow(X_out, 2) + pow(Z_out, 2))) * 180 / PI;
  pitch = atan(-1 * X_out / sqrt(pow(Y_out, 2) + pow(Z_out, 2))) * 180 / PI;

  // Low-pass filter
  rollF = 0.94 * rollF + 0.06 * roll;
  pitchF = 0.94 * pitchF + 0.06 * pitch;

  Serial.print(rollF);
  Serial.print("/");
  Serial.println(pitchF);
}Code language: Arduino (arduino)

Nu moeten we in de ontwikkelomgeving Processing deze waarden ontvangen en gebruiken om het 3D-object dat we gaan maken te roteren. Hier is de volledige verwerkingscode:

/*
    Arduino and ADXL345 Accelerometer - 3D Visualization Example 
     by Dejan, https://howtomechatronics.com
*/

import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;

Serial myPort;

String data="";
float roll, pitch;

void setup() {
  size (960, 640, P3D);
  myPort = new Serial(this, "COM8", 9600); // starts the serial communication
  myPort.bufferUntil('\n');
}

void draw() {
  translate(width/2, height/2, 0);
  background(33);
  textSize(22);
  text("Roll: " + int(roll) + "     Pitch: " + int(pitch), -100, 265);

  // Rotate the object
  rotateX(radians(roll));
  rotateZ(radians(-pitch));
  
  // 3D 0bject
  textSize(30);  
  fill(0, 76, 153);
  box (386, 40, 200); // Draw box
  textSize(25);
  fill(255, 255, 255);
  text("www.HowToMechatronics.com", -183, 10, 101);

  //delay(10);
  //println("ypr:\t" + angleX + "\t" + angleY); // Print the values to check whether we are getting proper values
}

// Read data from the Serial Port
void serialEvent (Serial myPort) { 
  // reads the data from the Serial Port up to the character '.' and puts it into the String variable "data".
  data = myPort.readStringUntil('\n');

  // if you got any bytes other than the linefeed:
  if (data != null) {
    data = trim(data);
    // split the string at "/"
    String items[] = split(data, '/');
    if (items.length > 1) {

      //--- Roll,Pitch in degrees
      roll = float(items[0]);
      pitch = float(items[1]);
    }
  }
}Code language: Arduino (arduino)

Beschrijving: Dus hier moeten we de seriële bibliotheek opnemen, de seriële poort en de baudrate definiëren die moet overeenkomen met de baudrate van de geüploade Arduino-schets. Vervolgens lezen we de binnenkomende gegevens en plaatsen deze in de juiste roll- en pitch-variabelen. In de hoofdtekenlus gebruiken we deze waarden om het 3D-object te roteren, en in dit geval is dat een eenvoudig vak met een bepaalde kleur en een tekst erop.

Als we de schets uitvoeren, verschijnt het 3D-object en volgt het de oriëntatie van de versnellingsmetersensor. We kunnen hier zien dat het object eigenlijk een beetje wankel is en dat komt omdat de versnellingsmeter niet alleen de zwaartekracht vastlegt, maar ook kleine krachten die worden gegenereerd door de bewegingen van onze hand. Om een ​​vloeiender resultaat te krijgen, kunnen we een eenvoudig laagdoorlaatfilter gebruiken. Hier heb ik zo'n filter in de Arduino-code geïmplementeerd, die 94% van de vorige staat inneemt en 6% van de huidige staat of hoek toevoegt.

// Low-pass filter
  rollF = 0.94 * rollF + 0.06 * roll;
  pitchF = 0.94 * pitchF + 0.06 * pitch;Code language: Arduino (arduino)

Met dit filter kunnen we merken dat het object nu een stuk soepeler beweegt, maar er is ook een bijwerking en dat is een tragere reactietijd. We kunnen ook opmerken dat we de Yaw, of rotatie rond de Z-as, missen. Met alleen de gegevens van de 3-assige versnellingsmeter kunnen we de Yaw niet berekenen.

Om dat te doen en de algehele prestaties van onze sensor voor het volgen van oriëntatie te verbeteren, moeten we een extra sensor, een gyroscoop, toevoegen en de gegevens ervan samenvoegen met de versnellingsmeter.

We kunnen dus ofwel de ADXL345-versnellingsmeter gebruiken in combinatie met een gyroscoopsensor, of de MPU6050 IMU gebruiken die zowel een 3-assige versnellingsmeter als een 3-assige gyroscoop op een enkele chip heeft geïntegreerd. Je kunt een meer gedetailleerde tutorial over deze sensor vinden in mijn volgende video.

Ik hoop dat je deze tutorial leuk vond en iets nieuws hebt geleerd. Stel gerust een vraag in de opmerkingen hieronder en vergeet niet mijn verzameling Arduino-projecten te bekijken.


Productieproces

  1. Besturing van servomotor met Arduino en MPU6050
  2. u-blox LEA-6H 02 GPS-module met Arduino en Python
  3. De temperatuur en vochtigheid op Blynk aflezen met DHT11
  4. Spraakherkenning en synthese met Arduino
  5. Muziek maken met een Arduino
  6. Hoe NMEA-0183 te gebruiken met Arduino
  7. Modbus gebruiken met Arduino
  8. Smart Coffee Machine met Arduino en Bluetooth
  9. Geanimeerde Smart Light met Alexa en Arduino
  10. Spraakherkenning met Arduino en BitVoicer Server
  11. AI-assistentrobot met Arduino en Python