
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);
}
*/