ESP8266 JSON Weather Display
This is my first attempt to receive data with an Arduino and the ESP8266 WiFi-Module. This program is based on the example by Seedstudio, and displays weather data on a small TFT display.
The JSON
The weather updates can be requested as JSON data from
http://api.openweathermap.org/data/2.5/weather?id=2925533
This was the result got from the website
1 |
{"coord":{"lon":8.68,"lat":50.12},"sys":{"message":0.0037,"country":"DE","sunrise":1420183442,"sunset":1420212885},"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"base":"cmc stations","main":{"temp":275.405,"temp_min":275.405,"temp_max":275.405,"pressure":1004.48,"sea_level":1039.53,"grnd_level":1004.48,"humidity":96},"wind":{"speed":6.69,"deg":239.001},"clouds":{"all":92},"rain":{"3h":4},"dt":1420188399,"id":2925533,"name":"Frankfurt am Main","cod":200} |
The Module
This Version has two LEDs, one for Power and another one which is connected to the TX-Pin. It runs at 3.3 Volt and the serial port is set to a data rate of 115200 baud. The CH_PD-Pin has to be high. After a reset, the module sends the following data:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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 |
Wiring
The wiring is quite simple. The wifi-module needs just two wires for power and two for the serial interface. As a display i used a 1.8″ (45.72 mm) TFT-display that is connected via SPI.
Arduino | ESP8266 Module | Display Module |
---|---|---|
3.3V | VCC & CH_PD | |
5V | VCC | |
GND | GND | GND & BKL |
0 (RX) | TX | |
1 (TX) | RX | |
8 | RESET | |
9 | RS | |
10 | LCD CS | |
11 | MOSI | |
13 | SLCK |
The Program
I changed the source code from Seedstudio a little bit, because at 115200 baud the 64 Byte uart-buffer from the Arduino fills up very fast. But overall the program is really simple.
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 |
#include <SoftwareSerial.h> #include <JsonParser.h> #define cs 10 // Pins for the display #define dc 9 #define rst 8 #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7735.h> // Hardware-specific library #include <SPI.h> Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst); using namespace ArduinoJson::Parser; #define SSID "<ssid>" // insert your SSID #define PASS "<password>" // insert your password #define LOCATIONID "2925533" // location id #define DST_IP "188.226.224.148" //api.openweathermap.org SoftwareSerial dbgSerial(2, 3); // RX, TX for debugging JsonParser<32> parser; void setup() { Serial.begin(115200); Serial.setTimeout(5000); dbgSerial.begin(9600); // for debuging 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"); // restet and test if module is redy 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"); // set to single connection mode } 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.0rnHost: api.openweathermap.orgrnrn"; 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; //timeout counter int n = 1; // char counter char json[100]="{"; while (!Serial.find(""main":{")){} // find the part we are interested in. 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; // from kelvin to degree celsius 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; } } |
Conclusion
The program is quite simple and could be extended with more features like a weather forecast. If you have any comments about the source code leave it down below.
Update: There was a bug in the code, which was found by Jody Roth. This is now fixed.
Source Code
The source of this document can be found here