Sensör ve devre laboratuvarı
Kart ve sensörler gerçek çipler gibi davranır: I2C adresi, kimlik yazmacı, uyku modu, bayt sırası, ölçek, gürültü ve sapma. Her görevde bir sensör çalışmıyor ya da yanlış ölçüyor; tahmin edin, çalıştırın, bağlantı şemasına ve grafiğe bakın, eksik satırı yazın.
- Kod sitenin geri kalanından ayrı bir alanda çalışır; hesabınıza, bu sayfaya ve internete erişemez.
- İlk çalıştırmada Python tarayıcınıza iner (birkaç saniye), sonra hızlıdır.
IMU: uyuyan sensörü uyandırın
MPU6050 I2C taramasında görünüyor, kimliği doğru, ama ivme hep sıfır. Önce tahmin edin: kablo mu kopuk, sensör mü bozuk, yoksa başka bir şey mi?
import math
from sv_lab import Gorev
from sv_lab.devre import Kart, Ortam, MPU6050, s16
kart = Kart(Ortam("salinim")) # elde sallanan kart
kart.bagla(MPU6050())
print("I2C adresleri:", [hex(a) for a in kart.i2c_tara()])
print("WHO_AM_I:", hex(kart.i2c_oku(0x68, 0x75)[0]))
# TODO: sensörü uyandırın (ipucu: kart.i2c_yaz(0x68, 0x6B, ...))
for _ in range(300):
b = kart.i2c_oku(0x68, 0x3B, 6) # ACCEL_XOUT_H … ACCEL_ZOUT_L, büyük uçlu
ax, ay, az = (s16(b[i], b[i + 1]) / 16384 for i in (0, 2, 4)) # 2 g aralığı: 16384 LSB/g
kart.kaydet("az (g)", az)
kart.kaydet("roll", math.degrees(math.atan2(ay, az)))
kart.bekle_ms(20)
Gorev("IMU'yu uyandır, ivmeden roll", [
("ivmeölçer yerçekimini görüyor", lambda k: max(k.seri("az (g)")) > 0.8),
("roll gerçeğe yakın (RMS < 3 derece)", lambda k: k.hata("roll", "roll")[1] < 3),
]).denetle(kart)
kart.devre()
kart.ciz("roll", gercek={"roll": "roll"}, birim="derece", baslik="Roll: ivmeden")
Takıldınız mı?
MPU6050 uyku modunda açılır: PWR_MGMT_1 (0x6B) yazmacına 0 yazılmadan ölçüm yapmaz. Kodu kendi yapay zekânıza da sorabilirsiniz; önerdiği satırı burada çalıştırın, ölçütlerin hangisini karşıladığına bakın.
Bu konunun tamamı: Sensörlerden Uçuşa Temel İHA Eğitimi
Tümleyen filtre: jiroskop kayar, ivmeölçer titrer
Jiroskobu toplayınca açı yavaş yavaş kayar; ivmeölçer motor titreşiminde gürültülüdür. İkisini nasıl birleştirirsiniz? ALFA = 0 ile çalıştırıp üç çizgiyi karşılaştırın.
import math
from sv_lab import Gorev
from sv_lab.devre import Kart, Ortam, MPU6050, s16
kart = Kart(Ortam("salinim"))
kart.bagla(MPU6050(titresim=0.12)) # motorların titreşimi
kart.i2c_yaz(0x68, 0x6B, 0x00)
ALFA = 0.0 # TODO: jiroskoba ne kadar güveneceksiniz? 0 ile 1 arası, ör. 0.98
DT = 0.01
roll_jiro = roll_filtre = 0.0
for _ in range(1500):
b = kart.i2c_oku(0x68, 0x3B, 14) # ivme (6) + sıcaklık (2) + jiroskop (6)
ay, az = s16(b[2], b[3]), s16(b[4], b[5])
gx = s16(b[8], b[9]) / 131.0 # 250 derece/sn aralığı: 131 LSB/(derece/sn)
roll_ivme = math.degrees(math.atan2(ay, az))
roll_jiro += gx * DT
roll_filtre = ALFA * (roll_filtre + gx * DT) + (1 - ALFA) * roll_ivme
kart.kaydet("ivmeden", roll_ivme)
kart.kaydet("jiroskoptan", roll_jiro)
kart.kaydet("tümleyen", roll_filtre)
kart.bekle_ms(10)
print("RMS hata (derece) ivmeden %.1f jiroskoptan %.1f tümleyen %.1f" % tuple(kart.hata(a, "roll")[1] for a in ("ivmeden", "jiroskoptan", "tümleyen")))
Gorev("Tümleyen filtre", [
("filtre gerçeğe yakın (RMS < 2,5 derece)", lambda k: k.hata("tümleyen", "roll")[1] < 2.5),
("filtre ivmeölçerden iyi", lambda k: k.hata("tümleyen", "roll")[1] < k.hata("ivmeden", "roll")[1]),
]).denetle(kart)
kart.ciz("ivmeden", "jiroskoptan", "tümleyen", gercek={"tümleyen": "roll"}, birim="derece", baslik="Roll")
Takıldınız mı?
ALFA = 0 yalnız ivmeölçeri kullanır; jiroskoba ağırlık verin (ör. 0,98). Kodu kendi yapay zekânıza da sorabilirsiniz; önerdiği satırı burada çalıştırın, ölçütlerin hangisini karşıladığına bakın.
Bu konunun tamamı: Sensörlerden Uçuşa Temel İHA Eğitimi
Barometre: basınçtan irtifa
Araç 5. saniyede kalkıp 30 m'ye çıkıyor. BMP280 kimliği doğru, kalibrasyon okunuyor, ama irtifa hep sıfır. Neden? Çalıştırıp devre şemasındaki uyarıya bakın.
from sv_lab import Gorev
from sv_lab.devre import Kart, Ortam, BMP280, bmp280_dengele
kart = Kart(Ortam("kalkis"))
kart.bagla(BMP280())
print("Kimlik:", hex(kart.i2c_oku(0x76, 0xD0)[0])) # 0x58
kal = kart.i2c_oku(0x76, 0x88, 24) # kalibrasyon bloğu
# TODO: ölçümü başlatın (ipucu: kart.i2c_yaz(0x76, 0xF4, ...))
p0 = None
for _ in range(40):
b = kart.i2c_oku(0x76, 0xF7, 6) # basınç (20 bit) + sıcaklık (20 bit)
adc_p = (b[0] << 12) | (b[1] << 4) | (b[2] >> 4)
adc_t = (b[3] << 12) | (b[4] << 4) | (b[5] >> 4)
sicaklik, p = bmp280_dengele(kal, adc_t, adc_p)
p0 = p0 or p # kalkış noktasının basıncı
irtifa = 44330 * (1 - (p / p0) ** (1 / 5.255))
kart.kaydet("irtifa", irtifa)
kart.bekle_ms(1000)
print("Son ölçüm: %.1f C, %.0f Pa, %.1f m" % (sicaklik, p, irtifa))
Gorev("Barometrik irtifa", [
("yerdeyken irtifa ~0", lambda k: all(abs(v) < 1 for v in k.seri("irtifa")[:5])),
("30 m'de 1 m'den az hata", lambda k: abs(k.seri("irtifa")[-1] - 30) < 1),
]).denetle(kart)
kart.devre()
kart.ciz("irtifa", gercek={"irtifa": "irtifa"}, birim="m", baslik="İrtifa")
Takıldınız mı?
BMP280 uyku modunda açılır: ctrl_meas (0xF4) yazmacına ölçüm ayarı yazılmalı (0x27 = sıcaklık ×1, basınç ×1, normal mod). Kodu kendi yapay zekânıza da sorabilirsiniz; önerdiği satırı burada çalıştırın, ölçütlerin hangisini karşıladığına bakın.
Bu konunun tamamı: Sensörlerden Uçuşa Temel İHA Eğitimi
Pusula: manyetik sapmayı kalibre edin
Kara aracının kartı kendi ekseninde iki tur dönüyor. Gövdedeki elektronik pusulaya sabit bir sapma ekliyor. Kalibrasyonsuz yön ne kadar şaşar? Tahmin edin, sonra en büyük ve en küçük değerlerden sapmayı bulun.
import math
from sv_lab import Gorev
from sv_lab.devre import Kart, Ortam, HMC5883L, s16
kart = Kart(Ortam("donus")) # kendi ekseninde 18 derece/sn
kart.bagla(HMC5883L())
kart.i2c_yaz(0x1E, 0x02, 0x00) # sürekli ölçüm modu
def oku():
b = kart.i2c_oku(0x1E, 0x03, 6)
return s16(b[0], b[1]), s16(b[4], b[5]) # sıra X, Z, Y: Y son iki bayt
xs, ys = [], []
for _ in range(400): # 20 sn: bir tam turdan fazla
mx, my = oku()
xs.append(mx); ys.append(my)
kart.bekle_ms(50)
x0, y0 = 0, 0 # TODO: sapmayı bulun: (max(xs) + min(xs)) / 2, y için de aynısı
print("Sapma: x0 = %.0f, y0 = %.0f" % (x0, y0))
for _ in range(200):
mx, my = oku()
kart.kaydet("yön", math.degrees(math.atan2(-(my - y0), mx - x0)) % 360)
kart.bekle_ms(50)
Gorev("Pusula kalibrasyonu", [
("yön hatası 5 dereceden küçük", lambda k: k.hata("yön", "yaw")[0] < 5),
]).denetle(kart)
kart.ciz("yön", gercek={"yön": "yaw"}, birim="derece", baslik="Yön (pusula)")
Takıldınız mı?
Sapma (hard iron) çıkarılmadı: her eksende (en büyük + en küçük) / 2. Kodu kendi yapay zekânıza da sorabilirsiniz; önerdiği satırı burada çalıştırın, ölçütlerin hangisini karşıladığına bakın.
Bu konunun tamamı: Sensörlerden Uçuşa Temel İHA Eğitimi
GPS: NMEA cümlesinden konum
Multikopter 40 m kuzeye, 25 m doğuya uçuyor; GPS seri porttan GGA cümlesi gönderiyor. 4011.31 gibi bir enlem 40,1131° mü? Tahmin edin, sonra izi karşılaştırın.
import math
from sv_lab import Arac, Gorev
from sv_lab.devre import Kart, Ortam, GPS
iha = Arac("multikopter", ad="SV-1")
iha.bekle(4).mod("GUIDED").arm().kalk(10)
iha.git(40, 25)
iha.calistir(40)
kart = Kart(Ortam(arac=iha)) # kartı uçan aracın üstüne koyun
kart.bagla(GPS())
EV = (40.1885, 29.0610) # kalkış noktası (derece)
def derece(nmea):
x = float(nmea)
return x / 100 # TODO: NMEA derece-dakikadır (ddmm.mmmm); ondalık dereceye çevirin
for _ in range(40):
for satir in kart.seri_oku():
p = satir.split(",") # $GPGGA,saat,enlem,N,boylam,E,...
en, boy = derece(p[2]), derece(p[4])
kart.kaydet("kuzey (m)", (en - EV[0]) * 111320)
kart.kaydet("doğu (m)", (boy - EV[1]) * 111320 * math.cos(math.radians(EV[0])))
kart.bekle_ms(1000)
print("Son cümle:", satir)
Gorev("GPS konumu", [
("kuzey 3 m'den yakın", lambda k: k.hata("kuzey (m)", "kuzey")[0] < 3),
("doğu 3 m'den yakın", lambda k: k.hata("doğu (m)", "dogu")[0] < 3),
]).denetle(kart)
kart.ciz("kuzey (m)", "doğu (m)", gercek={"kuzey (m)": "kuzey", "doğu (m)": "dogu"}, birim="m", baslik="GPS konumu")
Takıldınız mı?
NMEA enlemi derece ve dakikadır (ddmm.mmmm): int(x / 100) + (x % 100) / 60. Kodu kendi yapay zekânıza da sorabilirsiniz; önerdiği satırı burada çalıştırın, ölçütlerin hangisini karşıladığına bakın.
Bu konunun tamamı: Sensörlerden Uçuşa Temel İHA Eğitimi
Batarya: gerilim bölücüyle ölçüm
Deniz aracının 3S LiPo bataryası 12,6 V; kartın analog girişi en çok 5 V okur. 10 kΩ ve 3,3 kΩ'luk bölücüden gelen değeri doğru gerilime nasıl çevirirsiniz?
from sv_lab import Gorev
from sv_lab.devre import Kart, Ortam, GerilimBolucu
kart = Kart(Ortam("masa"))
kart.bagla(GerilimBolucu("A0", r1=10000, r2=3300))
ORAN = 1.0 # TODO: bölücü oranı: (R1 + R2) / R2
for _ in range(60):
ham = kart.analog_oku("A0") # 0–1023, 5 V referans
v_pin = ham * 5.0 / 1023
kart.kaydet("batarya (V)", v_pin * ORAN)
kart.bekle_ms(1000)
print("Son okuma: %.2f V" % kart.seri("batarya (V)")[-1])
Gorev("Batarya gerilimi", [
("gerçeğe 0,05 V'tan yakın", lambda k: k.hata("batarya (V)", "batarya")[1] < 0.05),
("pin 5 V'u aşmadı", lambda k: not any("referansın" in m for _, m in k.olaylar)),
]).denetle(kart)
kart.devre()
kart.ciz("batarya (V)", gercek={"batarya (V)": "batarya"}, birim="V", baslik="Batarya")
Takıldınız mı?
Bölücü oranı yok: Vbat = Vpin · (R1 + R2) / R2. Kodu kendi yapay zekânıza da sorabilirsiniz; önerdiği satırı burada çalıştırın, ölçütlerin hangisini karşıladığına bakın.
Bu konunun tamamı: Sensörlerden Uçuşa Temel İHA Eğitimi
Ultrasonik mesafe: süreyi metreye
HC-SR04 yankının dönüş süresini verir. Kart 35 °C sıcakta. 343 m/sn ile hesaplayınca kaç santim şaşarsınız? Önce tahmin edin.
from sv_lab import Gorev
from sv_lab.devre import Kart, Ortam, HCSR04
SICAKLIK = 35.0
kart = Kart(Ortam("salinim", sicaklik=SICAKLIK, mesafe=1.2))
kart.bagla(HCSR04(trig=9, echo=10))
for _ in range(100):
kart.dijital_yaz(9, 1); kart.dijital_yaz(9, 0) # 10 mikrosaniyelik tetik darbesi
sure = kart.darbe_olc(10) # mikrosaniye
mesafe = sure * 1e-6 * 343.0 # TODO: süre gidiş-dönüştür; ses hızı da sıcaklığa bağlı
kart.kaydet("mesafe (m)", mesafe)
kart.bekle_ms(100)
Gorev("Ultrasonik mesafe", [
("1 cm'den az hata (RMS)", lambda k: k.hata("mesafe (m)", "mesafe")[1] < 0.01),
]).denetle(kart)
kart.devre()
kart.ciz("mesafe (m)", gercek={"mesafe (m)": "mesafe"}, birim="m", baslik="Mesafe")
Takıldınız mı?
Süre gidiş-dönüştür (ikiye bölün) ve ses hızı sıcaklıkla değişir: 331,3 + 0,606·T. Kodu kendi yapay zekânıza da sorabilirsiniz; önerdiği satırı burada çalıştırın, ölçütlerin hangisini karşıladığına bakın.
Bu konunun tamamı: Sensörlerden Uçuşa Temel İHA Eğitimi