4.18. Useita sensoreita

Kourallinen OpenMV Cam -kameroita yhdistää kaksi kuvasensoria samalle kortille – yleisimmin värikameran FLIR® Lepton® -lämpösensorin rinnalle, mutta sama rakenne pätee väri-plus-tapahtuma-kortteihin ja mihin tahansa tulevaan kaksisensoriseen laitteistoon. Kullakin sensorilla on oma pikselimatriisinsa, oma ohjausväylänsä, ja se ajaa omaa putkeaan omalla kehysnopeudellaan. CSI-API laajenee kattamaan ne antamalla sovelluksen luoda yhden CSI-objektin fyysistä sensoria kohti.

4.18.1. Sensorin valitseminen

CSI-konstruktori ottaa cid-argumentin, joka nimeää tietyn sensorin kortilla. cid=-1 (oletus) valitsee ensisijaisen sensorin; nimetyt cid-vakiot valitsevat toissijaisen sirun ID:n perusteella:

import csi

csi_rgb     = csi.CSI()                    # primary colour sensor
csi_thermal = csi.CSI(cid=csi.LEPTON)      # FLIR® Lepton®

Kullakin instanssilla on oma konfiguraationsa – pikseliformaatti, kehyskoko, valotus- / vahvistussäätimet, kehyspuskuriallas – ja se nollataan, konfiguroidaan ja luetaan toisesta riippumatta. Tuettujen toissijaisten sensoreiden vakiot (LEPTON, GENX320 ja muut, jotka on lueteltu CSI-referenssissä) nimeävät sirun, jota sovellus odottaa toissijaisessa portissa; ajuri epäonnistuttaa konstruktoinnin, jos todellinen siru ei vastaa.

4.18.2. Kaappaaminen molemmista sensoreista

Kukin sensori ajaa kaappausputkeaan toisesta riippumatta – värisensori saattaa toimittaa kolmekymmentä kehystä sekunnissa, kun taas Lepton® toimittaa yhdeksän. Suoraviivainen tapa käsitellä tätä epäsuhtaa on antaa nopeamman sensorin ohjata silmukkaa ja lukea hitaampaa sensoria estämättä, ottamalla mitä tahansa on valmiina ja ohittamalla iteraatio, kun mitään ei ole:

import csi

csi_rgb     = csi.CSI()
csi_thermal = csi.CSI(cid=csi.LEPTON)

csi_rgb.reset()                        # powers the rail, pulses RESET
csi_rgb.pixformat(csi.RGB565)
csi_rgb.framesize(csi.QVGA)

csi_thermal.reset(hard=False)          # I2C reconfigure only
csi_thermal.pixformat(csi.GRAYSCALE)
csi_thermal.framesize(csi.QQVGA)

while True:
    rgb_img     = csi_rgb.snapshot()                  # blocks for next colour frame
    thermal_img = csi_thermal.snapshot(blocking=False)  # returns None if not ready
    if thermal_img is not None:
        # process aligned colour + thermal pair
        pass
    else:
        # process colour only on this iteration
        pass

Estävä snapshot() tahdistaa silmukan; estämätön palauttaa uusimman lämpökehyksen, kun tuore on saapunut edellisen kutsun jälkeen, ja None muutoin. Sovellus pysyy käynnissä värisensorin kehysnopeudella ja saa lämpökehyksen aina, kun Lepton® tuottaa sellaisen.

Vastakkainen malli – kaksi estävää tilannekuvaa peräkkäin – toimii myös, mutta silmukka ajaa silloin kahden sensorin hitaammalla nopeudella, ja nopeamman sensorin putki pysähtelee iteraatioiden välillä. Valitse se nopeus, jonka sovelluksen alapuolinen käsittely todella haluaa ohjata.

4.18.3. Nollaus jaetuilla virtalinjoilla

Jotkin kaksisensoriset kortit ajavat molempia siruja yksittäisestä virtalinjasta tai jakavat nollauslinjan. Näillä ensimmäinen reset() nostaa linjan ylös ja pulssittaa jaetun signaalin; myöhempien nollausten muilla CSI-instansseilla tulisi välittää hard=False, jotta ne uudelleenohjelmoivat vain oman sirunsa raahaamatta naapuria nollauksen läpi:

csi_rgb.reset()                        # primary -- powers the rail, pulses RESET
csi_thermal.reset(hard=False)          # secondary -- I2C reconfigure only

hard=True toissijaisella tässä rakenteessa nollaisi sivuvaikutuksena ensisijaisen uudelleen, kumoten kaiken konfiguroinnin, jonka sovellus oli jo työntänyt. Kunkin kaksisensorisen kortin referenssisivu mainitsee, ovatko virtalinjat jaettuja.

4.18.4. Virran lähteen valitseminen

Kameroilla, joilla on kaksi sensoria, on kaksi CSI-instanssia, mutta silti vain yksi virran kehyspuskuri niiden välillä. Konstruktorin argumentti valitsee, kumman sensorin kehykset syöttävät esikatselua:

csi_rgb     = csi.CSI()                    # primary
csi_thermal = csi.CSI(cid=csi.LEPTON,
                      stream=True)         # preview source

stream=True tekee nimetystä instanssista lähteen. Ilman stream=-argumenttia ensisijainen sensori (cid=-1, oletus) on lähde; instanssit, jotka on rakennettu toissijaisen sensorin cid=-arvolla, pysyvät hiljaa esikatselussa, ellei stream=True välitetä eksplisiittisesti. Kutsut snapshot()-metodiin valitsemattomalla sensorilla kaappaavat silti kehyksiä kyseisen sensorin kehyspuskureihin normaalisti – ne eivät vain päivitä esikatselua.