Lekce 20 - Arduino a využití 433,92 MHz

04.06.2013 16:19

Translate to English
  

Po nějaké době opět zdravím u dnešního tutoriálu, který se bude na přání věnovat využití frekvence 433,92Mhz (434Mhz) na bezdrátové ovládání čehokoliv na vzdálenost řekněme při dobrých podmínkách do 50m. Pracovat s ním budeme samozřejmě s Arduinem. K tomuto budeme potřebovat dva moduly pro frekvenci 433,92 MHz a to jeden vysílací a jeden přijímací. Cenu modulů sem ani psát nebudu, je hodně druhů a já používám nějaký ze zahraničí za cenu asi okolo 100 až 150 Kč.

Přijmač Vysílač

 

Všechny moduly vypadají od různých firem vesměs stejně rozhodující bude funkce, která je u všech modulů stejná. Vyobrazený modul vysílače má celkem 3 vývody z čehož jsou 2 pro napájení a jeden pro data. U přijímače jsou celkem 4 piny, ale data jsou na pinech 2 a 3, jsou propojena, takže je jedno kam vodič "připíchnete". Na modulech je zapojení čitelně značeno, takže by němel vzniknout problém. Napájecí napětí je našich klasických 5V z Arduina. 

Teď trošku k funkci. Představme si komunikaci mezi modulem (jednostranná od přijímače k vysílači) jako klasické vysílání rádia s tím, že probíhá digitálně (1000101010). Mnozí z Vás si ale myslí, že když přivedeme 1 (hodnota HIGH) na datový pin u vysílače tak se u přijímače objeví na datovém výstupu také jednička a když vysíláme 0 (hodnota LOW) tak na výstupu bude také 0. To není tak zcela pravda. V době dnešního digitálního vysílání to již na obrazovkách moc není vidět, ale v případě, kdy jste ztratili anténní příjem, tak jste na obrazovce viděli jen šum, v případě rádia také to jenom šumělo. A to je i v případě našeho přijímače. Neustále běhají na výstupu přijímače jedničky a nuly a to nekontrolovaně a zcela náhodně. Na vině je klasický šum z prostředí (vypínaní spotřebičů, atmosférické poruchy a jiné) a také ostatní vysílání na této frekvenci (meteostanice, dálková ovládání nebo jiná zařízení pracující z touto frekvencí 433 Mhz. Úkolem bude udělat v džungli jedniček a nul nějaká pravidla pro vysílač, který vyšle sekvenci dat v sekvenci, kterou si určíme a také abychom mohli naprogramovat Arduino s přijímačem tak, aby zrovna v záplavě jedniček a nul našel naše vysílání a zpracoval data jen taková, která chceme. 

Samozřejmně to zase zní trošku složitě. My si vše ulehčíme. My totiž použijeme knihovnu využívající již vymyšlený a fungující protokol komunikace pro výrobky firmy RFLightWave. Ta totiž při komunkaci (el.l zásuvky ovládané dálkovým ovládáním) odesílá vysílač přimači 10 4bitových hodnot (v překladu pošle 10 čísel v rozsahu od 0 do 15). Takže jako první si samozřejmě seženeme moduly vysílače a přijímače, dále budeme potřebovat 2 kusy nějakých Arduin (asi jedno jakých) a to je zatím vše.

Nejprve si postavíme vysílač. Modulek vysílače zapojíme např. přes kontaktní pole s Arduinem (v mém případě Arduino UNO). Napájení modulu klasicky a datový vstup jsem napojil na pin č. 3. jak můžete na obrázku níže vidět.

Vysílací modul bude obdobně zapojen s tím, že datový výstup s přijímače je na pin 2 s použitím Arduina MEGA.

Tak teď si stáhneme naše knihovny pro práci s vysílačem a přijímače. Knihovna je každá zvlášť pro přijímač a vysílač. Najdete ji na adrese zde. Po stažení si ze zipu nakopírujete z adresáře libraries dva adresáře LvRx a LvTx do adresáře libraries v prostředí Arduina. Kam kopírovat knihovny jsme si vysvětlili již v minulých dílech tak by Vám neměl vzniknout žádný problém. Kdyby na uvedeném odkazu již soubory nebyli, kontaktujte mě a já se pokusím nalézt jinde. 

Tak po nahrání knihoven si do Arduina s vysílačem nahrajeme i tento program:

Jak vidíte není složitý. Máme tam funkci lwtx_setup(3, 2);, která inicializuje vysílač a nastaví, že datový vstup vysílače je na pinu 3. Druhý parametr ta dvojka je že se vysílač data odvysílá 2x za sebou, kdyby se v tom davu jedniček a nul asi nějaké vysílání ztratilo. To zvyšuje spolehlivost přenosu. Soudím dle autora knihovny. Potom tam máme funkci lwtx_free();, která vrací zda je vysílač volný a nemá žádnou práci. Vrací TRUE nebo FALSE. Když je tedy volný, můžeme vysílat. A nakonec funkce lwtx_send(data); - ta odešle konečně naše data. Jedná se o čísla od 0 do 9. (jak jsem již uvedl, můžete zadat čísla až do 15 (4bitové hodnoty). Výsledek se zobrazí na serial port s tím, že Arduino každých 5 sekund odvysílá naše data a na Serial port vypíše "Data odeslana".  

Tak jestli vysílač funguje správně zjistíme až si zprovozníme přijímač. Do druhého Arduina si připojíme modul přijímače. U mne tedy na pin 2. Pozor - knihovna pro příjem používá pro detekci přijmu signálu tzv. přerušení, takže můžeme použít v případě Arduina UNO nebo MEGA pouze pin 2 nebo 3. Přerušení - interrupt si vysvětlíme u zřejmě dalšího tutoriálu, kde jej využijeme. 

Nyní si nahrajeme do Arduina s přijímačem tento program:

Vysílač necháme zapnutý a přijímač zapojíme také. Spustíme si SerialMonitor (nezapomeňte si nastavit správný COM - port, aby jste nesledovali vysílač, kde se objevuje pouze nápis "Data odeslana"). Na výstupu vidíme, že se nám tam objevují po 5 vteřinách čísla  1 2 3 4 5 6 7 8 9 0 tak jak jsme je odvysílali :-)

Tak pokud vidíte toto tak gratuluji, vše funguje bezvadně. Můžete si zkusit jaký má vysílač a přijímač dosah a připájet si jak u vysílače tak u přijímače antenku ve formě drátu nebo vodiče o délce 10 - 15 cm. V mém případě mám anténu pouze u vysílače a když jsem dal vysílač do druhé místnosti tak data na přijímač stále chodily. Ale samozřejmě že lepších výsledků dosáhnete, použijete-li anténu na obou zařízeních. 

Data jsme si tedy nějak odeslali, ale nějak nevyužili. V prvním případě si ukážeme jak jednoduše zapínat a vypínat třeba nějaké spotřebič nebo zásuvku. Jak to tedy uděláme. Jednoduše. Prostě budeme odesílat jak jednu hodnotu pro zapnutí tak druhou pro vypnutí.

Na kontaktní pole si tedy dáme u vysílače ještě 2 tlačítka, která připojíme k digitálnímu pinu 4 (pro zapnutí) a 5 (pro vypnutí). Nesmíme zapomenout na odpor cca 10KOhm, který připojíme piny ke GND (LOW), jinak v případě nestisknutého tlačítka tam nebyla ani LOW ani HIGH hodnota. Ale pro jistotu malý plánek :-):

  

Tak taková tlačítka tedy připojíme 2. Nahrajeme do Arduina tento prográmek:

Z programu je zřejmé, že jsme si připravili do proměnných "zapnuto" a "vypnuto" hodnoty. Rozdílná je pouze hodnota na konci, kde při zapnutí je 1. Program v cyklech hlídá, zda bylo stisknuto nějaké tlačítko. Když zjistí, že ano odešle příjímač hodnotu buď k zapnutí nebo vypnutí. Teď, když si zapneme přijímač a k němu SerialMonitor, uvidíme hodnoty, které byly přijmuty při stisku tlačítek. To čekání (delay(400);) je tam z důvodu, že stisk může trvat nějakou dobu a hodnoty by se neustále odesílali. 

Je to opravdu hodně zjednodušeno, ale funkci to splní, teď si jenom napíšeme jiný prográmek pro přijímač a k Arduinu s modulem přijímače připojíme LED diodu k pinu 3, která bude simulovat zapnutí třeba relé, ketré bude zapínat a vypínat zásuvku či jiný spotřebič (nezapomeňte na odpor tak cca 1,2 kOhm k LED). 

A co se nám stalo? Jedno tlačítko diodu rozsítí a druhé jí zhasne. A dálkové ovládání třeba k zásuvkám máme hotové :-). Samozřejmně můžeme přidat další tlačítka k ovládání čehokoliv jak jen je libo a co nám Arduino dovolí.

Já ještě na konci nastíním, jak využít také vysílač a přijímač k přenosu nějakých dat k druhému zařízení. A vyzkoušíme si třeba přenést hodnotu teploty z čidla DTH11, jehož funkci a použití jsme si popsali v lekci 6. Připravíme si tedy nějaké čidlo v mém případě již zmíněné DHT11 (samozřejmě můžete použít i cokoliv jiného z čehoz získáme nějakou hodnotu) a něco kam budeme tyto hodnoty na přijmači zobrazovat. Abych se vyhnul složitosti připojení, použiji LCD displej s modulem na I2C. 

Tak nejprve si nahrajeme program do vysílače upraveného pro získání hodnoty z DHT11. 

Vysvětlení k DHT11 najdete v lekci 6 takže to rozebírat nebudeme. Víme ale, že teplota z čidla je v celých číslech a na její uchování a přenos nám bude stačit nějaké 8-bitové číslo (0-255). Vysílač nám vysílá sekvenci 10ti 4bitových čísel. Použijeme tedy dvě poslední 4-bitová čísla do kterých si pomocí bitového posunu hodnotu o teplotě rozdělíme. Jak je vidět z kódu, je to velice jednoduché. Pokud by jsme potřebovali odeslat větší hodnotu než 255, použijeme více 4bitových čísel (bitový posun jsme si vysvětlili již u zápisu a čtení z EPROM) Například takto:

Tak vysílač je funkční, můžeme zkusit i bez displeje s připačem a ukázkou programu, kdy se hodnoty vypisují na SerialMonitor. Pokud, ale máme nějaký displej, připojíme a zkusíme si hodnotu o teplotě zobrazit. Jak jsem již podoktnul, já použiji LCD displej 16x2 znaků připojený na I2C modul, aby jsem měl zapojení co nejjednodušší a takto mi budou stačit k propojení displeje s Arduinem jen 4 vodiče. Kód pro přijímač je zde:

Přenos jakékoliv hodnoty je jednoduchý a pomocí rozložení hodnoty na 4bitové informace a následné složení není složité. Nyní by jste měli být schopni vytvořit i sami sofistikovanější projekty, kde budete  cokoliv řídit nebo přenášet hodnoty dálkově pomocí modulů na 433 MHz.

 

Zpět

Diskusní téma: Lekce 20 - Arduino a využití 433,92 MHz

Datum
Vložil
Titulek

Re: asj

Taky jsem řešil a hledal nějaké elegantní řešení a našel jsem toto... je to skvělé řešení... ukázka mého prog
V podstatě jde o to že data strukturuji, oděšlu přes bezdrát (433,92 SuperHet) a pak tu strukturu na druhé straně rozložím na původní data. je to část STRUCT a za int temp1 může být x-dalších a nejen int ale klidně float atd.

ten kontainer musí být na obou stranách stejný. v příkladu vyčítám jeden sensor DS18B20 ale v podstatě není problém jich použít více či i kombinovat více senzorů.... co nacpete na jedné straně do "kontaineru", na druhé vyleze.
Používám pro Přenost knihovnu VirtualWire (nyní je z ní RadioHead a VW už není rozvíjena)

použitý RF kit https://www.geeetech.com/433mhz-superheterodyne-3400-rf-link-kits-p-167.html
v rámci domu funguje bez problému jen s kouskem drátku



vysílač:

#include <VirtualWire.h>
#include <VirtualWire_Config.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

const int led = 4;
const int transmit_pin = 12;
boolean SenseSuccess = false;

float DS18B20 = 0.0;

void setup(void)
{
Serial.begin(9600);
sensors.begin();

// nastaveni vysilace 433MHz
vw_set_tx_pin(transmit_pin);
vw_set_ptt_inverted(true);
vw_setup(2000); // rychlost prenosu 2000bps

}

void loop(void)
{
SenseSuccess = PollSensors();
if(SenseSuccess == true)
{ TransmitData();
}
else {
LEDBlink();
LEDBlink();
LEDBlink();
}
delay(5000);

}

boolean PollSensors()
{
sensors.requestTemperatures();
DS18B20 = sensors.getTempCByIndex(0);

if( isnan(DS18B20))
{
return false;
}
else {
return true;
}
}

void TransmitData()
{
struct wData_STRUCT {
byte identifierB;
int temp1;
};

wData_STRUCT wData;

wData.identifierB = 100;
wData.temp1 = (DS18B20*100);

vw_send((uint8_t *)&wData, sizeof(wData));
vw_wait_tx();
LEDBlink();
}

void LEDBlink()
{
digitalWrite(led,HIGH);
delay(500);
digitalWrite(led,LOW);
delay(500);
}


Přijímač:

#include <VirtualWire.h>

const int led = 2;
const int receive_pin = 12;

struct wData_STRUCT {
byte identifierB;
int temp1;
};

wData_STRUCT wData;

float ts1 = 0.0;


void setup()
{
delay(1000);
Serial.begin(9600);

// Initialise the IO and ISR
vw_set_rx_pin(receive_pin);
vw_set_ptt_inverted(true);
vw_setup(2000); // 2000bps

vw_rx_start(); // Start prijimace
}

void loop()
{
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;

if (vw_get_message(buf, &buflen)) // Non-blocking
{
if (buflen == sizeof(wData_STRUCT))
{
memcpy( &wData, buf, sizeof(wData));
ts1 = (wData.temp1/100);
Serial.println(ts1);
LEDBlink();
}
else {
Serial.println("error");
LEDBlink();
LEDBlink();
LEDBlink();
}

}
}
void LEDBlink()
{
digitalWrite(led,HIGH);
delay(500);
digitalWrite(led,LOW);
delay(500);
}

Datum
Vložil
Titulek

Re: Re: asj

jinak k struktuře řeknu, že těch vysílačů od kterých se příjímají data může být více a každý může mít své ID, svoji vlastní strukturu ("konteiner").
ID je toto: wData.identifierB = 100;
ted ho v programu k ničemu nepoužívám, nechal jsem to tam k budoucímu využití.

tzn. jeden kontainer = jeden vysílač s x-senzory či daty. Nebo jeden vysílač může používat víče techto kontainerů a v jednom vysílat teploty každých 5min, v druhém pak třeba stav baterie jednou za hodinu.



Datum
Vložil
Titulek

Re: Re: Re: asj

Můžu poprosit o vysvětlení ke kontejnerum? Pokud vidím dobře tak v kodu u příjmače kontejner chybí a nepovedlo se mi zprovoznit.

Kde u příjmače uvedu kontejner?

Datum
Vložil
Titulek

Re: Re: asj

Ahoj, dík za tvůj příspěvek konečně funkční příklad :)
ještě mám dvě otázky

1. jak zobrazit třeba 25,5 st. nebo 25,78 prostě víc desetinných míst. různě jsem zkoušel měnit
ts1 = (wData.temp1/100); ale bez úspěchu.

2.a za jakých okolností se vypíše error ?
bylo by fajn kdyby to vyhodilo error když přestane vysílat vys. třeba když dojdou bat.

Dík moc

Datum
Vložil
Titulek

Re: Re: asj

Ahoj, díky za funkční příklad. Chtěl jsem se jen zeptat jestli je možné nějak poupravit nebo použít jinou knihovnu aby přijímač fungoval na Wemosu/ESP-8266?

Dále by mě zajímalo jak je to s Errorem? Aktuálně mi fugnuje program tak, že když odpojím čidlo tak se mi zobrazuje jen poslední známá hodnota což není moc dobré + ty dvě nuly za desetinnou čárkou jsou tam snad na víc (nic nezobrazují prostě jen dvě nuly za celou hodnotou... bylo by super kdyby to ty čísla za desetinnou čárkou zobrazovala reálně).

Datum
Vložil
Titulek

Re: Re: asj

Super, konečně funkční kod, už jsem přestával doufat, že někdy tu komunikaci rozchodím a astal se zázrak. Fakt díky

Datum
Vložil
Titulek

přijmač

Ahoj mám problém vysílač přijmout skoušel jsem ladit měnit antény a nepomohlo jen na krátké vzdálenosti přitom vysílač chytnu asi na 30 m v zastavené oblasti na příjmač co je na pokojoví programátor ke kotlu tak už nevím co stím

Datum
Vložil
Titulek

Dálkový teploměr

Ahoj,
mám asi blbej dotaz, ale lze udělat dálkový teploměr bez druhého Arduina? Nefunguje vysílací modul tak, že data ze senzoru prostě pošle a přijímač přijme a Arduino zpracuje?
Díky

Datum
Vložil
Titulek

Re: Dálkový teploměr

lze udělat že je ovládán samotným čipem ATMega328P-PU (lze jej vyjmout z Arduina a použít v pcb samostatně, tady je o tom taky článek) nebo lze použít třeba MCU ATtiny85.

https://blog.onlinux.fr/wp-content/uploads/2015/02/PIR-Atinny85-Sketch_bb.png

v odkazu je článek který ukazuje jak lze naprogramovat ATtiny85 pomocí desky Arduino Uno
https://create.arduino.cc/projecthub/arjun/programming-attiny85-with-arduino-uno-afb829

Datum
Vložil
Titulek

chyba v eeprom.h - náprava

Ahoj. Pokud to někomu napíše chybu při kompilaci - chyba v eeprom.h tak jděte do souboru LwTx.h a LwRx.h a změnte hodnotu v řádku - #define EEPROM_EN 1 na hodnotu 0. Takže řádek bude vypadat takto. #define EEPROM_EN 0

Pak lze kompilovat. Michal

<< 1 | 2 | 3 | 4 | 5 >>

Vyhledávání

arduino8.cz © 2015 Všechna práva vyhrazena.