Hőmérséklet távadó

Tartalom:

  • 1-2 km hatótáv áthidalása olcsó engedély nélkül használható RF távadóval
  • Házi készítésű egyszerű és olcsó Yagi antenna működése, felhasználása a megoldáshoz
  • Decibel fogalma és használata az antenna nyereségének kifejezésében
  • Hőmérséklet távadó Dallas DS18B20 hőmérséklet szenzorral és HC12 RF adóval, akkumulátoros áramszünet védelemmel
  • Arduino nano akkumulátoros táplálási tapasztalatok powerdown üzemmódban
  • Hőmérséklet vevő HC12 RF vevővel
  • Teljes forráskódok

A cikk írója: Római István
Szakmai bemutatkozásEredetileg rádió-TV műszerészként végeztem,  az iskola után a MOL elődjénél helyezkedtem el műszerészként. Itt végeztem el az „Irányítástechnikai műszerész” szakmunkás képzőt. Ez a szakma négy  nagy területet ölelt fel, mechanika, pneumatika, elektronika, hidraulika. Amikor én kezdtem, a műszerek 80%-a pneumatikus volt (1976). Kilenc évvel később egy földgáz CO2 mentesítő üzemben megismerkedtem egy számítógépes irányító rendszerrel. Ezt japánok szállították, akkoriban nagyon modernnek számított, egy része még COCOM listás.  Munkám során a számítógépet kellet figyelni, néha beavatkozni. Éjszakás műszakba bevittem a Commodore 64 gépemet, vettem rengeteg Data Becker könyvet és ismerkedtem a programozással.
Elérhetőség: romaipista@gmail.com  

Az RF hőmérséklet távadó úgy született, hogy a sógorommal beszélgetve felmerült, hogyan lehetne megoldani a libaól hőmérsékletének távoli figyelését, mert az egyik libatartónak már ilyen van. Ők is próbálkoztak a lakás és a mellette lévő ól között az ALDI-s időjárás állomás külső egységével, ami jó időjárási körülmények között működött is.  Esős-nedves időben kevésbé. A másik telep légvonalban kb. 1100m-re, úton közel 2km távolságban található. Nincs olyan készen kapható hőmérő, ami működhetne ekkora távolságból. Pedig éjszaka 2 óránként (télen) elautózni és megnézni az ól hőmérsékletét nem túl kellemes. Kényelmesebb az ágyból a hőmérőre pillantani és csak szükség esetén menni.  

A nagy távolság miatt esett a választás a HC12 nevű adó – vevő párosra.  Az adó teljesítménye 100mW, 1000m hatótávval reklámozzák. A hozzá mellékelt spirál antennával a hatótáv nevetséges, meg sem jegyeztem, hogy mekkora. A leírásban ajánlott 34 cm-es botantenna már 5-600 m távolság áthidalását tette lehetővé, de ez sem elég. Meg kellene növelni az antenna nyereséget és irányítani.  Ekkor jött a Yagi antenna ötlet.

Egy kis elmélet az antennákról. Az antenna tulajdonképpen egy nyitott rezgőkör, amely az adni vagy venni kívánt jel vivőfrekvenciájára van hangolva. A rezgőkör nyitottsága azt jelenti, hogy az adáskor betáplált teljesítmény a rezgőkörből kisugárzódik elektromágneses hullámok formájában, vételkor pedig a külső elektromágneses hullámok feszültséget indukálnak az antennában. Egy elméleti antenna minden irányban azonos teljesítménnyel sugároz. Azonban a valós antennák valamilyen kitüntetett irányba, vagy irányokba nagyobb teljesítménnyel sugároznak. Ezzel a tulajdonsággal kapcsolatos az antenna nyereség fogalma, amit dB-ben (decibel-ben) adnak meg. Az antenna nyeresége alatt azt a dB-ben kifejezett teljesítményviszonyt értjük, vagyis azt, hogy az antenna a fő sugárzási irányában hányszoros teljesítménnyel sugároz egy ugyanakkora teljesítménnyel táplált minden irányban sugárzó (elméleti) antennához képest.

A legegyszerűbb antenna a botantenna, ami egy függőlegesen elhelyezett vezetékdarab. A vezetékdarab hosszát a vivő frekvencia hosszával arányosan kell méretezni (pl. fél hullámhossz). Jelen esetben a HC12 modul adó frekvenciája 433MHz, aminek a fél hullámhossza (egyik online átváltó szerint) 34,642 cm.
A botantenna nyeresége a szakirodalom szerint 2,15dB vízszintes irányba.
Kis magyarázatra szorulhat a decibel érték jelentése. Eredetileg az 1920-as években arra találták ki a Bell telefontársaság szakemberei, hogy a vezeték hossza alapján bekövetkező hangerő csökkenés mértékét jellemezzék vele. A szerepe hasonló itt is, egy megadott értékhez viszonyított változás jellemzésére használjuk. Képlettel így lehet kifejezni:

Ahol Xo a referencia érték, X pedig az az érték aminek a viszonyát Xo-hoz képest szeretnénk megadni. Néhány decibel és hozzá tartozó arány adat:

Azért célszerű decibel-ben megadni a viszonyszámokat, mert hatalmas tartományokat lehet átfogni vele kicsi számokkal. Pl. a hangtechnikában a hallásküszöböt szokták 0dB-nek megadni. Ekkor a 140-dB-es hangerő, már fájdalmat okoz. Találtam is egy táblázatot amiből jól láthatóak az arányok:

Látható a táblázatból, hogy a hallásküszöb és a fájdalom küszöb között óriási hangintezitás különbség van!

Visszatérve az antennákra! Miért is van nyeresége az egyszerű botantennának? Mert a botantenna csak vízszintesen sugároz, pl. felfelé nem. Ha a vevő az antenna felett van, akkor nem fog működni botantennával, illetve az antennát el kell forgatni párhuzamosan a talajjal, hogy felé is energiát sugározzunk és legyen vétel. Viszont ennek köszönhetően visszintes irányban nagyobb az áthidalható távolság. A 2,15dB nyereség természetesen egy elméleti érték, és nem is nagyon nagy nyereséget jelent. Alig nagyobb a kisugárzott teljesítmény az elméleti antennához képest. Nekünk ennél sokkal jobb nyereség kell, így más antenna típust kell keresnünk.

A megoldás egyszerű: miért sugároznánk a teljesítmény jelentős részét körkörösen minden irányba, ha a vevőnk (vagy akár sok vevő berendezés is) egy meghatározott irányban található. Ekkor jön jól egy Yagi antenna! Ez az antenna párhuzamosan elhelyezett vezetékdarabokból áll, a méretezéséhez némi szaktudás kell!

A Yagi antenna adóra kötött adó eleme lehetne egy középen betáplált félhullámú dipólus is, ami egyszerűen csak két fémhuzal, melyeknek együttes hossza a vivőfrekvencia negyedhullámhossza. Így nézne ki:

Az ábrán látható két végén hajlított dipólus előnye, hogy a tartógerinc akár egy földelt fém tartórúd is lehet. Ez villámcsapás esetén hasznos lehet. Az ábrán az is látható, hogy kb. milyen irányba sugároz. A nyereség 10dB körüli. Az antennával nem kell nagyon pontosan „célozni”, elég az adót és a vevőt nagyjából egymás felé forgatni. Ez fontos, ha a távolság miatt már csak sejtjük az ellenállomás irányát. Ha a direktorok számát növeljük, akkor az antenna irány érzékenysége növekszik, azaz egyre pontosabban kell az adót és a vevőt egymás felé forgatni, viszont ugyanakkora adóteljesítménnyel jelentősen megnőhet az áthidalható távolság. Íme egy példa erre is:

Öregebb olvasók talán még emlékeznek a televíziózás hős korszakára, amikor a tetőn lógva ehhez hasonló antenákkal próbáltuk befogni a kékesi nagyadót, hogy legyen 2 db TV csatornánk. …és hétfőn nem láttál embert a tetőn, mert akkor adásszünet volt! Viszont akkoriban alig volt reklám!

Jelen esetben az alkalmazott adóberendezés a gyárilag hozzá adott antennával körkörös kisugárzással jó, ha 100m távolságot hidalna át. Azonban a Yagi antenna segítségével ugyanez a teljesítmény már 1100m-re is elegendőnek bizonyult.

Viszont felmerül az újabb probléma, mert az antennához meglehetősen nagy távolságból kellene elvezetni az adó jelét egy vezetékkel. De itt meg az antenna tápkábel és az antenna illesztése a probléma. Ekkor jött egy eretnek ötlet, hogy mi van akkor, ha az adót viszem a dipólhoz, és 2db 1cm-es vezetékkel parasztosan rákötöm a dipólra:

Kicsit fel is nagyítottam a bekötést a képen, hogy jól látható legyen!

Így viszont az  adatvezetékek lesznek hosszúak.   Némi reményt adott, hogy a vevő érzékenysége a legalacsonyabb 1200 baud sebességnél legnagyobb, a nagy távolság miatt úgy is ez kell. Így az adatvezetékeken hangfrekvencia jelenik meg, a néhány byte-nyi adat átvitelében a sebesség nem lényeges. Vettem 25m UTP vezetéket, ami azért szükséges, hogy a távadót betudjuk vinni az ól közepe felé. A DS18B20  hőmérő chip hosszú vezetékkel problémát  okozott.  A 25M-es UTP kábelen az összesodort vezetékeket párhuzamosítottam, lett 4 ér, amit a NANO és az adó modul közé bekötöttem. Az eredmény csoda, adatvesztés nélkül ad is vesz is.
A következő próba: mit csinál a Yagi-val. A Yagi öt elemes, az elemek hossza 30 cm körüli, az egész antenna hossza 60 cm körül van. Hirtelen nem tudtam a szükséges alucsöveket beszerezni, ezért vettem 1m 4×25-ös földkábelt, ennek az erei 5,5mm vastagok, gerincnek vettem egy falécet (a Yagi gerincének nem szükséges vezető, a dipól és a direktorok 0 potenciálon vannak a középpontban), U szöggel felszögeltem az elemeket és kész az antenna. Ha még működik is, akkor a mennyországban fogom magam érezni.

Az antenna méretei:

Dugdosós próbapanelen összeállítottam egy hőmérséklet adót és egy vevőt. Ennek kapcsolásáról és programjával később foglalkozunk. Az antennákat felszereltem egy-egy 3m-es lécre és irány a kiskunhalasi puszta. Az adót letámasztottam egy nagy nyárfához, az autóval eltávolodtunk pontosan 1km-re és bekapcsoltuk a vevőt.  És mutatta a hőmérsékletet! Eltávolodtunk még kb. 300m-t és ott is mutatott. Akkor veszítette el a jelet  a vevő, ha az antennát majdnem 90 fokkal elfordítottam az adótól. Nekem ennyi elég is!

Az antennát az ól végénél állítottuk fel, hogy minél magasabban tudjuk elhelyezni. Egy 1”-os csövet ástunk le kb. 70-80 cm-re, így 5,2m körüli magasságon van az antenna.

Ezen a téli felvételen nem sok látszik, de talán kivehető a fóliasátor sarkából induló rúd, tetején az antennával.

Hőmérséklet adó:

A hőmérséklet adó a DS18B20 nevű digitális hőmérséklet érzékelőt használja. A DS18B20 használata nagyon egyszerű.  A setup-ban azért van egy lekérdezés, mert bekapcsolás után a legelső lekérdezés alkalmával midig 85 fokot ad, így a programban már a helyes érték lesz az első is. A méréstartomány -55 – 125 fokig terjed, alapból 12 bites a felbontás, azaz 0,0625 fok. Ha valakit mélyebben érdekel a DS18B20 az interneten nagyon sok anyagot talál (pl. itt a starduino weboldalon is).

Mivel a vevő egység több adó jelét veszi, ezért valahogy tudatni kell vele, hogy ki küldte az adatot. Ez úgy történik, hogy minden adónak van egy száma, pl.1, amikor megméri a hőmérsékletet akkor a számából és a hőmérsékletből csinál egy sztringet és ezt küldi el. Az vevő majd a sztringből különválasztja az adó számát és a hőmérsékletet, és a megfelelő számú kijelzőre kiírja.

A hőmérsékletet egy 4 digites kijelzőn helyben is kiírja.

Mivel a felhasználók lassú hőmérséklet változás esetén nem hitték el, hogy valóban működik a mérés, ezért a 4. digit dp-je 1 Hz-es ütemben villog. Ettől mindenki megnyugodott!

A következő ötlet az volt, hogy jó volna ha az áramszünetet is jelezné. A két helyszín nem azonos hálózaton van, a távolin gyakrabban van áramszünet. Ha sokáig nincs áram, az még jó időben is probléma, mert elfogy az állatok vize. Ehhez kellett egy kis hardver módosítás is! Került a berendezésbe egy akku meg egy 3,6V-5V dc-dc konverter, bár valószínű enélkül is menne.  Ha egy telephelyről több távadó is működik akkor csak egynek kell az áramkimaradást figyelni, a többinek a  tápellátásra elég a 230/5V-os táp.

Nem kell nagy kapacitású akku, ha 1 percet kibír már jó, ez alatt több ciklusban leadja a vészjelzést, még ha ütközik két adás akkor is nagy valószínűséggel veszi a vevő.

Az adó egység főbb blokkjainak rajza áramkimaradás figyelés esetén:

A táp 230 bemenő oldalán azért van a 220 ohmos ellenállás mert már történt olyan, hogy a tápegységben valami zárlatos lett, a dióda híd szétrobbant, de az automatát leverte, majdnem kiolvadt a fagyasztó.  Így a zárlati áram max 1 A, az ellenállás egy pillanat alatt elég, a tápot nem, de a hálózatot megvédi. Az áramkimaradást a D4 csapon 0-val érzékeli, és 9-es adószámmal adja. A vevő a 9-ről tudja, hogy ez az áramkimaradás jelzése és aszerint dolgozza fel. Minden ciklusban adja, hogy van villany vagy nincs villany.

A nano és a kapcsolódó DS18B20 és a HC12 bekötésének rajza:

A kész adógység fotója:

A programba sok megjegyzést tettem, szerintem megérthető a működése. Az adóegység program forráskódja:

// HC12 hőmérséklet adó 1.
#include <OneWire.h>  // az egyvezetékes kommunikáció köyvtára
#include <DallasTemperature.h>   // a DS18B20 könyvtára
#include <SoftwareSerial.h>

SoftwareSerial mySerial(11, 12); //HC12 TX --> 11, HC12 --> 12

#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);
String str_outhom;
String str_hom;
String str_mp = "1";   // mérési pont száma

#include <Arduino.h>
#include <TM1637Display.h>   // a LED kijelző könyvtára
#define CLK 5  // a disply óra és adatvezetéke
#define DIO 6
TM1637Display display (CLK, DIO);
uint8_t ures[] = {64, 64, 64, 64}; // adathiány esetésa 4 g szegmens világít
uint8_t teszt[] = {255, 255, 255, 255}; // szegmens teszt 8.8.8.8.
void setup()
{
  pinMode(4, INPUT); // feszültség figyelése, normál= magas
  //pinMode(6,OUTPUT);        // riasztás kimenet
  //digitalWrite(6,HIGH);     // riasztás kimenet magasra állítás (normál)

  mySerial.begin(1200);
  sensors.begin();
  display.setBrightness(2);   // Fényerő beállítás -  midig kell
  display.setSegments(teszt);  // display teszt, minden szegmens bekapcsolása
  sensors.requestTemperatures();             // egy adatkérés, hogy ne 85°-kal induljon
  float homers = (sensors.getTempCByIndex(0)); //     "       "
  delay(3000);                               // kell egy kis várakozás
  display.setSegments(ures);   // display kikapcsolása
}
void loop()
{

  sensors.requestTemperatures(); // Parancs küldés a hőmérséklet beolvasásra
  float homers = (sensors.getTempCByIndex(0));

  str_hom = String(homers);
  str_outhom = str_mp + str_hom; // A küldendő string összeállítása

  mySerial.println(str_outhom);   // adás
  int hom = (homers * 10) + 0.5; // kerekítés és tizedesek levágása
  display.showNumberDecEx(hom, (0x20), false);  // Kijelzés 1 tizedessel.
  for (int b = 0; b < 4; b++)
  {
    display.showNumberDecEx(hom, (0xa0), false); //  a 4. dp villogtatása
    delay(500);
    display.showNumberDecEx(hom, (0x20), false);
    delay(500);
  }
  int fesz = digitalRead(4);
  if (fesz == LOW) {

    mySerial.println("90000");   // adás, a 9-es "állomás" a hálózat figyelés
    delay(500);                  // a "0000" a feszültség kimaradást jelzi
  }
  if (fesz == HIGH) {
    mySerial.println("91111");  // adás, normál állapot  "1111" van hálózat

  }
  for (int c = 0; c < 4; c++)        // adás utáni késleltetés a dp villogtatása
  {
    display.showNumberDecEx(hom, (0xa0), false);
    delay(500);
    display.showNumberDecEx(hom, (0x20), false);
    delay(500);
  }
}

A hőmérséklet vevő áramkimaradás jelzéssel.

A hőmérséklet vevő az adók által adott adatot a megfelelő kijelzőre továbbítja, figyeli, hogy az előző adat beérkezése óta mennyi idő telt el, ha több mint 60s akkor a kijelzőn a 4 g (a középső vízszintes) szegmens világít, valamint ha áramkimaradás jelzés érkezik akkor hang és fény jelzést ad.  A kijelzőre íráskor 0,1s-ig a 4 g szegmens felvillan így érzékelhetőbb a váltás. A hangjelzés gombnyomással nyugtázható, a fényjelzés az áramszünet végéig megmarad.

fotón látható dobozba még csak két kijelző lett beépítve, de a kivágások elkészültek a következő két kijelző számára is. A fotó készítésének pillanatában még csak két kijelzővel (adóval) működött a berendezés, de már készültem a következő két adó felszerelésére. A program forráskódokban már a négy adó vételének kezelése lett megvalósítva.

Talán érdekesség a négy kijelző működtetése, az órajel közös, csak az adatvezeték egyedi. Ezzel a megoldással kivezetést lehet megtakarítani. A hardver ugyanaz mint az adó csak a DS18B20 elmarad és négy kijelző csatlakozik, a D5 a közös órajel, a D6 – D7 – D8 – D9 pedig az adat vezetékek.

Az áramkimaradás hanggal történő riasztása utólag vetődött fel, egyszerűbbnek tűnt hardveresen megoldani. Tisztán szoftveresen elegánsabb lenne, de így is jól működik, kívülről meg nem látszik a megoldás. A riasztást egy TTL NAND kapukkal (7400 ill. jelen esetben még szovjet megfelelője) felépített R-S flip-flop végzi:

A flip-flop bekapcsoláskor az 1-es lábán lévő 100nF miatt midig azonos    állapotba áll be, 8-as kimenet magas, a hangjelzés néma.  

Áramkimaradáskor a D2 0-ra vált a 100nF-on keresztül az 5-ös láb kap egy 0 impulzust és átbillen, megszólal a riasztó, ha nyomógombot megnyomjuk az visszabillenti az R-S-t.   A fényjelző LED a D2-re van kötve, ami az áramszünet alatt végig 0, ezért az világít, majd akkor alszik ki, ha D2 magasra vált, azaz megszűnik az áramszünet.

Az R-S 1-es lábán lévő 100k-1uF a D3-ra csatlakozik – ez már a flanc – bekacsoláskor lefut egy kijelző teszt és megszólal hang is, és hogy ne kézzel kelljen nyugtázni ezért van a D3, itt lehet „szoftveresen Reset-elni”. Mégiscsak komolyabb hatást kelt. Ennek a piezzónak néhány mA  az áramfelvétele, de borzalmas hangja van.

A szoftver működése a sok megjegyzéssel nyomon követhető: figyeli a vevőt, ha van adat beolvassa a sztringet, leválasztja a mérőpont számát, a hőmérsékletet számmá alakítja. Mivel a LED display tizedes számot nem tud kijelezni, ezért az értéket meg kell szorozni 10-zel, majd a kijelzőn kiteszünk egy dp-t és helyre áll az érték. A negatív tartományban kell még egy kis korrekciót végezni, mert ott a kerekítés miatt csalt 0,1 fokot. A monitorra kiíratott és a kijelzőre kiírt érték között a negatív tartományban volt 0,1 fok eltérés.

A switc kiválasztja a megfelelő állomást és végrehajtja a kiírást vagy a riasztást. Ezután következik az időtúllépés vizsgálata ami a programból könnyen megérthető. Beolvassa a jelen időt, összeveti az eltárolt (tkezdx)+x-el, ha nagyobb akkor átváltja a kijelzőt. Ha a 60000-t átírjuk megváltozik az időtúllépés.

Mivel az adók 8-10s-onként adnak 4-6 ciklusnak kell kimaradnia, még ha ütközik is két adás az sem okoz problémát, ha meg jön egy érvényes adat helyre áll.

A vevő program forráskódja:

// Hőmérséklet vevő.
// A 4 csatornából egyenlőre csak 2 van  használva a másik kettő le van "tiltva".

#include <SoftwareSerial.h>
SoftwareSerial mySerial(11, 12); //HC12 TX --> 11, HC12 RX --> 12
#include <Arduino.h>
#include <TM1637Display.h>
#define CLK 5
#define DIO1 6
#define DIO2 7
#define DIO3 8
#define DIO4 9
TM1637Display disp1(CLK, DIO1);
TM1637Display disp2(CLK, DIO2);
TM1637Display disp3(CLK, DIO3);
TM1637Display disp4(CLK, DIO4);
uint8_t ures[] = {64, 64, 64, 64};
uint8_t teszt[] = {255, 255, 255, 255};


String all;   // mérőpont "száma"
int mp;     // mérőpont száma


String homget;  // vevőről beolvasott sztring
String hom;     // a beolvasott sztringről leválasztott "hőmérséklet"
float homers;   // a hom sztringből átalakított hőmérséklet
unsigned long tkezd1 = millis(); // kezdő idő, ill.az adatküldés ideje
unsigned long tkezd2 = millis(); //
unsigned long tkezd3 = millis();
unsigned long tkezd4 = millis();
int LEDout;               // a kijelzőre kerülő adat

void setup()
{
  pinMode(2, OUTPUT);  // Riasztó kimenet, L-re indít
  pinMode(3, OUTPUT);  // Riasztó leállíó kimenet, L-re leállít
  digitalWrite(2, HIGH);  // Kimenetek H-ra állítása
  digitalWrite(3, HIGH);

  disp1.setBrightness(2);  // a fényerő csak a 0-3 (8-11) hatásos
  disp2.setBrightness(2);
  disp3.setBrightness(2);
  disp4.setBrightness(2);
  disp1.setSegments(teszt);   //kijelző teszt 8.
  disp2.setSegments(teszt);
  disp3.setSegments(teszt);
  disp4.setSegments(teszt);
  delay(200);
  digitalWrite(2, LOW);   // riasztó hang teszt  0,5 sec
  delay(100);
  digitalWrite(2, HIGH);
  delay(500);
  digitalWrite(3, LOW);  // riasztó kikapcsolás
  delay(100);
  digitalWrite(3, HIGH);
  delay(2000);

  disp1 .setSegments(ures);   // kijelző törlés
  disp2 .setSegments(ures);
  disp3 .setSegments(ures);
  disp4 .setSegments(ures);
  delay(100);

  mySerial.begin(1200);   // HC-12 megnyitása
  Serial.begin(9600);  // soros port megnyitása

}

void loop()
{

  if (mySerial.available() > 1) // adatfigyelés kezdete

  {
    Serial.println("   Uj meresi ciklus!");
    homget = mySerial.readString(); // a küldött sztring beolvasása

    all = homget.substring(0, 1); // az állomásszám sztring leválasztása
    mp = all.toInt();           // átalakítása a mérésipont számává
    hom = homget.substring(1);  // hőmérséklet sztring leválasztása

    homers = hom.toFloat(); // átalakítása lebegőpontos számmá
    if (homers < 0) {
      homers = homers - 0.1;  // a negatív tartományban korrigálni kell a kerekítés miatt
    }
    LEDout = (homers * 10) + 0.5; // a kiírandó szám (*10) + 0.5 kerekítés, majd a kiírásnál a dp helyre teszi

    Serial.print("Meropont szama: ");
    Serial.println(mp);
    Serial.print("HomersekletLEDout: ");
    Serial.println(LEDout);
    Serial.print("strs hom:");
    Serial.println(hom);

    kiiras();
  }                           //  adatfigyelés kezdete zárul
  long jelen = millis();
  if (jelen > tkezd1 + 60000) {
    Serial.println("Lejart az 1. ido!");
    disp1 .setSegments(ures);
    tkezd1 = millis();
  }
  if (jelen > tkezd2 + 60000) {
    Serial.println("Lejart az 2. ido!");
    disp2 .setSegments(ures);
    tkezd2 = millis();
  }
  if (jelen > tkezd3 + 60000) {
    Serial.println("Lejart az 3. ido!");
    disp3 .setSegments(ures);
    tkezd3 = millis();
  }
  if (jelen > tkezd4 + 60000) {
    Serial.println("Lejart az 4. ido!");
    disp4 .setSegments(ures);
    tkezd4 = millis();
  }
}                               // loop zárul

void kiiras()                   // a display-re kiírás szubrutin
{
  switch (mp) {
    case 1 :  disp1 .setSegments(ures);
      delay(100);
      disp1.showNumberDecEx(LEDout, (0x20), false);
      Serial.print("1. ");
      Serial.println(LEDout);
      tkezd1 = millis();
      break;
    case 2 :  disp2 .setSegments(ures);
      delay(100);
      disp2.showNumberDecEx(LEDout, (0x20), false);
      Serial.print("2. ");
      Serial.println(LEDout);
      tkezd2 = millis();
      break;
    case 3 :  disp3 .setSegments(ures);
      delay(100);
      disp3.showNumberDecEx(LEDout, (0x20), false);
      Serial.print("3. ");
      Serial.println(LEDout);
      tkezd3 = millis();
      break;
    case 4 :  disp4 .setSegments(ures);
      delay(100);
      disp4.showNumberDecEx(LEDout, (0x20), false);
      Serial.print("4. ");
      Serial.println(LEDout);
      tkezd4 = millis();
      break;
    case 9 : Serial.print("Fesz.jelzes:");
      Serial.println(hom);
      hom = hom.substring(0, 4);
      Serial.print("Fesz.jelzes2:");
      Serial.println(hom);
      if (hom == "0000") 
     {
        digitalWrite(2, LOW); // riasztás
        Serial.println("Riasztas!");
      }
      if (hom == "1111")
      {
        digitalWrite(2, HIGH); // riasztás törlés
        Serial.println("Riasztas Torolva!");
      }
      break;
  }

}

A vételi oldalon szintén Yagi antennát kellett használni, az is csak akkor biztosított megfelelő vételt ha kb. 4m magasra emeltük, sajnos a lakásban már nem.  Ebben lehet az is közrejátszik, hogy a vétel irányában van egy beton falú épület kb. 15m-re. nem A vevő felépítése ugyan az mint az adóé, az adó-vevő modul az antennánál, a táp és az adatvezeték van levezetve. Mivel a sógorom a falat nem akarta átfúrni, hogy az antennától levezessük a vevőhöz az „antenna vezetéket”, valamit ki kellett találni. A véletlen segítségünkre lett.  A távadók beüzemelése közben powerbankról üzemeltetve a vevőt, próbáltam az adó antenna sugárzási szögét meghatározni, a vevőn a spirál antennája volt. Az derült ki, hogy nem derült ki semmi.  Ugyanis a telep kerítésén belül, kb. 50-80m távolságban, antenna előtt, mellett, mögött mindenütt tökéletes vétel volt.  Ez adta az ötletet.  Az antennával vett jelet egy kis késleltetéssel a modullal visszaadjuk. Ez az adó-vevő csak egy NANO + egy 230-as táp az antenna árboc melletti melléképületben elhelyezve. Ez a jel néhány m-re a lakásban a spirál antennával már tökéletesen vehető.  Kb. 4000 Ft többletköltség és gyakorlatilag „hordozható” a vevő.

A kész vevőegység fotója:

Az átjátszó adó program forráskódja:

// Az antennával vett jelet "visszasugározza", igy az antenna
// közelében az "igazi" vevő spirál anennával tudja venni.
// LED villogással jelzi, hogy a program fut
#include <SoftwareSerial.h>
SoftwareSerial mySerial(11, 12); //RX, TX
int state = 1;
long prev; //előző idő eltárolására

void setup() {
  Serial.begin(9600);
  mySerial.begin(1200);
  pinMode(13, OUTPUT);
  pinMode(2, OUTPUT);
}

void loop() {
  long ido = millis();//jelen idő  tárolása
  if ((ido > prev + 500)) // jelen idő összehasonlítása az eltárolt idővel
  {

    digitalWrite(13, state);   // NANO d13 led
    digitalWrite(2, state);   // előlepi LED jelzés
    prev = ido;
    state = !state;
  }
  if (mySerial.available() > 1) {  // A HC12 figyelése
    String input = mySerial.readString();  // A küldött adat beolvasása
    delay(50);
    Serial.println(input);       // Kiírás a képernyőre
    mySerial.println(input);    // Kiírás a HC-12-re (ADÁS)
  }
}

Üzemeltetés közben tapasztaltuk, hogy bár vízmentesnek gondoltuk az antennánál lévő dobozt, vízmentesnek vízmentes, de nem páramentes.  Tartós eső esetén bepárásodhat és ilyenkor megszűnik adni, ha kiszárad újra működik.   Megpróbáltuk az esőtől megvédeni a dobozt, de úgy, hogy a szellőzése megmaradjon.  Az idő majd eldönti, hogy az elgondolás helyes-e.

Időközben kísérletezgetni kezdtem az akkumulátoros táplálással. Az adót egy 1700mA órás lítium akummulátorra kapcsoltam. Kipróbáltam, hogy mennyi ideig működne egy NANO akkumulátorról.

Első kísérlet azt tisztázta, hogy mekkora feszültség tartományban működőképes a távadó. A NANON egy olyan program futott, hogy 1Hz-es ütemben villogott a beépített LED, jelezve e működést. A tápfeszt csökkentve 2,7V környékén leállt, 2,8V-nál már működött.
Második kísérlet, hogy mennyi áramot is vesz fel a NANO működés közben. Méregettem a NANO áramfelvételét (világító power LED),  normál üzem (delay utasítást hajtott végre) 20mA, powerDovn mód 5mA, idle mód 12mA. A NANO-n a táp LED és az előtét ellenállás között átvágtam a fóliát, „elsötétítettem”. Sajnos az áramfelvétele így is 2,5mA, ez a powerDown üzemmódban. (A poweDown üzemmódról itt olvashatsz részletesebben!)
Az adó maga 2,8 – 2,9V-ig üzemel, 3V-nál már stabilan, a hatótávot csak a próbáltam eltávolodással érzékelni, de a 3 és az 5V között nem volt látványos különbség. (A NANO 5V-ról ment a kísérlet közben.)

Összeraktam a kísérleti áramkört átvágott fóliával a nano (2.5mA), valamint a az adó, ami jelen esetben nem a HC12, hanem egy ASK adó, adáskor 30mA áramfelvétel, de olyan rövid ideig, hogy a DMM nem tudja mérni, ebből arra következtetek, hogy kevesebb mint 1s. Összesen 32 napig működött, mérte és adta a hőmérsékletet 64 másodpercenként. Nem rossz eredmény! „Csak” havonta kell tölteni.

Az akkumulátor feszültséget minden nap mértem:

Néhány fotó az elkészült akkumulátoros hőmérséklet távadóról:

…és végül az adóegység forráskódja, amiben az alvó mód bekapcsolása is megtörténik:

// Hőmérséklet távadó 2.
// Setup-ban a kijelző 3s-ig jelez utánna kiolt majd aludni megy, az alvásból resetre "kilép" újra indul 
//  ekkor ismét látható az aktuális hőmérséklet.
// 8 ciklus 8s-os alvást csinál majd egy mérést és adást.
// A sok Serial.println csak a hibakereséshez kell.
// A NANO-nak  és a TM1637 LED display-nek a POWER led fóliáját átvágtam, igy az áramfelvétel
// 3,5 mA, egy kb. 1800 mAh-s 18650-es akkuval kb. 20 napig üzemel
// Az adó-vevő tipusa: ASK Transmitter STX882+ ASK Receiver SRX882
// Az adó Data a D12 (MISO) csatlakozik
#include <OneWire.h> 
#include <DallasTemperature.h>
#include <RH_ASK.h>
#include <SPI.h>
#include "LowPower.h" 
#define ONE_WIRE_BUS 2 
 
OneWire oneWire(ONE_WIRE_BUS); 
 
DallasTemperature sensors(&oneWire);
String str_outhom; 
String str_hom;
String str_mp="2";
int hom;

float homers;
RH_ASK driver;
#include <Arduino.h>
#include <TM1637Display.h>
#define CLK 5   // display CLK
#define DIO 6   // display DIO
TM1637Display display (CLK, DIO);

void setup() 
{ 
 pinMode(13,OUTPUT);
 digitalWrite(13,0);
 Serial.begin(9600); 
if (!driver.init())
         Serial.println("init failed");

     
 sensors.begin(); 
  display.setBrightness(2);   // Fényerő beállítás -  midig kell
  sensors.requestTemperatures();             // egy adatkérés, hogy ne 85°-kal induljon
  homers=(sensors.getTempCByIndex(0)); //     "       "
  delay(1000);   // kell egy kis várakozás
  sensors.requestTemperatures();             // egy adatkérés
  homers=(sensors.getTempCByIndex(0));
  hom= (homers*10)+0.5;   // kerekítés és tizedesek levágása
 display.showNumberDecEx(hom,(0x20), false);   // Kijelzés 1 tizedessel.
 delay(3000);
 
 display.clear();  // kijelző törlés
  
 
  
} 
void loop() 
{ 

delay(100);

 sensors.requestTemperatures(); // Parancs küldés a hőmérséklet beolvasásra
 homers=(sensors.getTempCByIndex(0));
 
  // Serial.print("Homerseklet : ");
  // Serial.println(homers);
  str_hom=String(homers);
  str_outhom=str_mp+str_hom;    // A küldendő string összeállítása
  // Serial.println(str_outhom);
  static char *msg = str_outhom.c_str();   // A küldendő string beállítása

    driver.send((uint8_t *)msg, strlen(msg));    //Küldés
    driver.waitPacketSent();                     // várakozás a küldés befejezésére
    // Serial.print("Kimeno homerseklet:");
    // Serial.println(str_outhom);
    
  delay(100);  // ha itt nincs késleltetés akkoa sleep alatt a TX LED állandóan világít
   
 
    delay(131); // ez csak azért van, hogy minél ritkább legyen az egész másodpercekkel az "ütközés"
  for (int i=0; i<8; i++)  {
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);   // Működik ciklusban is.
  }
} 
   

Mennyire volt hasznos amit olvastál? Értékelés után szövegesen is leírhatod megjegyzéseidet és véleményedet!

Kattints egy csillagra az értékeléshez!

Szövegesen is leírhatod véleményedet! Ha kérdésed van, ne felejtsd el megadni az email címedet!