neděle 7. prosince 2014

OpenWRT a akcelerometr + kompas + gyro

Po zprovoznění I2C sběrnice si k ní můžeme připojit například obvody LSM303DLHC (akcelerometr + kompas) a nebo gyroskop L3GD20, vše skvěle zabaleno na STM32F3 Discovery Boardu. Na Discovery Boardu je nutné vymazat paměť MCU aby nám do komunikace "nekecal" a propojit následující vývody: PB6 na PA5, PB7 na PA7 a v neposlední řade zapojit PA6, tedy pin SA0 gyra, na logickou jedničku (výběr I2C módu).



Pomocí i2cdetect si vyhledáme dostupná zařízení:

root@OpenWrt:/tmp# i2cdetect -y 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- 19 -- -- -- -- 1e --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- 6b -- -- -- --
70: -- -- -- -- -- -- -- --

Akcelerometr má dle dokumentace adresu 00011001=0x19, digitální kompas 00001110=0x1e a nakonec gyroskop 1101010=0x6A nebo 1101011=0x6B, v závislosti na zapojení adresního pinu. Nejnižší bit adresy gyroskopu tvoří právě stav nožičky SDO.

Nyní si již stačí prostudovat významy registrů a můžeme začít laborovat s daty. Dále následuje jednoduchý příklad čtení hodnot X, Z a Y z kompasu.

#/bin/ash

# inicializace
# CRA_REG_M (00h)
# TEMP_EN | 0 | 0 | DO2 | DO1 | DO0 | 0 | 0 |
# DO2 | DO1 | DO0 | Minimum data output rate (Hz)
#  0  |  0  |  0  | 0.75
#  0  |  0  |  1  | 1.5
#  0  |  1  |  0  | 3.0
#  0  |  1  |  1  | 7.5
#  1  |  0  |  0  | 15
#  1  |  0  |  1  | 30
#  1  |  1  |  0  | 75
#  1  |  1  |  1  | 220

i2cset -y 0 0x1e 0x00 0x9c # 220 Hz, teploměr povolen

# CRB_REG_M (01h)
# GN2 | GN1 | GN0 | 0 | 0 | 0 | 0 | 0 |
# GN2 | GN1 | GN0 | Sensor input field range [Gauss] | Gain X, Y, and Z [LSB/Gauss] | Gain Z [LSB/Gauss] 
#  0  |  0  |  1  | +-1.3 | 1100 | 980
#  0  |  1  |  0  | +-1.9 | 855  | 760
#  0  |  1  |  1  | +-2.5 | 670  | 600
#  1  |  0  |  0  | +-4.0 | 450  | 400
#  1  |  0  |  1  | +-4.7 | 400  | 355
#  1  |  1  |  0  | +-5.6 | 330  | 295
#  1  |  1  |  1  | +-8.1 | 230  | 205

i2cset -y 0 0x1e 0x1 0xE0 # +-8.1 Gauss

# MR_REG_M (02h)
# 0 | 0 | 0 | 0 | 0 | 0 | MD1 | MD0 |
# MD1 | MD0 | Mode |
#  0  |  0  | Continuous-conversion mode
#  0  |  1  | Single-conversion mode
#  1  |  0  | Sleep mode. Device is placed in sleep mode
#  1  |  1  | Sleep mode. Device is placed in sleep mode

i2cset -y 0 0x1e 0x2 0x00 # Continuous-conversion mode

while true; do
   X=`i2cget -y 0 0x1e 0x3 w` # Xsová osa
   Z=`i2cget -y 0 0x1e 0x5 w` # Zetová osa
   Y=`i2cget -y 0 0x1e 0x7 w` # Ylonová osa
   Teplota=`i2cget -y 0 0x1e 0x31 w` # teplota
   #echo "X=$X,Z=$Z,Y=$Y"
   echo -e "$X\t$Z\t$Y\t$Teplota"
done



Obrázek znázorňuje zápis na adresu 0x00, zápis je uvozen start bitem, dále následuje 7bitů adresy, příznak čtení či zápisu (log. 1 = čtení, log. 0 = zápis) a potvrzení od senzoru (ACK). Dalším bajtem je adresa, tedy 0x00, a zapisovaná hodnota 0x9C, každý přijatý bajt je se slavem potvrzen.


Tento obrázek naopak znázorňuje čtení jedné hodnoty intenzity magnetického pole z registrů 0x03 a 0x04, načtená hodnota je 0xfdff. Nejprve je zaslána (zapsána) adresa a poté už čteme data.

Nyní bude potřeba se naučil používat matematické funkce, jako je například arkus tangens. K tomu stačí donistalovat knihovnu bc (opkg install bc). Dále je nutné příkaz správně zapsat, vypočteme si tedy sinus 0 a Ludolfova čísla. Parametr s znamená funkce sinus, přepínač -l tyto funkce "zapíná":

root@OpenWrt:/tmp# echo "s(0)" | bc -l
0
root@OpenWrt:/tmp# echo "s(3.14/2)" | bc -l
.99999968293183462021

Funguje to, jdeme na arkus tangens. Pomocí následujícího výpočtu tedy získáme úhel, kde máme zrovna sever. Ano dělení pro X=0 to nepůjde ale naštěstí se to tak často nestává (:-)
echo "180*a($Y/$X)/3.14" | bc -l

A máme jednoduchý kompas, výsledný cyklus bude tedy vypadat takto:

while true; do
   X=`i2cget -y 0 0x1e 0x3 w` # Xsová osa
   Z=`i2cget -y 0 0x1e 0x5 w` # Zetová osa
   Y=`i2cget -y 0 0x1e 0x7 w` # Ylonová osa
   Teplota=`i2cget -y 0 0x1e 0x31 w` # teplota
   #echo "X=$X,Z=$Z,Y=$Y"
   Xhex="${X//0x/}" # nahradíme 0x za nic
   Zhex="${Z//0x/}"
   Yhex="${Y//0x/}"
   Xhex="$(echo $Xhex | tr [a-f] [A-F])"
   Zhex="$(echo $Zhex | tr [a-f] [A-F])"
   Yhex="$(echo $Yhex | tr [a-f] [A-F])"

    Xvalue=$(echo "ibase=16; $Xhex" | bc) # HEX na BIN
   Zvalue=$(echo "ibase=16; $Zhex" | bc)
   Yvalue=$(echo "ibase=16; $Yhex" | bc)
   echo -e "$Xvalue\t$Zvalue\t$Yvalue\t$Teplota"
   echo "180*a($Yvalue/$Xvalue)/3.14" | bc -l
done

Jak otestovat funkčnost? Pokoušel jsem se přibližovat magnet po Zetové ose (červená), z obrázku je patrné jak dochází k ovlivňování všech os. Ale Zetová přeteče nejdříve a má také nejstrmější nárůst.


Dalším testem bylo kroužení magnetem okolo kompasu.

Výsledný vypočtený úhel by jistou sinusovitost pře notné dávce představivosti mohl vykazovat.


Pokračování? Co to takhle z legrace napsat v céčku?

Datasheet k LSM303DLHC
Datasheet L3GD20
Počítání v příkazové řádce

Žádné komentáře:

Okomentovat