Weather web monitor - Монитор погоды, который получает данные с сайта openweathermap.org и выводит на дисплей.
В промежутке времени с 23.00 до 7.00 автоматически выключает подсветку дисплея. В коде закоментированы строки, пока не нужные для использования на данном дисплее (16x2), так как не хватает место для вывода всей инфы. В будущем на мониторчике 20x4 будет выводится более подробная погода,а так же дата и время.
Что бы получать погоду с вашего города нужно в адресе изменить, в данном случае irkutsk поменять на moscow. Так же погоду можно забирать с yahoo weather или другого сервиса, который может выдавать данные в xml или другом простом формате.
Использованное оборудование:
- Arduino Uno R3
- Ethernet Shield W5100
- DS1307
- 16x2 дисплей
Скетч:
#include <Wire.h> #include <SPI.h> #include <Ethernet.h> #include <TextFinder.h> #include <LiquidCrystal_I2C.h> #include <EEPROM.h> #include "DS1307.h" //Массив, содержащий время компиляции char compileTime[] = __TIME__; //Массив, содержащий дату компиляции //char compileDate[] = __DATE__; DS1307 clock; LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); //Создание пользовательского значка градуса byte gradus[8] = { B00111, B00101, B00111, B00000, B00000, B00000, B00000, B00000}; byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xAD }; byte ip[] = { 192, 168, 0, 155 }; byte gateway[] = { 192, 168, 0, 1 }; byte subnet[] = { 255, 255, 255, 0 }; // Server openweathermap.org IPAddress server(162,243,58,21); EthernetClient client; TextFinder finder( client ); char place[50]; //char time[50]; void setup() { clock.begin(); lcd.begin (16, 2); lcd.createChar(1, gradus); // Start Ehternet Ethernet.begin(mac, ip); // Start Serial Port Serial.begin(9600); //Получаем часы, минуты, секунды byte hour = getInt(compileTime, 0); byte minute = getInt(compileTime, 3); byte second = getInt(compileTime, 6); /* //Получаем год, месяц и число int year = get4DigitInt(compileDate, 7); int day = getInt(compileDate, 4); int month; switch (compileDate[0] + compileDate[1] + compileDate[2]) { case 'J'+'a'+'n': month = 1; break; case 'F'+'e'+'b': month = 2; break; case 'M'+'a'+'r': month = 3; break; case 'A'+'p'+'r': month = 4; break; case 'M'+'a'+'y': month = 5; break; case 'J'+'u'+'n': month = 6; break; case 'J'+'u'+'l': month = 7; break; case 'A'+'u'+'g': month = 8; break; case 'S'+'e'+'p': month = 9; break; case 'O'+'c'+'t': month = 10; break; case 'N'+'o'+'v': month = 11; break; case 'D'+'e'+'c': month = 12; break; } char week[7][10] = { "1", "2", "3", "4", "5", "6", "7" }; */ //Импровизированный хэш времени //Содержит в себе количество секунд с начала дня unsigned int hash = hour * 60 * 60 + minute * 60 + second; //Проверяем несовпадение нового хэша с хэшем в EEPROM if (EEPROMReadInt(0) != hash) { //Сохраняем новый хэш EEPROMWriteInt(0, hash); //Готовим для записи в RTC часы, минуты, секунды, год, месяц, день clock.fillByHMS(hour, minute, second); //Вставляем часы, минуты, секунды //clock.fillByYMD(year, month, day); //Вставляем год, месяц, день // clock.fillDayOfWeek(String(week[weekday(month, day, year)]).toInt()); //Вставляем день недели //Записываем эти данные во внутреннюю память часов. //С этого момента они начинают считать нужное для нас время clock.setTime(); } } void loop() { //Получение времени clock.getTime(); int clo = clock.hour; // Если больше заданного значения времени (часов), то выключится подсветка дисплея if (clo > 22 || clo < 7 ) { lcd.noBacklight(); } else { lcd.backlight(); } if (client.connect(server, 80)) { // Call Wetter-API // w: ID from your City // http://api.openweathermap.org/data/2.5/weather?q=irkutsk&mode=xml&units=metric /// Serial.println("Connect to Yahoo Weather..."); client.println("GET /data/2.5/weather?q=irkutsk&mode=xml&units=metric HTTP/1.0"); client.println("HOST:api.openweathermap.org\n\n"); client.println(); Serial.println("Connected..."); Serial.print(clock.hour / 10); Serial.print(clock.hour % 10); Serial.print(":"); Serial.print(clock.minute / 10); Serial.print(clock.minute % 10); Serial.print(":"); Serial.print(clock.second / 10); Serial.print(clock.second % 10); Serial.print(" "); Serial.print(clock.dayOfMonth / 10); Serial.print(clock.dayOfMonth % 10); Serial.print("/"); Serial.print(clock.month / 10); Serial.print(clock.month % 10); Serial.print("/"); Serial.print(clock.year + 2000, DEC); Serial.print(" "); /* switch (clock.dayOfWeek) { case 1: Serial.print("MON"); break; case 2: Serial.print("TUE"); break; case 3: Serial.print("WED"); break; case 4: Serial.print("THU"); break; case 5: Serial.print("FRI"); break; case 6: Serial.print("SAT"); break; case 7: Serial.print("SUN"); break; } */ } else { lcd.clear(); lcd.print("connection failed"); // lcd.setCursor(0, 1); // lcd.print("Previous: "); // lcd.print("H="); // lcd.print(hum); // lcd.print("%"); Serial.println(" connection failed"); } if (client.connected()) { lcd.setCursor(14, 0); lcd.print(clock.minute / 10); lcd.print(clock.minute % 10); //lcd.clear(); // wind // Temperature if(finder.find("temperature value=") ) { int temperature = finder.getValue(); Serial.print("Temp C: "); Serial.println(temperature); lcd.setCursor(0, 0); lcd.print("T="); lcd.print(" "); lcd.setCursor(2, 0); lcd.print(temperature); lcd.write(1); lcd.print("C"); } else { lcd.setCursor(0, 0); lcd.print("T="); lcd.print(" "); lcd.setCursor(2, 0); lcd.print("---"); Serial.print("No Temperature Data"); } // Humidity if(finder.find("<humidity value=") ) { int humy = finder.getValue(); Serial.print("Humidity: "); Serial.println(humy); lcd.setCursor(8, 0); lcd.print("H="); lcd.print(" "); lcd.setCursor(10, 0); lcd.print(humy); lcd.print("%"); } else { lcd.setCursor(8, 0); lcd.print("H="); lcd.print(" "); lcd.setCursor(10, 0); lcd.print("---"); Serial.print("No Humidity Data"); } // pressure= if(finder.find("pressure value=") ) { int pres = finder.getValue(); pres = pres / 1.333; Serial.print("pressure=: "); Serial.println(pres); lcd.setCursor(0, 1); lcd.print("P="); lcd.print(pres); lcd.print("mm"); } else { lcd.setCursor(0, 1); lcd.print("P="); lcd.print(" "); lcd.setCursor(2, 1); lcd.print("---"); Serial.print("No pressure="); } //Поиск второго слова "speed" if(finder.find("speed value=") ) { int speed2 = finder.getValue(); //При желании выводить скорость ветра в метрах/секунду расскоментируйте строку ниже //speed2 = speed2 * 1000 / 3600; speed2 = speed2 * 3600 / 1000; Serial.print("speed: "); Serial.println(speed2); lcd.setCursor(8, 1); lcd.print("W="); lcd.print(" "); lcd.setCursor(10, 1); lcd.print(speed2); lcd.print("km/h"); } else { lcd.setCursor(8, 1); lcd.print("W="); lcd.print(" "); lcd.setCursor(10, 1); lcd.print("---"); Serial.print("No wind data"); } // END XML } else { Serial.println("Disconnected"); } client.stop(); client.flush(); //Время обновления данных с сервера delay(600000); } //Запись двухбайтового числа в память void EEPROMWriteInt(int address, int value) { EEPROM.write(address, lowByte(value)); EEPROM.write(address + 1, highByte(value)); } //Чтение числа из памяти unsigned int EEPROMReadInt(int address) { byte lowByte = EEPROM.read(address); byte highByte = EEPROM.read(address + 1); return (highByte << 8) | lowByte; } //Вычисление времени char getInt(const char* string, int startIndex) { return int(string[startIndex] - '0') * 10 + int(string[startIndex + 1]) - '0'; } /* //Вычисление года int get4DigitInt(const char* string, int startIndex) { return (string[startIndex ] - '0') * 1000 + (string[startIndex + 1] - '0') * 100 + (string[startIndex + 2] - '0') * 10 + (string[startIndex + 3] - '0'); } //Вычисление дня недели int weekday(int month, int day, int year) { int ix, tx, vx; switch (month) { case 2 : case 6 : vx = 0; break; case 8 : vx = 4; break; case 10 : vx = 8; break; case 9 : case 12 : vx = 12; break; case 3 : case 11 : vx = 16; break; case 1 : case 5 : vx = 20; break; case 4 : case 7 : vx = 24; break; } if (year > 1900) // 1900 was not a leap year year -= 1900; ix = ((year - 21) % 28) + vx + (month > 2); // take care of February tx = (ix + (ix / 4)) % 7 + day; // take care of leap year return (tx % 7); } */