Arduino Budík Shield je rozšiřovací modul, který obsahuje spoustu zajímavých prvků. Tento Shield má stejný formát jako desky Arduino UNO, přičemž využívá velké množství propojovacích pinů. Obsahuje čtyřmístný 7-segmentový displej s řadičem TM1636, obvod reálného času DS1307, sirénku, fotorezistor, termistor, čtyři LED diody v různých barvách a tři tlačítka. Můžeme s ním tedy vytvořit spoustu různých zapojení včetně zmíněného budíku.
Pro úspěšné propojení Budík Shieldu s Arduinem stačí tento Shield zapojit do Arduino desky.
Pro úspěšné nahrání uvedeného ukázkového kódu je nutné stáhnout a naimportovat knihovnu TickTockShield, návod, jak na to je uveden zde. Ukázkový kód obsahuje na svém začátku připojení potřebných knihoven a nastavení čísel propojovacích pinů. Dále se zde nachází proměnná s velikostí odporu u termistoru a nastavení tempa hraného tónu. V podprogramu setup nejprve nastavíme komunikaci po sériové lince a následně směr všech vstupních a výstupních pinů. V dalším kroku vypneme všechny LED diody pomocí podprogramu a zahájíme inicializaci displeje z knihovny. Nekonečná smyčka loop v sobě obsahuje obsluhu pro většinu použitých součástek. V prvním kroku zde vytvoříme proměnnou pro uložení frekvence hraného tónu a načteme do další proměnné informaci o stisknutých tlačítkách. Následně provedeme postupně kontrolu všech tří tlačítek, kdy každé tlačítko obsahuje jinou funkci. Pro první tlačítko načteme úroveň intenzity světla v okolí do proměnné, tuto informaci vytiskneme na druhou číslici displeje a vyčkáme půl sekundy. Pro druhé tlačítko snížíme tón o hodnotu 100 (pokud už není menší než 100), vytiskneme výšku tónu na displej a zároveň po sériové lince. A pro třetí tlačítko provedeme naopak zvýšení tónu do hranice 2000 společně s vytištěním na displej a sériovou linku. Pokud ale nebylo v aktuálním běhu stisknuto žádné tlačítko, provedeme následující úsek kódu. Načteme si hodnotu okolní teploty do proměnné, kterou zobrazíme na displeji, a poté s nastavenou rychlostí postupně blikneme všemi LED diodami. Na konci smyčky si už jen počkáme po dobu 500 ms nebo případně o 200 ms více, pokud bylo stisknuto nějaké tlačítko.
Pod smyčkou loop se nachází použité podprogramy. Jako první je zde uveden podprogram pro zobrazení teploty, který ze vstupní teploty vytvoří čtyři znaky, které se následně vytisknou na displej. Další čtyři podprogramy jsou věnované práci s LED diodami, kdy první dva slouží pro zapínání a vypínání jednotlivých diod a následující dva obsahují vždy zapnutí či vypnutí všech diod najednou. Jako další se zde nachází podprogram pro bliknutí všemi LED diodami, který se zadanou rychlostí postupně pomocí masky projde všechny LED diody. Další dva podprogramy jsou věnované práci s fotorezistorem, kdy první z nich zpracovává vstupní data z analogového pinu a přepočte je na odpor. Druhý podprogram pak využije vypočítaný odpor a podle jeho velikosti vrací úroveň intenzity světla zjednodušenou na 8 úrovní. Následující podprogram slouží pro načtení stavu tlačítek, kdy při stisku kteréhokoliv z nich vždy vytiskneme informaci po sériové lince a zároveň nastavíme číslo tlačítka na výstup z podprogramu. A poslední podprogram je spojený s hraním tónu na sirénce, kdy podle vstupní výšky tónu a trvání zahrajeme nastavený tón.
// Arduino budík shield
// připojení potřebných knihoven
#include "Wire.h"
#include <TimerOne.h>
#include <MsTimer2.h>
#include <EEPROM.h>
#include "TM1636.h"
#include "TickTockShield.h"
// nastavení čísel propojovacích pinů
#define pinTermistor A0
#define pinFotorezistor A1
#define LED1 2
#define LED2 3
#define LED3 4
#define LED4 5
#define tlacitko1 11
#define tlacitko2 10
#define tlacitko3 9
#define pinSirenka 6
// nastavení velikosti odporu u termistoru
#define termistorOdpor 10000
// proměnná pro nastavení tempa hraného tónu
int tempo = 300;
void setup() {
// komunikace po sériové lince rychlostí 9600 baud
Serial.begin(9600);
// nastavení směru vstupních a výstupních pinů
pinMode(pinTermistor, INPUT);
pinMode(pinFotorezistor, INPUT);
pinMode(tlacitko1, INPUT);
digitalWrite(tlacitko1, HIGH);
pinMode(tlacitko2, INPUT);
digitalWrite(tlacitko2, HIGH);
pinMode(tlacitko3, INPUT);
digitalWrite(tlacitko3, HIGH);
pinMode(pinSirenka, OUTPUT);
digitalWrite(pinSirenka, LOW);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
// vypnutí všech LED diod pomocí podprogramu
vypniLED();
// inicializace displeje z knihovny
tm1636.init();
}
void loop() {
// vytvoření proměnné pro uložení frekvence hraného tónu
static int ton = 1000;
// načtení informací o stisknutých tlačítkách do proměnné
int16_t cisloTlacitka = nactiTlacitka();
// kontrola stavu jednotlivých tlačítek
if (tlacitko1 == cisloTlacitka) {
// načtení intenzity světla v okolí do proměnné
uint8_t urovenIntenzitySvetla = nactiIntenzituSvetla();
// vyčištění celého displeje a vypsání intenzity světla
// na druhou číslici displeje (číslování od nuly)
tm1636.clearDisplay();
tm1636.display(1, urovenIntenzitySvetla);
// výpis informací o intenzitě po sériové lince
Serial.print("Uroven intenzity svetla 0-7: ");
Serial.println(urovenIntenzitySvetla);
// pauza po dobu půl sekundy
delay(500);
}
else if (tlacitko2 == cisloTlacitka) {
// snížení hraného tónu o 100, pokud je jeho hodnota větší než 100
if (ton > 100) {
ton -= 100;
}
// vyčištění celého displeje a výpis tónu po jednotlivých číslicích
tm1636.clearDisplay();
tm1636.display(0, (ton / 1000));
tm1636.display(1, ((ton % 1000) / 100));
tm1636.display(2, 0);
tm1636.display(3, 0);
// zavolání podprogramu pro zahrání nastaveného tónu
zahrajTon(ton, tempo);
// vytištění frekvence hraného tónu po sériové lince
Serial.print("Hrany ton: ");
Serial.println(ton);
}
else if (tlacitko3 == cisloTlacitka) {
// zvýšení hraného tónu o 100, pokud je jeho hodnota menší než 2000
if (ton < 2000) {
ton += 100;
}
// vyčištění celého displeje a výpis tónu po jednotlivých číslicích
tm1636.clearDisplay();
tm1636.display(0, (ton / 1000));
tm1636.display(1, ((ton % 1000) / 100));
tm1636.display(2, 0);
tm1636.display(3, 0);
// zavolání podprogramu pro zahrání nastaveného tónu
zahrajTon(ton, tempo);
// vytištění frekvence hraného tónu po sériové lince
Serial.print("Hrany ton: ");
Serial.println(ton);
}
// pokud není stisknuto tlačítko, vykonej následující
else {
// načtení okolní teploty do proměnné
int8_t teplota = nactiTeplotu();
// výpis teploty pomocí podprogramu
zobrazTeplotu(teplota);
// nastavení rychlosti blikání v rozsahu 1-10
byte rychlost = 5;
// zavolání podprogramu pro bliknutí všemi LED diodami
blikniLED(rychlost);
}
// pokud bylo stisknuto nějaké tlačítko, počkej 200ms navíc
if (cisloTlacitka > 0) {
delay(200);
}
// pauza po dobu 500ms
delay(500);
}
// podprogramu pro načtení teploty z termistoru,
// teplota může být v rozsahu -40 až +125°C
int8_t nactiTeplotu() {
// vytvoření pomocných proměnných
float teplota, odpor;
int a;
int B = 3975;
// načtení hodnoty z termistoru
a = analogRead(pinTermistor);
// výpočet odporu termistoru
odpor = (float)(1023 - a) * termistorOdpor / a;
// výpočet teploty z odporu termistoru a jeho měřící konstanty B
teplota = 1 / (log(odpor / termistorOdpor) / B + 1 / 298.15) - 273.15;
// vrácení teploty ve formátu integer (celé číslo)
return (int8_t)teplota;
}
// podprogram pro zobrazení teploty na displeji
void zobrazTeplotu(int8_t teplota) {
// vytvoření pole pro uložení číslic
int8_t teplotaPole[4];
// pokud je teplota záporná, nastavíme na první znak záporné znaménko
// a poté převedeme teplotu na kladnou pro správný výpis
if (teplota < 0) {
teplotaPole[0] = INDEX_NEGATIVE_SIGN;
teplota = abs(teplota);
}
// pokud je teplota menší než 100°C, první znak bude prázdný
else if (teplota < 100) {
teplotaPole[0] = INDEX_BLANK;
}
// v ostatních případech zobrazuje nultý znak stovky
else {
teplotaPole[0] = teplota / 100;
}
// přepočet naměřené teploty pro správný výpis na zbývající znaky displeje,
// na poslední znak se vypíše znak "C" (hexadecimálně 12)
teplota %= 100;
teplotaPole[1] = teplota / 10;
teplotaPole[2] = teplota % 10;
teplotaPole[3] = 12;
// výpis teploty na displej
tm1636.display(teplotaPole);
}
// zapnutí LED diody
inline void zapni(int pinLED) {
digitalWrite(pinLED, HIGH);
}
// vypnutí LED diody
inline void vypni(int pinLED) {
digitalWrite(pinLED, LOW);
}
// zapnutí všech LED diod
inline void zapniLED() {
zapni(LED1);
zapni(LED2);
zapni(LED3);
zapni(LED4);
}
// vypnutí všech LED diod
inline void vypniLED() {
vypni(LED1);
vypni(LED2);
vypni(LED3);
vypni(LED4);
}
// postupné rozsvícení všech čtyř LED diod, při volání se nastavuje rychlost
// v rozmezí 1 - 10
void blikniLED(byte rychlost) {
// pokud je hodnota v platném rozsahu, zahaj blikání
if ((rychlost > 0) && (rychlost < 11)) {
// vytvoření masky pro blikání
uint8_t maska = 0x01;
// for smyčka pro bliknutí všemi LED diodami
for (uint8_t i = 0; i < 4; i ++) {
if (maska & 0x01)
zapni(LED1);
else
vypni(LED1);
if (maska & 0x02)
zapni(LED2);
else
vypni(LED2);
if (maska & 0x04)
zapni(LED3);
else
vypni(LED3);
if (maska & 0x08)
zapni(LED4);
else
vypni(LED4);
maska <<= 1;
// pauza se počítá z nastavené rychlosti
delay(500 / rychlost);
}
// vypnutí všech LED diod
vypniLED();
}
}
// získání dat z fotoodporu
float aktualniIntenzita() {
// načtení dat z fotoodporu
int fotoOdpor = analogRead(pinFotorezistor);
// přepočtení odporu podle druhu senzoru
float prepocetOdporu;
prepocetOdporu = (float)(1023 - fotoOdpor) * 10 / fotoOdpor;
// vrácení přepočtených dat z fotoodporu
return prepocetOdporu;
}
// načtení intenzity světla v rozsahu 0-7 (0 je největší intenzita, 7 je tma)
uint8_t nactiIntenzituSvetla() {
// vytvoření pomocných proměnných
uint16_t odpor;
uint8_t urovenIntenzitySvetla;
// získání dat z fotoodporu
odpor = (uint16_t)aktualniIntenzita();
// vytištění dat po sériové lince
Serial.print("Fotoodpor: ");
Serial.println(odpor);
// převod intenzity světla dle naměřeného odporu na menší rozsah
if (odpor < 10) urovenIntenzitySvetla = 0;
else if (odpor < 50) urovenIntenzitySvetla = 1;
else if (odpor < 80) urovenIntenzitySvetla = 2;
else if (odpor < 110) urovenIntenzitySvetla = 3;
else if (odpor < 140) urovenIntenzitySvetla = 4;
else if (odpor < 170) urovenIntenzitySvetla = 5;
else if (odpor < 200) urovenIntenzitySvetla = 6;
else urovenIntenzitySvetla = 7;
// vrácení úrovně intenzity světla
return urovenIntenzitySvetla;
}
// načtení stavu všech tlačítek
int16_t nactiTlacitka() {
// vytvoření proměnné, do které se uloží na začátku záporné číslo,
// abychom poznali, že případně nebylo stisknuto žádné tlačítko
int16_t cisloPinu = -1;
// kontrola stisku všech tlačítek, pokud je některé stisknuto po dobu 20ms,
// zaznamenáme jeho číslo do proměnné
if (digitalRead(tlacitko1) == LOW) {
delay(20);
if (digitalRead(tlacitko1) == LOW) {
cisloPinu = tlacitko1;
Serial.println("Stisknuto tlacitko 1.");
}
}
else if (digitalRead(tlacitko2) == LOW) {
delay(20);
if (digitalRead(tlacitko2) == LOW) {
cisloPinu = tlacitko2;
Serial.println("Stisknuto tlacitko 2");
}
}
else if (digitalRead(tlacitko3) == LOW) {
delay(20);
if (digitalRead(tlacitko3) == LOW) {
cisloPinu = tlacitko3;
Serial.println("Stisknuto tlacitko 3");
}
}
// vrácení čísla pinu tlačítka
return cisloPinu;
}
// přehrání tónu na sirénce
void zahrajTon(int ton, int trvani) {
// for smyčka, která ze zadaných údajů zahraje nastavený tón
for (long i = 0; i < trvani * 1000L; i += ton * 2) {
digitalWrite(pinSirenka, HIGH);
delayMicroseconds(ton);
digitalWrite(pinSirenka, LOW);
delayMicroseconds(ton);
}
}
Po nahrání ukázkového kódu do Arduino desky s připojeným budík Shieldem dostaneme například tento výsledek:
Arduino Budík Shield je vhodný jako jedno ze základních rozšíření pro začátečníky i pokročilé. Díky tomu, že obsahuje mnoho prvků, s kterými lze pracovat, se hodí na projekty jako například vstupní terminál, teploměr či právě náhrada digitálních hodin s budíkem. Jak bylo řečeno na začátku, na Shieldu se také nachází obvod pro práci s reálným časem DS1307, na který už byl publikován tento návod. Případně pro další ukázku mohu doporučit ukázkový kód přímo z knihovny, který lze najít v nabídce Soubor-Příklady-TickTockShield-RealTimeClock.
Motorizovaný kulový ventil. Má široké uplatnění v různých průmyslových a obytných instalacích. Může být integrován do automatických systémů řízení, kde je možné ovládat průtok dálkově nebo automatizovaně podle předem nastavených podmínek.
Motorizované kulové vently s obvodem CR01, CR02, CR03 nebo CR04 je poměrně jednoduché po elektrické stránce správně zapojit. U ventilu s obvodem CR05 je tomu ale trochu jinak - ventil si sám nehlídá krajní polohy otevření, nebo zavření. Z toho důvodu vznikl tento článek, ukazující některé výhody, použití a především správné zapojení ventilu s obvodem CR05.