21. Sissejuhatavalt sünkroonsest ühendusest (I2C ning SPI) õhurõhu anduri BMP280 näitel
<- eelmine peatükk
järgmine peatükk ->
21.0. Seosed eelmiste peatükkidega
Oleme kokku puutunud terve rea anduritega. Kuna kõigi anduritega mingi füüsikalise suuruse väärtust mõõdame, siis peame ka anduri data-viigult vastava info kokku korjama—ning kasutatavaks tegema.
Tuletame meelde, kuidas 19. peatükis mõõtsime ultrahelianduriga kaugust. Meil oli punase värvikoodiga tähistatud toitejuhe, musta värvikoodiga maaühendus. Neile kahele lisaks kasutasime veel kahte eraldi värvidega tähistatud juhet—ühega kontrollisime ultrahelisaatjalt välja saadetavat ultrahelisignaali (Trig-tähistusega viik) ning teiselt peegelduse vastuvõtmise registreerimist (Echo- tähistusega viik). Kui fototakistil oli kaks viiku, infrapuna-anduril oli kokku kolm viiku, siis ultraheliga toimetaval HC-SR04 kauguse-anduril oli vaja ühendada juba neli viiku.
Selles peatükis aga uurime situatsiooni, milles meil on vaja ühendada veelgi rohkem viikusid—võimalik, et peame mõtlema ka nii, et Arduinol võiks ühel hetkel vabu viikusid puudu tulla.
21.1. Peatüki eesmärk ja selgitused
Peatüki eesmärk on mitte niivõrd mõõta õhurõhku kuivõrd pigem uurida, et kuidas ühendada õhurõhuandurit, mille plaadil on palju andurite viikusid: tutvuda I2C ning SPI protokollidega.
I2C ja SPI protokolle kõrvutame varem Serial monitori ning USART osades asünkroonsest sidest õpituga: toome välja erinevused. Uurime, mis juhul eelistame kasutada I2C-d, SPI-d või asünkroonset sidet (UART = Universal Asynchronous Receiver-Transmitter). Selgemaks saab mõistete sünkroonne versus asünkroonne sisu.
Selle peatüki läbimise järel õpilane oskab:
Õpetame tegelikult seda, kuidas järgmisest raskusastmest jagu saada. Kogu peatükki läbivas ühes tabeli koostamise harjutuses suuname kasutama märkmete süstematiseerimiseks tabeli formaati. Lisalugemises põhjendame viikude kohta märkmete tegemise mõistlikkust matemaatilise näitega.
Õpilasele meelde jäänud ka selgitused taktiallika (takti-andja moodul) ning taktikuulaja (takti-järgiv moodul) kohta. Inglise keeles on need traditsioonist kantuna tähistatud terminitega master ja slave. Sellisele inglise keeles levinud erialasele sõnakasutusele leidub ingliskeelses maailmas häälekaid vastaseid. Ent väljakujunenud ingliskeelse erialakeele tõttu peame neid mõisteid ikkagi rakendama nii nagu nad esinevad inglise keeles. Ent kuidas öelda nende kohta eesti keeles? Mina eelistan öelda nende kohta taktiallikas ning taktikuulaja. Kas kellelgi võiks olla parem idee?
Head keelekasutus-retsepti siin ei tundu olema—näiteks mida hakata peale oluliste lühendist terminiks saanud MOSI ja MISO-ga? (Lahtikirjutatult Master Out, Slave In ning Master In, Slave Out.) Parema puudumisel jääme neid kahte olulist sideviisi selgitades ikkagi vana traditsiooni juurde: kasutame MOSI ja MISO—sest vastasel juhul ei ole meile kättesaadav see traditsioon, millest meil erialase edu nimel tuleb aru saada. MOSI ja MISO on sünkroonse side mõistmiseks vajalikud.
21.2. Töövahendid:
21.3. Tegevused
Kuna me õhurõhu mõõtmiseks vajalikust anduri-moodulist suure tõenäosusega alguses veel midagi tõsisemat ei oska arvata, siis alustame internetist BMP280 ja BME280 kohta info otsimise harjutusega. Harjutame päriselus uue anduriga kokkupuutumise reaalsust.
Harjutus A
Teeme läbi meile tundmatus teemas orienteerumisega alustamiseks vajaliku rutiini.
- Kas leiate internetist näiteks BME280: Data sheet pdf?1 Laadige tooteinfo brošüür alla ning vaadelge BME280 või BMP280 koha esitatud pilti.
- Uurige (vajadusel luubiga), mis on BMP280 plaadikese peale kirjutatud. Tehke märkmeid, sest kui puutute mingi töövahendiga kokku esimest korda, siis võib selle viikude hulk (näiteks seitse viiku!) olla piisvalt suur, et anda põhjust sügavamalt detailidesse süüvida. Veidi hiljem—kui on tehtud märkmed—saate neid kasutada. Märkmed ei erinegi ehk väga dokumentatsioonist?
- Pange paberile või arvutisse kirja, mis tähised on Teie käes oleval õhurõhuanduril.
- Veenduge, et kas ikka on BMP või on BME või veel midagi muud. Tähistust ära kasutades võiks olla võimalik netist veel materjali leida.
Minul on alustuseks hoopis GY-BME/P280 tähisega lillat värvi plaadike, mille viikude tähised ei vasta sellele, mis on kirjas Adafruit ja Bosch poolt antud tootekirjeldustes. Avastan oma meelehärmiks, et mäletan siiski veel midagi õhurõhu kohta… ja ongi kõik, mis alustuseks mulle teada on. Mis nüüd teha? Minulgi jääb üle vaid surfata. Eesmärgiks on õhurõhk Arduinot kasutades ära mõõta; selleks pean aga mõistma seda, kuidas skeem kokku panna ja tööle saada.
Harjutus B, mis kasvab üle koduseks tööks
Kuidas teha tabeli formaadis märkmeid järjekordse elektroonilise detaili viikude kohta
Mina alustaks nii:
Viigu tähis | Viigu funktsioon | Mis värvi juhtmega ühendan | Kuhu ühendan | Kommentaarid ja lisainfo |
---|---|---|---|---|
SCK (GY-BME/P280 peal ka SCL) | Rütmi ette andva taktgeneraatori funktsioon | Sinise värvi võtan SCK ja SCL—takti-juhtme värvikoodiks | Ühendamine erineb I2C ja SPI kasutamise korral: SPI korral kasutan digitaal-viiku number 13, sest see on Arduino Unol ehitatud toetama takti-funktsiooni. I2C puhul aga läheb sinine juhe analoog-viigule number 5. | Takti tarvis on ühendus Arduinoga oluline nii I2C kui ka SPI korral. |
SDA (SDA kohta saad peatükki lugedes täita ise.) | ||||
Lisa ka ülejäänud viigud, mis edasi lugedes leiad. |
Kas sai alustuseks pisut segane?
Me ei tea teemast suurt midagi, ent juba sunnitakse märkmeid tegema.
Antud peatüki eesmärk on õpetada ka iseseisvat uurimist. Seega me ei kohku tagasi, kui peame peatükis sisalduva kohta tabelit pidama. Meid ei häiri ka see, kui peame tabeli mingil hetkel ümber tegema.
Mõelge, kas töö käigus targemaks saades võiksite tahta märkmetabelit ümber korraldada: näiteks mingist hetkest võite tahta I2C ning SPI kohta info eraldi lahtritesse tuua—ja seda veel enne kui aru saame, milleks üldse meile I2C või SPI.
Või teeks hoopis kaks eraldi märkmetabelit? Üks on I2C kohta ning teine SPI kohta? Vahel me ju märkame ka ilma erialaste eelteadmisteta, et keerukas uus info võiks olla kuidagi mugavamalt ja täpsemalt struktureeritud. Seda märkamist saab treenida.
NB!
- Hea on kirjutada tabelisse, mille oleme kohe alustuseks loonud arvutis—näiteks võime teha seda ka käepärases tekstitöötlusprogrammis.
- Stressivabamaks märkmete tegemise harjumuse välja kujundamiseks võtke ette midagi, millega Te olete ammu kursis: Mõelge sellele, et iga andurit läbib vool: leidke näiteks musta juhtme ühendamise koht nii Arduinol kui ka õhurõhuanduri-plaadil. Pange see kirja, mida juba teate—see annab võimaluse teadmisi süsteemina näha.
- Alustuseks võite panna kirja kõigi õhurõhuanduri viikude tähised. Tehke endale andurist joonis, märkige sellele viigutähised.
Kas saame niiviisi talitades inspiratsiooni märkmete süsteemsemaks esitamiseks?
Võrrelge märkmeid, jooniseid ja tabeleid kaasõpilaste omadega—robootikatunnis julgustame õpilasi omavahel infot jagama.
Vihje harjutus B vormistamiseks
Koopeerige eespool toodud tabeli algus oma arvutisse ja asuge peatükki lugedes seda täiendama.
21.3.1.Teooria mitme anduri ühendamise kohta:
Harjutus B-ga jätkamiseks
BMP 280 ja BME 280 puhul kasutatakse tegelikult mitut andurit.
- Leidke koht tootekirjelduses, kust see välja tuleb!
- Kui leidsite internetist hea joonise, siis joonistage see ümber oma märkmetesse.
- Ehkki on ka võimalus kopeerida (Ctrl+C ning siis Ctrl+V), ometi ise läbi joonistades jääb paremini meelde. Kasutame ka paberit ja erinevat värvi pliiatseid.
- Kas viikusid peaks BMP 280 ja BME 280 peal olema pigem rohkem kui tegelikult näeme?
Kui meil on juba selle ühe BMP 280 või BME 280 anduri näol tegemist mooduliga, milles on tegelikult mitu andurit, siis mida arvata sellise mooduli puhul suhteliselt vähesest hulgast viikudest?
Kuidas on üldse võimalik, et andmed mitme anduri korraga töös olles omavahel segi ei lähe? Mida peame tegema selleks, et mitme anduri andmevood oleks lahus hoitud? Kas peaksime kehtestama mingid reeglid?
Selleks, et süsteemiosad omavahel koostööd teha saaks, tuleb süsteemis toimuvat protsessi korrastada: näiteks anda ette omavaheline takt (suhtlusrütm) või reguleerida omavahelist suhtlemisjärjestust algus- ja lõpusignaalidega nii, et ühes süsteemis toimetavad ja samu viikusid jagavad andurid ning protsessor ei suhtleks läbisegi üheaegselt ühes ja samas kanalis üksteist häirides.
Hea suhtluse huvides on, et keegi peab kuulama siis, kui keegi teine räägib. Rääkija ja kuulaja rollid peavad aga organiseeritult vahelduma—et kõik info ja tagasiside toimida saaks. Vastasel korral ei tule koostööst midagi välja.
Suhtlusreeglite selgitamist alustame sünkroonse ning asünkroonse meetodi kirjeldamisest.
- Sünkroonse ühendusprotokolli korral on taktiallikana (inglise keeles master) talitleva süsteemiosa poolt ette antud takt, mille järgi meie süsteemi teised osad omavahel rääkija ja kuulaja rolle täidavad. Süsteemis osad, mis rütmi ette ei anna (inglise keeles slave) on taktikuulajad: kasutavad taktiallika (master) poolt dikteeritud takti.
- Asünkroonsus seevastu justkui märgiks süsteemisiseselt suhtlemist iga süsteemiosa omas rütmis—keegi ei anna ette takti. Ent korrastamata kujul ei saa toimida ka asünkroonne side. Meenutame, et andsime oma programmi void setup() osas asünkroonse side alustamise käsus Serial.begin (9600) ning ka Serial monitori vastavas aknas ette ühe ja sama baudi-väärtuse. Eelmistes peatükkides veendusime, et erinevuste korral side ei toiminud. Seega on asünkroonses sides takti puudumisel ikkagi oluline, et side toimuks vähemalt sama kiirusega. (Baudides mõõdetakse impulsside edastamise kiirust.)
- Sünkroonse suhtlusprotokolli näiteks toome I2C ning SPI.
- Asünkroonset suhtlusprotokolli illustreerib kursuse peatükkides 7, 8 ja 12 vaadeldud Serial monitori temaatika.
Nii asünkroonse kui ka sünkroonse protokolli korral on oluline, et kui kedagi on vaja „kuulata“, siis see süsteemiosa „räägibki“. Võimaliku „korraga rääkimise“ puhul peame eristama rääkijaid—suhtlus ei saa toimuda „läbisegi“— igal juhul on vajalik korrastatus.
Mõtleme veel viikude ja juhtmete hulgale.
a) Saame vajaliku viigu ühendada „otse“. Niiviisi oleme talitanud näiteks potentsiomeetriga sisendit andes. Näideteks sobivad ka ultraheliga kauguse mõõtmine ning LCD ekraani ühendamine. Aga kas Arduino peal oleks alati piisaval hulgal viikusid võtta?
Kujutage ette seisu, et iga Teie andurimoodulil paikneva eraldi sensori (ja neid võib olla rohkem kui vaid temperatuur, õhurõhk, niiskus jne) kohta on vajalik ühendada Arduinoga kõik iga sensori juhtmed—pean silmas iga anduriplaadil asuva sensori eraldi ühendamist Arduino viikudega.
- Kas niiviisi saaksime heidutava „juhtmemetsa“ ja pilt läheks pigem keerukamaks?
- Mitu viiku on Arduino UNO-l?
b) Mitme anduri ühendamiseks on kaks levinud võimalust: protokollid I2C (I2C loeme eesti keeles i-ruut-c) ning SPI.
(Tegelikult mitme anduri ühendamise „keerukust“ kui sellist vältida ei õnnestu—kui viikude osas on moodul tehtud lihtsamaks, siis selle mooduli tarvis kasutatav programm peab minema keerukamaks.)
Taktiallikas (master) versus taktikuulja (slave):
Võime jagada sünkroonsetesse skeemidesse ühendatud elektroonilised üksused kaheks:
- ühed on programmeeritud juhtima—side takti dikteerima;
- teised on programmeeritud alluma—toimima ette antud takti järgides.
Et takti dikteerivatest osadest ning takti järgivast osadest koosnevad süsteemid toimiks, peame kõik need vajalikud süsteemiosad üheks ladusalt infot vahetavaks vooluahela-tervikuks ühendama.
21.3.2. I2C protokoll
I2C on lahtikirjutatult IIC, inglise keeles Inter-Integrated Circuit .
Alustame sünkroonsete ühenduste kirjeldamist I2C-st kuna I2C protokolli puhul on viikude-ühenduste arv väiksem SPI omast: I2C puhul on lisaks 5V ja GND viikudele rakendatud veel SCK ning SDA.
I2C protokoll on mõeldud ühendamaks a) mitut erinevat vooluringi-osa b) ühe või mitme takti-allikast mikroprotsessori kiibiga. 2
2 Ehkki me selles peatükis nii kaugele ei jõua, siiski olgu öeldud, et läbimõeldud korrastatuse puhul saab taktiallikaid (master) niisiis olla ka mitu.
21.3.2.1. SCK või SCL viik:
Märkmete tegemiseks mõeldud Harjutus B jaoks kopeerisime eestpoolt tabeli-formaadi, millesse oli SCK (mõnel plaadil SCL) markeeringuga viigu kohta lisatud infot: selle kokkuvõtteks saame öelda, et SCK-viiku on vaja süsteemiosade „ühise ajastuse“ signaali tarvis.
Et oleks võimalik sünkroonne toimimine SCK-ahelasse lülitatud mikroskeemide vahel, peab omavahel jagama infot ühise takti kohta. Infojagamise toimimiseks on aga vaja eraldi viik (SCK/SCL) ühendada ühtse takti jälgimise võimekusega toetatud Arduino viiguga. I2C puhul on selleks A5 viik. Valisime vastavat SCK infot kandva juhtme värvikoodiks sinise värvi.
Kordame asünkroonse toimimise meenutuseks, et UART3 puhul puutusime kokku signaali-kiirusega: andsime ette baudid (impulssi sekundis4). Meil ei läinud vaja eraldi SCK viiku.
Põhjuseks on, et UART puhul infot ühtse kella-aja-arusaama kohta sideühenduses endas ei jagata—see on ette määratud meie poolt baudides (impulssi sekundis) väljendatud väärtusega nii programmis kui ka Serial monitoris „kellasid õigeks pannes“—st suhtluse kiirus mõlema partneri vahel on ette määratud.
Kiiruse ettemääramisele lisaks on asünkroonse side korral vaja kasutada ka andme-bittidele ette lisatult a) start-bitti, et teavitada suhtluse algusest—ning lõppu lisatult b) stopp-bitti, et teavitada suhtlus-ühiku lõpust.
Võtame kokku asünkroonse side lihtsa omakäelise skeemiga.
3 Universal Asynchronous Receiver-Transmitter: asynchronous = asünkroonne = mitte-sünkroonne. Eesti keelde panduna: Universaalne Asünkroonne Vastuvõtja-Saatja.
4 Sümboli- ja biti-kiiruste vaheteo täpsemaks mõistmiseks vt https://www.electronicdesign.com/technologies/communications/article/21802272/whats-the-difference-between-bit-rate-and-baud-rate
21.3.2.2. SDA viik:
Vaid ühtsest taktist I2C puhul aga ei piisa: vaja on, et ühtses taktis liiguks ka data. Seega I2C protokolli järgi suhtlema pidaval anduril peab lisaks SCK (SCL) viigule olema veel ka andmete edastamise viik ja sellega ühendatud juhe kuni vastava viiguni Arduinol. Sellist rolli täitvaks viiguks on anduril SDA tähistusega viik.
Täiendame nüüd märkmete-tabelit ka SDA viigu kohta: tegemist on Serial Data jaoks ettenähtud viiguga. (SDA-markeeringut vahel mõnel anduril ei näe, selle asemele on kirjutatud SDI—kirjutame SDI lahti kui Serial Data Input.)
(Vihje: märkige SDA/SDI kohta teadasaadu Harjutus B tarvis Teie poolt koostatavasse tabelisse!)
SDA/SDI on SCK/SCL järel teine side-viik, mida peame ühendama Arduinoga I2C protokollis suhtlemise tarvis! Kokku on niisiis kaks side-viiku iga mooduli kohta.
Toome siinkohal üldpõhimõtte kohta ka joonise.
Neile kahele lisaks vajame aga ka toidet ja maaühendust. (Vt järgnev Fritzing skeem.)
BME280 või BMP280 õhurõhuanduri + temperatuurianduri näitude praktiliseks kasutuselevõtuks näeb kogu skeem välja nii nagu allpool Fritzing vahendusel näitame. Lisaks sideviikude ühendamisele tuleb ühendada ka toide ja maaühendus.
Koostage vastav vooluahel.
21.3.3. Programm
Programm, millega saame käivitada I2C skeemi, on leitav Arduino IDE-st: File -> Examples -> Adafruit BMP280 Library -> bmp280test
Käivitame Arduino IDE-st programmi. Laeme selle Arduinole nii, et aktiveerime selles toodud võimaluse, mille kõrval on kommentaariks, et I2C jaoks.
Vihje: vaata minu poolt selle peatüki teksti kopeeritud näidisprogrammi tekstis punasega esitatud osasid!
Vaata kollase värviga märkust—see käib I2C kohta!
Aktiviseerida tuleb õige osa, vastasel korral ei saavuta me töötavat süsteemi.
NB!
Kuna sedakorda meil ei lähe tarvis viikude eraldi deklareerimist—töö teeb ära meie eest Arduino arhitektuur ning seda arvestav teek—siis „muudame inaktiivseks“ kõik selle, mida me antud programmis I2C tarvitamise korral käivitada ei tohi.
Ja kas pakute ise välja, mida ette võtta muutujatega?
Tehke vajalikud muudatused käsitsi File -> Examples -> Adafruit BMP280 Library -> bmp280test abil võetud programmitekstis ja kontrollige, kas kompileerub, see järel laadige Arduinole ja käivitage.
Kui ei õnnestunud, siis võrrelge oma Arduino IDE ekraanil olevat järgneva programmitekstiga, milles kommentaariga //MUUDATUS on tähistatud kõik see, mida muutsime, et toimiks I2C.
#include <Wire.h> #include <SPI.h> #include <Adafruit_Sensor.h> #include <Adafruit_BMP280.h> //MUUDATUS ALATES SIIT //#define BMP_SCK 13 //#define BMP_MISO 12 //#define BMP_MOSI 11 //#define BMP_CS 10 Adafruit_BMP280 bme; // I2C //Adafruit_BMP280 bme(BMP_CS); // hardware SPI //Adafruit_BMP280 bme(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK); //MUUDATUS KUNI SIIA void setup() { Serial.begin(9600); Serial.println(F("BMP280 test")); if (!bme.begin()) { Serial.println("Could not find a valid BMP280 sensor, check wiring!"); while (1); } } void loop() { Serial.print("Temperature = "); Serial.print(bme.readTemperature()); Serial.println(" *C"); Serial.print("Pressure = "); Serial.print(bme.readPressure()); Serial.println(" Pa"); Serial.print("Approx altitude = "); Serial.print(bme.readAltitude(1013.25)); // this should be adjusted to your local forcase Serial.println(" m"); Serial.println(); delay(2000); }
Vaadelge töötavat skeemi:
Mitu viiku/juhet on mängus ja mis need oleks?
Vahemärkus Harjutus B osas: Kas kaaluksite eraldi märkmete tabel koostamist I2C jaoks? Järgmises osas me vaatame SPI protokolli, millel on rohkem viikusid kui I2C protokollil.
Vahemärkus anduri näitude kohta:
Minu poolt selles tekstis kirjapandu läbimängimiseks kasutatud andur GY-BME/P280 näitas muude mõõteriistadega mõõdetud temperatuurist üsna erinevat temperatuuri. Ka kõrgus merepinnast on mul üsna käest ära—olen praegu Tallinnas ja Serial monitori ekraanilt näen, et GY-BME/P280 andmetel on mu asupaigal kõrgust üle 66 meetri, muud andmed seda ei kinnita. Eile ühe teise GY-BME/P280 plaadiga toimetades mu kirjutuslaua kõrguseks 55 meetrit allpool merepinda. Iga andurit tuleb alati testida ja vajadusel kalibreerida. Ei saa pimesi usaldada...
- Miks me ei lähe edasi näitude kordategemisega?
Antud õppetunnis on teemaks pigem sünkroonse side kaks protokolli. I2C-ga oleme nüüd põgusalt tutvunud, järgmisena võtame ette SPI.
21.4. SPI protokoll: Serial Peripheral Interface
Ka SPI protokoll esindab sünkroonset sidet.
21.4.1. Alustame võrdlusest: meenutame kuidas kasutas kahe signaali edastust I2C
Meenutame, et I2C puhul on vaja kahte suhtlus-juhet: andmete (data) edastamine toimub eraldi juhtmega (SDA), ent ning „ühtset kella-aega“ (clock), takti hoiab eraldi juhe (SCK).
„Kellaks“ on tegelikult „üles-alla“ võnkuv takt-signaal, mis näitab andmete vastuvõtjale täpselt kätte hetke, mil andme-juhtme kaudu tulevat on vaja lugeda.
Kella-signaal (SCK) koosneb tõusvast osast („ülespoole“: LOW -> HIGH) ja sellele järgnevast langevast osast („allapoole“: HIGH -> LOW) (vt joonis) ning järgib etteantud takti. Iga sellise kaheosalise signaali-mustri järel vastuvõtja teab, et tuleb paralleelselt ära lugeda ka saatjalt saabunud andme-oleku signaal (data-juhe (SDA)).
Kuna takti-signaal saabub sünkroonselt data-signaaliga, siis kiiruste etteandmise vajalikkus ei oma sellist kriitilist tähendust kui asünkroonse side korral. (UART-iga eksperimenteerides nägime, et baudid on üliolulised.)
Seega on SDA-SCK kommunikatsioonis võimalik kasutada lihtsamat lahendust kui UART puhul. Niiviisi I2C toimibki.
20.4.2. MOSI viik ja MISO viik
Ent nüüd lisame I2C sünkroonse side kirjeldusele (SCK-SDA) ka master-slave mustri.
Oluline on see, et üks osapool—milleks tavaliselt on mikrokontroller, annab sides ette takti ja muud komponendid (näiteks sensorid) peavad seda takti arvestama data lugemisel ja edastamisel.
Master-seade annab ette takti, slave-seadmed kasutavad master-seadme poolt etteantud taktsignaali.
I2C puhul SDA kohta öeldu—st data ülekannet puudutav sideosa—nõuab aga SPI protokolli töö kirjelduseni jõudmiseks aga lisatäpsustust: jagame eelmisel joonisel SDA (Serial Data) signaali kaheks: jagame eelpool näidatud Data-ühenduse kaheks.
Seega siit kaks lühendit-mõistet:
A) MOSI (Master Out/ Slave In) ja
B) MISO (Master In / Slave Out).
Näitlikkuse huvides „täiendame“ I2C kohta tehtud omakäelist joonist: SDA asemele peame panema MOSI ja MISO ühendused.
Seda muudatust tehes oleme saanud I2C ühenduse asemele SPI ühenduse.
Data-liiklus jaotati kahele eraldi viigule:
Master Out, Slave In viigule ning Master In, Slave Out viigule.
A) MOSI:
- Kui data saadetakse master-seadmelt slave-seadmele, siis saadetakse seda läbi MOSI-ühenduse.
- Master annab ette takti.
- Master saadab välja andmed (data).
- Slave võtab vastu andmed (data)—ja loeb seda vastavalt Master etteantud taktile.
Selline andmeliiklus toimub MOSI-ühenduse kaudu—selleks on vajalik MOSI-viikudele ühendatud MOSI-juhe.
Harjutus B tabelile mõeldes:
Leiame oma BME 280 pealt viigu, mille tähiseks on SDI. SDI = Serial Data In. See on meie jaoks ka MOSI.
NB!
Harjutus B tabelile mõeldes:
SDI—seega MOSI!
BME280 võtab vastu (Slave In) data Arduino protsessorilt (Master Out).
Enne järgmise skeemi (vt 21.4.5. skeem SPI jaoks) koostamist kordame selle info üle! Leiame oma BME280 pealt viigu, mille tähiseks on SDI. (SDI = Serial Data In)
Vihje Harjutus B tarvis—mõelge, kuidas panete selle info tabelisse. SPI ja I2C on soovitav nüüd juba paigutada eraldi tabelitesse.
B) MISO:
- Kui data saadetakse slave-seadmelt master-seadmele, siis saadetakse seda läbi MISO-ühenduse.
- Master annab ette takti.
- Slave saadab välja data.
- Master võtab vastu data—ja loeb seda samuti vastavalt master poolt—st iseenda poolt etteantud taktile.
Selline andmeliiklus toimub MISO-ühenduse kaudu—selleks on vajalikud MISO-viikudele ühendatud MISO-juhe.
NB!
Harjutus B tabelile mõeldes:
Leiame oma BME 280 pealt viigu, mille tähiseks on SDO. (SDO = Serial Data Out) See on meie jaoks ka MISO. SDO—MISO!
BME280 seega saadab (Slave Out) data Arduino protsessorile (Master In).
Vihje Harjutus B tarvis—mõelge, kuidas panete selle info tabelisse.
Kuna SPI-protokolliga suhtlevatel seadmetel on alati eraldi send ja receive ühendused, siis saab korraga paralleelselt nii infot vastu võtta kui ka teisele osapoolele saata.
Sellist võimalust nimetatakse inglise keeles full duplex.
21.4.3. Veel viikusid
Slave Select (SS), ka Chip Select (CS)
Kirjeldatud MOSI, MISO ja SCK ühendustega on võimalik toime tulla, kui meil on üks master-seade ja üks slave-seade.
SS (Slave Select) annab võimaluse teavitada slave-seadet sellest, et on vaja midagi teha.
Koostame selle kohta omakäelise joonise.
Üldjuhul on SS ühendus positsioonis HIGH—see hoiab slave inaktiivses seisundis. Enne data saatmist slave-seadmele viiakse SS LOW positsiooni—slave-seade „äratatakse üles“. Kui info liigutamine on aset leidnud, viiakse SS ühendus taas HIGH positsiooni ja seega muutub slave-seade taas inaktiivseks.
Kui meil on aga mitu slave-seadet, siis peame kuidagi aru saama, et kellega parajasti suhtlus käib.
SPI kasutamise korral on kaks võimalust korraga mitme slave ühendamiseks.
1. Igal slave-seadmel on oma SS ühendus, mille kaudu teda aktiivseks muudetakse.
Iga SS ühendust saame eraldi LOW positsiooni viia ja inaktiivses faasis HIGH tasemel hoida. Nii väldime seda, et aktiveerime korraga ühe SS ühendusega mitut Slave-seadet. Eeldame, et meil on piisavalt vähe Slave-seadmeid ja meil on piisavalt viikusid SS ühenduste tarvis. 5
2. Alternatiiv aga on aktiveerida korraga kõik Slave-seadmed—need on MOSI ja MISO tarvis ühendatud jadaühenduse vormis.
Sellisel juhul Master-seadme MOSI jõuab esimese Slave-seadme MOSI-sse, ent selle seadme MISO on ühendatud järgmise MOSI-ga, järgmise seadme MISO on ühendatud ülejärgmise MOSI-ga jne jne.
Seega läbiks näiteks Masteri poolt saadetud datasignaal kõige viimase Slave-seadmeni jõudmiseks kõiki Slave-seadmeid—ühest lähtuv MOSI on ühendatud järgmise Slave-seadme MISO viiguga—kuni viimane Slave-seade selles jadas saadab oma MISO-viigult signaali Master-seadme MISO-le.
Saame sellist ühendusviisi kasutada vaid juhtudel, kui Master-seade saadab teavet kõigile: näiteks saame niiviisi panna toimima mingit järjestust LED-isid, luua jadamisi ühendatud LED-idega värvimänge.6
Korraks vaatame ka oma BME280 peale. Kas sinna on kirjutatud SS või on seal CS? Mõlemad markeeringud viitavad samale sisule.
Täidame tähelepanekud Harjutus B tabelisse.
5 Kui ühenduste arvu piir aga siiski suuremate süsteemide korral võiks probleemina ette tulla, saame kasutada ka nn binaarseid dekoodreid, suurendades niiviisi ühenduste arvu. Hetkel me seda ei käsitle.
6 Master-seadme poolt siiski saab ka vastu võtta jadamisi toimivatelt Slave-seadmetelt tulevaid signaale, ent see oleks tehniliselt keerukam—vaja oleks viimaselt Slave-seadmete jada liikmelt tuleva signaali kättesaamiseks läbi kuulata kõik selle viimase ja Master-seadme vahele ühendatud seadmed.
21.4.4. Programm SPI ühendusele
Võtame taas lahti näidisprogrammi Arduino IDE-st: File -> Examples -> Adafruit BMP280 Library -> bmp280test
Laeme selle Arduinole nii, et saaksime aktiveerida selles SPI kasutamiseks lisatud koodi-osa; vajalikud on ka vastavad viigu-numbreid tähistavad muutujad. Viikusid meil sedakorda ise määrata ei õnnestu, sest vastava töö teeb meie eest ette ära teek (library) koos Arduinoga. Ühendage viigud vastavalt programmis öeldule. Käivitage programm nii, et viikude deklareerimisest oleks kasu. Allpool on toodud programmi tekstis vajalike muudatuste kohad on ümbritsetud kommentaariga //MUUDATUS lisaks näete ka skeemi.
#include <Wire.h> #include <SPI.h> #include <Adafruit_Sensor.h> #include <Adafruit_BMP280.h> //MUUDATUS #define BMP_SCK 13 // SCK sinine #define BMP_MISO 12 // SDI roheline #define BMP_MOSI 11 // SDO valge #define BMP_CS 10 // CS kollane //Adafruit_BMP280 bme; // I2C //Adafruit_BMP280 bme(BMP_CS); // hardware SPI Adafruit_BMP280 bme(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK); //MUUDATUS void setup() { Serial.begin(9600); Serial.println(F("BMP280 test")); if (!bme.begin()) { Serial.println("Could not find a valid BMP280 sensor, check wiring!"); while (1); } } void loop() { Serial.print("Temperature = "); Serial.print(bme.readTemperature()); Serial.println(" *C"); Serial.print("Pressure = "); Serial.print(bme.readPressure()); Serial.println(" Pa"); Serial.print("Approx altitude = "); Serial.print(bme.readAltitude(1013.25)); // this should be adjusted to your local forcase Serial.println(" m"); Serial.println(); delay(2000); }
21.4.5. Skeem SPI jaoks
21.5. Kodutöö
Tehke õpitu põhjal märkmeid ja looge tunni alguses alustatud tabeli põhjal kaks eraldi tabelit:
- ühes andke infot BME280 viikude kohta I2C korral ning
- teises andke infot BME280 viikude kohta SPI korral.
Vajadusel muutke tabelis info esitamise korda—tehke see endale mugavaks abivahendiks, sest sellest teemast on õpetajal kindlasti huvi küsida küsimusi nii kordamise tunnis kui ka kontrolltöös.
Esitage järgmiseks tunniks kaks tabelit viikude koha tehtud märkmetega õpetajale kontrolliks.
21.6. Kaks lisalugemist
21.6.1. Võrdleme I2C, SPI ja UART
I2C, SPI ja UART osas on kindlasti tekkinud küsimus: millal on mida tark kasutada?
Nii I2C kui ka SPI on mõeldud suhteliselt väikese distantsi pealt suhtlemiseks—harilikult ühe suuremal hulgal komponente sisaldava seadme piires. I2C ning SPI on sarnased selle poolest, et võimalik on mõlema puhul kaasata suur hulk slave-seadmeid. I2C abil on võimalik ühendada ühte süsteemi ka mitu master-seadet.
Millal kasutada UART Serial port (järjestikport) võimalusi?
UART puhul (mis on asünkroonne, sest takti-infot me ei saada eraldi ühendusega vaid selle täpsustame eelnevalt baudidega deklareerides ette) on oluline, et baudid, mis deklareeritud programmis—oleks ka vastavuses sellega, mis Serial monitori peal valitud. Kui aga lubada endale lohakust—st esineb erinevus programmis antud ja Serial monitoril valitud baudide vahel—siis see muudab Serial monitorile kuvatava info loetamatuks. Tegelikult üldjuhul ei tulegi midagi läbi—signaal läheb kaotsi.
Võrrelduna SPI ja I2C-ga: UART puhul on rohkem vaja riistvaralist tuge; see teeb aga projekti veidi kallimaks. Tehniliselt vajame iga 8 biti saatmiseks ka ühte algusbitti ja lõpetusbitti. Suurema infohulga peale võib selline meetod tasapisi ka probleeme tekitada, selle valikkursuse raames tehtavates skeemides seda aga ei juhtu. UART sobib infovahetuseks kahe seadme vahel—rohkemate lisamine on üsna komplitseeritud. UART puhul ei jaga me seadmeid master- ja slave-seadmeteks, sest ükski seade ju ei anna ette infolugemise takti—seda asendabki iga kaheksa biti ees alustus-bit ning nende lõpus lõpetus-bit.
Seega, kui meil on vaja liigutada enda jaoks mugavalt väikesi andmekoguseid kahe seadme vahel, siis on UART hea käepärane vahend.
Millal kasutada I2C võimalusi?
I2C puhul (mis on sünkroonne sidepidamise viis) on vaja vähem juhtmeid kui SPI puhul: kasutame SCK takti-infot ja SDA Serial Data signaali. SCK-signaali saame alati parasjagu toimetavalt master-seadmelt. Meil on võimalus ühendada rohkem kui ühe slave-seadmega rohkem kui üks master-seade.
Seega, kui meil on vaja liigutada enda jaoks mugavalt väikesi datakoguseid kahe seadme vahel, siis on UART hea käepärane vahend. Kui seadmeid on rohkem kui kaks, siis I2C.
Millal kasutada SPI võimalusi?
SPI puhul (mis on sünkroonne sidepidamise viis) on paraku vaja vähemalt nelja juhet ainuüksi andmeliikluse tarvis. Samas aga saame kasutada võimalust ühendada rohkem kui ühte slave-seadet master-seadmega—see on kordades kergem kui sama üritada UART-iga. Seega me UART-iga midagi sellist ei ürita. Teeme seda SPI-ga.
Häda aga võib meid tabada juhtmeuputuse näol—kui ikka ühendame suurt hulka slave-seadmeid, siis juhtmeid on vaja ka piisavalt. Sel juhul võivad otsa saada vabad ühendused Arduinol. Selles kursuses meil midagi sellist tulemas ei ole.
SPI-st jätame meelde, et võimalik on vaid üks ainus Master-seade. SPI aga võimaldab samaaegset info saatmist vastuvõtmist: MISO ja MOSI! Surfamiseks otsisõnad: „Full duplex“ !
Seega, kui meil on vaja liigutada üheaegselt vastupidises suunas liikuvat suuremat infokogust ja kui on alati vaid üks infosaatja, ent palju info vastuvõtjaid—siis kasutame SPI ühendust.
Lisalugemine 2
Olen palunud õpilastel kirja panna ka vahel tüütult pisikesi nüansse. Harjutus B puhul vaatlesite viikude tähiseid ja tegite nende kohta märkmeid nii palju kui see tundmatul teemal alustuseks võimalikuks osutus.
Vaevarikas selle harjutuse juures oli see, et veel ei saa me aru, kuhu mida peaks ühendama, kas üldse peame kõiki viikusid ühendama, kas mõnede ühendamiseks on mitu võimalust või on veel mingi variant, millest me teadlikud ei ole—ent peaksime kõike juba teadma ja tabelisse märkima. Selline ebakindel algus on alati häiriv…
Et veidigi lihtsam oleks orienteeruda, siis mina viin iga mulle uue teema kohta esialgu paratamatult napid märkmed lünklikult täidetud tabeli kujule. Asun siis lisa leidma tooteinfot uurides. Edasi uurides muutub ka esialgne esitlusstruktuur.
Algajana on mul sageli kasutada olnud midagi väga odavat, millel ei pruugi haakuda omavahel ei ühendused ega ka plaadile kantud info.
Mul on kaks võimalust:
- jätkata kahtlemata väsitavat otsimist;
- ent on võimalik ka kohe proovida viikusid enam-vähem ettekujutusele vastava arusaamaga ära ühendada—kas ehk BME seitse viiku ei pruugigi tunduda eriti palju, et kõiki kombinatsioone läbi katsetada?
Varasemalt oleme vaadelnud arvu 3 faktoriaali arvutamist:
3! = 3 x 2 x 1 = 6.
Mõtleme tehte sisu üle.
- Kui on kaks viiku, siis oleks justkui kaks võimalust neid asetada: 1-2, seejärel 2-1.
- Kui on kolm viiku, siis aga rohkem: esimene on 1-2-3; teine on 1-3-2; kolmas on 2-1-3; neljas on 2-3-1; viies on 3-2-1; kuues aga 3-1-2. Kas said kõik võimalused kirja või on veel mõni võimalus? Lihtne jälgida?
Ent asi areneb:
7!= 7x 6 x 5 x 4 3 x 2 x 1 = 5040
Igaks juhuks teeme asja veel keerukamaks—igaühte nendest seitsmest BME anduri viigust saate ju ühendada ka vaat et igasse pessa, mis Arduinol võimalik. Loendage, mitu pesa on võimalik … Mõistame, et huupi ühendamine läheb üsna hullusti käest ära…
Tõsisema huvi korral võtke otsisõnadeks „permutations, combinations“. Kui olete teooriat uurinud, siis võite eelmistele otsisõnadele lisada ka „calculator“. Veenduge, et võimaluste rohkust ei ole realistlik omal nahal läbi katsetada.
Ja kõige krooniks: huupi ühendades on tegelikult üsna suur tõenäosus mingi andur või protsessoriga moodul üldse ära rikkuda. Tegelikult oleks pidanud just sellest alustamagi.