Погодная станция на основе Arduino и Wi-Fi модуля ESP8266

Недавно вышедший на рынок Wi-Fi модуль ESP8266 вызвал небольшой ажиотаж в обществе радиолюбителей благодаря своей дешевизне. Впрочем, поскольку данный чип является новинкой, информации о его использовании пока не так много.

https://alashed-media.s3.eu-north-1.amazonaws.com/wiki/digitrode/186-pogodnaya-stanciya-na-osnove-arduino-i-wi-fi-modulya-esp8266/images/pogodnaya-stanciya-na-osnove-arduino-i-wi-fi-modulya-esp8266-1.jpg

Но в сети все же стали появляться проекты с применением данного модуля, информация о которых упрощает работу с ESP8266. Одним из таких проектов стала погодная станция, которая отображает погоду на ЖК-дисплее. Соединение с сетью Wi-Fi осуществляется с помощью ESP8266.

Модуль

В данном случае применяется модуль ESP8266ex WI07c, который имеет два светодиода для индикации питания и вывода TX. Он работает с напряжением 3.3 В, а скорость передачи данных по последовательному порту составляет 115200 бод. Вывод CH_PD должен находиться в высоком логическом состоянии.

https://alashed-media.s3.eu-north-1.amazonaws.com/wiki/digitrode/186-pogodnaya-stanciya-na-osnove-arduino-i-wi-fi-modulya-esp8266/images/pogodnaya-stanciya-na-osnove-arduino-i-wi-fi-modulya-esp8266-2.png

После сброса модуль отправляет следующие данные:

AT+RST
OK

 ets Jan  8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x40100000, len 24236, room 16
tail 12
chksum 0xb7
ho 0 tail 12 room 4
load 0x3ffe8000, len 3008, room 12
tail 4
chksum 0x2c
load 0x3ffe8bc0, len 4816, room 4
tail 12
chksum 0x46
csum 0x46

ready

Соединение

Соединение платы Arduino Uno с Wi-Fi модулем и дисплеем весьма простое. Модулю нужны два провода для питания и два провода для последовательного порта. TFT-дисплей 1.8 дюйма соединяется по шине SPI.

https://alashed-media.s3.eu-north-1.amazonaws.com/wiki/digitrode/186-pogodnaya-stanciya-na-osnove-arduino-i-wi-fi-modulya-esp8266/images/pogodnaya-stanciya-na-osnove-arduino-i-wi-fi-modulya-esp8266-3.png https://alashed-media.s3.eu-north-1.amazonaws.com/wiki/digitrode/186-pogodnaya-stanciya-na-osnove-arduino-i-wi-fi-modulya-esp8266/images/pogodnaya-stanciya-na-osnove-arduino-i-wi-fi-modulya-esp8266-4.jpg

Программа

Код проекта довольно простой:

#include <SoftwareSerial.h>
#include <JsonParser.h>

#define cs   10  // Выводы на дисплей
#define dc   9
#define rst  8

#include <Adafruit_GFX.h>    // Графическая библиотека
#include <Adafruit_ST7735.h> // Аппаратная библиотека
#include <SPI.h>

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);

using namespace ArduinoJson::Parser;

#define SSID "<ssid>" // введите ваш SSID
#define PASS "<password>" // введите ваш пароль
#define LOCATIONID "2925533" // id местоположения
#define DST_IP "188.226.224.148" //api.openweathermap.org
SoftwareSerial dbgSerial(2, 3); // RX, TX для отладки
JsonParser<32> parser;

void setup()
{
  Serial.begin(115200);
  Serial.setTimeout(5000);
  dbgSerial.begin(9600); // для отладки
  dbgSerial.println("Init");
  tft.initR(INITR_BLACKTAB);
  tft.setRotation(1);
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(2, 2);
  tft.setTextColor(ST7735_WHITE);
  Serial.println("AT+RST"); // сброс и проверка, если модуль готов
  delay(1000);
  if(Serial.find("ready")) {
    dbgSerial.println("WiFi - Module is ready");
    tft.println("WiFi - Module is ready");
  }else{
    dbgSerial.println("Module dosn't respond.");
    tft.println("Module dosn't respond.");
    tft.println("Please reset.");
    while(1);
  }
  delay(1000);
  // try to connect to wifi
  boolean connected=false;
  for(int i=0;i<5;i++){
    if(connectWiFi()){
      connected = true;
      tft.println("Connected to WiFi...");
      break;
    }
  }
  if (!connected){
    tft.println("Coudn't connect to WiFi.");
    while(1);
  }
  delay(5000);
  Serial.println("AT+CIPMUX=0"); // установка в режим одиночного соединения
}
void loop()
{
  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += DST_IP;
  cmd += "\",80";
  Serial.println(cmd);
  dbgSerial.println(cmd);
  if(Serial.find("Error")) return;
  cmd = "GET /data/2.5/weather?id=";
  cmd += LOCATIONID;
  cmd += " HTTP/1.0\r\nHost: api.openweathermap.org\r\n\r\n";
  Serial.print("AT+CIPSEND=");
  Serial.println(cmd.length());
  if(Serial.find(">")){
    dbgSerial.print(">");
  }else{
    Serial.println("AT+CIPCLOSE");
    dbgSerial.println("connection timeout");
    tft.fillScreen(ST7735_BLACK);
    tft.setCursor(2, 2);
    tft.setTextColor(ST7735_WHITE);
    tft.println("connection timeout");
    delay(1000);
    return;
  }
  Serial.print(cmd);
  unsigned int i = 0; //счетчик времени
  int n = 1; // счетчик символов
  char json[100]="{";
  while (!Serial.find("\"main\":{")){}
  while (i<60000) {
    if(Serial.available()) {
      char c = Serial.read();
      json[n]=c;
      if(c=='}') break;
      n++;
      i=0;
    }
    i++;
  }
  dbgSerial.println(json);
  JsonObject root = parser.parse(json);
  double temp = root["temp"];
  double pressure = root["pressure"];
  double humidity = root["humidity"];
  temp -= 273.15; // Перевод градусов кельвины-цельсии
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(2, 25);
  tft.setTextColor(ST7735_BLUE);
  tft.setTextSize(2);
  tft.print("Temp: ");
  tft.print((int)temp);
  tft.print(".");
  tft.print((int)((temp-(int)temp)*10));
  tft.println(" C");
  tft.setCursor(2, 55);
  tft.setTextColor(ST7735_GREEN);
  tft.setTextSize(2);
  tft.print("Press: ");
  tft.print((int)pressure);
  tft.setCursor(2, 85);
  tft.setTextColor(ST7735_YELLOW);
  tft.setTextSize(2);
  tft.print("Humidity: ");
  tft.print((int)humidity);
  tft.println("%");
  dbgSerial.println(temp);
  dbgSerial.println(pressure);
  dbgSerial.println(humidity);
  dbgSerial.println("====");
  delay(600000);
}

boolean connectWiFi()
{
  Serial.println("AT+CWMODE=1");
  String cmd="AT+CWJAP=\"";
  cmd+=SSID;
  cmd+="\",\"";
  cmd+=PASS;
  cmd+="\"";
  dbgSerial.println(cmd);
  Serial.println(cmd);
  delay(2000);
  if(Serial.find("OK")){
    dbgSerial.println("OK, Connected to WiFi.");
    return true;
  }else{
    dbgSerial.println("Can not connect to the WiFi.");
    return false;
  }
}