Szélsebességmérő

Szeretem egy-egy érzékelő használata előtt megérteni, hogy hogyan is működik, és ez a mérni kívánt fizikai jellemzők tulajdonságaira is igaz. Nyilván nem fogok kiselőadást írni a meteorológia rejtelmeiről, de meg szeretném tudni, mire számíthatok.

Ez különösen fontos lesz akkor, amikor majd beüzemelem a mérőeszközt. Ez a szerkezet ugyanis 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 lényeges kérdés 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 alkalamazni, így viszonylag rövid időn belül akár három adatunk is lehet. Pillanatnyi szélsebesség, széllökés (pl. 10 másodpercig tartó átlagos szélsebesség), és átlagos szélsebesség pl. 1 perc alatt.
Nekem egyébként is csak egy nagyon 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 nagyon és sokat fúj, akkor hamarabb kell újra locsolni. Ehhez nem kell pontosan mérni, nagyon-nagyon elnagyolt adatok is jók lesznek. Senkit nem érdekel, hogy éppen most mekkora a szélsebesség. Épp ezért én a példa programban egy percig mértem, és így állítottam elő egy 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 hívtam. 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 (ez a terv). 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. Beraktak egy ilyen alakzatot a szélcsatornába, megmérték az erőt egy adott szélsebességnél, és kiszámolták a fenti képletből. 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 egy egyensúlyi állapot, és a forgó rendszerre az erők eredője nulla.  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, és 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 történő 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 mozogna. Í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 ellenőrizzük le. 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. Már csak azt kell megtudnunk, körpálya esetén mennyi 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 43 cm-el! Készen is vagyunk.

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, mert nem emlékszem, hogy 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 hálá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ék belsejében 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 meg fogom nézni, hogy mit produkál a gyakorlatban, és ha kell valamilyen fotocellás megoldásra cserélem. Vagy veszek egy másik reed relét, de nem lesz kedvem évente a tetőre mászni, így inkább fotocella, esetleg 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ödni fog. Ez elég meglepő, piszokgyors. 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 akarom 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ödött, mert programban a master adatkérésekor meghívott függvényen kívül nem tudtam adatokat írni az I2C buszra. Pontosabban írni lehetett, a program a slave-ben hiba nélkül futott, de az adatokat a master nem kapta meg. Így maradt az a megoldás, hogy amikor a master kéri az adatokat, küldi a slave. Közben persze nem számolja az impulzusokat. 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 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élsebesseég ");
  Serial.print((float)meresido/1000);
  Serial.print(" másodperc alatt:");
  Serial.println(szelsebesseg);
  Serial.print("Széllökes:");
  Serial.println(szellokes);
  Serial.print("Meresidő 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élsebesseég 15.04 másodperc alatt:16.50
Széllökes:17.75
Meresidő msec-ban:15036

Slave-tol fogadott adatok:Átl. szélsebesseég 15.04 másodperc alatt:7.67
Széllökes:18.50
Meresidő msec-ban:15037

Slave-tol fogadott adatok:Átl. szélsebesseég 15.04 másodperc alatt:0.00
Széllökes:18.50
Meresidő msec-ban:15037

Mennyire volt hasznos amit olvastál?

Kattints egy csillagra az értékeléshez!

Sajnálom, hogy amit olvastál nem volt hasznos számodra!

Szeretném ha elégedett lennél!

Írd le kérlek, hogy mi nem tetszett!?