Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.
Obě strany předchozí revize Předchozí verze Následující verze | Předchozí verze | ||
2017:greenhouse-ctrl [2018/01/15 00:59] Josef Křivský |
2017:greenhouse-ctrl [2018/01/15 07:28] (aktuální) Josef Křivský |
||
---|---|---|---|
Řádek 8: | Řádek 8: | ||
Cílem tohoto projektu je co nejvíce automatizovat obsluhu a udržování běžného zahradního skleníku. Obsahem návrhu je kompletní software řízení a obsluhy, ale také co nejjednodušší hardware pro příslušné periferie. Základní myšlenkou je možnost kontroly a nastavení jednotlivých vlastností skleníku z pohodlí domova, za pomoci ethernetového rozhraní a běžného PC. Pomocí definovaných příkazů je tak možné jak kontrolovat vlhkost půdy, teplotu a osvětlení ve skleníku, tak nastavit jejich limitní hodnoty pro spuštění zavlažování, odvětrávání/vytápění skleníku a přisvětlení zářivkami. | Cílem tohoto projektu je co nejvíce automatizovat obsluhu a udržování běžného zahradního skleníku. Obsahem návrhu je kompletní software řízení a obsluhy, ale také co nejjednodušší hardware pro příslušné periferie. Základní myšlenkou je možnost kontroly a nastavení jednotlivých vlastností skleníku z pohodlí domova, za pomoci ethernetového rozhraní a běžného PC. Pomocí definovaných příkazů je tak možné jak kontrolovat vlhkost půdy, teplotu a osvětlení ve skleníku, tak nastavit jejich limitní hodnoty pro spuštění zavlažování, odvětrávání/vytápění skleníku a přisvětlení zářivkami. | ||
+ | |||
+ | {{ :2017:xkrivs00:img_20180115_063847_7.jpg?400 |}} | ||
+ | |||
---- | ---- | ||
Řádek 13: | Řádek 16: | ||
FRDM-K64F | FRDM-K64F | ||
- | |||
- | |||
Řádek 41: | Řádek 42: | ||
====== Vývoj HW ====== | ====== Vývoj HW ====== | ||
- | Požadavkem na celou konstrukci automatizovaného skleníku byla především jednoduchost implementace/instalace, ale také cena celého systému. Vzhledem k velkému možství některých součástek v inventáři zadavatele, byly proto použity především ony. | + | Požadavkem na celou konstrukci automatizovaného skleníku byla především jednoduchost implementace/instalace, ale také cena celého systému. Vzhledem k velkému možství některých součástek v inventáři zadavatele, byly proto použity především ony. |
+ | |||
+ | Seznam použitých komponetů: | ||
+ | * Mikrokontrolér FRDM-K64F | ||
+ | * Servo Hitec HS-485HB | ||
+ | * NTC Termistor Eclipsera 1488979094 | ||
+ | * Arduino modul pro měření intenzity světla BH1750 | ||
+ | * Půdní Vlhkoměr Modul pro Arduino | ||
+ | |||
+ | Odkazy na stránky výrobců/prodejců: | ||
+ | |||
+ | *http://hitecrcd.com/products/servos/sport-servos/analog-sport-servos/hs-485hb-deluxe-hd-ball-bearing-servo/product | ||
+ | *https://www.nxp.com/products/processors-and-microcontrollers/arm-based-processors-and-mcus/kinetis-cortex-m-mcus/k-seriesperformancem4/k2x-usb/freedom-development-platform-for-kinetis-k64-k63-and-k24-mcus:FRDM-K64F | ||
+ | *https://arduino-shop.cz/arduino/1574-ntc-termistor-10k-1-3950-1m-vodotesna-sonda-1488979094.html | ||
+ | *https://arduino-shop.cz/arduino/902-arduino-mereni-intenzity-svetla-1420672425.html | ||
+ | *https://arduino-shop.cz/arduino/1399-pudni-vlhkomer-modul-pro-arduino-1474354607.html | ||
---- | ---- | ||
Řádek 50: | Řádek 66: | ||
Použité knihovny v soubotu main.c | Použité knihovny v soubotu main.c | ||
- | |||
* #include "mbed.h" | * #include "mbed.h" | ||
Řádek 63: | Řádek 78: | ||
Peripherals.h: | Peripherals.h: | ||
<code c> | <code c> | ||
- | |||
class Humid | class Humid | ||
{ | { | ||
Řádek 79: | Řádek 93: | ||
}; | }; | ||
- | /** | ||
- | |||
- | */ | ||
class Temp | class Temp | ||
{ | { | ||
Řádek 102: | Řádek 113: | ||
}; | }; | ||
- | /** | ||
- | |||
- | */ | ||
class Vent | class Vent | ||
{ | { | ||
public: | public: | ||
- | Vent(PinName PWM = D8); | + | Vent(PinName PWM = D9); |
void open(uint8_t percent = 100); | void open(uint8_t percent = 100); | ||
void close(void); | void close(void); | ||
Řádek 117: | Řádek 125: | ||
}; | }; | ||
- | /** | ||
- | |||
- | */ | ||
class Fan | class Fan | ||
{ | { | ||
Řádek 130: | Řádek 135: | ||
}; | }; | ||
- | /** | ||
- | |||
- | */ | ||
class Heat | class Heat | ||
{ | { | ||
Řádek 143: | Řádek 145: | ||
}; | }; | ||
- | /** | ||
- | |||
- | */ | ||
class Water | class Water | ||
{ | { | ||
Řádek 156: | Řádek 155: | ||
}; | }; | ||
- | /** | ||
- | |||
- | */ | ||
class Light | class Light | ||
{ | { | ||
Řádek 168: | Řádek 164: | ||
DigitalOut lighting; | DigitalOut lighting; | ||
}; | }; | ||
- | |||
</code> | </code> | ||
Řádek 174: | Řádek 169: | ||
<code c> | <code c> | ||
- | |||
- | #include "mbed.h" | ||
- | #include "Peripherals.h" | ||
- | |||
- | |||
Humid::Humid(PinName AInp, PinName AOut):ain(AInp),dop(AOut) | Humid::Humid(PinName AInp, PinName AOut):ain(AInp),dop(AOut) | ||
{ | { | ||
Řádek 300: | Řádek 290: | ||
{ | { | ||
- | float width = ((6 * percentage)+900); | + | uint16_t width = ((6 * percentage)+900); |
| | ||
while(width != (6*percent)+900) | while(width != (6*percent)+900) | ||
Řádek 308: | Řádek 298: | ||
width-=1; | width-=1; | ||
pwm.pulsewidth_us(width); | pwm.pulsewidth_us(width); | ||
- | wait_ms(25); | + | wait_ms(10); |
} | } | ||
else | else | ||
Řádek 314: | Řádek 304: | ||
width+=1; | width+=1; | ||
pwm.pulsewidth_us(width); | pwm.pulsewidth_us(width); | ||
- | wait_ms(25); | + | wait_ms(10); |
} | } | ||
} | } | ||
+ | percentage = percent; | ||
} | } | ||
void Vent::close(void) | void Vent::close(void) | ||
{ | { | ||
- | for(float width=((6 * percentage)+900); width>900; width-=1) | + | open(0); |
- | { | + | |
- | pwm.pulsewidth_us(width); | + | |
- | wait_ms(25); | + | |
- | } | + | |
} | } | ||
Řádek 343: | Řádek 330: | ||
fan = 0; | fan = 0; | ||
} | } | ||
- | + | . | |
- | Heat::Heat(PinName DOut):heater(DOut) | + | . |
- | { | + | . |
- | heater = 0; | + | |
- | } | + | |
- | + | ||
- | void Heat::Start(void) | + | |
- | { | + | |
- | heater = 1; | + | |
- | } | + | |
- | + | ||
- | void Heat::Stop(void) | + | |
- | { | + | |
- | heater = 0; | + | |
- | } | + | |
- | + | ||
- | Water::Water(PinName DOut):sprinkler(DOut) | + | |
- | { | + | |
- | sprinkler = 0; | + | |
- | } | + | |
- | + | ||
- | void Water::Start(void) | + | |
- | { | + | |
- | sprinkler = 1; | + | |
- | } | + | |
- | + | ||
- | void Water::Stop(void) | + | |
- | { | + | |
- | sprinkler = 0; | + | |
- | } | + | |
- | + | ||
- | Light::Light(PinName DOut):lighting(DOut) | + | |
- | { | + | |
- | lighting = 0; | + | |
- | } | + | |
- | + | ||
- | void Light::Start(void) | + | |
- | { | + | |
- | lighting = 1; | + | |
- | } | + | |
- | + | ||
- | void Light::Stop(void) | + | |
- | { | + | |
- | lighting = 0; | + | |
- | } | + | |
</code> | </code> | ||
+ | Za zmínku stojí především třídy Humid a Temp, které nejen zapouzdřují různé proměnné a vstupy, ale také nad nimi provádějí řadu výpočtů. U třídy Humid se jedná pouze o úpravu snímaného napětí ze zesilovače a měření v pulzním režimu (z důvodu elektrolýzy na elektrodách snímače vlhkosti). Třída Temp však již provádí poměrně složité výpočty při převodu snímaného napětí z děliče (tvořen rezistorem a NTC termistorem) na hodnotu okolní teploty. Veškeré další třídy jsou v této knihovně již pouze kopie třídy Fan, které slouží k ovládání reléových výstupů, a které mají jen rozdílné názvy a výstupní piny na desce FRDM-K64F. | ||
Řádek 408: | Řádek 353: | ||
Light illumination; // Ovládání světel | Light illumination; // Ovládání světel | ||
- | + | enum STAT // Proměnná pro uložení stavu celého systému | |
- | char line1[50], line2[50], line3[50]; // Řetězce pro vypsání stavu skleníku | + | { |
+ | READY = 1, SETTINGS, MANUAL, ERROR | ||
+ | }sklenikstav; | ||
</code> | </code> | ||
+ | Stav systému sklenikstav je díky třídám pouze pomocnou proměnnou pro rozhodovací stromy uživatelského rozhraní. | ||
- | * Ovládací vlákna RTOS (zde již probíhá periodická kontrola stavu skleníku, a jemu příslušné reakce periferií) | + | * Ovládací vlákna RTOS (zde již probíhá periodická kontrola stavu skleníku, a příslušné reakce periferií) |
<code c> | <code c> | ||
- | void watering_thread() | + | void watering_thread(void) |
{ | { | ||
while(true) | while(true) | ||
Řádek 537: | Řádek 485: | ||
avglx /= 6; | avglx /= 6; | ||
| | ||
- | /*if(avglx<light.getLimit()) | + | if(avglx<light.getLimit()) |
{ | { | ||
illumination.Start(); | illumination.Start(); | ||
Řádek 546: | Řádek 494: | ||
illumination.Stop(); | illumination.Stop(); | ||
} | } | ||
- | */ | ||
| | ||
Thread::wait(300000); | Thread::wait(300000); | ||
Řádek 552: | Řádek 499: | ||
} | } | ||
</code> | </code> | ||
+ | Tato vlákna mají zajišťovat plnou automatičnost skleníku po jeho prvotním nastavení. Bohužel se díky problémům s různými verzemi systému MBED a jeho knihoven nepodařilo (díky nedostatku času) najednou zprovoznit vlákna a ovládání skleníku přes ethernetové rozhraní. Ačkoliv RTOS sám o sobě funguje, nebylo by možné nastavovat skleník on-line, čímž bychom přišli o jakoukoliv možnost okamžitého zásahu, a zároveň by nebyla splněna nejdůležitější část zadání. | ||
* Funkce rozhodovacího stromu pro Ethernetové rozhraní skleníku (přímé ovládání) | * Funkce rozhodovacího stromu pro Ethernetové rozhraní skleníku (přímé ovládání) | ||
+ | <code c> | ||
+ | int evaluate(char *str) | ||
+ | { | ||
+ | switch(sklenikstav) | ||
+ | { | ||
+ | case READY: | ||
+ | if (strcmp(str, "help") == 0) | ||
+ | { | ||
+ | return 1; | ||
+ | } | ||
+ | else if (strcmp(str, "stav") == 0) | ||
+ | { | ||
+ | return 2; | ||
+ | } | ||
+ | else if (strcmp(str, "set") == 0) | ||
+ | { | ||
+ | . | ||
+ | . | ||
+ | . | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | int main(void) | ||
+ | { | ||
+ | . | ||
+ | . | ||
+ | . | ||
+ | int x = evaluate(message); | ||
+ | if(sklenikstav == READY) | ||
+ | { | ||
+ | if (x == 0) | ||
+ | { | ||
+ | client.send_all("Neplatny prikaz!\r\n", 18); | ||
+ | client.send_all(commandwait, sizeof(commandwait)); | ||
+ | } | ||
+ | else if (x == 1) | ||
+ | { | ||
+ | char helpmsg[] = "stav\t\t-Zobrazeni aktualnich informaci\r\nset\t\t-Nastaveni skleniku\r\nman\t\t-Ovladani skleniku\r\nexit/quit\t-Konec\r\n"; | ||
+ | client.send_all(helpmsg, sizeof(helpmsg)); | ||
+ | client.send_all(commandwait, sizeof(commandwait)); | ||
+ | number = 0; | ||
+ | . | ||
+ | . | ||
+ | . | ||
+ | } | ||
+ | </code> | ||
+ | Jak lze vidět, jedna z těchto funkcí se nachází ve funkci main, a druhá je pouze jako pomoc při určování obdržených řetězců. V závislosti na obdrženém textu pak tyto funkce přepínají jak stavy systému (pouze pro potřeby komunikace s uživatelem), tak výstupy mikrokontroléru. Tyto funkce jsou obdobou absolvovaného cvičení č.5, pouze značně složitější, a proto je tu nebudu uvádět celé. Uvedu pouze stavy systému a jejich akceptované příkazy. | ||
+ | |||
+ | === Celý kód === | ||
+ | |||
+ | https://os.mbed.com/users/civava/code/sklenik-2017/ | ||
+ |