Tartalom:
- Szélsebességek alakulása Magyarországon
- Háromágú szélkerék forgási sebességének kiszámítása a szélsebességből (kicsi matek)
- Reed relé alkalmasságának vizsgálata, hall szenzorra cserélés szükségességének meghatározása
- Mérési módszerek kidolgozása, pillanatnyi szélsebesség, széllökés, átlagos szélsebesség
- Mérés az adott időben történt impulzusszámmal
- Szélsebesség mérő lekérdezését végző Arduino (slave) összekötése egy távolabbi lekérdező Arduino programmal (master)
- Példa programok
———————————————————————————-
Ez a szerkezet sok más szenzorral ellentétben, nem írja ki, hogy mennyi a mért érték. Két kontaktus jelet ad minden fordulatnál (megszakítja a zárt kontaktust, vagy zárja azt, ahogy tetszik) és vagy elhisszük a leírásban megadott egyetlen adatot, vagy sem. A leírást azt állítja, hogy 2,5 km/h szélsebességnél egyet fordul egy másodperc alatt. Nyilván ez egy erősen közelítő érték. A szél szinte soha nem fúj egyenletesen, házak közelében örvények keletkeznek, széllökések jönnek mennek. Elhiggyük? Vajon ez azt is jelenti, hogy 25km/h esetén 10-et fordul másodpercenként? Csupa jó kérdés. Nézzük megelső körben, hogy melyik kérdés lényeges ezek közül?
Magyarországon elég sok statisztika áll rendelkezésre a szelek természetéről. Találtam is egy térképet az átlagos szélsebességekkel:
Ez a térkép innen származik: https://www.met.hu/eghajlat/magyarorszag_eghajlata/altalanos_eghajlati_jellemzes/szel/
Azt jól lehet látni, hogy jellemzően minden zöld, tehát 2-3 km/h szélsebességre számíthatunk. Még a nagyobb átlagos szélsebességek is 5-6 km/h körül adódnak, tehát az egyetlen megadott adat a szenzorról abban a tartományban van, ami a leggyakoribb környezetünkben. Még esetleg a gyakoriságról is jól jöhet egy kis infó. Íme egy sokkal nehezebben értelmezhető grafikon:
Ráadásul ez m/sec-ben lett megadva, ami ugye 3,6-al szorzandó, hogy km/h mértékegységet kapjunk. Ez alapján szerintem már inkább a 3-6km/h az átlagos, de nem nagy a különbség, így nem igazán érdekel melyik ábrának van igaza. Ebből meg az nem derül ki, hogy mi a maximális szélsebesség. Az ábra azt sugallja, hogy 15 m/s (54 km/h) felett semmi nincs, pedig ez nem igaz. Olvastam valahol, hogy Magyarországon a szélsebesség rekord 144 km/h.
Fontos adat lenne számunkra a szélsebesség mérőről, hogy mekkora a minimális szélsebesség, amin a szélkerék megindul. Hát ezt nem adták meg, reméljük, hogy 0,5-1km/h környékén már mér. Látható az utóbbi ábrából, hogy elég csekély a 0 szélsebesség valószínűsége, tehát 1-2km/h lágy szellő mindig fújdogál. Amit a konkrét szenzorunkról érdemes tudni, hogy a háromlapátos forgó tengelyre egy mágnest szereltek, ami egy reed relét kapcsolgat. Úgy tapasztaltam, hogy egy fordulat alatt kétszer szakítja meg a folyamatosan zárt kontaktust, mégpedig 1/3-os kitöltési tényezővel (1/3 ideig zárva, 2/3 ideig nyitva a kontaktus). Egy körül fordulás alatt két felfutóélet tapasztaltam a később megtalálható mintaprogrammal. Ez bizony elég kevés. Pont abban a tartományban, ahol a jellemző szélsebességek tapasztalhatók Magyarországon, nagyon kicsi a felbontás. Ez azt eredményezi, hogy a kontaktusok számlálása esetén elég hosszú ideig kell mérni, hogy értékelhető számot kapjunk. Pl. ha egy másodperc alatt egy impulzust mérünk, akkor a szélsebesség kb. 0,6 km/h, ha egyáltalán megindul a szélkerék ekkora sebességnél. Sebaj, legfeljebb hosszú ideig fogunk mérni, és ebből az adatból készítünk átlagot.
Van azonban más lehetőség is. Ha nagyon kicsi a fordulatszám, akkor megmérhetjük egy fordulat (két impulzus felfutó éle vagy lefutó éle) között eltelt időt. Ebből egészen pontosan megtudhatjuk a pillanatnyi szélsebességet, nem kell sok impulzust begyűjteni. Ezt a technikát lehet párhuzamosan is alkalmazni, így viszonylag rövid időn belül lehet adatunk.
Nekem csak egy elnagyolt átlagra lesz szükségem, mert csak azt akarom kideríteni, hogy a szél mennyire szárítja ki a meglocsolt földet, így a pillanatnyi sebességgel nem szándékozom foglalkozni. Ha sokat fúj, akkor hamarabb kell újra locsolni. Ehhez nem kell pontosan mérni, átlagos adatok is jók lesznek. Épp ezért a példa programban egy percig mértem, és így állítottam elő az egy perces átlagot. Azonban kísérlet képen csináltam egy 10 másodperces mérést is, aminek az eredményét széllökésnek neveztem el. Abból indultam ki, hogy egy-egy hirtelen „széllökés” esetén a szélsebességmérő 5-10 másodperc alatt sem áll le, lendületből lassulva forog. A széllökés a hajszárító produkálta. A széllökéseknek csak a maximális adata érdekel, tehát az, hogy egy adott időn belül mi volt a legmagasabb szélsebesség. Nehogy már ne tudjam, hiszen olyan hasznos!
Virtusból szeretném leellenőrizni, hogy vajon a megadott 2,5 km/h adat helyes-e. Ehhez elő kell venni az internetet, és beszerezni pár adatot. Mekkora erővel hat egy homorú és egy domború félgömbre a szél? Van ehhez képlet:
Egyszerűbb mint aminek látszik. „Fe” a megfújt felületre ható erő. Az a furcsa jel az egyenlőségjeltől jobbra a ró, ezt a későbbiekben q-val fogom helyettesíteni. Ez a levegő sűrűsége, ami egy konkrét szám, de mint ki fog derülni, nem is lesz rá szükség. A „Cw” a légellenállási együttható, aminek az értékét különböző alakzatokra meg lehet találni a neten. Ha félgömb homorú fele felől fúj a szél, akkor 1,4, a domború felel felől 0,4. Ez tapasztalati mérési eredmény ha nem tévedek. Beraknak egy alakzatot a szélcsatornába, megmérik az erőt egy adott szélsebességnél, és kiszámolják a fenti képletből az értékét. Az autók Cw értékét is így mérik. Egy modern autó Cw-je 0,2 – 0,3 között van. A legideálisabb cseppformánál 0,02 körüli érték. Az „A” a félgömbünk szélirányba mutatott keresztmetszetének felülete. Ez sem fog kelleni, de ez még titok. A „V” a szélsebesség.
Mivel macerás lenne a képletet a fenti formátumban megjelenítenem, az alábbi módon fogom felírni :
F=½ * q * A * C * V2
(ebben a felírásban a „*” a szorzás)
Egy szélkeréken egyszerre három félgömbre hatnak a szél által keltett erők. Mindhárom félgömböt egyszerre éri ideális esetben a szél, és a forgó mozgás addig gyorsul vagy lassul, amíg beáll az egyensúlyi állapot, és a forgó rendszerre ható erők eredője nulla lesz. Fel kellene írnunk egy egyenletet. Ez egyszerűbb mint gondolnánk. Tételezzük fel, hogy épp abban a helyzetben van a szélkerék, hogy az egyik félgömb a homorú felével teljes felületét mutatja a széliránybak, tehát rá maximális erő hat, ami a szél irányába mozdítja. Le is fotóztam az én szélkerekemet ebben az állapotban (piros nyilak jelzik a szélirányt):
Persze a tartórúd nem fogja engedni az egyenes vonalú elmozdulást, így kényszerből körpályán mozog, de most ezzel ne törődjünk. Azt is feltételezzük, hogy már beállt az egyensúlyi állapot, tehát a tengelyre nem hat forgatónyomaték, így a rendszer gyorsulás nélkül egyenletesen forog. Ebben a pillanatban a tengely másik oldalán két félgömb is a domború felét mutatja a szélirányba. Nem a teljes felületüket, hiszen egyik is és másik is 60 fokban elfordul a merőleges iránytól a kialakítás miatt. Most hanyagoljuk el, hogy ezek felülete egy kicsit kisebb mintha merőlegesen állnának, és azzal se foglalkozzunk, hogy egyik jobbra a másik balra fordul 60 fokkal. Akkor lesz az eredő erő nulla, ha a tengelyre ható fogató nyomaték ebben a pillanatban nulla, vagyis a szélkerék jobb és bal oldalára ugyanakkora erő hat. Vagyis a bal oldali erő azonos a jobb oldali erőkkel:
½ * q * A * C1 * (Vsz-Vp)2 = ½ * q * 2A * C2 * (Vsz+Vp)2
Itt a Vsz a szél sebessége, a Vp pedig a félgömbök pillanatnyi sebessége. A jobb oldali félgömb az ugye együtt mozog a széliránnyal, ezért olyan mintha kisebb sebességgel fújná a szél a szélsebesség és a saját szélirányba haladó sebességének a különbségével. Így a rá ható erő kiszámításakor ezzel a sebesség különbséggel kell számolni. A bal oldalon pont ellentétes az elmozdulás, mert a széllel szembe fordulnak a félgömbök. Tehát itt a két sebesség összegével kell számolnunk. A félgömbök felülete A, és a jobb oldalon kettő van, tehát 2A. A bal oldali domború félgömbök légellenállási együtthatója C1 (0,4), míg a jobb oldal C2 (1,4). Még nem írtam be a konkrét felületet, hátha nem is lesz rá szükség. Sajnos itt még egy lényeges korrekcióra szükség van, amit alapból nem írtam fel, nehogy érthetetlenül bonyolult legyen az egyenlet. A bal oldali félgömbök szélirányba történő elmozdulásának sebessége nem azonos a jobb oldali félgömb szélirányba történő elmozdulási sebességével, mert épp 60 fokos szögben állnak. Ha nem tévedek, akkor itt 60 fok cosinusával kell számolni, ami éppen 0,5. Tehát a szélirányba csak a teljes sebesség felével mozognak. Így a képletünk immár pontosabb formában:
½ * q * A * C1 * (Vsz-Vp)2 = ½ * q * 2A * C2 * (Vsz+0,5 * Vp)2
Nyilván a rudazat légellenállását is elhanyagoljuk. Mivel nem vagyok matematikus, egy két ismeretlenes másodfokú egyenletet nem fogok tudni megoldani, ezért további egyszerűsítésekre lesz szükség. Kiküszöbölhetjük az egyik ismeretlent, ha beírjuk egy konkrét értékét. Pl. legyen a szélsebesség 2,5 km/h. Azért pont ennyi, mert ezt meg is adták nekünk a szélkerék katalógusában, vagyis azt, hogy 2,5 km/h szélsebesség esetén másodpercenként egyet fordul körbe. Nosza, tegyük is meg, helyettesítsük be a szélsebességet:
½ * q * A * C1 * (2,5-Vp)2 = ½ * q * 2A * C2 * (2,5+0,5 * Vp)2
Azt is tudjuk, hogy egy félgömb homorú oldaláról megfújva 1,4 légellenállási együtthatóval rendelkezik. Ugyanez a félgömb a domború oldalán már csak 0,4 légellenállási együtthatót produkál. Ezt is írjuk be.
½ * q * A * 1,4 * (2,5-Vp)2 = ½ * q * 2A * 0,4* (2,5+0,5 * Vp)2
Azt rögtön látjuk, hogy az egyenlet mindkét oldalát el lehet osztani q-val és A-val, sőt megszorozhatjuk 2-vel, hogy az a csúnya ½ is eltűnjön az elejéről:
1,4 * (2,5-Vp)2 = 2 * 0,4* (2,5+0,5 * Vp)2
Így már sokkal szebb, rendezzük gyorsan:
1,4 * (2,5-Vp)2 = 2 * 0,4* (2,5+0,5 * Vp)2
1,4 * (6,25-5Vp+Vp2) =0,8* (6,25+2,5Vp+0,25Vp2)
8,75-7Vp+ Vp2=5+2Vp+0,2 Vp2
3,75-5Vp+0,8V p2=0
Előkerestem egy online másodfekú megoldáskereső programot, és a következő eredményeket kaptam:
Vp1=1,66 , Vp2=0
A két eredmény közül csak az egyik ad számunkra értelmezhető megoldást, vagyis 1,66 km/h a végeredmény.
Az eredmény tükrében folytassuk az ellenőrzést. Azt már tudjuk az egyenlet megoldásából, hogy a 2,5 km/h szélsebesség hatására a félgömbjeink 1,66km/h sebességgel haladnak a körpályán. Ez elég nehezen értelmezhető hiszen nem egyenes vonalban mozognak, de ne elmélkedjünk sokat, fogjuk fel úgy, hogy légüres térben adunk az egyik félgömbnek egy 1,66 km/h kezdő lökést. Számoljuk ki, mekkora utat tenne meg ezzel a sebességgel egy másodperc alatt. Ismét segítenek a neten található online sebesség átváltó programok: 1,66km/h = 46 cm/másodperc. Vagyis 46 cm-t haladna előre a félgömbünk egy másodperc alatt. De nem egyenesen halad, hanem körpályán, így azt kell megtudnunk, körpálya esetén mennyi fordulatot jelent ez az út, vagyis a körpálya hossza kell. A félgömb közepe a tengelytől 7cm-re van (ezt el kell hinnetek nekem), vagyis a kör kerülete: (7+7)*3,14=43,96. Ennyi elhanyagolással, kerekítéssel és egyszerűsítéssel a 46cm gyakorlatilag azonos a kb.44 cm-el! Készen is vagyunk, hiszen a 46cm út megtételével a félgömbünk majdnem pontosan egyszer megy körbe a körön, vagyis egyet fordul a rendszer! Elég sok dolgot elhanyagoltunk, ezért a megoldás nem teljesen meggyőző, de lehet némi köze a valósághoz!
Be kel vallanom, hogy életemben először használtam másodfokú egyenlet megoldó tudásomat egy valós gyakorlati célra. Eddig mindig csak mintapéldákat házifeladatokat oldottam meg. Nem emlékszem, hogy valaha szükségem lett volna rá! Szégyen bevallani, de ez a tudás éppenhogycsak megüti a gimnáziumi matematika és fizika tudásanyag alapszintjét, mégsem ment könnyen. Minden esetre halával tartozom gimnáziumi tanáraimnak: Szabó Zsuzsa matematika, Monostori Lászlóné fizika és Borbáth Gábor anyagszerkezettan tanáraimnak, akiktől valós életben használható tudásomat megszereztem. És persze megemlíthetném még Dr. Császár Ákosné egyetemi matematika tanáromat, valamint Dr. Füzessy Zoltán fizika tanáromat, akik ezt az alaptudást használható szintre mélyítették.
Tehát az a megállapítás, hogy a szélsebesség mérő 2,5 km/h szélsebességnél egyet fordul, úgy tűnik igaz. Köszönjük meg tanáraimnak!
Még annyit kell megjegyeznem, hogy a szélkerékben található reed relé nem túl biztató megoldás. Ha 2,5km/h sebességgel fúj a szél, akkor fordulatonként (másodpercenként) 2-szer kapcsol, vagyis naponta 172800-szor. Ez évente 63 millió. Egy átlagos reed relé élettartama a katalógusok szerint 100millió. Nem túl biztató! Idővel inkább valamilyen hall érzékelős megoldásra cserélem. Persze vehetnék 300 Ft-ért 10 db reed relét és ebből jó sokáig javítgathatom az elromlott alkatrészt, de nem lesz kedvem évente a tetőre mászni, így inkább hall szenzor (már meg is rendeltem)!!
Majdnem elfelejtettem a maximális szélsebességet! Mi lesz, ha közel 150 km/h-val fúj odakint. Hát tudom mi lesz, felborul a kerti asztalunk! A szélsebesség mérővel még nincs tapasztalatom, de tegyük fel, hogy túléli. 150 km/h esetén már 60-at fordul (biztos nem igaz így, mert ezek a rendszerek nem szoktak lineárisak lenni). Ebben az esetben a reed relé már 120-at kellene kapcsoljon másodpercenként. Vajon fogja ezt produkálni, vagy folyamatosan zárva lesz a kontaktus, mert a tehetetlenség fog győzni?! Erről alig találtam adatot. Valahol annyit azért találtam, hogy a meghúzási idő 0,6ms és az elengedés 0,2ms. A 120Hz frekvencia az kb. 8ms, tehát a reed relé még ekkora szélsebességnél is működhet. Ez elég meglepő! Azonban néhány szélvihar, és el is használtuk a reed relé élettartamát.
És vajon prelles a reed relé kontaktusa? Nem, nem az, ezt már kipróbáltam! Olvastam, hogy a kontaktusokat higannyal futtatják be, és ezért nem prelles.
És íme a mintaprogram:
bool elozo; //segéd változó előző kontaktus állpot tárolására bool most; //segéd változó a pillanatnyi kontaktus állpot tárolására int imp1=0; //segédváltozó a 10 másodperces (széllökés) impulzus számláláshoz int imp2=0; //segédváltozó a 1 perces (átlagos szélsebesség) impulzus számláláshoz float szel_seb_tmp=0; //segéd változó a szélsebesség tárolására float szelsebesseg=0; //a kiszámított szélsebesség float szellokes=0; //a kiszámított széllökés, csak a maximális értéket tartjuk meg long ido_tmp1=millis(); //segéd változó a 10 másodperc méréséhez long ido_tmp2=millis(); //segéd változó az egy perc méréséhez void setup() { Serial.begin(9600); Serial.println("Indul..."); pinMode(2,INPUT); //2-es kivezetésre kötöttem a kontaktus jelét digitalWrite(2,HIGH); //felhúzó ellenállás bekapcsolása elozo=digitalRead(2); //máris vezünk egy mintát a bemenetből } void loop() { most=digitalRead(2); //a pillanatnyi kontaktus állapot beolvasása if(elozo==LOW and most==HIGH) { //felfutó él imp1++; //növeljük az impulzus számlálókat imp2++; } elozo=most; if (millis()>ido_tmp1+10000) { //letelt a 10 másodperc, értékelünk és töröljük az impulzus számlálót szel_seb_tmp=((imp1/2)*2.5)/10; //kiszámítjuk az impulzus számból a sebességet 10 másodpercre if (szellokes<szel_seb_tmp) { //csak akkor tároljuk, ha nagyobb mint az eddigi maximum szellokes=szel_seb_tmp; } imp1=0; ido_tmp1=millis(); } if (millis()>ido_tmp2+60000) { //letelt az egy perc kiírjuk az átlag és széllökés adatokat, töröljük az impulzusszámlálót szelsebesseg=((imp2/2)*2.5)/60; //kiszámítjuk az impulzus számból a sebességet 60 másodpercre Serial.print("Átl. szélsebesseég uts. percben:"); Serial.println(szelsebesseg); Serial.print("Széllökes:"); Serial.println(szellokes); imp2=0; ido_tmp2=millis(); } }
Ezzel azonban még nincs vége az ismerkedésnek. Sokféle módon lehet megoldani az impulzusok számlálását, pl. lehetne megszakításokat is használni. Első körben azonban ezt elvetettem, mert a megszakítások használata megérzésem szerint impulzus vesztést okozhat. Ennek oka, hogy amikor valamilyen más időigényes feladatot lát el a program, esetleg le is kell majd tiltani a megszakítást, nehogy zavart okozzon. Viszont az impulzusok loop()-ban történő számlálgatása közben elég sok idő áll rendelkezésre. Jó lenne tudni, melyik impulzus (magas/alacsony) milyen hosszú. Azaz kíváncsi lettem a kitöltési tényezőre. Írtam ehhez egy minta programot. Csak a fel és lefutó éleket, azaz a kontaktus változását figyeli:
bool elozo; //segéd változó előző kontaktus állpot tárolására bool most; //segéd változó a pillanatnyi kontaktus állpot tárolására long ido_low=millis(); //segéd változó az alacsony szint (zárt kontaktus) idejénak mérésére long ido_high=millis(); //segéd változó az magas szint (nyitott kontaktus) idejénak mérésére int sorszam; void setup() { Serial.begin(9600); Serial.println("Indul..."); pinMode(2,INPUT); //2-es kivezetésre kötöttem a kontaktus jelét digitalWrite(2,HIGH); //felhúzó ellenállás bekapcsolása elozo=digitalRead(2); //máris vezünk egy mintát a bemenetből } void loop() { most=digitalRead(2); //a pillanatnyi kontaktus állapot beolvasása if(elozo==LOW and most==HIGH) { //felfutó él Serial.print(sorszam); Serial.print("Low idő:"); Serial.println(millis()-ido_low); //az alacsony szint ideje a kezdőpont és a pillanatnyi idő különbsége ido_high=millis(); //itt kezdődik a magas szint idejémnek mérése sorszam++; } if(elozo==HIGH and most==LOW) { //lefutóél Serial.print(sorszam); Serial.print("High idő:"); Serial.println(millis()-ido_high); //a magas szint ideje a kezdőpont és a pillanatnyi idő különbsége ido_low=millis(); //itt kezdődik az alacsony szint idejének mérése sorszam++; } elozo=most; }
Ime egy kiragadott futási eredmény:
151Low idő:98
152High idő:63
153Low idő:99
154High idő:54
155Low idő:98
156High idő:64
157Low idő:99
158High idő:54
159Low idő:101
160High idő:63
161Low idő:100
162High idő:54
163Low idő:99
164High idő:64
165Low idő:98
166High idő:54
167Low idő:100
A kiírt adat msec-ben értendő, de az a mintaprogramból is kiderül. Az adatokból két dolog is látható. Egyrészt a reed relé tényleg nem prelles. Másrészt a kitöltési tényező valóban nem azonos a magas és alacsony impulzus hosszaknál. A magas szint kb. fele az alacsony szintnek. Vagyis kb 1/3 – 2/3 arányt látunk, tehát ha valami hosszabb műveletet kell csinálni, akkor azt a programban a második if belsejébe kell elhelyezni, egészen pontosan a ido_low=millis(); utasítás sor mögé. Ekkor ugyanis hosszabb időnk van a következő állapotváltozásig. Ha ekkor a feladat olyan sokáig tart, hogy az élváltozás közben bekövetkezik, akkor azt az állapot változást sajnos kihagytuk, és elveszítettünk egy impulzust.
Esetleg fontos lehet, hogy a fenti kísérletben mekkora volt a szél. Ezt akár ki is számolhatjuk, mert egy fordulat az 300 msec körül van (egy impulzus pedig 50+100 msec, akkor kettő 300) Vagyis kb. 3 fordulat másodpercenként. Mivel egy fordulat 2,5 km/h, három fordulat 7,5 km/h. Egyszerű mint a pofon. Tehát egy Magyarországon átlagos szél esetén 100 msec időnk van. Mennyi ez viharban? 150 km/h / 7,5 km/h = 20. Vagyis ennek az időnek a huszad része áll rendelkezésre, azaz kb 5 msec. Ez megnyugtató! Ez alatt elég sok mindent lehet csinálni! Pl. el lehet küldeni a mérési adatokat egy másik Arduino-nak I2C buszon keresztül.
A szélsebesség mérőt egy meglévő időjárás állomás kiegészítésre is felakarom felhasználni. Írtam is egy demó programot, ami egy Arduino nano-ban méri a szélsebességet, és I2C buszon elküldi az adatokat az időjárás állomás master programja felé. Bár a tervem az volt, hogy a kontaktus zárt állapotában rendelkezésre álló hosszabb idő alatt küldöm el az adatokat, ez sajnos nem működhet, mert a slave önmagától nem küldhet adatot. Ezt a masternek kell kezdeményezni! Így maradt az a megoldás, hogy amikor a master kéri az adatokat, a slave küldi, és közben persze nem számolja az impulzusokat. (Azóta kitaláltam a spanyol viaszt, azaz rájöttem, hogy a slave az egyik kivezetésen jelezhet a master-nek, ha adata van! Majd legközelebb fel is használom ezt a remek ötletet!) Szerencsére a küldés ideje jóval az impulzusok közötti időtartam alatt van. A slave programjában ki is írtam az értékét, 120mikrosec körüli érték, úgy hogy az I2C busz sebességét a lehető leglassúbbra állítottam a master programjában. Ez megnyugtató érték, még 150km/h szélsebességnél sem fogok túl sok impulzust elveszíteni (5msec két impulzus idő távolsága).
Slave programja:
#include<Wire.h> bool elozo; //segéd változó előző kontaktus állpot tárolására bool most; //segéd változó a pillanatnyi kontaktus állpot tárolására int imp1=0; //segédváltozó a 10 másodperces (széllökés) impulzus számláláshoz int imp2=0; //segédváltozó az átlagos szélsebesség impulzus számláláshoz int meresido=0; //utolsó master kiolvasás óta eltelt idő mmsec-ben int max_imp=0; //a maximális impulzussám tárolására (10 másodperces széllökés maximum) long ido_tmp1=millis(); //segéd változó a 10 másodperc méréséhez long meres_ido=millis(); //segéd változó annak megállapítására, hogy mennyi idő telt el az utolsó master kiolvasás óta void setup() { Serial.begin(9600); Serial.println("Slave indul..."); pinMode(2,INPUT); //2-es kivezetésre kötöttem a kontaktus jelét digitalWrite(2,HIGH); //felhúzó ellenállás bekapcsolása elozo=digitalRead(2); //máris vezünk egy mintát a bemenetből Wire.begin(8); // I2C kommunikáció inicializálása 8-as eszköz címmel (mivel slave, címet kell megadni) Wire.onRequest(master_ker); //Ezt a funkciót hívja meg az Arduino, amikor a master adatot kér } void loop() { most=digitalRead(2); //a pillanatnyi kontaktus állapot beolvasása if(elozo==HIGH and most==LOW) { //Lefutó él, az alacsony szint hosszabb, és több idő áll rendelkezésre //Itt más feledatokat is elvégezhetne a program, ha arr szükség lenne imp1++; //növeljük a 10 secundumos szállökés impulzus számlálót (10 másodpercenként töröljük) imp2++; //növeljük az átlagsebesség impulzus számlálót (az adat küldése törli) } elozo=most; //a következő ciklus majd megállapítja, hogy volt-e változás if (millis()>ido_tmp1+10000) { //letelt a 10 másodperc, értékelünk és töröljük az impulzus számlálót if (max_imp<imp1) { //csak akkor tároljuk, ha nagyobb mint az eddigi maximum max_imp=imp1; } imp1=0; //töröljük imp1-et, és ezzel újra kezdjük a széllökés mérést ido_tmp1=millis(); } } void master_ker() /************************************************************************* * Ez a függvény akkor indul, amikor a master adatot kér a slave-től * * úgy tapasztaltam, hogy a kért adatokat ebben a függvényben kell kiírni * * az I2C buszra, különben a master nem kapja meg az adatokat. * * Nem foglalkoztam azzal, hogy a meres_ido változó egy long változó * * amibe a meres kezdetének időpontját tárolom. Ez időnként átfordul * * (nullázódik), és ekkor hamis értéket fog adni az iőmérés. * **************************************************************************/ { meresido=millis()-meres_ido; //meghatározzuk, mennyi idő telt el az utolsó master lekérdezés óta long ido_tmp=micros(); //mérni fogjuk az I2C kommunikáció idejét mikrosecundum-ban Wire.write((imp2 & 0xFF)); //imp2 változó felső byte átvitele Wire.write(((imp2 >> 8) & 0xFF)); //imp2 változó alsó byte átvitele Wire.write((max_imp & 0xFF)); //max_imp változó felső byte átvitele Wire.write(((max_imp >> 8) & 0xFF)); //max_imp változó alsó byte átvitele Wire.write(meresido & 0xFF); //meresido változó felső byte átvitele Wire.write((meresido >> 8) & 0xFF); //meresido változó alsó byte átvitele Serial.print("Elküldve ("); //kiírjuk a soros portra a fogadott byte-okat Serial.print(micros()-ido_tmp);Serial.print(" mikrosec):"); //I2C kommunikáció időigényének kiírása Serial.print(imp2); Serial.print(", "); Serial.print(max_imp); Serial.print(", "); Serial.println(meresido); imp2=0; //töröljük az átlag sebesség mérésére használt impulzustárolót //lekérdezéstől lekérdezésig átlagolunk meres_ido=millis(); //meresi idő megállapításához a kezdő időpont tárolása; }
…és a slave futásának eredménye a soros monitoron:
Slave indul…
Elküldve (116 mikrosec):0, 0, 317
Elküldve (116 mikrosec):145, 59, 15030
Elküldve (112 mikrosec):130, 142, 15037
Elküldve (116 mikrosec):18, 142, 15037
Master programja:
/********************************************************************************************************************* * Ez a demo program a szélsebességmérő Arduino program I2C buszo keresztül történő lekérdezésére készült. * * A program 15 másodpercenként kérdez az I2C buszon keresztül 6 byte-ot. Első két byte a szélsebesség impulzusszáma,* * a 3. és 4. byte a széllökés impulzusszáma, a 5. és 6. az utolsó lekérdezés óta eltelt idő milisecundum-ban. * * A beolvasott adatok alapján kiírja az előző lekérdetzés óta eltelt időben (15 másodperc) kapott impulzusok * * alapján a szélsebesség átlagos értékét, valamint a 10 másodperces széllökések maximumát * *********************************************************************************************************************/ #include<Wire.h> int tmp1; //segéd változó, a szélsebesség impulzusszámát olvassuk bele a slave-től int tmp2; //segéd változó, a széllökés impulzusszámát olvassuk bele a slave-től int meresido; //a slave ennyi ideig mért a legutolso adat lekérdezés óta float szelsebesseg=0; //a kiszámított szélsebesség float szellokes=0; //a kiszámított széllökés, csak a maximális értéket tartja meg a slave, a maximum törléséről //a slave programja nem gondoskodik void setup() { Serial.begin(9600); // soros port inicializálása Serial.println("Master indul..."); Wire.begin(); // I2C kommunikáció inicializálása, nincs cím, ezért master } void loop() { TWBR = 255; //az I2C busz sebességének beállítása a lehető legkisebb frekvenciára (30khz) delay(15000); //15 másosdpercenként kérdezzük le az eredményt slve-től. //A lekérdezés elindít egy új átlagsebesség mérést a slave-nél. Wire.requestFrom(8,6); // a master kér hat bájtot a slave-től tmp1=((Wire.read() << 0) & 0xFF) + ((Wire.read() << 8) & 0xFFFF); //szelsebesség 2 byte fogadás (összerakva int-nek) tmp2=((Wire.read() << 0) & 0xFF) + ((Wire.read() << 8) & 0xFFFF); //szellökés 2 byte fogadás (összerakva int-nek) meresido=((Wire.read() << 0) & 0xFF)+((Wire.read() << 8) & 0xFFFF); //uts lekérdezés óta eltelt iső msec-ben 2 byte-on fogadva (összerakva int-nek) Serial.print("Slave-tol fogadott adatok:"); //kiírjuk a soros portra a fogadott byte-okat szelsebesseg=((tmp1/2)*2.5)/(float)(meresido/1000); //kiszámítjuk az impulzus számból a sebességet a meresidő-re szellokes=((tmp2/2)*2.5)/10; //kiszámítjuk az impulzus számból a sebességet 10 másodpercre Serial.print("Átl. szélsebesség "); Serial.print((float)meresido/1000); Serial.print(" másodperc alatt:"); Serial.println(szelsebesseg); Serial.print("Széllökes:"); Serial.println(szellokes); Serial.print("Merésidő msec-ban:"); Serial.println(meresido); Serial.println(); }
… és egy futási eredmény a mesterről is:
Master indul…
Slave-tol fogadott adatok:Átl. szélsebesseég 28.73 másodperc alatt:4.91
Széllökes:17.75
Meresidő msec-ban:28728S
Slave-tol fogadott adatok: Átl. szélsebesség 15.04 másodperc alatt:16.50
Széllökes:17.75
Merésidő msec-ban:15036
Slave-tol fogadott adatok: Átl. szélsebesség 15.04 másodperc alatt:7.67
Széllökes:18.50
Merésidő msec-ban:15037
Slave-tol fogadott adatok: Átl. szélsebesség 15.04 másodperc alatt:0.00
Széllökes:18.50
Merésidő msec-ban:15037