Multifunkčná lampa
Zo stránky SensorWiki
Autor: | Meno Priezvisko | |
Študijný odbor: | Aplikovaná informatika | 3. Bc. (2019) |
Opis projektu
Čo
Témou môjho projektu je multifunkčná lampa využívajúca OLED display, na ktorom je zobrazená teplota a vlhkosť. Lampa je riadená mikropočítačom Arduino UNO R3.
Prečo?
- Tento projekt som si vybral kvôli tomu, že som sa chcel naučiť pracovať s Arduinom a elektronikou, keďže som nemal príležitosť vo väčšej miere pracovať s touto technológiou. Zaujímalo ma hlavne použitie senzorov, práca s nameranými veličinami a ich reprezentácia na výstup.
- Taktiež som chcel vytvoriť užitočnú vec, ktorá by mi i po dizajnovej stránke pasovala do mojej izby.
Ako ?
Sem príde podrobný návod na výrobu.
Potrebné súčiastky a nástroje - krabica
- platňa bukovej preglejky
- lepidlo na drevo
Hardvér
- Arduino UNO
- Relé modul, pracovné napätie 5V
- Vidlica do zásuvky
- Zdroj - Input 240 V AC - Output 5V DC
- Senzor teploty a vlhkosti DHT11
- 2x tlačítko
- OLED display 1.3 s kontrolerom SH1106
- vhodná mala objimka na žiarovku, E14 pätica
- 2x svorkovnica pre 3 káble
- káble
- 2x rezistor 10k
- 6 M3 skrutiek a 6 matíc
- malá led žiarovka, E14,rozmer 80x45 mm alebo menšia
Softvér
- softvér na technické kreslenie (napr. Autodesk Fusion 360)
- Corel - práca s laserom, úprava na vhodný formát pre laser
- Arduino IDE
Iné nástroje
- pilník
- breadboard
- spájkovačka
- multimeter
- vŕtačka + vrták 2.6
- skrutkovače
Postup výroby
- nakresliť si vhodnú krabicu, prípadne si ju vygenerovať
- zložiť krabicu
- zapojiť si komponenty, podľa schémy najskôr pomocou breadboard, potom pospájkovať
- naprogramovať si Arduino- naimportovať knižnice <dht.h>, <u8glib.h> a odtestovať funkčnosť, napríklad pomocou Serial Monitor
- komponenty rozmiestniť, navŕtať diery, namontovať na krabicu pomocou M3 skrutiek
- nalepiť tlačidlá a display
- odskúšať funkčnosť
Médiá:U8glib.rar, Médiá:DHTLib.rar, Médiá:lampaKod.ino, Médiá:lampaKrabica.rar
Použité zdroje:
- Tutoriál na programovanie displaya a DHT11 senzora: https://makersportal.com/blog/2018/9/3/arduino-i2c-oled-display-temperature-and-humidity
- Zapojenie relé: http://www.circuitbasics.com/setting-up-a-5v-relay-on-the-arduino/
Analýza
Pri analýze pred začatím môjho projektu som dohľadal vhodné súčiastky na môj výrobok. Zapojenie a výber súčiastok som konzultoval s človekom, ktorý má určité skúsenosti v danej problematike.
- použil som IIC zbernicu pre komunikáciu s displayom. Dôvod použitia bola redukcia použitia pinov v Arduine, preto bola IIC uprednostnená pred SPI.
- na použitie v interiéri plne postačuje senzor DHT11 s rozsahom 0 - 50 stupňov. Rozsah vlhkosti je 20 - 90 % s odchýľkou 4%. Alternatívou je drahší DHT22, ktorý meria od -40 do 100 stupňov a vlhkosť na celej škále.
- použil som 1.3" OLED display, pretože má dobrú čitatelnosť z rôznych uhlov a pekné farby. Použil som lacnejšiu verziu s kontrolerom SH1106.
- na lampu je vhodné použiť led žiarovku, ktorá sa menej zahrieva oproti obyčajnej, lampa je z dreva.
Popis riešenia
Na schéme nižsie môžete vidiet spôsob zapojenia súčiastok. Využívam zdroj, ktorý konvertuje 240 V na 5V, ktoré sú vhodné na napájanie Arduina. Na napájanie je vhodné využiť jeden z 5V pinov arduina, na mojom klone je ich viac ako na arduine, takže zobrazenie je ilustračné. Tlačidlá dávajú signál na ovládanie relé a prehadzujú veličiny zobrazené na displayi.
Schéma zapojenia snímača
Algoritmus a program
Vytvoril som jednoduchý program v jazyku C, vo vývojovom protredí Arduino ide. Kód je rozdelený do jednoduchých funkcii. Použité knižnice sa nachádzajú v sekcii Postup výroby.
- na začiatku sa vo funkcii setup nastaví stav relé na HIGH, resp vypnuté. Nastavia sa piny na preddefinované hodnoty.
- modeButtonSetup(); -> funkcia na prácu s tlacidlom, ktoré ovláda zobrazovanie
- relaySetup() -> funkcia na ovládanie relé pomocou svojho tlačidla
- drawTemperature() a drawHumidity() -> používajú premenné, v ktorých sú zaznamenané veličiny a vykresľujú ich na display
Vyberte podstatné časti zdrojového kódu, použite na to prostredie source:
/* A nezabudnite zdroják hojne komentovať */
#include <dht.h>
#include "U8glib.h" // kniznica pre OLED display
///////////////////////////PREMENNE/////////////////////////////////////////
int currentStateMode = HIGH;
int previousStateMode = LOW;
int modeButtonReading;
int modePin = 3;
long time = 0;
long debounce = 100;
int relayButtonPin = 4;
int relayPin = 5;
int currentStateRelay = HIGH;
int previousStateRelay = LOW;
int relayButtonReading;
int flameSensorPin = 0;
int buzzerPin = 7;
int flameSensorReading;
int temperature=0;
int hum=0;
#define DHTPIN 2
dht myDHT;
//////////////////////////////////////////////////////////////////////////////////////
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE); //volim ovladac SH1106
///////////////////////////////Obrazok teplomera - bitmap/////////////////////////////
static unsigned char temp[] U8G_PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0xFC, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0xC3, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC6, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0F, 0xC4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC4, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x0C, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x01, 0x80, 0x00,
0x00, 0x30, 0x00, 0x00, 0x0C, 0x01, 0x83, 0xFF, 0x00, 0x3E, 0x00, 0x00, 0x0C, 0x01, 0x80, 0x00,
0x00, 0x3F, 0x00, 0x00, 0x0C, 0x01, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x3F, 0xFC, 0x71, 0x80, 0x00,
0x00, 0x3E, 0x00, 0xF8, 0x7C, 0x71, 0x80, 0x00, 0x00, 0x1E, 0x03, 0x80, 0x0C, 0x71, 0x83, 0xE0,
0x00, 0x08, 0x0E, 0x00, 0x0C, 0x71, 0x83, 0xE0, 0x00, 0x00, 0x18, 0x00, 0x0C, 0x71, 0x80, 0x00,
0x00, 0x00, 0x30, 0x00, 0x0C, 0x71, 0x80, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0C, 0x71, 0x80, 0x00,
0x00, 0x00, 0xC0, 0x00, 0x0C, 0x71, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x0C, 0x71, 0x83, 0xFF,
0x00, 0x01, 0x00, 0x00, 0x0C, 0x71, 0x83, 0xFF, 0x00, 0x03, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00,
0x00, 0x02, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00,
0x00, 0x06, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x71, 0x83, 0xE0,
0x00, 0x0C, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00,
0x1E, 0x0C, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00, 0x7F, 0x0C, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00,
0x7F, 0x0C, 0x00, 0x00, 0x0C, 0x71, 0x83, 0xFF, 0x1E, 0x0C, 0x00, 0x00, 0x0C, 0x71, 0x83, 0xFF,
0x06, 0x0C, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00,
0x00, 0x04, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00,
0x00, 0x06, 0x00, 0x00, 0x0C, 0x71, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x18, 0x70, 0xC0, 0x00,
0x00, 0x03, 0x00, 0x00, 0x30, 0x70, 0x60, 0x00, 0x00, 0x01, 0x00, 0x00, 0x60, 0x70, 0x30, 0x00,
0x00, 0x01, 0x80, 0x00, 0xC0, 0x1C, 0x18, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x80, 0x1E, 0x08, 0x00,
0x00, 0x00, 0x60, 0x01, 0x00, 0x1F, 0x0C, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x1F, 0x84, 0x00,
0x00, 0x00, 0x18, 0x03, 0x00, 0x7F, 0xC6, 0x00, 0x00, 0x08, 0x0E, 0x03, 0x00, 0xFF, 0xC6, 0x00,
0x00, 0x1E, 0x03, 0x82, 0x00, 0xFF, 0xC6, 0x00, 0x00, 0x3E, 0x00, 0xFE, 0x01, 0xFF, 0xC6, 0x00,
0x00, 0x3F, 0x00, 0x3F, 0x01, 0xFF, 0xC6, 0x00, 0x00, 0x3F, 0x00, 0x03, 0x1F, 0xFF, 0xC6, 0x00,
0x00, 0x3E, 0x00, 0x03, 0x1F, 0xFF, 0x84, 0x00, 0x00, 0x30, 0x00, 0x01, 0x0F, 0xFF, 0x84, 0x00,
0x00, 0x00, 0x00, 0x01, 0x87, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x83, 0xFE, 0x18, 0x00,
0x00, 0x00, 0x00, 0x07, 0xC0, 0xF8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x30, 0x00,
0x00, 0x00, 0x00, 0x07, 0xF8, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xCC, 0x01, 0x80, 0x00,
0x00, 0x00, 0x00, 0x03, 0x87, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x78, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void modeButtonSetup(void){ //funkcia pre tlacitko -> vypnutie, zapnutie po kliknuti
modeButtonReading = digitalRead(modePin);
if(modeButtonReading == HIGH && previousStateMode == LOW && millis() - time > debounce){
if(currentStateMode == HIGH){
currentStateMode = LOW;
}
else currentStateMode = HIGH;
time = millis();
}
previousStateMode = modeButtonReading;
}
void relaySetup(){
relayButtonReading = digitalRead(relayButtonPin);
if(relayButtonReading == LOW && previousStateRelay == HIGH&& millis() - time > debounce){ //ovladanie rele, podobne ako pri klasickom tlacidle
if(currentStateRelay == HIGH){
currentStateRelay = LOW;
}
else currentStateRelay = HIGH;
time = millis();
}
digitalWrite(relayPin,currentStateRelay);
previousStateRelay = relayButtonReading;
}
///////////////////////// vykreslovanie teploty/////////
void drawTemperature(void)
{
u8g.drawBitmapP( 0, 0, 8, 64, temp);////////for drawing bitmap of size 64*64 and location is x=0,y=0
char s[2] = " ";
u8g.setFont(u8g_font_fur35n); // font
u8g.setPrintPos(67, 50); //nastavenie pozicie, kam vypisat teplotu
u8g.println(temperature); //vypis teploty
u8g.setFont(u8g_font_osr18);
s[0] = 176; //znak stupen(kruzok)
u8g.drawStr(116, 28, s); //vypis stupna
}
/////////////////vykreslovanie vlhkosti///////////////////////
void drawHumidity(void)
{
u8g.setFont(u8g_font_fub17);
u8g.setFontRefHeightExtendedText();
u8g.setDefaultForegroundColor();
u8g.setFontPosTop();
u8g.drawStr(4, 0, "Vlhk. %");
u8g.drawFrame(4, 40, 122, 24);
u8g.drawBox(8, 44, (114 * hum / 100), 16); //obdlznik, ktory znazornuje percenta pomocou zaplnenia bielou
//
if (hum > 99)
{
u8g.setPrintPos(90, 15);
}
else
{
u8g.setPrintPos(100, 15);
}
u8g.print(hum);
}
void setup(void)
{
Serial.begin(9600);
pinMode(modePin,INPUT);
pinMode(relayButtonPin, INPUT);
pinMode(relayPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
digitalWrite(relayPin,HIGH); //na zaciatku je rele nezopnute, cize HIGH
}
void loop(void) {
relaySetup();
delay(1000); //delay na nacitanie hodnot zo senzora
int readData = myDHT.read11(DHTPIN);
temperature = myDHT.temperature;
hum = myDHT.humidity;
modeButtonSetup();
///////////////////////////////zobrazovanie//////////////////
if(currentStateMode == HIGH){
u8g.firstPage();
do {
drawTemperature();
} while( u8g.nextPage() );
}
else{
u8g.firstPage();
do {
drawHumidity();
} while( u8g.nextPage() );
}
}
Zdrojový kód: Médiá:lampaKod.ino
Výsledok
S výsledkom svojej práce som spokojný, najmä s tým nehmatateľným, čiže s rozšírením svojich schopností. Naučil som sa mnoho nových vecí, ktoré určite využijem v budúcnosti. Lampa splnila moje požiadavky, ktoré som si položil na začiatku, aby bola aspoň trochu "smart", spĺňala svoj účel a bola pekná aj z estetického hľadiska.
Návrhy na zlepšenie
- zväčšenie krabice, pretože dané komponenty sú v nej príliš natesno. Taktiež by mala byť vyššia aby sa tam zmestila aj väčšia žiarovka.
- pridanie viacerých senzorov, napr. zaznamenávanie CO2.
- zaťaženie lampy a pridanie gumových prúžkov na spodok aby sa tlačidlá lepšie stláčali a lampa "neutekala" po stole.