İçindekiler:

Wallace - Kendin Yap Otonom Robot - Bölüm 5 - IMU Ekle: 9 Adım
Wallace - Kendin Yap Otonom Robot - Bölüm 5 - IMU Ekle: 9 Adım

Video: Wallace - Kendin Yap Otonom Robot - Bölüm 5 - IMU Ekle: 9 Adım

Video: Wallace - Kendin Yap Otonom Robot - Bölüm 5 - IMU Ekle: 9 Adım
Video: İskoçya ve İrlanda’da Tarih, Kültür - Atilla TUNA 2024, Aralık
Anonim
Image
Image

Wallace ile birlikte ilerliyoruz. Wallace adı, "Wall-E"nin bir karışımından ve önceki bir projeden (ses tanıma) geldi ve "espeak" yardımcı programını kullanırken kulağa biraz İngiliz geliyordu. Ve bir uşak ya da uşak gibi. Ve nihai hedef de bu: bu projenin faydalı bir şeye dönüşmesi. Böylece "Wallace".

Wallace hareket edebilir, IR mesafe sensörlerini kullanarak engellerden kaçınabilir (son zamanlarda, bir şekilde kızardılar(?) (bir şansım olduğunda buna bakmak zorundayım), ayrıca bazı akustik mesafe sensörleri de var (bunlardan üçü aynı anda bozuldu) zaman, bir MCP23017 genişletici ile birlikte) ve son olarak, bir şeye ne zaman çarptığını bilmek için motor akımındaki değişiklikleri algılayabilir.

Sensörlere ek olarak, Wallace 100 hareketi "hatırlar" ve hareket geçmişini kullanarak bazı temel analizlere sahiptir.

Wallace'ın şu ana kadarki hedefi, yalnızca ilerlemeye devam etmeye çalışmak ve ne zaman tekrar eden bir düzende (örneğin bir köşede) takılıp kaldığını ve gerçekten ilerlemediğini bilmektir.

Hareket ve navigasyon için birkaç yinelemeden geçtim ve sürekli baş ağrısı rotasyon sırasında oldu.

Wallace izlenen bir robot olduğundan ve yazılımda işleri daha basit tutmak istedim (daha sonra için), döndürmek için sadece yerinde döndürmesini/döndürmesini sağladım. Böylece motorlara eşit fakat zıt güç/görev çevrimi uygulayın.

Karşılaşılan sorun, Agent 390 robot platformunun tasarımından kaynaklanmaktadır. Palet kayışları yanlara sürtünme eğilimindedir. Daha da kötüsü, bir taraf bunu diğerinden daha fazla yapıyor.

Döşemede ve düz giderken sorun olmadı. Halı üzerinde ortaya çıkıyor. İzleri kirlendikten sonra Wallace'ı halıdan uzak tutmayı seçtim (kiri çok kolay toplarlar).

Asıl sorun, döşeme üzerinde dönerken.

Yazılımın yüksek düzeyde bir görev döngüsü uygulamasına sahipsem, o zaman aşağı yukarı tutarlı bir şekilde döner. Bununla birlikte, düşük bir görev döngüsü sırasında, gerçekten dönebilir veya dönmeyebilir. Veya biraz dönebilir ve sonra yavaşlayabilir. Döndürme eylemi, yazılım aracılığıyla kontrol edilemez veya en iyi ihtimalle çok zor görünüyor.

Sorun, navigasyon sırasında ve engellerin etrafından dolaşırken veya engellerden uzaklaşırken ortaya çıkıyor. Ya çok çılgınca uzaklaşabilir ya da gerçekten hareket etmeden çok küçük vardiyalar yapmaya çalışırken sıkışabilir.

Ve böylece yukarıdaki açıklama bu Eğitilebilirliği motive etti.

Başlangıçta, bir hareket algılama biriminin (IMU) tanıtılmasından vazgeçmek veya gecikmek istedim, çünkü bunlar A) karmaşık, B) gürültülü, C) hatalar zamanla ortaya çıkabilir, vb. uçuş süresi IR lazer sensörlerine atlayarak çok iyi yapabileceğimizdi. Ve lazerleri kullanarak, mesafedeki değişiklikleri izleyerek robotun dönüp dönmediğini bilebiliriz.

Aslında bunu akustik sensörlerle de (bir nevi) şimdi yapabiliriz.

Ancak tüm bunlar, basit bir soruyu yanıtlamanın çok dolaylı, karmaşık bir yoludur: "Döndük mü, dönmedik mi?"

ToF lazer sensörlerini kullanmak için atlamak beni bir sonraki yazılım düzeyine götürecekmiş gibi geldi; yani, SLAM (Simultaneous Localization and Mapping). Henüz oraya gitmeye hazır değildim.

Bir robot projesini katmanlar halinde yapmak iyi bir şeydir, ilk (alt) katmanlar daha basit ve sonraki (üst) katmanlar daha soyut ve daha zor konularla uğraşıyor.

Katmanlar şöyle düşünülebilir:

  1. robot fiziksel çerçevesi / mekanik yapısal temel
  2. ilkel sürücü sistemi (Ahududu, Roboclaw, motorlar, kablolama, vb., temel yazılım, klavyeyle çalışan)
  3. sensörleri desteklemek için gerekli devreler (çift yönlü voltaj değiştirici, port genişletici, E-Stop, güç dağıtımı, vb.)
  4. engellerden kaçınma sensörleri (akustik, IR)
  5. temel, temel konumlandırma ve hareket algılama (ivmeölçer, jiroskop, manyetometre, motor kodlayıcılar, tekerlek kodlayıcılar)

Kendi listenizi oluşturabilirsiniz. Bu listeyle ilgili noktalar, muhtemelen bunları aşağı yukarı bu sırayla yapmanız gerektiği ve ayrıca her bir katmanı iyi bir çalışma durumuna getirmek için biraz zaman harcarsanız, işler daha karmaşık hale geldikçe bunun size yardımcı olacağıdır.

Yukarıdaki liste, yazılımdaki bu kavramsal katmanlarla aşağı yukarı eşleştirilebilir.

  • SLAM (Eş Zamanlı Lokalizasyon ve Haritalama)
  • Hareket, Dönme Kontrolü ve Farkındalığı
  • Temel Engelden Kaçınma
  • Sensör Verilerinin Kontrolü ve Tespiti
  • Temel Hareket İleri, Geri, Sol ve Sağ, Hızlanma, Yavaşlama, Durma

Gördüğünüz gibi, bu liste için ilk öğeler, "neredeyim" ve "nereye gidiyorum" gibi daha soyut konuları ve soruları ele alan üst, daha karmaşık katmanlar olurken, sonraki öğeler ise "A sensörünün nasıl konuşulacağı/dinleneceği" veya "bu tekerleğin nasıl hareket ettirileceği" ile ilgilenen alt yazılım katmanları.

Şimdi, bir katmanda başladığınızda, onu tamamlamış olacaksınız ve bir sonraki katmanda olacak, asla bir öncekine geri dönmeyecek demiyorum. Bir robot projesi, modern, yinelemeli yazılım geliştirme yöntemlerine (çevik, SCRUM, vb.) çok benzer olabilir.

Ben sadece her birine zaman ayırmayı söylüyorum. Her birinde ne kadar yapacağınızı dengelemeniz gerekecek ve belirli bir katmanda ne yapmaya çalıştığınıza zaman ve zahmete değecek karar vereceksiniz.

Rakip iki fikir veya yön arasında belirli bir "çatışma" veya "gerilim" vardır.

Biri, A problemini çözmek için "tak-çalıştır" dediğim şeydir.

Diğeri ise DIY (kendin yap). Ve bu diğer fikir için en iyi etiket bile olmayabilir.

İşte her birine bir örnek, umarım iki seçenek arasındaki gerilimi veya çelişkiyi görürsünüz.

Bu örnek için, SLAM, engellerden kaçınma ve temel temel hareketi aynı anda çözülecek tek bir problem olarak ele alalım.

  1. Tak ve çalıştır yoluna gitmeye karar verirsek, hemen (bütçeye bağlı olarak) en üste monte edilen döner lazerler veya alan derinliği kamerası veya ToF lazerleri ve IMU (bunun konusu) gibi şeylere atlarız. Eğitilebilir).
  2. Öte yandan, ikinci rotaya gitmek istiyorsak, bazı akustik sensörlerden veya IR sensörlerinden mümkün olan her türlü bilgiyi çıkarmaya çalışabiliriz veya hiç sensör yok - sadece motor akımı izlemeyi kullanırız (çarpma)

#1 vs #2 hakkında ne söylenebilir? Bir şey, #2 yaparak çok daha fazlasını öğrenmiş olacağımız olurdu. Yalnızca akustik sensörlerle çalışmanın sınırlamaları, bizi çok daha fazla konu hakkında düşünmeye zorluyor.

Öte yandan, # 2 ile bir şeyler yapmaya çok odaklanırsak, akustik sensörlerden yapmamız gerekenden fazlasını istediğimiz için zaman kaybediyor olabiliriz.

Üzerinde düşünülmesi gereken bir kavram veya fikir daha: Hangi donanım ve yazılım karışımı "nasıl yapılır" sorularına en iyi yanıt verir ve hangi yazılım karışımı (ve donanım?) "ne", "ne zaman", "nerede" sorusuna yanıt verir.. Çünkü "nasıl yapılır" tipik olarak bir yanıt almak için "ne", "ne zaman" ve "nerede"nin bağlı olduğu daha düşük seviyeli bir sorudur.

Her neyse, yukarıdakilerin hepsi sadece düşünülmesi gereken bir şeydi.

Benim durumumda, çok çaba sarf ettikten ve sürekli rahatsız edici pist sürtünme sorunu yaşadıktan ve tutarlı kontrol ve hareket elde edemedikten sonra, başka bir şey yapmanın zamanı geldi.

Böylece bu Eğitilebilir - bir IMU.

Amaç, IMU robotun kendi ekseni etrafında dönmediğini söylerse görev döngüsünü artırmamızdır. Çok hızlı dönüyorsak, görev döngüsünü azaltırız.

Adım 1: IMU Sensörü

IMU Sensörü
IMU Sensörü
IMU Sensörü
IMU Sensörü

Ve Wallace'a eklenecek bir sonraki sensörümüz IMU'dur. Biraz araştırmadan sonra bir MPU6050'ye yerleşiyordum. Ancak o zamanlar MPU9050 (ve daha yakın zamanda MPU9250) daha da iyi bir fikir gibi görünüyordu.

Gitme kaynağım Amazon oldu (ABD'de). Bu yüzden iki tane sipariş ettim.

Aslında elde ettiğim şey (bunun üzerinde kontrol yok gibi görünüyor; Amazon hakkında sevmediğim şey bu) iki MPU92/65 idi. Tanımı biraz merak ediyorum. Görsellere bir göz atın; bu bir "aile" tanımı gibi görünüyor. Her durumda, benim takıldığım şey bu.

Eklemek çok basit - bağlantı rayları olan bir proto kartı alın, sensörü karta lehimleyin, 10 pimli vidalı bir terminal bloğu ekleyin (benimki Pololu'dan aldım).

Herhangi bir paraziti en aza indirmek için bu sensörleri her şeyden uzağa yerleştirmeye çalıştım.

Bu aynı zamanda bazı naylon cıvatalar/somunlar kullanmak anlamına geliyordu.

I2C protokolünü kullanacağım. Umarım toplam tel uzunluğu çok kötü olmaz.

Temel bağlantılar ve voltaj seviyeleri vb. hakkında başka yerlerde pek çok bilgi var, bu yüzden burada tekrar etmeyeceğim.

2. Adım: Her Şey Her Zaman Temiz ve Kolay Değildir

Bu yazıda, bu MPU-92/65 için çok fazla çevrimiçi görünmüyor. Mevcut olan, çoğu sensörde olduğu gibi, Arduino kullanan örnekler gibi görünüyor.

Çok temiz olmayan bir süreç sunarak bu Talimatları biraz farklı hale getirmeye çalışıyorum, çünkü işler her zaman hemen çalışmaz.

Sanırım bu Eğitilebilir Yazılar, düz A-B-C, 1-2-3 "bunu böyle yaparsın" dan daha çok bir bloga benziyor.

Adım 3: İlk Test

İlk test
İlk test
İlk test
İlk test

Bir önceki adımdaki görüntülerden sensörlere giden kırmızı ve siyah teller elbette VCC (5V) ve GND'dir. Yeşil ve sarı kablolar I2C bağlantılarıdır.

Başka I2C projeleri yaptıysanız veya bu serileri takip ediyorsanız, "i2cdetect" hakkında zaten bilgi sahibisinizdir ve bu, Raspberry'nin yeni sensörü görüp görmediğini bilmek için ilk adımdır.

Bu adımdaki resimlerden de görebileceğiniz gibi, ilk denememiz başarısız oldu. IMU görünmüyor (cihaz kimliği 0x68 olmalıdır).

Ancak iyi haber şu ki, I2C veriyolu çalışıyor. Bir cihaz 0x20 görüyoruz ve bu MCP23017 bağlantı noktası genişleticidir (şu anda HCSR04 akustik sensörlerinden sorumludur).

Resimde görmek kolay değil, ancak IMU'dan gelen aynı renkli yeşil ve sarı kabloları MCP23017'ye bağladım (resimde sol alt kısma bakın)

Bazı sorun giderme işlemleri yapmamız gerekecek.

4. Adım: Sorun Giderme

Image
Image
Sorun giderme
Sorun giderme
Sorun giderme
Sorun giderme

Bir voltmetrede (yüksek tonlu olan) süreklilik ayarını kullanarak VCC(5V), GND, SDA ve SCL bağlantılarını test ettim. Bunlar iyiydi.

Sonraki deneme, MCP23017'yi I2C veriyolundan ayırmak ve veriyolunda yalnızca MPU-92/65'i bırakmaktı. Bu sonuçsuz kaldı - "i2cdetect" daha sonra hiçbir cihaz göstermedi.

Ardından, sensörü totem direğinden çıkardım ve doğrudan 5V'den 3V'a çift yönlü veriyoluna yeniden bağladım; yani, doğrudan Ahududu'ya. (daha kısa teller?).

Ve işte. Bu sefer başarı var. "i2cdetect" kullanarak 0x68'in göründüğünü görüyoruz.

Ama bu sefer neden işe yaradığını henüz bilmiyoruz. Tellerin uzunluğundan olabilir mi? Önceki konum?

Not: ADO'nun topraklanmış olup olmaması herhangi bir fark yaratmadı. Yerleşik çekme ve aşağı çekme dirençleri olabilir. Aynısı FSYNC için de geçerli olabilir.

Ardından, MCP23017'yi yeniden bağladım. Yani şimdi I2C veriyolunda iki cihazımız var. (resme bakın). Başarılı, şimdi i2cdetect ile hem 0x20 hem de 0x68 görüyoruz.

Videolar, sorun giderme sırasında neler olduğuna biraz daha değiniyor.

Adım 5: Sensörün Verilerini Okuma

Image
Image
Sensörün Verilerini Okumak
Sensörün Verilerini Okumak
Sensörün Verilerini Okumak
Sensörün Verilerini Okumak

Çeşitli Yaklaşımlar

Sensörden faydalı bilgiler almak için birden fazla yaklaşım benimsemeye karar verdim. İşte bunlar, herhangi bir sırayla değil:

  1. bazı temel programlamayı deneyin
  2. kayıtlarla ilgili bazı çevrimiçi belgelere bakın
  3. başkalarının örneklerine ve/veya koduna bir göz atın

Neden bu yaklaşımlar? Neden sadece var olan bir kitaplığı veya kodu aramıyorsunuz?

Bazı fikirleri deneyerek ve deneyerek, yalnızca bu belirli sensör hakkında bazı bilgileri daha iyi özümseyebiliriz, aynı zamanda bazı teknikler, beceriler ve yeni bir şeyle ve çok fazla belgesi olmayan bir şeyle uğraşma hakkında düşünme yolları da kazanabiliriz; birçok bilinmeyene sahip olabilecek bir şey.

Ayrıca, kendi fikirlerimizle oynayıp bazı fikirlerimizi denedikten ve biraz fikir edindikten sonra, başka birinin kodunu veya kitaplığını değerlendirmek için daha iyi bir konumda oluruz.

Örneğin, github'da MPU9250 için bazı C++ kodlarına baktıktan sonra, bunun beni, henüz yapmak istemediğim kesintileri kullanmaya zorladığını fark ettim.

Ayrıca kalibrasyon gibi ekstra şeylerle birlikte gelir; yine, henüz ilgilenmediğim bir şey.

"Robot evet mi hayır mı dönüyor" basit soruyu cevaplamak için yapmam gereken şey, sadece bazı kayıtları okuyarak çok basit bir şekilde cevaplanabilir.

Kayıtlar

Bu yazıda, bu sensörde fazla bir şey yok gibi görünüyor. Aslında, bu Instructable ile birlikte gelen resimlere bir göz atarsanız ve gerçek çiplerin üzerindeki yazılara yakından bakarsanız, bunun bir nakavt olup olmadığını merak ediyorum. Gördüklerimi Invense'den hiçbir şeyle ilişkilendirmiyorum. Ne olursa olsun, bulduğum modeller için kayıt bilgilerine bakmayı seçtim: MPU-6050 ve MPU-9250.

Her iki durumda da aşağıdakiler her ikisi için de aynıdır. Ve yeni başlayanlar için, bunun bu MPU-92/65 için de aynı olacağını varsayıyoruz.

59 - 64 - ivmeölçer ölçümleri

65, 66 - sıcaklık ölçümleri 67 - 72 - jiroskop ölçümleri 73 - 96 - harici sensör verileri

Bir not: MPU-6050'de manyetometre YOK gibi görünürken, MPU-9250'de (bunu da varsayıyoruz) bir manyetometre var.

Kayıt belgesinden toplanan bazı daha ilginç, umarım yararlı bilgiler:

Manyetometre Bilgisi:

manyetometre kimliği: 0x48 kayıtları 00 - 09: 00H WIA 0 1 0 0 1 0 0 0 01H INFO INFO7 INFO6 INFO5 INFO4 INFO3 INFO2 INFO1 INFO0 02H ST1 0 0 0 0 0 0 DOR DRDY 03H HXL HX7 HX6 HX5 HX4 HX3 HX2 H HxH HX15 HX14 HX13 HX12 HX11 HX10 HX9 HX8 05H HYL HY7 HY6 Hy5 HY4 HY3 HY2 HY1 HY0 06H HYH HY15 HY14 HY13 HY12 HY11 HY10 HY9 HY8 saat 07 HZL HZ7 HZ6 HZ5 HZ4 HZ3 HZ2 HZ1 HZ0 08h HZH HZ15 HZ14 HZ13 HZ12 HZ11 HZ10 HZ9 HZ8 09h ST2 0 0 0 BITM HOFL 0 0 0 her kaydın ne anlama geldiğinin dökümü: HXL[7:0]: X ekseni ölçüm verileri daha düşük 8bit HXH[15:8]: X ekseni ölçüm verileri daha yüksek 8bit HYL[7:0]: Y ekseni ölçüm verileri daha düşük 8bit HYH[15:8]: Y ekseni ölçüm verileri daha yüksek 8bit HZL[7:0]: Z ekseni ölçüm verileri daha düşük 8bit HZH[15:8]: Z ekseni ölçüm verileri daha yüksek 8 bit

Programlama

Kayıt belgelerindeki diğer bir bilgi biti, yalnızca yaklaşık 100 kadar kayıt olduğu görülüyor. Bu yüzden bir taktik, cihaza (0x68) erişen ve sadece hangi verilerin görülebildiğini görmek için anlamlarına bakılmaksızın sırayla bir dizi kaydı okumaya çalışan basit bir program yazmak olabilir.

Ardından, aynı kodu kullanarak art arda geçişler yapın ve verileri bir geçişten diğerine karşılaştırın.

Buradaki fikir, verisi olmayan (sıfır veya FF?) veya kesinlikle hiç değişmeyen kayıtları muhtemelen ortadan kaldırabileceğimiz ve ayrıca değişenlere odaklanabileceğimizdir.

Ardından, yalnızca değişenlere bakıyoruz, o kayıt için gerçekten belirli bir sabit değer olup olmadığını görmek için o kaydın en son N okumalarının ortalamasını alan bir ortalama alma işlevi ekliyoruz. Bu, sensörü çok hareketsiz ve aynı yerde tuttuğumuzu varsayar.

Son olarak, sensörle hafifçe dürtmek (ivmeölçer, jiro) veya üzerine üflemek (sıcaklık) veya döndürmek (önceki iki artı manyetometre) gibi şeyler deneyebilir ve bunun değerler üzerinde ne gibi bir etkisi olduğunu görebiliriz.

Kablolama Pi kitaplığını mümkün olduğunca kullanmayı seviyorum. I2C desteği vardır.

İlk çalıştırma:

/********************************************************************************

* inşa etmek için: gcc first.test.mpu9265.c -o first.test.mpu9265 -lwiringPi * * çalıştırmak için: sudo./first.test.mpu9265 * * bu program sadece MCP23017'den bir dizi (olası) kayıt çıkarır, * ve ardından MPU9265'ten (veya o 0x68 adresindeki başka bir MPU'dan) * * MCP23017'ye zaten * güvendiğim için sensörden bile okuyabildiğimi doğrulamak için kullandım. *********************************************************** ******************************/ #include #include #include #include #include int main(int argc, char** argv) { puts("Bakalım MCP23017 @ 0x20 ne diyecek:"); hata = 0; int deviceId1 = 0x20; int fd1 = kablolamaPiI2CSetup(deviceId1); if (-1 == fd1) { fprintf (stderr, "WiringPi I2C aygıtı açılamıyor: %s\n", strerror (errno)); dönüş 1; } for (int reg=0;reg<300;reg++) { fprintf(stderr, "%d ", kablolamaPiI2CReadReg8(fd1, reg));fflush(stderr); gecikme(10); } koyar(""); puts("Bakalım MPU9265 @ 0x20 ne diyecek:"); hata = 0; int deviceId2 = 0x68; int fd2 = kablolamaPiI2CSetup(deviceId2); if (-1 == fd2) { fprintf (stderr, "WiringPi I2C aygıtı açılamıyor: %s\n", strerror (errno)); dönüş 1; } for (int reg=0;reg<300;reg++) { fprintf(stderr, "%d ", kablolamaPiI2CReadReg8(fd2, reg));fflush(stderr); gecikme(10); } koyar(""); 0 döndür; }

İkinci koşu:

/********************************************************************************

* inşa etmek için: gcc second.test.mpu9265.c -o second.test.mpu9265 -lwiringPi * * çalıştırmak için: sudo./second.test.mpu9265 * * Bu program, okunan değerin yanında kayıt numarasını verir. * * Bu, çıktıyı bir dosyaya yönlendirmeyi (yönlendirmeyi) kullanışlı hale getirir ve ardından * karşılaştırmak için birkaç çalıştırma yapılabilir. Hangi kaydın önemli olduğu ve verilerin nasıl davranabileceği hakkında * biraz fikir verebilir. *********************************************************** ******************************/ #include #include #include #include #include #include int main(int argc, char** argv) { int deviceId = -1; if (0) { } else if (!strncmp(argv[1], "0x20", strlen("0x20"))) { deviceId = 0x20; } else if (!strncmp(argv[1], "0x68", strlen("0x68"))) { deviceId = 0x68; } else if (!strncmp(argv[1], "0x69", strlen("0x69"))) { deviceId = 0x69; } puts("Bakalım MPU9265 @ 0x20 ne diyecek:"); hata = 0; int fd = kablolamaPiI2CSetup(deviceId); if (-1 == fd) { fprintf (stderr, "WiringPi I2C aygıtı açılamıyor: %s\n", strerror (errno)); dönüş 1; } for (int reg=0;reg<300;reg++) { fprintf(stderr, "%d:%d\n", reg, wirePiI2CReadReg8(fd, reg));fflush(stderr); gecikme(10); } 0 döndür; }

Üçüncü koşu:

/********************************************************************************

* inşa etmek için: gcc üçüncü.test.mpu9265.c -o üçüncü.test.mpu9265 -lwiringPi * * çalıştırmak için: sudo./üçüncü.test.mpu9265 * * Bu program ikincisinin bir sonucudur. Yalnızca bir çalıştırma ve bir sonraki çalıştırma arasındaki farkı belirten * kayıtlarından okur.*********************************************************** ******************************/ #include #include #include #include #include #include int main(int argc, char** argv) { int deviceId = -1; if (0) { } else if (!strncmp(argv[1], "0x68", strlen("0x68"))) { deviceId = 0x68; } else if (!strncmp(argv[1], "0x69", strlen("0x69"))) { deviceId = 0x69; } puts("Bakalım MPU9265 @ 0x20 ne diyecek:"); hata = 0; int fd = kablolamaPiI2CSetup(deviceId); if (-1 == fd) { fprintf (stderr, "WiringPi I2C aygıtı açılamıyor: %s\n", strerror (errno)); dönüş 1; } for (int reg=61;reg<=73;reg++) { fprintf(stderr, "%d:%d\n", reg, wirePiI2CReadReg8(fd, reg));fflush(stderr); gecikme(10); } for (int reg=111;reg<=112;reg++) { fprintf(stderr, "%d:%d\n", reg, wirePiI2CReadReg8(fd, reg));fflush(stderr); gecikme(10); } for (int reg=189;reg<=201;reg++) { fprintf(stderr, "%d:%d\n", reg, wirePiI2CReadReg8(fd, reg));fflush(stderr); gecikme(10); } for (int reg=239;reg<=240;reg++) { fprintf(stderr, "%d:%d\n", reg, wirePiI2CReadReg8(fd, reg));fflush(stderr); gecikme(10); } 0 döndür; }

Peki şimdiye kadar ne öğrendik? Renkli vurgulanmış alanları olan tablonun görüntüsü, çıktının ilk kayıt kümeleriyle eşleştiğini gösterir.

Şimdiye kadar elde edilen sonuçlar yeni sorular üretebilir.

Soru: "harici" grup için neden yalnızca bir kayıt sonucu var?

Soru: Tüm bu bilinmeyen kayıtlar nedir "??????"

Soru: Program kesintiye dayalı olmadığı için çok yavaş veri mi istedi? çok hızlı?

Soru: Sensör çalışırken bir şeyler deneyerek sonuçları etkileyebilir miyiz?

Adım 6: Okumalara / Verilere Daha Fazla İnceleyelim

Her şeyden önce bir sonraki adımın programı şu şekilde geliştirmek olduğunu düşünüyorum:

  • ne kadar döngü gecikmesi (ms) konusunda esnek olun
  • kayıt başına çalışan bir ortalama vermek için kaç okuma konusunda esnek olun

(Programı bir dosya olarak eklemek zorunda kaldım. Buraya eklerken bir sorun gibi görünüyordu. "fourth.test.mpu9265.c")

10 ms'lik bir döngüde ortalama olarak son 10 okumayı kullanan bir çalışma:

sudo./fourth.test.mpu9265 0x68 10 10

61:255 0 255 0 255 0 255 0 0 0: 102 62:204 112 140 164 148 156 188 248 88 228: 167 63:189 188 189 187 189 188 188 188 188 189: 188 64: 60 40 16 96 208 132 116 252 172 36: 112 65: 7 7 7 7 7 7 7 7 7 7: 7 66:224 224 224 240 160 208 224 208 144 96: 195 67: 0 0 0 0 0 0 0 0 0 0: 0 68:215 228 226 228 203 221 239 208 214 187: 216 69: 0 255 0 255 255 0 255 0 0 0: 102 70:242 43 253 239 239 45 206 28 247 207: 174 71: 0 255 255 0 255 255 255 255 255 255: 204 72: 51 199 19 214 11 223 21 236 193 8: 117 73: 0 0 0 0 0 0 0 0 0 0: 0 111: 46 149 91 199 215 46 142 2 233 199: 132 112: 0 0 0 0 0 0 0 0 0 0: 0 189:255 0 255 0 255 0 0 255 0 255: 127 190: 76 36 240 36 100 0 164 164 152 244: 121 191:188 188 188 188 187 188 187 189 187 189: 187 192: 8 48 48 196 96 220 144 0 76 40: 87 193: 7 7 7 7 7 8 7 7 7 7: 7 194:208 224 144 240 176 240 224 208 240 224: 212 195: 0 0 0 0 0 0 0 0 0 0: 0 196:243 184 233 200 225 192 189 242 188 203: 209 197:255 0 0 0 255 0 255 0 0 255: 102 198:223 39 247 43 245 22 255 221 0 6: 130 199: 0 255 255 255 0 255 255 255 255 0: 178 200:231 225 251 1 252 20 211 216 218 16: 164 201: 0 0 0 0 0 0 0 0 0 0: 0 239: 21 138 196 87 26 89 16 245 187 144: 114 240: 0 0 0 0 0 0 0 0 0 0: 0

İlk, en soldaki sütun kayıt numarasıdır. Ardından, bu kayıt için son 10 okumaya gelin. Son olarak, son sütun her satırın ortalamasıdır.

61, 69, 71, 189, 197 ve 199 kayıtları ya yalnızca ikili, ya da hazır/hazır değil ya da 16 bitlik bir değerin (negatif?) yüksek baytı gibi görünüyor.

Diğer ilginç gözlemler:

  • 65, 193 kaydeder - çok sabit ve aynı değer
  • kayıt 63, 191 - çok sabit ve aynı değer
  • 73, 112, 195, 201, 240 - hepsi sıfırda

Bu gözlemleri daha önceki çok renkli, vurgulanmış tablo görüntüsüyle ilişkilendirelim.

65 - sıcaklık kaydı

Kayıt 193 - ??????

Kayıt 63 - ivmeölçer

Kayıt 191 - ??????

Kayıt 73 - harici

112'ye kaydolun ve - ??????

Eh, hala bilinmeyenlerimiz var, ancak faydalı bir şey öğrendik.

Kayıt 65 (sıcaklık) ve kayıt 63 (ivmeölçer) çok sabitti. Bu beklediğimiz bir şey. Sensöre dokunmadım; Robot bilgisayarımla aynı masanın üzerinde durduğundan, herhangi bir tesadüfi titreşim dışında hareket etmiyor.

Bu sıcaklık/ivmeölçer kayıtlarının her biri için yapabileceğimiz ilginç bir test var. Bu test için programın başka bir versiyonuna ihtiyacımız var.

7. Adım: Sıcaklığı ve Hızlanmayı Etkileyebiliriz

Önceki adımlarda sıcaklık için en az bir kayıt ve hızlanma için bir kayıt daralttık.

Programın bu sonraki sürümüyle ("fifth.test.mpu9265.c"), aslında her iki kayıt için de bir değişikliğin gerçekleştiğini görebiliriz. Lütfen videoları izleyin.

Daha Fazla Kazma

Geri dönüp kayıt bilgilerine bir göz atarsak, şunların olduğunu görürüz:

  • jiroskop için üç adet 16 bit çıkış
  • ivmeölçer için üç adet 16 bit çıkış
  • manyetometre için üç adet 16 bit çıkış
  • sıcaklık için bir 16 bit çıkış

Ancak, basit test programlarımız tarafından elde edilen sonuçların tümü tek 8 bitlik çıktılardı. (tek kayıtlar).

Şimdi aynı yaklaşımı deneyelim ama bu sefer 8 yerine 16 bit okuyalım.

Muhtemelen aşağıdaki gibi bir şey yapmamız gerekecek. Sadece bir 16 bit çıktı olduğu için sıcaklığı örnek olarak kullanalım.

//dosya tanıtıcı fd al…

int tempRegHi = 65; int tempRegLo = 66; int hiByte = kablolamaPiI2CReadReg8(fd, tempRegHi); int loByte = kablolamaPiI2CReadReg8(fd, tempRegLo); int sonuç = hiByte << 8; // 16 bitlik bir değer sonucunun üst kısmına yüksek sıralı 8 bit koyun |= loByte; // şimdi lo sırasına 8 bit ekleyin, tam 16 bitlik bir sayı elde edin // bu sayıyı yazdırın veya öncekinden yatay grafik görüntüleme işlevini kullanın

Önceki adımlarımızdan, 65 numaralı kaydın oldukça sabit olduğunu, 66 numaralı kaydın çok gürültülü olduğunu gördük. 65 yüksek dereceli bayt ve 66 düşük dereceli bayt olduğundan, bu mantıklı.

Okuma için, register 65'in verilerini olduğu gibi alabiliriz, ancak register 66'nın değerlerinin ortalamasını alabiliriz.

Veya tüm sonucun ortalamasını alabiliriz.

Bu bölüm için son videoya bir göz atın; 16 bitlik sıcaklık değerinin tamamının okunduğunu gösterir. Kod "altıncı.test.mpu9265.c"

Adım 8: İvmeölçer ve Jiroskop

Image
Image

Bu bölümdeki videolar, "seventh.test.mpu9265.c" test programı kullanılarak ivmeölçer ve jiroskoptan alınan çıktıları gösterir. Bu kod 1, 2 veya 3 ardışık bayt çiftini (yüksek ve düşük baytlar) okuyabilir ve değerleri tek bir 16 bit değerine dönüştürür. Böylece, herhangi bir tek ekseni okuyabilir veya ikisini birlikte okuyabiliriz (ve değişiklikleri toplar) veya üçünü de okuyabiliriz (ve değişiklikleri toplar).

Tekrarlamak gerekirse, bu aşama için, bu Eğitilebilirlik için, sadece basit bir soruyu cevaplamak istiyorum: "robot döndü mü/döndü mü?". 90 derece döndü mü gibi kesin bir değer aramıyorum. Bu daha sonra SLAM yapmaya başladığımızda gelecek, ancak basit engellerden kaçınma ve rastgele hareket için gerekli değil.

Adım 9: (devam ediyor) Manyetometre

i2cdetect aracını kullanırken MPU9265, tabloda 0x68 olarak görünür:

0 1 2 3 4 5 6 7 8 9 a b c d e f

00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --

IMU'nun manyetometre kısmından okumak için gereken ekstra adımlar vardır.

Invesense kayıtlarının PDF belgesinden:

37'DEN 39'A KAYITLAR – I2C SLAVE 0 KONTROLÜ

  • KAYIT 37 - I2C_SLV0_ADDR
  • KAYIT 38 - I2C_SLV0_REG
  • KAYIT 39 - I2C_SLV0_CTRL

Önerilen: