WiFi Module
Remove the LCD Display module and button module. Take a cable and unwrap it. Plug one side into the WiFi socket and the other into any Digital socket.











Upload
Upload the following code. The example below uses the D8 digital pin.
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
#include "WiFiEsp.h"
#include <Wire.h>
#include "Seeed_BME280.h"
#include <math.h>
#include "Arduino.h"
#include "SI114X.h"
#include "SoftwareSerial.h"
//Create Serial communication Object
SoftwareSerial Serial1(8, 9); // RX, TX
//Create sensor objects
SI114X sunlightSensor;
BME280 bme280;
//title to use for your webpage
String title = "Your Weather Station";
//Weather variables
float temperature;
float humidity;
float pressure;
float uv;
//Wifi settings
char ssid[] = "Weather Node"; // your network SSID (name)
char pass[] = "password"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
int reqCount = 0; // number of requests received
//Wifi server object
WiFiEspServer server(80);
// use a ring buffer to increase speed and reduce memory allocation
RingBuffer buf(8);
void setup()
{
//Start Serial Communication with computer and WiFi module
Serial.begin(9600); // initialize serial for debugging
Serial1.begin(9600); // initialize serial for ESP module
WiFi.init(&Serial1); // initialize ESP module
//Start sunlight sensor commmunications
while (!sunlightSensor.Begin()) {
Serial.println("Sunlight Error");
delay(1000);
}
//Start BME280 communications
if (!bme280.init()) {
Serial.println("BME Error");
}
//Print out debugging messages
Serial.print("Attempting to start AP ");
Serial.println(ssid);
// start access point
status = WiFi.beginAP(ssid);
//Print out more debugging info
Serial.println("Access point started");
printWifiStatus();
// start the web server on port 80
server.begin();
Serial.println("Server started");
}
void loop()
{
//Get temperature
temperature = bme280.getTemperature();
//convert to F from C
temperature = temperature * 1.8 + 32;
//Get humidity
humidity = bme280.getHumidity();
//Get pressure
pressure = bme280.getPressure();
//Get uv value and convert to UV Index values
uv = (float)sunlightSensor.ReadUV() / 100;
//Wait for a device to connect to the WiFi
WiFiEspClient client = server.available(); // listen for incoming clients
// if you get a client,
if (client) {
// print a message out the serial port
Serial.println("New client");
// initialize the circular buffer
buf.init();
// loop while the client's connected
while (client.connected()) {
// if there's bytes to read from the client,
if (client.available()) {
// read a byte, then
char c = client.read();
// push it to the ring buffer
buf.push(c);
// you got two newline characters in a row
// that's the end of the HTTP request, so send a response
if (buf.endsWith("\r\n\r\n")) {
sendHttpResponse(client);
break;
}
}
}
// give the web browser time to receive the data
delay(10);
// close the connection
client.stop();
Serial.println("Client disconnected");
}
}
void sendHttpResponse(WiFiEspClient client)
{
client.print(
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
// the connection will be closed after completion of the response
"Connection: close\r\n"
// refresh the page automatically every 20 sec
"Refresh: 20\r\n"
"\r\n");
client.print(
"<!DOCTYPE HTML>\r\n"
"<html>\r\n"
"<head>\r\n"
"<style>\r\n"
"</style>\r\n"
"</head>\r\n"
"<body>\r\n"
"<h1>" + title + "</h1>\r\n"
"<br>\r\n");
// Print # of requests received
client.print("Requests received: ");
client.print(++reqCount);
client.print("<p id=\"date\"></p>"
"<script>"
"document.getElementById(\"date\").innerHTML = 'Date: ' + Date();"
"</script>"
"<p><br>\r\n");
// Print temperature
client.print("Temperature: ");
client.print(temperature);
client.print("F"
"<br>\r\n"
"Humidity: ");
client.print(humidity);
client.print("%"
"<br>\r\n"
"Air Pressure: ");
client.print(pressure);
client.print("Pa"
"<br>\r\n"
"UV Index: ");
client.print(uv);
client.print("<br>\r\n"
"</body>\r\n"
"</html>\r\n");
}
void printWifiStatus()
{
// print your WiFi IP address
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print where to go in the browser
Serial.println();
Serial.print("To see this page in action, connect to ");
Serial.print(ssid);
Serial.print(" and open a browser to http://");
Serial.println(ip);
Serial.println();
}
Observe
To make sure we have everything set up correctly, open up the Serial Monitor. The WiFi module needs to initialize. After that, an IP will show up and we'll need that for the next step. In my case the IP address is
192.168.4.1
. Go over to your WiFi settings on any device with a web browser, and connect to "Weather Node". The password is "password". Once connected, head over to a web browser and type in that IP address. You'll be taken to a page that displays the current weather data from your weather station.
Modify
You can change the
ssid[]
to change the name of the WiFi network and the
pass[]
to any password you'd like. You can change the
title
variable to what you'd like your weather station to be called on the webpage.
Experiment
Check out the HTML and CSS page to learn more about customizing your Weather Station webpage.
Connecting to WiFi
If you'd like to upload your weather data to the internet and be able to monitor it remotely then start here to connect your WiFi module to a WiFi network.
Upload
Upload the following code.
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
#include "WiFiEsp.h"
#include "SoftwareSerial.h"
//Creates serial communication object
SoftwareSerial Serial1(8, 9); // RX, TX
void setup() {
// initialize serial for debugging
Serial.begin(9600);
// initialize serial for ESP module
Serial1.begin(9600);
// initialize ESP module
WiFi.init(&Serial1);
// Print WiFi MAC address
printMacAddress();
}
void loop()
{
// scan for existing networks
Serial.println();
Serial.println("Scanning available networks...");
//function to scan for wifi networks
listNetworks();
//Wait 10 seconds before scanning agian
delay(10000);
}
void printMacAddress()
{
// get your MAC address
byte mac[6];
//This is a unique hardware address for the wifi module
WiFi.macAddress(mac);
// print MAC address
char buf[20];
//replaces %02X with a MAC address byte
sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]);
Serial.print("MAC address: ");
Serial.println(buf);
}
void listNetworks()
{
// scan for nearby networks
int numSsid = WiFi.scanNetworks();
//This runs when there isn't a wifi connection
if (numSsid == -1) {
Serial.println("Couldn't get a WiFi connection");
//The Arduino will stay in this loop forever if it can't get a connection
while (true);
}
// print the list of networks seen
Serial.print("Number of available networks:");
Serial.println(numSsid);
// print the network number and name for each network found
for (int thisNet = 0; thisNet < numSsid; thisNet++) {
//Print the network number
Serial.print(thisNet);
Serial.print(") ");
//Print network name
Serial.print(WiFi.SSID(thisNet));
//Print out the signal strength
Serial.print("\tSignal: ");
Serial.print(WiFi.RSSI(thisNet));
Serial.print(" dBm");
//Print password type
Serial.print("\tEncryption: ");
printEncryptionType(WiFi.encryptionType(thisNet));
}
}
void printEncryptionType(int thisType) {
// read the encryption type and print out the name
switch (thisType) {
case ENC_TYPE_WEP:
Serial.print("WEP");
break;
case ENC_TYPE_WPA_PSK:
Serial.print("WPA_PSK");
break;
case ENC_TYPE_WPA2_PSK:
Serial.print("WPA2_PSK");
break;
case ENC_TYPE_WPA_WPA2_PSK:
Serial.print("WPA_WPA2_PSK");
break;
case ENC_TYPE_NONE:
Serial.print("None");
break;
}
Serial.println();
}
Observe
Open up the Serial Monitor and wait for the WiFi module to scan. It will print out a list of all the possible WiFi networks it can connect to. You should see the name of your normal WiFi network.
Modify
Before uploading this next bit of code, swap out ssid with your WiFi network's name and pass with its password.
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
/*
WiFiEsp example: UdpNTPClient
Get the time from a Network Time Protocol (NTP) time server.
Demonstrates use of UDP to send and receive data packets
For more on NTP time servers and the messages needed to communicate with them,
see http://en.wikipedia.org/wiki/Network_Time_Protocol
*/
#include "WiFiEsp.h"
#include "WiFiEspUdp.h"
#include "SoftwareSerial.h"
//Create channel for communication to wifi module
SoftwareSerial Serial1(8, 9); // RX, TX
//Wifi settings
char ssid[] = "YOURWIFINETOWRK"; // your network SSID (name)
char pass[] = "YOURPASSWORD"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
//Location of the time server
char timeServer[] = "time.nist.gov"; // NTP server
unsigned int localPort = 2390; // local port to listen for UDP packets
//Communication settings
const int NTP_PACKET_SIZE = 48; // NTP timestamp is in the first 48 bytes of the message
const int UDP_TIMEOUT = 2000; // timeout in miliseconds to wait for an UDP packet to arrive
byte packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing packets
// A UDP instance to let us send and receive packets over UDP
WiFiEspUDP Udp;
void setup()
{
// initialize serial for debugging
Serial.begin(9600);
// initialize serial for ESP module
Serial1.begin(9600);
// initialize ESP module
WiFi.init(&Serial1);
// attempt to connect to WiFi network
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network
status = WiFi.begin(ssid, pass);
}
// you're connected now, so print out the data
Serial.println("You're connected to the network");
//Open the communication port
Udp.begin(localPort);
}
void loop()
{
// send an NTP packet to a time server
sendNTPpacket(timeServer);
// wait for a reply for UDP_TIMEOUT miliseconds
unsigned long startMs = millis();
while (!Udp.available() && (millis() - startMs) < UDP_TIMEOUT) {
}
//Print out the information received
Serial.println(Udp.parsePacket());
//If packet is sent from the time server
if (Udp.parsePacket()) {
Serial.println("packet received");
// We've received a packet, read the data from it into the buffer
Udp.read(packetBuffer, NTP_PACKET_SIZE);
// the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, esxtract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
Serial.print("Seconds since Jan 1 1900 = ");
Serial.println(secsSince1900);
// now convert NTP time into everyday time:
Serial.print("Unix time = ");
// Unix time starts on Jan 1 1970, which is 70 years after NTP time starts.
// Seventy years is 2208988800 seconds after we add in the extra days for the leap years.
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears;
// print Unix time:
Serial.println(epoch);
// print the hour, minute and second:
Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
Serial.print(':');
if (((epoch % 3600) / 60) < 10) {
// In the first 10 minutes of each hour, we'll want a leading '0'
Serial.print('0');
}
Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
Serial.print(':');
if ((epoch % 60) < 10) {
// In the first 10 seconds of each minute, we'll want a leading '0'
Serial.print('0');
}
Serial.println(epoch % 60); // print the second
}
// wait ten seconds before asking for the time again
delay(10000);
}
// send an NTP request to the time server at the given address
void sendNTPpacket(char *ntpSrv)
{
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(ntpSrv, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
Observe Again
Open up the Serial Monitor and check it out. You should connect to your WiFi network then you'll see reports with the time in the UNIX standard. If it doesn't connect make sure your ssid and pass are correct.
Wunderground
Wunderground is a weather reporting service that supports the use of personal weather stations or PWS. We'll be using that PWS service as the endpoint for our weather data. We'll need to register an account, create our PWS, then push data to it.
Register
Head over to this link to sign up for a Wunderground account. Once joined, head over to this link to create your personal weather station name and details. You'll need to type in your location so the service know where you are reporting the weather. Hit Verify Location on the bottom to go to the next page. There are two required fields on this page. Neighborhood is the name of your weather station so name it something descriptive to your area. The other field is Station Hardware. Since we build our weather stations, scroll down that list and select other. Once finished with the settings, press Submit to get your ID and KEY that we need for the next section. The information on the next page is what we'll put into the Arduino sketch so keep it open. If you ever need to find your ID and KEY again just navigate here.
Upload
Copy the code below but before uploading your code, replace the WID and WKEY with your ID and KEY from Wunderground. Also change ssid[] and pass[] to your WiFi network name and password so we can send data. After doing both of those changes, upload the code.
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
#include "WiFiEsp.h"
#include <Wire.h>
#include "Seeed_BME280.h"
#include <math.h>
#include "Arduino.h"
#include "SI114X.h"
#include "SoftwareSerial.h"
//Defines for Wunderground variables
#define WID "WUNDERGROUND_ID"
#define WKEY "WUNDERGOUND_KEY"
#define getPayload "/weatherstation/updateweatherstation.php?ID=" WID "&PASSWORD=" WKEY "&dateutc=now&tempf=%s&humidity=%s&baromin=%s&UV=%s&action=updateraw"
//Create serial communication object
SoftwareSerial Serial1(8, 9); // RX, TX
//Wifi settings
char ssid[] = "YOURWIFINETOWRK"; // your network SSID (name)
char pass[] = "YOURPASSWORD"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
//Server URL for later
char server[] = "weatherstation.wunderground.com";
//Storage for getPayload
char buf[200];
// Initialize the Ethernet client object
WiFiEspClient client;
// Construct sensor objects
SI114X sunlightSensor;
BME280 bme280;
// Variables for weather measurements
float temperature;
float humidity;
float pressure;
float uv;
// Letter version of the variables from above
char cTemp[8];
char cHum[8];
char cPress[8];
char cUv[8];
// Variable to hold time
unsigned long previousMillis = 0;
// Milliseconds to wait between updates.
const long interval = 2 * 60 * 1000L;
void setup() {
// Initialize serial for debugging
Serial.begin(9600);
// Initialize serial for ESP module
Serial1.begin(9600);
// Initialize ESP module
WiFi.init(&Serial1);
// Initialize sunlight sensor
while (!sunlightSensor.Begin()) {
Serial.println("Sunlight Error");
delay(1000);
}
// Initialize BME280 sensor
if (!bme280.init()) {
Serial.println("BME Error");
}
// Attempt to connect to WiFi network
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network
status = WiFi.begin(ssid, pass);
}
// You're connected now, so print out the data
Serial.println("You're connected to the network");
// Print out all info about wifi connection
printWifiStatus();
// Run updateWeather function
updateWeather();
// Run sendData function
sendData();
}
void loop() {
// Store the current time
unsigned long currentMillis = millis();
// Check to see if enough time has passed
if (currentMillis - previousMillis >= interval) {
// Save the last time data was sent
previousMillis = currentMillis;
// Run updateWeather function
updateWeather();
// Run sendData function
sendData();
}
// While there is a connection to the server
while (client.available()) {
// Store the response
char c = client.read();
// And print it to the serial console
Serial.write(c);
}
// If the server's disconnected, stop the client:
if (!client.connected()) {
// Prints debugging messages
//Serial.println();
//Serial.println("disconnecting from server.");
// Disconnect the server
client.flush();
client.stop();
}
}
void updateWeather() {
// Read temp and convert to F
temperature = bme280.getTemperature();
temperature = temperature * 1.8 + 32;
// Read humidity
humidity = bme280.getHumidity();
// Read Pressure and convert to inches of water
pressure = bme280.getPressure() * 0.00040146;
// Read UV and convert to UV Index range
uv = (float)sunlightSensor.ReadUV() / 100;
}
void sendData() {
// Convert float numbers to char arrays
dtostrf(temperature, 4, 2, cTemp);
dtostrf(humidity, 4, 2, cHum);
dtostrf(pressure, 4, 2, cPress);
dtostrf(uv, 4, 2, cUv);
// Try and send the data
if (client.connect(server, 80)) {
// Make a HTTP request:
sprintf(buf, getPayload, cTemp, cHum, cPress, cUv);
client.println(String("GET ") + buf + String(" HTTP/1.1"));
//Serial.println(String("GET ") + buf + String(" HTTP/1.1"));
client.println("Host: weatherstation.wunderground.com");
client.println("Connection: close");
client.println();
}
}
void printWifiStatus()
{
// Print the SSID of the network you're attached to
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// Print your WiFi shield's IP address
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// Print the received signal strength
long rssi = WiFi.RSSI();
Serial.print("Signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
Observe
Open up the Serial Monitor and you'll see a couple of steps. The first is the initialization of the WiFi module. Then the connection to your local WiFi network. Once, you're online the weather station will attempt to send weather data to Wunderground. Assuming your ID and Key are correct you'll see a success message and within a few minutes you can visit your PWS page to see your weather data.