Operácie

Navigačná aplikácia s kompasom HMC5883L: Rozdiel medzi revíziami

Zo stránky SensorWiki

StudentDVPS (diskusia | príspevky)
StudentDVPS (diskusia | príspevky)
 
(18 medziľahlých úprav od rovnakého používateľa nie je zobrazených.)
Riadok 4: Riadok 4:
|Študijný odbor:  || Aplikovaná mechatronika a elektromobilita || 1. Ing.  ('''2016''')  
|Študijný odbor:  || Aplikovaná mechatronika a elektromobilita || 1. Ing.  ('''2016''')  
|}
|}


== Zadanie ==
== Zadanie ==
[[Súbor:HMC5883L-nahlad.png|300px|right||thumb|HMC5883L PCB]]
Pomocou troj osého magnetometra HMC5883L vytvorte aplikáciu ktorá bude slúžiť ako smerový navigačný systém.
Pomocou troj osého magnetometra HMC5883L vytvorte aplikáciu ktorá bude slúžiť ako smerový navigačný systém.
[[Súbor:HMC5883L-nahlad.jpg|300px|right||thumb|HMC5883L PCB layout]]


=== Body zadania ===
=== Body zadania ===
Riadok 25: Riadok 25:
*[https://en.wikipedia.org/wiki/I%C2%B2C I2C zbernica]
*[https://en.wikipedia.org/wiki/I%C2%B2C I2C zbernica]
*[https://www.arduino.cc/en/Reference/Wire I2C/TWI pre Arduino]
*[https://www.arduino.cc/en/Reference/Wire I2C/TWI pre Arduino]


__TOC__
__TOC__
Riadok 250: Riadok 252:


Senzor namerá jednu sadu údajov a zapíše ich do 6 dátových registrov. Po zápise pin DRDY prejde do úrovne high až kým sa nezačne ďalšie meranie alebo niesú dáta prečítané.
Senzor namerá jednu sadu údajov a zapíše ich do 6 dátových registrov. Po zápise pin DRDY prejde do úrovne high až kým sa nezačne ďalšie meranie alebo niesú dáta prečítané.
[[Súbor:Uno.png|300px|right||thumb|Arduino UNO]]




Riadok 260: Riadok 263:
Keďže senzor HMC5883L vysiela dáta o magnetickej indukcii cez zbernicu I2C, ako riadiacu jednotku musíme zvoliť mikropočítač, ktorý podporuje takúto komunikáciu. Arduino Uno poskytuje jednoduchý spôsob pripojenia pre komunikáciu cez I2C zbernicu so senzorom HMC5883L a taktiež poskytuje potrebné napájanie (3.3 V). Napájanie a komunikácia riadiacej jednotky je zabezpečená z PC cez USB rozhranie.  
Keďže senzor HMC5883L vysiela dáta o magnetickej indukcii cez zbernicu I2C, ako riadiacu jednotku musíme zvoliť mikropočítač, ktorý podporuje takúto komunikáciu. Arduino Uno poskytuje jednoduchý spôsob pripojenia pre komunikáciu cez I2C zbernicu so senzorom HMC5883L a taktiež poskytuje potrebné napájanie (3.3 V). Napájanie a komunikácia riadiacej jednotky je zabezpečená z PC cez USB rozhranie.  
Viac na [https://www.arduino.cc/en/main/arduinoBoardUno Arduino Uno]
Viac na [https://www.arduino.cc/en/main/arduinoBoardUno Arduino Uno]
[[Súbor:Uno.png|300px|left||thumb|Arduino UNO]]




Riadok 269: Riadok 271:


Tento softvér priamo obsahuje knižnicu ''Wire.h'' pre komunikáciu cez I2C zbernicu pomocou SDA a SCL vývodov. Na doske pre Arduino Uno sú vývody SDA a SCL umiestnené blízko AREF pinu. Knižnica používa 7-bit adresy zariadení pričom adresy 0-7 sú rezervované.
Tento softvér priamo obsahuje knižnicu ''Wire.h'' pre komunikáciu cez I2C zbernicu pomocou SDA a SCL vývodov. Na doske pre Arduino Uno sú vývody SDA a SCL umiestnené blízko AREF pinu. Knižnica používa 7-bit adresy zariadení pričom adresy 0-7 sú rezervované.


== Popis riešenia ==
== Popis riešenia ==
=== Zapojenie senzora ===
Senzor s ktorým sme pracovali bol už osadený na doske plošných spojov. Po kontrole dosky sme zistili že výrobca pri osádzaní postupoval podľa odporúčaní [https://cdn-shop.adafruit.com/datasheets/HMC5883L_3-Axis_Digital_Compass_IC.pdf datasheetu] a pridal aj stabilizátory napätia, pre kompatibilitu s 5V logikou.


Sem opíšete ako konkrétne ste problém vyriešili. Začnite popisom pripojenia k procesoru
{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
(nezabudnite na schému zapojenia!) a zdôraznite ktoré jeho periférie ste pritom využili.
|
|-
| [[Súbor:HMC5883L-PCB.PNG|250px|center|thumb|PCB layout odporúčaný výrobcom]]
| [[Súbor:HMC5883L-nahlad.png|250px|center|thumb|Modul s HMC5883L a stabilizátormi napäatia]]
|}


'''Schéma zapojenia snímača'''
[[Súbor:Zapojenie.png]]


[[Súbor:Example.jpg]]
=== Schéma zapojenia modulu ===
[[Súbor:Schema kompas.jpg|300px]]


Pozn.: Názov obrázku musí byť jedinečný, uvedomte si, že Obr1.jpg už pred vami skúsilo
== Algoritmus ==
nahrať už aspoň 10 študentov.  
Na začiatku programu definujeme použité knižnice. Taktiež definujeme adresu HMC5883L a dve premenné ''flag'' a ''lockHeading''.
<source lang="c">
#include <Wire.h>
 
#define addr 0x1E
 
int flag;
float lockHeading;
</source>


[[Súbor:MojObrazok.jpg|center|250px]]


=== Algoritmus a program ===
'''Nastavenie'''


Uveďte stručný popis algoritmu, v akom jazyku a verzii vývojového prostredia ste ho vytvorili.  
Definujeme funkciu ''setup'' a spustíme sériovú linku, I2C zbernicu.
Je vhodné nakresliť aspoň hrubú štruktúru programu napríklad vo forme vývojového diagramu.  
<source lang="c">
Rozsiahly program pre lepšiu prehľadnosť rozdeľte do viacerých súborov.
void setup()
{
  Serial.begin(9600);
  Wire.begin();
</source>


Vyberte podstatné časti zdrojového kódu, použite na to prostredie ''source'':
Senzor nastavíme do kontinuálneho meracieho režimu.
<source lang="c">
  Wire.beginTransmission(addr);
  Wire.write(0x02);
  Wire.write((byte)0x00);
  Wire.endTransmission();
</source>


Po sériovej linke pošleme informácie pre užívateľa.
<source lang="c">
<source lang="c">
/* A nezabudnite zdroják hojne komentovať */
  Serial.println("WELCOME TO iNAV");
  Serial.println("Press button when heading in desired direction and system will lock on.");  
  Serial.println();
  Serial.println();
</source>


int main(void) {
Počkáme na ustálenie systému a uzavrieme funkciu ''setup''.
   
<source lang="c">
    printf("Hello, World!\n"); 
  delay(500);
    return(0);
}
}
</source>
</source>


Nezabudnite však nahrať aj kompletné zdrojové kódy vášho programu!


Zdrojový kód: [[Médiá:Serial.h|serial.h]] a [[Médiá:Pip.c|main.c]]
'''Telo programu'''
 
Definujeme funkciu ''loop'' a premenné pre výsledky pre jednotlivé osi.
<source lang="c">
void loop()
{
  int x,y,z;
</source>
 
Register pointer senzoru nastavíme na adresu 0x03.
<source lang="c">
  Wire.beginTransmission(addr);
  Wire.write(0x03);
  Wire.endTransmission();
</source>
 
Prečítame bit na adrese 0x03, uložíme ho ako MSB x-osi. Po prečítaní bitu sa register pointer posunie o jednu adresu a teda prečítame dáta na adrese 0x04 t.z. LSB x-osi. Bitovými operáciami skombinujeme MSB a LSB do jedného 16 bitového čísla. Takto prečítame všetkých 6 dátových bitov.
<source lang="c">
  Wire.requestFrom(addr, 6);
  if(6<=Wire.available())
    {
      x = Wire.read()<<8; //MSB  x
      x |= Wire.read(); //LSB  x
      z = Wire.read()<<8; //MSB  z
      z |= Wire.read(); //LSB z
      y = Wire.read()<<8; //MSB y
      y |= Wire.read(); //LSB y
    }
</source>


[[Médiá:MojProgram.c|program.c]]
Získané dáta prepočítame na stupne. Keďže iba kompasom nevieme zistiť orientáciu v priestore, smerovanie počítame iba v rovine XY.
<source lang="c">
  float heading = atan2((double)y,(double)x)*(180/3.1416)+180;
</source>


Zistíme či tlačidlo nieje stlačené.
<source lang="c">
int key = analogRead(A3);


if(key>1000)
  {
</source>


Ak tlačidlo bolo stlačené tak si smer z premennej ''heading'' uložíme do premenej ''lockHeading'' a povolíme príznak stlačenia tlačidla ''flag''.
<source lang="c">
    Serial.println("!!! LOCKED ON !!!");
    Serial.print("HEADING > ");
    Serial.print(heading);
    Serial.println("Deg");
    lockHeading=heading;
    flag=1;
  }
</source>


=== Overenie ===
Ak bol požadovaný smer nastavený pokračujeme v podmienke.
<source lang="c">
if(flag==1)
</source>


Nezabudnite napísať čosi ako užívateľský návod. Z neho by malo byť jasné čo program robí,
Ak je rozdiel ''heading - lockHeading'' > 0 znamená to že ak chce užívateľ smerovať v požadovanom smere musí sa otočiť doľava. Vypíšeme odchýlku od žiadaného smeru v stupňoch a smer potrebnej korekcie.
ako sa prejavuje a aké má užívateľské rozhranie (čo treba stlačiť, čo sa kde zobrazuje).
<source lang="c">
Ak ste namerali nejaké signály, sem s nimi. Ak je výsledkom nejaký údaj na displeji,
  if((heading - lockHeading)>0)
odfotografujte ho.  
  {
    Serial.print("Turn left by ");
    Serial.print(abs((heading - lockHeading)));
    Serial.println("Deg");
  }
</source>


Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.
Ak je rozdiel ''heading - lockHeading'' < 0 znamená to že ak chce užívateľ smerovať v požadovanom smere musí sa otočiť do prava. Vypíšeme odchýlku od žiadaného smeru v stupňoch a smer potrebnej korekcie.
<source lang="c">
  else
  {
    Serial.print("Turn right by ");
    Serial.print(abs((heading - lockHeading)));
    Serial.println("Deg");
  }
}
</source>


Počkáme na ďalší merací cyklus.
<source lang="c">
delay(1500);
}
</source>


[[Category:MEMS]] [[Category:I2C]]
[[Category:MEMS]] [[Category:I2C]]

Aktuálna revízia z 23:32, 31. máj 2016

Autori: Peter Griger, Ivan Beliansky
Študijný odbor: Aplikovaná mechatronika a elektromobilita 1. Ing. (2016)


Zadanie

HMC5883L PCB

Pomocou troj osého magnetometra HMC5883L vytvorte aplikáciu ktorá bude slúžiť ako smerový navigačný systém.

Body zadania

  • K použitému senzoru nájdite datasheet a preštudujte jeho štruktúru, spôsob pripojenia, komunikácie, a čítania dát.
  • Na základe predošlých vedomostí navrhnite spôsob pripojenia k vhodnej riadiacej jednotke.
  • Napíšte program v prostredí Arduino zabezpečujúci:
    • Komunikáciu so snímačom
    • Načítanie a spracovanie potrebných dát
    • Vyhodnotenie a prezentácia údajov v reálnom čase
  • Dokumentáciu odovzdajte prostredníctvom tejto wiki stránky.

Literatúra


Analýza

Použitý senzor

HMC5883L Bloková schéma
HMC5883L Pinout

HMC5883L je senzor na snímanie slabých magnetických poli využívaný v magnetografii alebo ako kompas. Obsahuje trojicu magnetorezistívnych senzorov HMC118X, obvody pre spracovanie výsledkov a úpravu vlastností senzora, I2C rozhranie a 12 bitový analógovo-číselný prevodník ktorý zabezpečuje smerovú presnosť 1° až 2° pri rozsahu ±8Gs.Využíva jav anizotropickej magnetorezistivity čo zabezpečuje linearitu a vysokú citlivosť pre každú os. HMC5883L je vyrábaný firmou Honeywell v púzdre LPCC-16 s rozmermi 3,0mm x 3,0mm x 0,9mm.

Pinout

C Pin Funkcia
1 SCL Hodinový signál I2C zbernice
2 VDD Napájacie napätie
3 NC Nepripojené
4 S1 Napätie IO obvodov
5 NC Nepripojené
6 NC Nepripojené
7 NC Nepripojené
8 SETP Set/Reset
9 GND Pripojenie na zem
10 C1 Stabilizačný kondenzátor
11 GND Pripojenie na zem
12 SETC Set/Reset kondenzátor
13 VDDIO Napätie 1.71V IO obvodov
14 NC Nepripojené
15 DRDY Pin prerušenia
16 SDA Dátová linka I2C zbernice

Mapa registrov

Adresa Názov Prístup
0h00 Konfiguračný register A Read/Write
0h01 Konfiguračný register B Read/Write
0h02 Register nastavenia módu merania Read/Write
0h03 Dáta osi X MSB Read
0h04 Dáta osi X LSB Read
0h05 Dáta osi Z MSB Read
0h06 Dáta osi Z LSB Read
0h07 Dáta osi Y MSB Read
0h08 Dáta osi Y LSB Read
0h09 Status register Read
0h10 Identifikačný register A Read
0h11 Identifikačný register B Read
0h12 Identifikačný register C Read


I2C/TWI zbernica

Hodnoty magnetickej indukcie v jednotlivých osiach sú dostupné cez I2C rozhranie čím sa senzor stáva vhodným pre priame pripojenie k mikropočítaču. Hodnoty magnetickej indukcie je možné čítať cez I2C s pravidelnou frekvenciou alebo pri vyvolanom prerušení, podľa nastaveného módu merania.

Pri I2C komunikácii sa používajú dva signály "Serial Clock Line (SCL)" a "Serial Data Line (SDA)". SDA je obojsmerná linka používaná na posielanie a príjem dát z/na rozhranie. Pri prenose sa počíta z externými "pull-up" registrami na SDA a SCL linke. Keď je linka voľná obidva signály sú na vysokej úrovni. Slave adresa akcelerometra je 0x1E. Viac o I2C prenose je uvedené v I2C zbernica.


Postup prenosu jedného bajtu

  • Master vyšle štartovaciu podmienku na adresu HMC5883L (0x1E) s RW bitom nastaveným na nulu pre zápis, a MMA8491Q odošle potvrdenie (ACK bit).
  • Potom Master vyšle adresu registra, z ktorého chce čítať a HMC5883L pošle potvrdenie (ACK bit).
  • Master vyšle opakovanú štartovaciu podmienku a potom adresuje HMC5883L s RW bitom nastaveným na jednotku pre čítanie z predtým vybraného registra.
  • HMC5883L potom potvrdí a pošle dáta z požadovaného registra.
  • Master nepotvrdzuje príjem, ale vyšle stop podmienku a ukončí prenos dát.


Módy operácie senzora

Senzor HMC5883L funguje v troch meracích režimoch, ktoré sú nastaviteľné pomocou registra s adresou 0h03.


Obsah registra

M7 M6 M5 M4 M3 M2 M1 M0
0/1 0 0 0 0 0 0/1 0/1

Bit M7 nastavuje štandardnú (M7 = 0, default) alebo vysokorýchlostnú (M7 = 1) I2C zbernicu.

Bity M6-M2 sú 0.


Nastavenie M1 a M0

M1 M0 Režim
0 0 Kontinuálny režim
0 1 Režim jedného merania
1 0 Stand-by
1 1 Stand-by


Režimy

Kontinuálny režim

Senzor opakovane meria a zapisuje hodnoty do dátových registrov podľa nastavenej frekvencie. Keď sa zapíše všetkých 6 dátových registrov, pin DRDY prejde do úrovne high až kým sa nezačne ďalšie meranie.


Režim jedného merania

Senzor namerá jednu sadu údajov a zapíše ich do 6 dátových registrov. Po zápise pin DRDY prejde do úrovne high až kým sa nezačne ďalšie meranie alebo niesú dáta prečítané.

Arduino UNO


Stand-by

Meracie a tvarovacie obvody sú neaktívne, funguje iba I2C rozhranie. V tomto režime senzor má senzor nízku spotrebu (2e-6 A).


Riadiaca jednotka

Keďže senzor HMC5883L vysiela dáta o magnetickej indukcii cez zbernicu I2C, ako riadiacu jednotku musíme zvoliť mikropočítač, ktorý podporuje takúto komunikáciu. Arduino Uno poskytuje jednoduchý spôsob pripojenia pre komunikáciu cez I2C zbernicu so senzorom HMC5883L a taktiež poskytuje potrebné napájanie (3.3 V). Napájanie a komunikácia riadiacej jednotky je zabezpečená z PC cez USB rozhranie. Viac na Arduino Uno


Programové prostredie

Program pre činnosť mikropočítača budeme vyvíjať vo voľne dostupnom softvérovom prostredí (IDE) vytvorenom pre tento účel spoločnosťou Arduino. ARDUINO Software 1.6.9

Tento softvér priamo obsahuje knižnicu Wire.h pre komunikáciu cez I2C zbernicu pomocou SDA a SCL vývodov. Na doske pre Arduino Uno sú vývody SDA a SCL umiestnené blízko AREF pinu. Knižnica používa 7-bit adresy zariadení pričom adresy 0-7 sú rezervované.


Popis riešenia

Zapojenie senzora

Senzor s ktorým sme pracovali bol už osadený na doske plošných spojov. Po kontrole dosky sme zistili že výrobca pri osádzaní postupoval podľa odporúčaní datasheetu a pridal aj stabilizátory napätia, pre kompatibilitu s 5V logikou.

PCB layout odporúčaný výrobcom
Modul s HMC5883L a stabilizátormi napäatia


Schéma zapojenia modulu

Algoritmus

Na začiatku programu definujeme použité knižnice. Taktiež definujeme adresu HMC5883L a dve premenné flag a lockHeading.

#include <Wire.h>

#define addr 0x1E

int flag;
float lockHeading;


Nastavenie

Definujeme funkciu setup a spustíme sériovú linku, I2C zbernicu.

void setup()
{
  Serial.begin(9600);
  Wire.begin();

Senzor nastavíme do kontinuálneho meracieho režimu.

  Wire.beginTransmission(addr);
  Wire.write(0x02);
  Wire.write((byte)0x00);
  Wire.endTransmission();

Po sériovej linke pošleme informácie pre užívateľa.

  Serial.println("WELCOME TO iNAV");
  Serial.println("Press button when heading in desired direction and system will lock on.");  
  Serial.println();
  Serial.println();

Počkáme na ustálenie systému a uzavrieme funkciu setup.

  delay(500);
}


Telo programu

Definujeme funkciu loop a premenné pre výsledky pre jednotlivé osi.

void loop()
{
  int x,y,z;

Register pointer senzoru nastavíme na adresu 0x03.

  Wire.beginTransmission(addr);
  Wire.write(0x03);
  Wire.endTransmission();

Prečítame bit na adrese 0x03, uložíme ho ako MSB x-osi. Po prečítaní bitu sa register pointer posunie o jednu adresu a teda prečítame dáta na adrese 0x04 t.z. LSB x-osi. Bitovými operáciami skombinujeme MSB a LSB do jedného 16 bitového čísla. Takto prečítame všetkých 6 dátových bitov.

  Wire.requestFrom(addr, 6);
  if(6<=Wire.available())
     {
      x = Wire.read()<<8; //MSB  x 
      x |= Wire.read(); //LSB  x
      z = Wire.read()<<8; //MSB  z
      z |= Wire.read(); //LSB z
      y = Wire.read()<<8; //MSB y
      y |= Wire.read(); //LSB y
     }

Získané dáta prepočítame na stupne. Keďže iba kompasom nevieme zistiť orientáciu v priestore, smerovanie počítame iba v rovine XY.

  float heading = atan2((double)y,(double)x)*(180/3.1416)+180;

Zistíme či tlačidlo nieje stlačené.

 int key = analogRead(A3);

 if(key>1000)
   {

Ak tlačidlo bolo stlačené tak si smer z premennej heading uložíme do premenej lockHeading a povolíme príznak stlačenia tlačidla flag.

    Serial.println("!!! LOCKED ON !!!");
    Serial.print("HEADING > ");
    Serial.print(heading); 
    Serial.println("Deg");
 
    lockHeading=heading;
    flag=1;
   }

Ak bol požadovaný smer nastavený pokračujeme v podmienke.

 if(flag==1)
 {

Ak je rozdiel heading - lockHeading > 0 znamená to že ak chce užívateľ smerovať v požadovanom smere musí sa otočiť doľava. Vypíšeme odchýlku od žiadaného smeru v stupňoch a smer potrebnej korekcie.

   if((heading - lockHeading)>0)
   {
     Serial.print("Turn left by ");
     Serial.print(abs((heading - lockHeading)));
     Serial.println("Deg");
   }

Ak je rozdiel heading - lockHeading < 0 znamená to že ak chce užívateľ smerovať v požadovanom smere musí sa otočiť do prava. Vypíšeme odchýlku od žiadaného smeru v stupňoch a smer potrebnej korekcie.

   else
   {
     Serial.print("Turn right by ");
     Serial.print(abs((heading - lockHeading)));
     Serial.println("Deg");
   }
 }

Počkáme na ďalší merací cyklus.

 delay(1500);
}