Arduino Nano ESP32‘den bahsettiğim yazı dizisinin önceki bölümünde Arduino’nun ESP32 platformu üzerine kurulu yeni Nano serisi kartının temel kodlama örneklerinden bahsetmiştim.
Bu bölümde de Arduino Nano ESP32 ile yaptığım hava durumu / saat projesini paylaşıyorum.
Project: WeaClock
WiFi desteğine sahip olması sayesinde ESP32 her zaman IoT projelerinin merkezinde yer aldı. Internete bağlanarak NTP altyapısı üzerinden saat ve tarihi alan uygulamalar en popüler olanları oldu.
Internette API adı verilen bağlantı arabirimleri üzerinden sunulan veriler arttıkça insanlar bu verileri ESP32’ler ile evlerine taşımaya başladı. Bunların en temellerinden biri de her gün ihtiyacımız olan hava durumu verileri.
Arduino Nano ESP32 ile yaptığım IoT projem iki temel internet verisini birleştiriyor: NTP üzerinden saat ve tarih, OpenWeatherMap üzerinden ise yerel hava durumu.
WeaClock adını verdiğim bu küçük proje, kolay anlaşılabilmesi için ekran olarak yaygın kullanılan SSD1306 128×64 I2C ekran kullanıyor.
WeaClock kodu OpenWeatherMap API’si üzerinden aldığı yerel hava durumu verisini işlemek için Arduino_JSON kütüphanesini kullanıyor. Edindiği verileri OLED ekranda görüntülemek için ise son zamanlarda kullanıp çok memnun kaldığım U8G2 kütüphanesini kullanıyor.
Proje Kodu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
#include <Wire.h> #include <U8g2lib.h> // https://github.com/olikraus/u8g2 #include <WiFi.h> #include <time.h> #include <HTTPClient.h> #include <Arduino_JSON.h> // https://github.com/arduino-libraries/Arduino_JSON const char* ssid = "*****"; // WiFi SSID (Görünen ad) const char* parola = "*****"; // WiFi Parola String openWeatherMapApiKey = "*****"; // OpenWeatherMap API Key String city = "Istanbul"; // Bulunduğunuz şehir String countryCode = "TR"; // Bulunduğunuz ülkenin iki harf kodu static const unsigned char logo[] PROGMEM = { 0x00, 0x0F, 0xE0, 0x01, 0x3C, 0x00, 0x80, 0x1F, 0xF0, 0x03, 0x7E, 0x00, 0x80, 0x19, 0x30, 0x03, 0x66, 0x00, 0x80, 0x19, 0x30, 0x03, 0x66, 0x00, 0xC0, 0x3F, 0xF8, 0x07, 0xFF, 0x00, 0xE0, 0x7F, 0xFC, 0x8F, 0xFF, 0x01, 0x60, 0x60, 0x0C, 0x8C, 0x81, 0x01, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, 0x00, 0x00, 0x00, 0x30, 0xC3, 0x98, 0x3F, 0x7E, 0xFE, 0x30, 0xC3, 0x98, 0x3F, 0x7E, 0xFE, 0x30, 0xC3, 0x9D, 0x01, 0x18, 0x06, 0x30, 0xC3, 0x9D, 0x01, 0x18, 0x06, 0x30, 0xC3, 0x9F, 0x01, 0x18, 0x06, 0x30, 0xC3, 0x9A, 0x1F, 0x18, 0x7E, 0x30, 0xC3, 0x9A, 0x1F, 0x18, 0x7E, 0x30, 0xC3, 0x9A, 0x01, 0x18, 0x06, 0x30, 0xC3, 0x98, 0x01, 0x18, 0x06, 0x30, 0xC3, 0x98, 0x01, 0x18, 0x06, 0x30, 0xC3, 0x98, 0x3F, 0x18, 0xFE, 0x30, 0xC3, 0x98, 0x3F, 0x18, 0xFE, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x30, 0xC3, 0x18, 0x1F, 0x3E, 0x38, 0x30, 0xC3, 0x18, 0x1F, 0x3E, 0x38, 0x30, 0xC3, 0x98, 0x31, 0x63, 0x7C, 0x30, 0xC3, 0x98, 0x31, 0x63, 0xC6, 0x30, 0xC3, 0x98, 0x31, 0x03, 0xC6, 0x30, 0xC3, 0x9F, 0x31, 0x03, 0xC6, 0x30, 0xC3, 0x9F, 0x31, 0x03, 0xC6, 0x30, 0xC3, 0x9F, 0x31, 0x03, 0xFE, 0x30, 0xC3, 0x98, 0x31, 0x03, 0xFE, 0x30, 0xC3, 0x98, 0x31, 0x63, 0xC6, 0x30, 0xC3, 0x98, 0x31, 0x63, 0xC6, 0x30, 0xC3, 0x18, 0x1F, 0x3E, 0xC6, 0x30, 0xC3, 0x18, 0x1F, 0x3E, 0xC6, 0x30, 0x07, 0x00, 0x00, 0x00, 0x00, 0x38, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x60, 0x60, 0x0C, 0x8C, 0x81, 0x01, 0xE0, 0x7F, 0xFC, 0x8F, 0xFF, 0x01, 0xC0, 0x3F, 0xF8, 0x07, 0xFF, 0x00, 0x80, 0x19, 0x30, 0x03, 0x66, 0x00, 0x80, 0x19, 0x30, 0x03, 0x66, 0x00, 0x80, 0x1F, 0xF0, 0x03, 0x7E, 0x00, 0x00, 0x0F, 0xE0, 0x01, 0x3C, 0x00 }; const char* projectName = "NANO ESP32 WEACLOCK"; const char* WIFI_CONNECT = "WiFi BAĞLANIYOR..."; // WiFi Connecting const char* WIFI_CONNECTED = "WiFi BAĞLANDI!"; // WiFi Connected const char* TIME_FAIL = "ZAMAN ALINAMADI!!"; // Couldn't Get Time const char* DAYS[7] = {"PAZ", "PTS", "SAL", "CAR", "PER", "CUM", "CTS"}; //const char* DAYS[7] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"}; bool nokta = true; char saat[10]; String jsonBuffer; U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE); void setup() { u8g2.begin(); u8g2.setFont(u8g2_font_6x12_me); u8g2.setFontMode(1); u8g2.setDrawColor(1); u8g2.setFontPosTop(); u8g2.setContrast(255); u8g2.clearBuffer(); u8g2.drawXBMP(41, 0, 46, 48, logo); u8g2.drawUTF8(((128 - (u8g2.getUTF8Width(projectName))) / 2), 55, projectName); u8g2.sendBuffer(); delay(2000); u8g2.clearBuffer(); u8g2.drawUTF8(((128 - (u8g2.getUTF8Width(WIFI_CONNECT))) / 2), 30, WIFI_CONNECT); u8g2.sendBuffer(); WiFi.begin(ssid, parola); while (WiFi.status() != WL_CONNECTED) delay(500); u8g2.clearBuffer(); u8g2.drawUTF8(((128 - (u8g2.getUTF8Width(WIFI_CONNECTED))) / 2), 30, WIFI_CONNECTED); u8g2.sendBuffer(); delay(1000); u8g2.clearBuffer(); configTime(10800, 0, "tr.pool.ntp.org"); } void loop() { gosterSaat(); delay(1000); gosterSaat(); delay(1000); gosterSaat(); delay(1000); gosterSaat(); delay(1000); gosterSaat(); delay(1000); gosterSaat(); delay(1000); gosterSaat(); delay(1000); gosterSaat(); delay(1000); gosterSaat(); delay(1000); gosterSaat(); delay(1000); gosterHava(); delay(10000); } void gosterSaat() { struct tm timeinfo; if(!getLocalTime(&timeinfo)){ u8g2.drawUTF8(((128 - (u8g2.getUTF8Width(TIME_FAIL))) / 2), 30, TIME_FAIL); u8g2.sendBuffer(); return; } char tarih[12]; strftime(tarih, 12, "%d.%m", &timeinfo); if (nokta == true) { saat[10]; strftime(saat, 10, "%H:%M", &timeinfo); nokta = false; } else { saat[10]; strftime(saat, 10, "%H %M", &timeinfo); nokta = true; } u8g2.clearBuffer(); u8g2.setFont(u8g2_font_inb33_mn); u8g2.drawUTF8(((127 - (u8g2.getUTF8Width(saat))) / 2), 0, saat); u8g2.setFont(u8g2_font_inb16_mf); u8g2.drawUTF8(0, 44, tarih); u8g2.drawUTF8(((128 - (u8g2.getUTF8Width(DAYS[timeinfo.tm_wday])))), 44, DAYS[timeinfo.tm_wday]); u8g2.sendBuffer(); } void gosterHava() { String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "," + countryCode + "&APPID=" + openWeatherMapApiKey; jsonBuffer = httpGETRequest(serverPath.c_str()); JSONVar myObject = JSON.parse(jsonBuffer); double sicaklik = myObject["main"]["temp"]; sicaklik = sicaklik - 273.15; char sicak[10]; dtoa(sicaklik, sicak, 1); double nem = myObject["main"]["humidity"]; char nm[10]; dtoa(nem, nm, 0); double bas = myObject["main"]["pressure"]; char basinc[10]; dtoa(bas, basinc, 0); u8g2.clearBuffer(); u8g2.setFont(u8g2_font_inb27_mf); u8g2.drawUTF8(0, 0, sicak); u8g2.setFont(u8g2_font_inb19_mf); u8g2.drawUTF8(((127 - (u8g2.getUTF8Width("°C")))), 8, "°C"); u8g2.setFont(u8g2_font_inb16_mf); u8g2.drawUTF8(0, 44, basinc); u8g2.setFont(u8g2_font_6x12_me); u8g2.drawUTF8(56, 53, "hPa"); u8g2.drawUTF8(((100 - (u8g2.getUTF8Width("%")))), 53, "%"); u8g2.setFont(u8g2_font_inb16_mf); u8g2.drawUTF8(((128 - (u8g2.getUTF8Width(nm)))), 44, nm); u8g2.sendBuffer(); } String httpGETRequest(const char* serverName) { WiFiClient client; HTTPClient http; http.begin(client, serverName); int httpResponseCode = http.GET(); String payload = "{}"; if (httpResponseCode>0) payload = http.getString(); http.end(); return payload; } char* dtoa(double dN, char *cMJA, int iP) { char *ret = cMJA; long lP=1; byte bW=iP; while (bW>0) { lP=lP*10; bW--; } long lL = long(dN); double dD=(dN-double(lL))* double(lP); if (dN>=0) { dD=(dD + 0.5); } else { dD=(dD-0.5); } long lR=abs(long(dD)); lL=abs(lL); if (lR==lP) { lL=lL+1; lR=0; } if ((dN<0) & ((lR+lL)>0)) { *cMJA++ = '-'; } ltoa(lL, cMJA, 10); if (iP>0) { while (*cMJA != '\0') { cMJA++; } *cMJA++ = '.'; lP=10; while (iP>1) { if (lR< lP) { *cMJA='0'; cMJA++; } lP=lP*10; iP--; } ltoa(lR, cMJA, 10); } return ret; } |
Yukarıdaki kodu çalıştırabilmek için;
- SSD1306 çipli 128×64 OLED ekranı I2C0 üzerinden Nano ESP32’ye bağlamanız,
- Eksik kütüphaneleri Arduino IDE’nin Kütüphane Yöneticisi üzerinden yüklemeniz,
- Kod içindeki WiFi SSID ve WiFi Parola bölümlrini doldurmanız,
- OpenWeatherMap sitesine üye olarak alacağınız API Key bölümlerini doldurmanız gerekiyor.
Sıradaki bölümde Arduino Nano ESP32’nin bootloader yapısı ve diğer inceliklerinden bahsedeceğim.