Жироскоп, акселерометър и магнитометър MinIMU-9 и Arduino

MinIMU-9 е устройство, което съчетава жироскопа L3G4200D, акселерометъра и магнитомера LSM303DLH. Дава достъп по I2C до 9 стойности, които са напълно достатъчни за определяне на абсолютното му разположение в пространството.

Платката съдържа два регулаторa на напрежението, които дават възможност да се подава захранване от 2.6 до 5.5V на пин VIN. На пинове 1.8V и 3V може да се захранват други устройства с ток 150 и 300mA. Пиновете на платката са на отстояние 2.56mm което я прави съвместима с бредборд.

Жироскопът, акселерометърът и магнитомерът имат различни адреси и са достъпни на обща линия. Адресът на жироскопът по подразбиране е 1101001 , но най-младшия бит (LSB) може да се промени на 0, като пин SA0_G се даде на маса (GND). Акселерометърът има адрес 0011000 и най-младшият му бит (LSB) се променя на 1 , като пин SA0_A се даде на късо с пин 1.8V. Адресът на магнитомерът е 0011110 и не може да се променя. По I2C шината могат да се конфигурират и трите устройства.

Жироскопът измерва ъглова скорост, т.е колко бързо се върти около ос. Трите оси X, Y и Z са по-известни като Roll, Pitch и Yaw. Мерната единица е RPM (завъртания в минута) или °/s (градуса в секунда). По I2C може да се задава чутсвителност от ±250, ±500 и ±2000°/s. Тя се определя от 4ти и 5ти бит на регистъра с адрес 0x23.

Жироскопът се задейства като се напрaвят 1ци битове от 0 до 3 на регистър 0x20. Стойността, която връща за всяка ос е от 16 бита. Стойностите за Х, Y и Z са достъпни съответно в регистри: 0x29 и 0x28, 0x2B и 0x2A, 0x2D и 0x2C.

Акселерометърът измерва ускорението по 3 оси. Чрез трите стойности може да се определи в какво положение е устройството, ако е неподвижно или какво е движението му ако се движи. Използва се също и за засичане на свободно падане.

Контролните регистри и регистрите за изходните данни на акселерометъра в LSM303DLH имат същите адреси като тези на жироскопа L3G4200D. За чувствителността му се задават стойности ±2, ±4 и ±8g, съответно като 00,01 и 11 на 4ти и 5ти бит в регистър 0x23. Задействa се отново през регистър 0x20.

Чрез битовете DR1 и DR0 се задава честотата на измерване т.е . колко пъти в секунда се измерва ускорението.

Магнитометарът служи за измерване силата на магнитното поле по три оси. Мерната единица за интензитета на полето е тесла (Т), но тъй като размерността и е прекалено голяма се използва единицата Gauss (1 Gaus = 100 000 nT). Магнитометарът може да засече и слабото магнитно поле на земята и затова намира приложение в мобилните телефони като компас. Чувствителността на магнитометара може да се поменя на ±1.3, ±1.9, ±2.5, ±4.0, ±4.7, ±5.6 и ±8.1 като се редактира регистър 0x01.

Честотата, с която се обновяват стойностите за 3те оси се задава от регистър 0x00. Стойностите за X,Y и Z са достъпни съответно в регистри 0x03 и 0x04,0x05 и 0x06,0x07 и 0x08.

Пример

Даденият по-долу код инициализира жироскопа, акселерометъра и магнитометъра, но в Serial Monitor връща данни само от едно устройство. В програмния цикъл само една функция прочита данни за X, Y и Z. В примера това е функцията на жироскопа.

Устройството се свързва към Arduino като пинове SCL и SDA се свържат съответно към A5 и А4 на Arduino, а пин VIN и GND са към 5V и GND.

Кода, който трябва да се зареди на Arduino е следният:

/*

 Описание: 
 * Инициализира жироскопа, акселерометъра и магнитометъра 
 * В програмния цикъл е активна само функцията за четене 
   от жироскопа
 * В Serial Monitor връща данни за X, Y и Z само от него

 Свързване:
 SCL -> A5
 SDA -> A4
 VIN -> 5V
 GND -> GND

 Tihomir Trifonov (11-2011)
 email:tisho@inbox.com

 с подкрепата на Robotev.com

*/

#include <Wire.h>//библиотека за I2C комуникация

int x;
int y;
int z;

int readRegister(int deviceAddress, byte regAddress);// чете от регистър
void writeRegister(int deviceAddress, byte regAddress, byte val);// записва
void readACC(); // чете данните за X, Y и Z от акселерометъра
void readGYRO();// X, Y и Z от жироскопа
void readMAG();//  X, Y и Z от магнитометъра

void setup(){ // начални инициализации

  Wire.begin();// започва комуникация по I2C 
  Serial.begin(9600);// серийна комуникация с PC

  // инициализира жироскопа L3G4200D
  writeRegister(0b01101001, 0x23, 0b00110000);// чувствителност 2000dps
  writeRegister(0b01101001, 0x20, 0b00001111);// normal mode, enable X, Y, Z

  // инициализира акселерометъра в LSM303DLH
  writeRegister(0b0011000, 0x23, 0b00110000);// чувствителност 8g
  writeRegister(0b0011000, 0x20, 0b00100111);// enable, normal mode, 50 Hz

  // инициализира магнитометъра в LSM303DLH
  writeRegister(0b0011110, 0x01, 0b11100000);// чувствителност 8.1 Gauss
  writeRegister(0b0011110, 0x02, 0b00000000);// Continuous-conversion mode

  delay(1500);
}

void readACC(){// чете данните за X, Y и Z от акселерометъра

  byte xMSB = readRegister(0b0011000, 0x29);// чете старшия байт
  byte xLSB = readRegister(0b0011000, 0x28);// чете младшия байт
  x = ((xMSB << 8) | xLSB)>>4;// 12 бита за X

  byte yMSB = readRegister(0b0011000, 0x2B);
  byte yLSB = readRegister(0b0011000, 0x2A);
  y = ((yMSB << 8) | yLSB)>>4;// 12 бита за Y

  byte zMSB = readRegister(0b0011000, 0x2D);
  byte zLSB = readRegister(0b0011000, 0x2C);
  z = ((zMSB << 8) | zLSB)>>4;// 12 бита за Z
}

void readGYRO(){// чете данните за X, Y и Z от жироскопа

  byte xMSB = readRegister(0b1101001, 0x29);
  byte xLSB = readRegister(0b1101001, 0x28);
  x = ((xMSB << 8) | xLSB);// 16 бита за X

  byte yMSB = readRegister(0b1101001, 0x2B);
  byte yLSB = readRegister(0b1101001, 0x2A);
  y = ((yMSB << 8) | yLSB);// 16 бита за Y

  byte zMSB = readRegister(0b1101001, 0x2D);
  byte zLSB = readRegister(0b1101001, 0x2C);
  z = ((zMSB << 8) | zLSB);// 16 бита за Z
}

void readMAG(){//  чете данните за X, Y и Z от магнитометъра

  byte xMSB = readRegister(0b0011110, 0x03);
  byte xLSB = readRegister(0b0011110, 0x04);
  x = ((xMSB << 8) | xLSB);// 16 бита за X

  byte yMSB = readRegister(0b0011110, 0x05);
  byte yLSB = readRegister(0b0011110, 0x06);
  y = ((yMSB << 8) | yLSB);// 16 бита за Y

  byte zMSB = readRegister(0b0011110, 0x07);
  byte zLSB = readRegister(0b0011110, 0x08);
  z = ((zMSB << 8) | zLSB);// 16 бита за Z
}

void loop(){ // програмен цикъл

 //// само 1 ф-я трябва да е активна 
   readGYRO();// чете от жироскопа
 //readACC(); // чете от акселерометъра
 //readMAG(); // чете от магнитометъра
 ////

 // Извжежда X, Y и Z в Serial Monitor
  Serial.print("X:");
  Serial.print(x);
  Serial.print(" Y:");
  Serial.print(y);
  Serial.print(" Z:");
  Serial.println(z);

  delay(100); // забавя изпълнението
}

void writeRegister(int deviceAddress, byte address, byte val) {// записва в регистър
    Wire.beginTransmission(deviceAddress);  //адрес на устройството
    Wire.send(address); // aдрес на регистъра
    Wire.send(val); // стойност за запис в регистъра
    Wire.endTransmission();// край 
}

int readRegister(int deviceAddress, byte address){// чете съдържанието на регистър

    int v;// съхранява 1 байт
    Wire.beginTransmission(deviceAddress);// адрес на устройството
    Wire.send(address); // адрес на регистъра
    Wire.endTransmission();// край

    Wire.requestFrom(deviceAddress, 1); // изисква 1 байт
    while(!Wire.available()) {} // изчаква получаването на байта

    v = Wire.receive(); // присвоява го на промелива
    return v; // връща байта през името на функцията
}

Share