Eğitimler
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
- Arduino yazılımını (IDE) Arduino 101'e Başlarken bölümünde açıklandığı gibi kurun .
- 101'i bilgisayarınıza bağlayın.
- Arduino yazılımını (IDE) başlatın ve Araçlar> Pano menüsünden Arduino / Genuino 101'i seçin.
- 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.
- İşleme yazılımını indirin ve başlatın ve aşağıda gösterilen İşleme koduyla bir dosya oluşturun.
- Seri bağlantı noktasını 101'inizin kullandığı portla değiştirin (bkz. "Çizimin İşlenmesi" bölümü).
- 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.
- 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:
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. setGyroRate ( 25 ) ;
CurieIMU. setAccelerometerRate ( 25 ) ;
Filtre. başlar ( 25 ) ;
CurieIMU. setGyroRange ( 250 ) ;
loop()
işlevinde, CurieIMU okuması için ayarladığımız örnekleme oranına göre bir örnek göndermemiz gerekecek: // 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 ) ;
pitch = filtre. getPitch ( ) ;
başlık = filtre. getYaw ( ) ;
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.
ve işletim sisteminize karşılık gelen hatların açılması:
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.
{
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ş ) ;
}
Kod
Arduino Kodu
#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
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
}