Okos otthon is fókuszban

Arduino kalandok

Arduino kalandok

433 MHz - part 2

2018. február 05. - denx

Mivel nem tudtam hogy is fogjak hozzá a hőmérő jeleinek elkapásához, így először próbálkoztam mindenféle zsákutca-módszerrel, de most inkább a jó megoldást osztom meg

Adatok Elemzése

Első körben kíváncsi voltam, hogy egyáltalán ad-e használható adatot a vevő egység. Erre láttam több helyen is egy nagyon egyszerű módszert: a vevőegység adat lábáról érkező jeleket - némi szintillesztés után (értsd ellenállásokkal) - egy PC-s hangkártya line in bemenetére kötve egy hangszerkesztő programmal simán lehet addig nagyítani a hullámot, míg végül látható és elemezhető jel lesz belőle. Mivel nekem csal laptopom van, amin már kb 10 éve nem gyárt senki line in csatlakozó, így ezt egy USB-s hangkártyával lehetett volna megoldani. Igen, ebből már talán ki is derült, hogy én nem ezt a módszert választottam. 

Logikai Analizátor

Fórumokon találkoztam a kifejezéssel: "logikai analizátor", avagy angolul "Logic Analyzer". Ebből megkerestem a legegyszerűbb, legolcsóbb verziót az Alin, vaskos 7 dolcsi körüli árat kellett érte leszurkolnom. Elsőre soknak tűnt (az 1-2 dodo körüli számokhoz vagyok szokva) de hamar kiderült, hogy ekkora bizniszt ritkán csinál az ember: az eredeti termék, amit a szemfüles kínai szakemberek "koppintottak" 599 dolcsiba kerül! Hoppá! és ami tovább fokozta az érzést: az eredeti cucc programja ingyenes és tökéletesen működik az "utángyártott" eszközzel!

Ahogy a képen is látszik, az eszköz 24 MHz-en képes működni, vagyis másodpercenként 24 millió mintát képes érzékelni, mindezt 8+1 vonalon egyszerre. Nekem, ehhez a feladathoz ennek a töredéke is bőven sok volt, a mérést 0.5 millió minta / másodperces tempóval olvastattam vele mindössze 1 bemeneten. Ami pedig ebből kijött, az sokat segített a 433-as vevőegység működésének megértésében.

Analizálás Eredménye

Az olcsó vevőegységekre szakértők szerint jellemző, hogy ha nem kap értelmes jelet, akkor mint egy régi analóg rádió, ez is fehér zajt közvetít, vagyis megállás nélkül váltakozó alacsony és magas jelszintek váltakoznak nagyon gyors egymásutánban. A mintául szolgáló pilight projektben ezt egy speciális módszerrel szűrték: ott egy mikrokontrollert alkalmaznak, hogy a raspi számítási kapacitását ne ez a feladat kösse le. Mivel az Aruino eleve egy mikrokontroller, az ezen futó programot fel lehet készíteni ilyen feladat megoldására is.

A jeleket úgy lehet dekódolni, hogy a rövid magas jelszintek közötti alacsony szintű "szünetek" hossza 3 hosszúságú lehet:

  • Rövid: ez nagyjából 2000 μs (mikroszekundum, a másodperc egymilliomod része)
  • Hosszú: kb. 4000 μs
  • Nagyon hosszú: kb. 8000 μs

A rövid szünetet lehet 0-nak értelmezni, a hosszút 1-nek, a nagyon hosszút arra használja az eszköz, hogy az első csomag indítása előtt ebből kiküld 10-et, majd kezdi az adást. Az adás végével megint küld 2 nagyon hosszú jelet. De a biztonság kedvéért az adást a 2 S jel után megismétli, összesen 6x. Erre azért van szükség, hogy ha több eszköz is ugyanakkor adna ugyanezen a frekvencián, akkor is legyen esélye a fogadónak legalább 1 csomagot egészben elkapnia. (A konkrét időjárás állomás ha jól emlékszem 48 másodpercenként ad.)

Mivel a fent leírt időtartamok nincsenek kőbe vésve és az adó oldalon sem atomóra ketyeg, így nyilvánvalóan ráhagyással kell kezelni ezeket az időtartamokat, de szerencsére ezek annyira jól elkülöníthetőek, hogy különösebb számítási igény nélkül is könnyedén feldolgozható adatokat lehet nyerni a következő módszerrel:

  • Az 1500-nál rövidebb jeleket figyelmen kívül kell hagyni. Ez segít a fehér zaj kiszűrésében, illetve a rövid (kb 400 us hosszúságú) magas jelszintű "tüskéket" is, amik elválasztják a nekem fontos szüneteket. (Az utóbbira majd meglátjuk később miért lesz szükség.)
  • A 9000-nél hosszabb jeleket szintén kiszűrhetjük.
  • A 7500-nál hosszabb jeleket S-ként kell értelmezni
  • A 3000-nél rövidebbeket logikai 0-ként, az ennél hosszabbakat logikai 1-ként kell kezelni.

 Arduino Program

Arduino alatt a dolgot két féle képpen lehet megvalósítani: vagy folyamatosan olvasgatjuk a bemenetet, ahova a vevő adat lába van kötve, vagy megszakítást használunk. A fejlesztés során az első is jó lehet, de a második a kulturáltabb megoldás, ezt fogom bemutatni.

Nano és Uno alatt két digitális bement van, ami megszakítást (interrupt) vált ki, ezek a D2 és D3 lábak. Én rákötöttem a vevő egység lábát a 2-es bemenetre, és elkészítettem hozzá a kódot is:

 

#define PIN 2

#define FILTER_MIN 1500
#define FILTER_MAX 9000
#define MEDIUM_LEN 3000
#define STOP_MIN 7500

#define BUFF_SIZE 50

volatile bool avail = false;
volatile byte buff[BUFF_SIZE];
volatile byte buffEnd = 0;

void setup() {
  Serial.begin(115200);
  pinMode(PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(PIN), handler, CHANGE);
}

void handler() {
  static unsigned long lastMs = 0, currMs,diffMs;
  currMs = micros();
  diffMs = currMs - lastMs;
  lastMs = currMs;

  if (diffMs > FILTER_MIN && diffMs < FILTER_MAX) {
    if (!avail) {
      if (diffMs > STOP_MIN) {
        if (buffEnd == 42) {
          avail = true;
        } else {
          buffEnd = 0;
        }
      } else {
        if (buffEnd < BUFF_SIZE) {
          if (diffMs < MEDIUM_LEN) {
            buff[buffEnd++] = 0;
          } else {
            buff[buffEnd++] = 1;
          }
        }
      }
    }
  }
}

void loop() {
  if (avail) {
    Serial.println("--Data arrived: ");
    for (int i = 0; i < buffEnd; i++)
      Serial.println(String(buff[i]));
    Serial.println();
    buffEnd = 0;
    avail = false;
  }
}

Ez a kód annyit tesz, hogy ha változik a bemenet állapota (mindegy hogy magasból alacsonyba, vagy fordítva) akkor a handler nevű függvény lefut. ez először is microsec pontossággal meghatározza hogy mennyi ideje hívták meg utoljára. Ez az időtartam a további számítások alapja. Ha túl rövid, vagy túl hosszú, akkor nem csinál semmit a függvény. Ha hosszabb mint 7500 μs, akkor start/stop bitnek veszi és megnézi, hogy pontosan 42 elem van-e a pufferben. Ha igen, akkor pont jókor jött a stop bit és az avail nevű változó átállításával jelzi, hogy lehet feldolgozni a puffert. Ha nem pont ennyi van a pufferben, akkor úgy veszi, hogy ez nem egy értelmes üzenet, így eldobja a puffer tartalmát. Ezután jön a már fentebb ismertetett logika, ami segít eldönteni, hogy 0 vagy 1 bit érkezett. Ezt pakolgatja a kód a buff nevű változóba (ha még van benne hely).

Külön érdemes odafigyelni a változók definíciójára: amiket a megszakításkezelő kód is használ, azokat volatile kulcsszóval kell deklarálni, így nem lesz gond. Ugyan a mikrokontroller nem képes több szálú kódfuttatásra, de a megszakítás egy érdekes állatfaj, érdemes körültekintően írni a kódot!

A loop függvény csak annyit tesz, hogy vizsgálja van-e értelmes adat a pufferben, ha igen, akkor kiírja azt a soros portra, majd "törli" a puffert és az avail változó visszaállításával jelzi, hogy a puffer tartalmát feldolgozta.

Mire idáig eljutottam, addigra eltelt már jó pár óra és hatalmas eredményként éltem meg, hogy sikerült a megfelelő mennyiségű 0 és 1 adatot csomagban elkapnom. Ezek értelmezése, feldolgozása és a kód publikálása egy következő bejegyzésben lesz kifejtve.

A bejegyzés trackback címe:

https://ardu.blog.hu/api/trackback/id/tr5113618618

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása