Genuino101CurieIMUOrientationVisualiser

Bu eğitimde, ivmeölçerin ve jiroskopun X, Y ve Z değerlerini okumak için Genuino 101'in yerleşik 6 eksenli ivmeölçer / jiroskopun nasıl kullanılacağı gösterilmektedir. Jiroskop tahtanın yönünü belirlerken, ivmeölçer tahtanın açısal hızını ölçer. İvmeölçer ve jiroskop birlikte, kartın yönünü tam olarak tanımlamak için kullanılabilen bir Ataletsel İzleme Birimi (IMU) oluşturur. Bu örnekte Madgwick'in filtre algoritması, 6 eksenin değerlerinden kareler hesaplamak için kullanılır. Bundan sonra, çeyrekler, İşleme tarafından alınan ve bir nesnenin X, Y ve Z eksenleri etrafındaki dönüşünü kontrol etmek için kullanılan Euler açılarını Pitch, Yaw ve Roll hesaplamak için kullanılır.

Gerekli Donanım

CurieIMU kütüphanesi Genuino / Arduino 101 içine yerleştirilmiş IMU'yu (ivmeölçer + jiroskop) kullanır.

Talimatlar

  1. Arduino yazılımını (IDE) Arduino 101'e Başlarken bölümünde açıklandığı gibi kurun .
  2. 101'i bilgisayarınıza bağlayın.
  3. Arduino yazılımını (IDE) başlatın ve Araçlar> Pano menüsünden Arduino / Genuino 101'i seçin.
  4. Madgwick kütüphanesini kütüphane yöneticisinden yükleyin. Bunu yapmak için Arduino Yazılımını (IDE) açın, "Çizim -> Kitaplığı Dahil Et -> Kitaplıkları Yönet" e gidin. Orada 'Madgwick'i arayabilir ve kütüphaneyi doğrudan oradan kurabilirsiniz. Kitaplıkları yükleme ve içe aktarma hakkında daha ayrıntılı bir açıklama için lütfen kitaplıklar kurulum kılavuzuna bakın.
  5. İşleme yazılımını indirin ve başlatın ve aşağıda gösterilen İşleme koduyla bir dosya oluşturun.
  6. Seri bağlantı noktasını 101'inizin kullandığı portla değiştirin (bkz. "Çizimin İşlenmesi" bölümü).
  7. Madgwik kütüphanesinde bulunan örneği Visualizer101 adlı örneğe 101 yükleyin ve kartın düz ve kırtasiye olduğundan emin olun, böylece kalibrasyonu doğru şekilde gerçekleştirin.
  8. Birkaç saniye sonra, İşleme çizimini çalıştırın, tahtanızın yönünü ayarlayın ve İşleme çizimi, tahtanızın bir görselleştirmesini verirken izleyin. Pocessing, Madgwick kütüphanesinin "ekstralar" klasöründe bulunur.

Devre

Nasıl çalışır

Madgwick filtre algoritması açık kaynaklıdır ve Madgwick'in bilgi ve raporlarında iyi bir şekilde belgelenmiştir. Madgwick filtre algoritması, doktora çalışması sırasında Sebastian Madgwick tarafından geliştirilmiştir. ve düşük örnekleme oranlarında bile hesaplamalı olarak ucuz ve verimli olacak şekilde tasarlanmıştır. Algoritma bir jiroskop ve ivmeölçerden ham değerleri alır ve bunları, etrafında dönme meydana gelen ekseni temsil etmek için x , y ve z değerleri içeren 4 boyutlu sayılar olan dört dördüncüyü ve ω değerini döndürmek için kullanır. aynı eksen etrafında oluşan dönme değerini temsil eder. Bu kuaterniyonlar Euler açıları eğimini, sapmasını ve yuvarlanmasını hesaplamak için kullanılabilir; 1700'lerde Leonhard Euler tarafından sunulan rijit bir cismin yönünü x , y ve z cinsinden tanımlamak için kullanılan üç açı. Madgwick'in Raporundaki denklemler (7) (8) (9) eğim, yuvarlanma ve sapma değerlerini hesaplamak için kullanılır ve işlevleri kütüphaneye dahil edilir.

Arduino / Genuino 101'in İşlemdeki yerleşik IMU'sunun, kartın yaptığı gibi hareket edecek bir 3D temsilini oluşturabiliriz. Bu, Madgwick filtre algoritması ile elde edilen Euler açı eğimi, yuvarlanma ve sapma değerleri ile elde edilir. Bu değerler daha sonra Seri İşleme'den gönderilebilir ve Arduino 3D modelinin konumunu hesaplamak için İşleme yöntemlerinin açı bağımsız değişkenleri olarak şu yöntemleri kullanarak kullanılabilir: applicationMatrix () , https://processing.org/reference/pushMatrix_.htmlpushMatrix ve popMatrix () fonksiyonları.

Arduino Kroki

Çizim, ivmeölçer / cayrodan veri almak için CurieIMU kitaplığı içindeki işlevleri kullanır.

İşleme'de 3D temsili görmek için Arduino taslağının iki ana işlevi içermesi gerekir; sapma, eğim ve yuvarlanma değerlerini hesaplamak için IMU verilerini ve algoritmasını kullanma ve bu değerleri İşleme'ye göndermek için el sıkışma şeklinde seri iletişimin etkinleştirilmesi.

İlk olarak, kütüphanedeki Madgwick sınıfından işlevlere erişmek için bir Madgwick nesnesi oluşturmalıyız. Burada filtre diyoruz:

Madgwick filter;
[Kodu Al]
setup() işlevinde, ivmeölçer ile cayro ve filtrenin örnek hızını 25Hz olarak ayarlayarak CurieIMU'nun ön yapılandırmasını gerçekleştiririz:
CurieIMU. begin ( ) ;
CurieIMU. setGyroRate ( 25 ) ;
CurieIMU. setAccelerometerRate ( 25 ) ;
Filtre. başlar ( 25 ) ;
Sonra ivmeölçer aralığını 2g ve cayro aralığını 250 ° / s olarak ayarladık:
CurieIMU. setAccelerometerRange ( 2 ) ;
CurieIMU. setGyroRange ( 250 ) ;
loop() işlevinde, CurieIMU okuması için ayarladığımız örnekleme oranına göre bir örnek göndermemiz gerekecek:
microsPerReading = 1000000/25;
Daha sonra ivmeölçer ve jiroskop verilerini CurieIMU kütüphanesinden aşağıdaki işlevleri kullanarak 'alabiliriz' ve ham verileri ivme (g) ve açısal hıza (° / s) dönüştürebiliriz:
CurieIMU. readMotionSensor ( aix , aiy , aiz , gix , giy , giz ) ;

// ham verilerden yerçekimi ve derece / saniye birimine dönüştür
ax = convertRawAcceleration ( aix ) ;
ay = convertRawAcceleration ( aiy ) ;
az = convertRawAcceleration ( aiz ) ;
gx = convertRawGyro ( gix ) ;
gy = convertRawGyro ( giy ) ;
gz = convertRawGyro ( giz ) ;
Daha sonra Madgwick kütüphanesinden updateIMU () fonksiyonunu kullanabiliriz.
Filtre. updateIMU ( gx , gy , gz , balta , ay , az ) ;
Bundan sonra, rulo, ilik ve sapma değerlerini filtreden elde etmeye hazırız:
roll = filtre. getRoll ( ) ;
pitch = filtre. getPitch ( ) ;
başlık = filtre. getYaw ( ) ;
Bu değerler seri port üzerinden saniyede 25 kez İşleme uygulamasına gönderilir.

Kodda görüldüğü gibi, jiroskop değerleri değişken bir faktör tarafından ölçeklendirilmiştir, böylece algoritma ile iyi çalışan bir aralığa sığarlar. Bu ölçeklendirme olmadan, fonksiyona girilen değerler çok yüksektir ve tahta hareketinin görselleştirilmesi, 101'in pozisyonundaki küçük değişikliklere karşı çok hassas hale gelir, küçük bir değişikliği büyük bir değişiklik olarak yorumlar ve 'sanal' panoya neden olur döndürmek.

Tam kodu sayfanın alt kısmında bulabilirsiniz.

Gx, gy, gz, ax, az, ay için seri baskıların hata ayıklama için yorumlarda döngü içinde kaldığını ve İşleme ile iletişim kurulurken yorumlanması gerektiğini unutmayın.

Çizim İşleme

Henüz varsa, yapmanız gereken ilk şey den İşleme son sürümünü indirmek için olduğunu processing.org . İşleme, kullanıcının tanıdık void setup() ve void loop() yapısında dinamik görüntüler çizmesine izin veren Arduino'ya benzer bir dildir. İşleme özelliğini kullanma hakkında daha fazla bilgi için lütfen Başlangıç kılavuzunu ziyaret edin.

İşleme kodu, daha sonra Arduino kartının 3D modelini hareket ettiren dönüşüm matrisini hesaplamak için kullanılan, ayrıştırılan ve yaw , pitch ve roll atanan seri porttan gelen verileri alır.

İşleme'nin Arduino'nun gönderdiği bağlantı noktasından okumasını sağlamak için myPort'un seri bağlantı noktası adınızla değiştirilmesi gerekir. Setup () öğesinde, bu Seri'nin ikinci parametresidir.

myPort = yeni Seri ( bu , Seri . listesi ( ) [ 0 ] , 9600 ) ;
Doğru bağlantı noktası, Seri sınıfından list () işlevi kullanılarak bulunabilir. Köşeli parantez içindeki sayı, seri bağlantı noktasının numarasını gösterir ve 0, 1, 2 vb. Olacaktır. Makinenizde yalnızca bir COM bağlantı noktası varsa çizim çalışır. Alternatif olarak, 101 kartının " COMx " bağlantı noktasını - 101 kartından Arduino Software (IDE) programlamak için kullanılan - doğrudan bu satırı yorumlayabilirsiniz
myPort = yeni Seri ( bu , Seri . listesi ( ) [ 0 ] , 9600 ) ;

ve işletim sisteminize karşılık gelen hatların açılması:

myPort = yeni Seri ( bu , "COM5:" , 9600 ) ; // Pencereler
myPort = yeni Seri ( bu , "/ dev / ttyACM0" , 9600 ) ; // Linux
myPort = yeni Seri ( bu , "/dev/cu.usbmodem1217321" , 9600 ) ; // Mac

Bağlantı noktası dizesini, COM bağlantı noktanız için doğru adla değiştirmeniz gerekir.

Şüpheniz varsa, bu adı belirlemek için mevcut seri bağlantı noktalarınızın listesini ayrı bir çizimde yazdırabilirsiniz .

Daha sonra serialEvent () işlevi veri almak ve ayrıştırmak için kullanılır.

void serialEvent ( )
{
int newLine = 13 ; // ASCII'de yeni satır karakteri
Dize mesajı ;
yapmak {
message = myPort. readStringUntil ( newLine ) ; // porttan yeni satıra kadar oku
if ( mesaj ! = boş ) {
String [ ] list = bölünmüş ( kırpma ( mesaj ) , "" ) ;
if ( liste. uzunluk > = 4 && liste [ 0 ] . eşittir ( "Yönlendirme:" ) ) {
yaw = şamandıra ( liste [ 1 ] ) ; // yalpaya dönüş
zift = şamandıra ( liste [ 2 ] ) ; // şamandıra aralığına dönüştür
roll = şamandıra ( liste [ 3 ] ) ; // şamandıra rulosuna dönüştür
}
}
} while ( mesaj ! = boş ) ;
}
Bu seri bağlantı noktasından ASCII karakteri 13'e (yeni satır) kadar okur ve virgül karakterini kullanarak değerleri ayırmak için split () işlevini kullanır. Arduino'dan yaw, pitch, roll sırayla gönderdiğimizi bildiğimiz için, her dizeyi bir kayan noktaya dönüştürebilir ve bunları String dizisi listesindeki [] ilk üç değere atayabiliriz. Dizeler daha sonra şamandıralara dönüştürülür ve şamandıra değişkenlerinde saklanır. Tam Arduino ve İşleme çizimleri aşağıda görülebilir.

Kod

Arduino Kodu

#include <CurieIMU.h>
#include <MadgwickAHRS.h>

Madgwick filtresi ;
imzasız uzun microsPerReading , microsPrevious ;
float accelScale , gyroScale ;

void setup ( ) {
Seri . başlar ( 9600 ) ;

// IMU'yu başlatın ve filtreleyin
CurieIMU. begin ( ) ;
CurieIMU. setGyroRate ( 25 ) ;
CurieIMU. setAccelerometerRate ( 25 ) ;
Filtre. başlar ( 25 ) ;

// İvmeölçer aralığını 2G olarak ayarlayın
CurieIMU. setAccelerometerRange ( 2 ) ;
// Jiroskop aralığını 250 derece / saniyeye ayarlayın
CurieIMU. setGyroRange ( 250 ) ;

// güncellemeleri doğru hıza ayarlamak için değişkenleri başlat
microsPerReading = 1000000/25;
microsPrevious mikrosaniye () =;
}

void loop ( ) {
int aix , aiy , aiz ;
int gix , giy , giz ;
şamandıra baltası , ay , az ;
şamandıra gx , gy , gz ;
şamandıra rulosu , eğim , yön ;
İşaretsiz uzun microsNow;

// veri okuma ve filtreyi güncelleme zamanının geldiğini kontrol et
microsNow mikrosaniye () =;
if ( microsNow - microsPrevious > = microsPerReading ) {

// CurieIMU'dan ham verileri oku
CurieIMU. readMotionSensor ( aix , aiy , aiz , gix , giy , giz ) ;

// ham verilerden yerçekimi ve derece / saniye birimine dönüştür
ax = convertRawAcceleration ( aix ) ;
ay = convertRawAcceleration ( aiy ) ;
az = convertRawAcceleration ( aiz ) ;
gx = convertRawGyro ( gix ) ;
gy = convertRawGyro ( giy ) ;
gz = convertRawGyro ( giz ) ;

// yönü hesaplayan filtreyi güncelleyin
Filtre. updateIMU ( gx , gy , gz , balta , ay , az ) ;

// başlığı, eğimi ve ruloyu yazdırma
roll = filtre. getRoll ( ) ;
pitch = filtre. getPitch ( ) ;
başlık = filtre. getYaw ( ) ;
Seri . print ( "Yönlendirme:" ) ;
Seri . baskı ( başlık ) ;
Seri . yazdır ( "" ) ;
Seri . baskı ( adım ) ;
Seri . yazdır ( "" ) ;
Seri . println ( rulo ) ;

// bir önceki seferki artışı artırdığımızdan, uygun hızı koruyoruz
microsPrevious = microsPrevious + microsPerReading ;
}
}

float convertRawAcceleration ( int aRaw ) {
// 2G serisini kullandığımız için
// -2g ham değeri -32768 ile eşleşir
// + 2g, 32767 ham değerine eşlenir

şamandıra a = ( aRaw * 2.0 ) / 32768.0 ;
dönüş a ;
}

float convertRawGyro ( int gRaw ) {
// 250 derece / saniye aralık kullandığımız için
// -250, -32768 ham değerine eşlenir
// +250, 32767 ham değerine eşlenir

şamandıra g = ( gRaw * 250.0 ) / 32768.0 ;
dönüş g ;
}

İşleme Kodu

ithalat işlemi. seri . *;
Seri myPort ;

şamandıra sapma = 0.0 ;
şamandıra aralığı = 0.0 ;
şamandıra rulosu = 0.0 ;

geçersiz kurulum ( )
{
boyut ( 600 , 500 , P3D ) ;

// yalnızca bir seri bağlantı noktanız etkinse
myPort = yeni Seri ( bu , Seri . listesi ( ) [ 0 ] , 9600 ) ; // yalnızca bir seri bağlantı noktanız etkinse

// seri bağlantı noktası adını biliyorsanız
// myPort = yeni Seri (bu, "COM5:", 9600); // Pencereler
// myPort = yeni Seri (bu, "/ dev / ttyACM0", 9600); // Linux
// myPort = yeni Seri (bu, "/dev/cu.usbmodem1217321", 9600); // Mac

textSize ( 16 ) ; // metin boyutunu ayarla
textMode ( ŞEKİL ) ; // metin modunu şekle ayarla
}

geçersiz çekiliş ( )
{
serialEvent ( ) ; // gelen seri mesajı oku ve ayrıştır
arka plan ( 255 ) ; // arka planı beyaz olarak ayarla
ışıklar ( ) ;

tercüme ( genişlik / 2 , yükseklik / 2 ) ; // konumu merkeze ayarla

pushMatrix ( ) ; // nesneyi başlat

float c1 = cos ( radyan ( rulo ) ) ;
şamandıra s1 = günah ( radyan ( rulo ) ) ;
float c2 = cos ( radyan ( zift ) ) ;
şamandıra s2 = günah ( radyan ( zift ) ) ;
şamandıra c3 = cos ( radyan ( sapma ) ) ;
şamandıra s3 = günah ( radyan ( sapma ) ) ;
matrix ( c2 * c3 , s1 * s3 + c1 * c3 * s2 , c3 * s1 * s2 - c1 * s3 , 0 ,
- s2 , c1 * c2 , c2 * s1 , 0 ,
c2 * s3 , c1 * s2 * s3 - c3 * s1 , c1 * c3 + s1 * s2 * s3 , 0 ,
0 , 0 , 0 , 1 ) ;

drawArduino ( ) ;

popMatrix ( ) ; // nesnenin sonu

// Değerleri konsola yazdır
baskı ( rulo ) ;
yazdır ( " \ t " ) ;
baskı ( adım ) ;
yazdır ( " \ t " ) ;
baskı ( yaw ) ;
println ( ) ;
}

void serialEvent ( )
{
int newLine = 13 ; // ASCII'de yeni satır karakteri
Dize mesajı ;
yapmak {
message = myPort. readStringUntil ( newLine ) ; // porttan yeni satıra kadar oku
if ( mesaj ! = boş ) {
String [ ] list = bölünmüş ( kırpma ( mesaj ) , "" ) ;
if ( liste. uzunluk > = 4 && liste [ 0 ] . eşittir ( "Yönlendirme:" ) ) {
yaw = şamandıra ( liste [ 1 ] ) ; // yalpaya dönüş
zift = şamandıra ( liste [ 2 ] ) ; // şamandıra aralığına dönüştür
roll = şamandıra ( liste [ 3 ] ) ; // şamandıra rulosuna dönüştür
}
}
} while ( mesaj ! = boş ) ;
}

void drawArduino ( )
{
/ * işlevi, IMU ile döndürülen şekilleri içerir * /
inme ( 0 , 90 , 90 ) ; // anahat rengini daha koyu deniz mavisine ayarla
dolgu ( 0 , 130 , 130 ) ; // dolgu rengini daha açık deniz mavisine ayarla
kutu ( 300 , 10 , 200 ) ; // Arduino board taban şeklini çiz

inme ( 0 ) ; // anahat rengini siyah olarak ayarla
dolgu ( 80 ) ; // dolgu rengini koyu gri olarak ayarla

tercüme ( 60 , - 10 , 90 ) ; // konumu Arduino kutusunun kenarına ayarla
kutu ( 170 , 20 , 10 ) ; // pin başlığını kutu olarak çiz

tercüme ( - 20 , 0 , - 180 ) ; // konumu Arduino kutusunun diğer kenarına ayarla
kutu ( 210 , 20 , 10 ) ; // diğer pin başlığını kutu olarak çiz
}

See Also