Arduino WiFi-Connected Weather Station With Android User Interface - CodeProject
Arduino WiFi-Connected Weather Station With Android User Interface - CodeProject
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
articles
Q&A
forums
Sign in
lounge
Searchforarticles,questions,tips
CPOL
Rate this:
5.00 52 votes
Build a cheap, under 30, Weather Station Sensor Node with the help of an Arduino board, and use WiFi connection to control it
with any Android device.
1/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
a voltmeter for the 5V power supply it is fairly easy because the ATmega 328 but also ATmega 168 and some other
MCU comes with a builtin voltmeter voltage sensor, which has a relatively low accurracy if not calibrated, but provides
valuable information with no additional costs;
the amount of free RAM for the Arduino MCU mainly used for debugging reasons, it provides useful information for
later improvements. Same as for the voltmeter, no additional hardware is required, and it only costs a few MCU cycles
with respect to MCU usage;
compute the average temperature and humidity this is done in the software, and provides useful information for the
weather station user.
Disclaimer: working with electricity is dangerous. For this project we use 5V and 3.3V voltage levels, which is safe for the human
body under any environment conditions. However, the low voltage is obtained from a mains connected power brick, and
therefore we highly recommend you to take safety precautions and to use a trustful brand for the power supply. We cannot be
held responsible for any caused damage! Do it at your own risk and/or ask help from an electronics engineer.
Hardware configuration
The hardware components required for this project are presented below. These components were mostly bought from eBay and
Amazon, and the listed prices include postage costs within Germany for some also in the EU. If you are willing to wait between
two and five weeks to receive the items, you can also buy them from China online shops Aliexpress, eBay, and so on, for less
than half of the prices we show further.
Hardware Component
Estimative Price
Description
3 5 EUR
We use a clone, but it has the same functionality as the original device.
While the quality of the original Arduino Pro Mini is higher, so it is the price
two to four times higher.
6 8 EUR
Most of these modules have a 4Mb 512KB flash memory, allowing to use
AT firmware version below 1.1.0 released on June 2015. New modules are
now available, and the SPI flash IC was updated to an 8Mb 1MB one,
allowing them to use the latest AT firmware, which provides more and
improved AT commands. We strongly recommend to use an ESP8266
module with 1MB flash and latest AT firmware.
1 3 EUR
4 6 EUR
35 EUR
A common cathode GND in our case LED is a good choice for the DUO
LED. Two separate LEDs of any size and color may be used as long as they
require less than 2025mA and have a forward voltage less than 5V
supplied by the Arduino I/O pins.
A 5% variation is allowed for the regulated power brick. Notice that cheap
and low quality power supplies are not recommended since often they
have a bad regulation and usually out of the 5% error range, so it may
produce damage to the other components or even put your live in danger.
A power brick with a higher Ampere value can be used, but usually these
are more expensive. In addition, one can use an USB port as power supply
for our device, that is able to supply 500mA or more current USB ports of
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
2/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
5V@1A(5%)
RegulatedPowerSupply
GR N
8
13
12
A0
A1
A2
A3
V C C R ST
G N D R AW
R eset
M ini
Arduino P ro
C 106
5
G N D R ST
G N D V C C R X I TX O
11
10
R X I TX O
C1
100nF
Temperature:
4080C,0.5C
Humidity:
0100%,2%
C 106
B LK
WiFiLED
50
55
60
50
55
60
G H
G H
45
45
40
R6
3.3k
R3
10k
35
R5
560
35
R4
560
30
25
20
15
10
R2
560
5.0V
HV
C han2
LV
LV
C han1
G N D R X O TX I
40
30
25
20
15
10
C2
1F
A B C D E
R X O LV
A B C D E
TX I
H V G N D R X I TX O
HV
TX O R X I
330
R1
R7
3.3k
3.3V
Figure 1: The Complete Breadboard Design for the Weather Station Hardware.
The hardware is divided in a few blocks:
the power supply: Arduino Pro Mini board needs 512V obtained from a 5V@1A power brick, but the ESP8266 WiFi
module requires 3.3V regulated voltage which we obtain by using a stepdown linear regulator.
the sensor node controller: the Arduino Pro Mini board represents the controller board, which runs all the logic for this
project;
an WiFi communication module: we have used the cheap and easy to use ESP8266 module for the WiFi communication
between the sensor node and the Android device;
the sensor(s): temperature and humidity values are obtained from a DHT22 sensor;
logic level voltage converter: allows a voltage safe Serial/UART communication between the Arduino board which uses 5V
signals and the ESP8266 module which requires 3.3V signals;
WiFi status LEDs: a DUO, common cathode green/red LED, is used to visually indicate the WiFi state.
Note: many of the breadboards we are aware of, does not have a default connection between the GND lines for the two power
grids, therefore you need to add a connection wire between the two GND lines, as shown in Figure 1. Also, some breadboards
have every power grid splited in two halfs, so you have to use a jumper wire if this is the case.
For the breadboard schematic, red wires were used for +5V, orange for 3.3V and black for GND connections. For
communication lines, we use green and blue for RX/TX lines, and yellow for data pin of DHT22 sensor. In Figure 2, we show the
full electronics schematic, of our weather station sensor node.
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
3/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
C1
100nF
10
R2
560
G H
5.0V
10
C2
1F
A B C D E
330
R1
3.3V
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
4/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
LM317T
5V
3
ADJ
C1
100nF
Voltage OUT
Regulator
Variable
5.0V
IN
C2
1F
3.3V
R1
330
R2
560
5/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
resistors. Normally, a 10K resistor can be used, but we observed periodical resets of our WiFi module we tested a few of
them. Using test and trial method, we found that the 3.3K resistor works the best for all our ESP8266 modules.
Note: the ESP826601 module is shown in the schematic, since this was available as Fritzing component, but actually in the real
board we use an ESP826602 module. This should make no difference, and and in general we should be able to use any version
of these modules. There are about thirteen versions of ESP8266 modules, which differes in form, size and available I/O, but all
have the same WiFi functionality.
DHT22 Sensor
The DHT22 sensor allows to obtain temperature readings in the range [40,80]C with a typical accuracy of 0.5C and
a resolutin of 0.1units(C). However, in real tests, the accuracy we could observe is closer to 1C. The sensor can also
read humidity values in the range [0,100]%, with a typical accuracy of 2units(%) and a resolution of 0.1units.
In our real tests, the accuracy was about 5%.
The DHT22 sensor can be connected to either 3.3V line or to 5V line, and we decided to use the 5V line. The data pin of the
sensor check the datasheet for more details is connected to 5V rail via one 10K resistor, to avoid communication errors this
line must stay HIGH when the sensor does not communicate via the data pin. The sensor data pin is connected to digital pin 9
of the Arduino board.
TX
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
6/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
VCC
GND
Connects to
First TX LV
First RX LV
First TX HV
First RX HV
Second TX LV
Second RX LV
Second TX HV
Second RX HV
LV GND
HV GND
LV
HV
Connects to
RX
TX
RESET
CH_PD
GND
VCC
LM317 IC Pin
Connects to
Input
Output
3.3V rail
Adj
Software Configuration
The Arduino Code
The Arduino code can be written, compiled and deployed to the Arduino board by either using Fritzing or the Arduino IDE this
may be preferred in some cases, because it usually works out of the box. For our project, the following Arduino libraries are
needed:
ArduinoESP8266, used for the UART communication between the ESP8266 module and the Arduino board. Clone the
library repository, rename the folder to ESP8266 and copy it to libraries subfolder, part of the Arduino Software
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
7/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
installation folder.
DHTLib, used for the communication with the DHT22 sensor. This library supports DHT11 sensors as well, in case you use
it as a replacement for DHT22. Clone the library repository, rename it to DHT and copy it to libraries subfolder, part of
the Arduino Software installation folder.
An Arduino program also known as sketch has the following minimal structure:
Hide Copy Code
//1.constantsdefinition(optionalifnoconstantisneeded)
//2.includeheadersforusedlibraries(optionalifnolibraryisused)
//3.definetheglobalvariables(optionalifnoglobalvariableisrequired)
//programinitialization
voidsetup(){
//writeherethesetupcode.
}
//infiniteloopcycle
voidloop(){
//thecodefromthismethodloopsaslongastheArduinoboardispowered.
}
In the setup method we write initialization code, which is executed only once, when the Arduino is powered or after a
software or hardware reset. The loop method contains the code which loops in the Arduino MCU as long as the board receives
power.
//ArduinopinnumberusedforthecommunicationwithDHT22sensor.
#defineDHT22_PIN9
//pinsnumberforWiFidisabledLED
#defineWIFI_DISABLED_LED_PIN7
//pinsnumberforWiFienabled/activeLED
#defineWIFI_ACTIVE_LED_PIN8
//arduinopinusedtoconnecttotheCH_PD(PowerDown)WiFimodulepin
#defineWIFI_CH_PD_PIN2
//arduinopinusedtoconnecttotheRESETWiFimodulepin
#defineWIFI_RESET_PIN3
Pin 9 is used for data communication with the DHT22 sensor, pins 7 and 8 are used for the red and green LEDs WiFi status
LEDs, pin 2 allows to put the WiFi into a sleep mode and to wake it up and pin 3 allows us perform a hardware reset of the
WiFi module, which requires to pull it down set pin to LOW for at least 200ms.
#include<dht.h>
#include<ESP8266.h>
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
8/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
When using this directive, <> tells to the compiler and linker to look in the libraries subfolder of the Arduino IDE installation,
while using double quotes means the library files are in the your arduino skecth folder.
//DHT22sensorcontrollerclass
dhtDHT;
//ESP8266WiFimodulecontroller
ESP8266esp(Serial);
//storetheaveragetemperatureandhumidity
//values,startingwithlastsystemreset
floatavgTemperature=0;
floatavgHumidity=0;
//utilityvariableusedtocomputetheaveratetemperaturevalue
unsignedlongavgDhtStep=1;
//datatemplateforsensors
constcharSENSORS_DATA_TEMPLATE[]PROGMEM=
"{\"temperature\":%s,\"avgTemperature\":%s,\"humidity\":%s,\"avgHumidity\":%s,
\"voltage\":%s,\"freeRam\":%d}";
The dht22 variable represents an instance of the library which controls the communication with the DHT22 sensor. The esp
variable represents an instance of the ESP8266 library used to communicate with the WiFi module. As parameter for the
constructor we provide the Serial object, so the communication is made on the UART0 port of the Arduino board. When
using Arduino Pro Mini also Nano or UNO board, this is the only serial port available. However, the library is designed to work
with all the Arduino boards, and some of them have up to four UART ports, accessed via Serial, Serial1, Serial2 and
Serial3 global objects.
Since we like to know the average temperature and humidity values measured by our Weather Station, we define the
avgTemperature, avgHumidity and avgDhtStep variables. The first two are used to store the average temperature
and humidity values, while the latter is used to count how many time the temperature value was read, so the correct average
value can be computed according with the formula: avg=(avg*(n1)+newValue)/n;
The SENSORS_DATA_TEMPLATE variable stores the template JSON structure used to communicate with the Android
application. The special PROGMEM variable modifier enforces the storage of the value in the flash memory instead of RAM, thus
freeing up about 120Bytes of RAM about 6% of the total RAM of the ATmega328P MCU, used by the Arduino Pro Mini, Nano
and UNO boards.
Copy Code
voidsetupWiFi(){
//STEP1:
//SetpinsusedforWiFistatusLEDsasOUTPUT.
pinMode(WIFI_ACTIVE_LED_PIN,OUTPUT);
pinMode(WIFI_DISABLED_LED_PIN,OUTPUT);
//STEP2:
//ArduinopinconnectedtoESP8266CH_PDpinissettoOUTPUT.
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
9/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
//Tokeepthemoduleactive,thispinmustbekeptHIGH.
pinMode(WIFI_CH_PD_PIN,OUTPUT);
digitalWrite(WIFI_CH_PD_PIN,HIGH);
//ArduinopinconnectedtoESP8266RESETpinissettoOUTPUT.
//Toavoidrandomresents,wekeepthisHIGH.
pinMode(WIFI_RESET_PIN,OUTPUT);
digitalWrite(WIFI_RESET_PIN,HIGH);
//STEP3:
//performahardwarereset(ESP8266RESETpingoesLOW)
digitalWrite(WIFI_RESET_PIN,LOW);
delay(200);
//allowESP8266moduletoboot
digitalWrite(WIFI_RESET_PIN,HIGH);
//STEP4:
//baud115200,communicationwithESP8266module
Serial.begin(115200);
//STEP5:
//waitfortheESP8266moduletostart,aftertheforcedhardwarereset.
//Wecheckthewifistateonceasecond,untiltheESP8266WiFimoduleresponds.
while(!checkWiFi()){
delay(1000);
};
//STEP6:
//startUDPconnectionwaitonallports
esp.atCipstartUdp();
}
The WiFi module related initialization requires the following steps:
1. The Arduino pins used for the WiFi status LEDs i.e., defined by the WIFI_ACTIVE_LED_PIN and
WIFI_DISABLED_LED_PIN constants are set to output.
2. The Arduino pins used to control the CH_PD and RESET lines of the ESP8266 module i.e., defined by the
WIFI_CH_PD_PIN and WIFI_RESET_PINconstants are set to OUTPUT, so we can set them LOW or HIGH
depending on the case. These two pins needs to stay HIGH during the normal operation.
3. Perform a hardware reset by pulling down the WiFi module RESET pin set it LOW for about 200ms.
4. Start UART/Serial communication with the module at 115200 baud rate.
5. Wait for the WiFi module to boot, which takes two seconds or more.
6. Start UDP communications, and wait for incomming data on all the ports. We could have used only one specific port, but
we like to be flexible.
UDP communication is used for the WiFi data transmission between the Android device and our Weather Station sensor node.
The checkWiFi method used to check if the WiFi module is in active state communicates via UART lines is shown below:
Hide Copy Code
booleancheckWiFi(){
if(esp.at()==ESP8266::Error::NONE){
digitalWrite(WIFI_DISABLED_LED_PIN,LOW);
digitalWrite(WIFI_ACTIVE_LED_PIN,HIGH);
returntrue;
}else{
digitalWrite(WIFI_ACTIVE_LED_PIN,LOW);
digitalWrite(WIFI_DISABLED_LED_PIN,HIGH);
returnfalse;
}
}
This method returns true if the ESP8266 module responds to AT command, and false otherwise. The AT command is used
to check if the module is active, and it does not represents a real command for the module. In addition, the checkWiFi
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
10/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
method enables or disables the red/green LED, providing visual indication of the current WiFi state.
Since the WiFi setup must run only once, when the hardware powers up, we call the setupWiFi module inside the Arduino
specific setup method:
Hide Copy Code
voidsetup(){
//setupWiFiESP8266module
setupWiFi();
//addothercodehere...
}
voidupdateDHTData(){
if(dht22.read22(DHT22_PIN)==DHTLIB_OK){
avgTemperature=(avgTemperature*(avgDhtStep1)+dht22.temperature)/(float)avgDhtStep;
avgHumidity=(avgHumidity*(avgDhtStep1)+dht22.humidity)/(float)avgDhtStep;
}
}
The latest temperature and humidity values are available by reading the temperature and humidity properties of the
dht22 object. The read22 method is used to perform a reading when DHT22 sensor is used, but instead, one can use
read11 to get the same effect when the DHT11 sensor is used. The method returns DHTLIB_OK when the reading was
successful, and various error codes if problems were encountered. For simplicity reasons, we ignore the possible errors, but in a
further tutorial we discuss also how to solve such possible problems.
Reading 5V Supply Voltage Value by Using the Secret Builtin Arduino Voltmeter
Some ATmega MCUs, such as ATmega328/168p have a builtin voltage sensor, which can be accessed by the code. This sensor
is not very accurate accuracy is within 10% range. It uses the builtin 1.1V voltage reference available for these MCUs some
other ATmega MCUs also have a 2.56V internal voltage reference. The following code allows to read the AVcc line voltage,
which by default is connected to VCC line of the Arduino board:
Hide Copy Code
floatgetVcc(){
longresult;
//read1.1VreferenceagainstAVcc
ADMUX=_BV(REFS0)|_BV(MUX3)|_BV(MUX2)|_BV(MUX1);
//waitforVreftosettle
delay(2);
//convert
ADCSRA|=_BV(ADSC);
while(bit_is_set(ADCSRA,ADSC));
result=ADCL;
result|=ADCH<<8;
//BackcalculateAVccinmV
result=1103700L/result;
//returnresponseinvolts
returnresult/1000.0;
}
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
11/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
While this looks complicated, it actually uses a few MCU registers and some bits operations to read the VCC value agains the
builtin 1.1V voltage reference, which has a pretty good stability once calibrated. By using a good quality multimeter and a stable
voltage source, it is possible to "software calibrate" the internal voltage reference for individual MCUs when needed.
voidloop(){
chardata[10]={0},*ipdData=data;
//IncommingdatafromESP8266module
//Lengtmustbegreaterthan7bytes("+IPD,n:")
if(Serial.available()>7&&esp.ipd(ipdData)==ESP8266::Error::NONE){
//processtherequest
processRequest(ipdData);
}
//asmalldelaybeforecheckingagaindforWiFiincommingdata
delay(25);
}
The ipd method, part of the ESP8266 library is used to split the received data over WiFi, and retain only the important parts.
The WiFi module sends data in the following format: +IPD,n,id:ipdData, where n is the length of the ipdData, id is
the communication link ID an integer between 0 and 4, and ipdData represents the relevant data bytes. The first parameter
of the ipd method is a reference parameter, a pointer to the received databytes. This method has additional optional
parameters, providing information about the number of databytes and the connection id. Further, a method named
processRequest is used to decode the data and perform required actions.
Since we expect data in the +IPD,n: format, the link id is not used, it makes sense to process data only after receiving at
least 7 bytes. In addition, for this simple project, we expect only a single databyte, representing the data update request. In a
further version of this project we like to support much more commands, therefore we use this generic form. Also, for the same
reasons, we define an enumeration which defines the list of the available commands:
Hide Copy Code
enumclassCommand{
GET_ALL_SENSORS_DATA=97
};
The data we receive via TX line of the ESP8266 module so RX line of our Arduino board is: +IPD,1:a. The ascii
representation for 97 the Command::GET_ALL_SENSORS_DATA enumeration literal is the char a.
The processRequest method code is shown below:
Hide Copy Code
voidprocessRequest(char*data){
charprogmemData[150]={0};
char*pData=progmemData;
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
12/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
//firstcharrepresentsthecommand
charcmd=*(data);
switch((Command)cmd){
caseCommand::GET_ALL_SENSORS_DATA:
createSensorsDataFromTemplate(pData);
esp.atCipsend(pData);
break;
default:
//nothingtodo...
break;
}
}
Its main purpose is to decode the received command and to respond with the required data. As discussed earlier, we only have
one command, so also only one action case, but this will be extended, so we use the general structure even for this simplest
case. The relevant code regards the call to createSensorsDataFromTemplate method. It uses the JSON based data
template, replaces the placeholders with real data and send the response to the Android device by calling atCipsend
method, part of the ESP8266 library.
Hide Copy Code
voidcreateSensorsDataFromTemplate(char*&data){
charbuffTemp[7]={0},buffAvgTemp[7]={0},buffAvgHum[7]={0},
buffHum[7]={0},buffVcc[5]={0},tmpl[140]={0};
char*pTmpl=tmpl;
uint8_ttemplateLen=1;
//readtemplatefromPROGMEM
getPMData(SENSORS_DATA_TEMPLATE,pTmpl,templateLen);
//createdatastringfromtemplatebyreplacing
//parameterswiththeiractualvaluesfromsensors
sprintf(data,pTmpl,
dtostrf(dht22.temperature,6,1,buffTemp),
dtostrf(avgTemperature,6,1,buffAvgTemp),
dtostrf(dht22.humidity,6,1,buffHum),
dtostrf(avgHumidity,6,1,buffAvgHum),
dtostrf(getVcc(),4,2,buffVcc),
getFreeMCUMemory());
}
Using the getPMData utility method also part of the ESP8266 library, the data template string is read from the flash memory.
Replacing the parameters with real values is made by using the standard sprintf method. While for a fully fledged C/C++
environment one will use %x.yf syntax with sprintf for floating points numbers, this will not work with Arduino code.
Instead we use dtostrf to format the temperature and humidity values we like values with just one digit after the decimal
point.
13/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
In addition, you have to disconnect the ESP8266 TX line during the Arduino programming time, otherwise this operation fails.
Since we have to do this on every code update, a jumper or a switch can be used to make task easier.
<usespermissionandroid:name="android.permission.ACCESS_WIFI_STATE"/>
<usespermissionandroid:name="android.permission.INTERNET"/>
In addition, we like to disable the autolock feature of the Android device, as long as this application is active, which requires to
set the following permission:
Hide Copy Code
<usespermissionandroid:name="android.permission.WAKE_LOCK"/>
The same AndroidManifest.xml file defines the Android OS version required to run this application. We have tested this
application with Android 4.3.1 API 18 and 4.4.2 API 19 and 5.0.1 API 21. Therefore it is safe to set the miminum require
version to API 18 by using the following parameter:
Hide Copy Code
<usessdkandroid:minSdkVersion="18"android:targetSdkVersion="21"/>
While this application may run on Android OS older than 4.3.1 API 18, our tests with Android 2.3.3 API 10 failed.
<ScrollViewxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true">
<TableLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/main">
<TableRowandroid:layout_width="fill_parent"
android:layout_height="wrap_content">
<!tablerowcontent>
</TableRow>
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
14/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
<!moretablerows...>
</TableLayout>
</ScrollView>
For example, the row used to show the current temperature value is shown below:
Hide Copy Code
<TableRowandroid:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextViewandroid:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Temperature:"
android:id="@+id/temperatureLabel"/>
<TextViewandroid:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="N/A°C"
android:id="@+id/temperatureValueTextView"/>
</TableRow>
Each UI element has an android:id attribute, with an unique value, used to access the UI element from the Android Java
code. The result user interface is shown in Figure 5.
15/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
We use an Android activity to implement our class. This is the simplest way to create an Android application, specially this is
your first Android application.
Hide Copy Code
publicclassMainActivityextendsActivity{
//...herecomeallthepropertiesandmethods...
}
For the UDP communication with the Weather Station sensor node we use Java DatagramSocket, and initialize it for port
1024 other ports, starting with 1025, can be used as well. This code should execute before trying to send any UDP packet over
the network. In this scenario, we request sensor data from the Weather Station node, once every 10 seconds. Feel free to modify
it to another value if you like:
Hide Shrink
Copy Code
publicclassMainActivityextendsActivity{
intudpPort=1025;
DatagramSocketsocket;
//otherproperties....
@Override
publicvoidonCreate(BundlesavedInstanceState){
//herearesomeotherinitializations
(newThread(newRunnable(){
@Override
publicvoidrun(){
try{
socket=newDatagramSocket(udpPort);
while(true){
if(appInBackground)continue;
try{
sendUdpData(Commands.GET_ALL_SENSORS_DATA,null);
Thread.sleep(10000);
}catch(Exceptione){
e.printStackTrace();
}
}
}catch(Exceptione){
e.printStackTrace();
}
}
})).start();
}
}
An anonymous Java thread is used to request periodical data updates. The 10 seconds delay is obtained by using the
Thread.sleep static method, and the data update request is performed by the sendUdpData method.
Hide Copy Code
voidsendUdpData(Commandscmd,byte[]params){
try{
finalDatagramPacketpacket;
intparamsLength=(params!=null?params.length:0);
bytedata[]=newbyte[paramsLength+1];
bytecommand[]=newbyte[1];
command[0]=cmd.getValue();
System.arraycopy(command,0,data,0,command.length);
if(params!=null)System.arraycopy(params,0,data,1,params.length);
packet=newDatagramPacket(data,data.length,getBroadcastAddress(),udpPort);
socket.send(packet);
}catch(IOExceptione){
e.printStackTrace();
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
16/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
}
}
The sendUdpData method takes two parameters: the command to send and its optional parameters. Remember, for the
Arduino code, an enumeration was used to define all the available commands well, just one command for now, but this will
change later. Now, the same applies for the Android application: using a Java enumeration, we define the
GET_ALL_SENSORS_DATA command with the same command code, 97 this is what the Arduino application expects.
Hide Copy Code
enumCommands{
GET_ALL_SENSORS_DATA((byte)97);
privatefinalbyteid;
Commands(byteid){this.id=id;}
publicbytegetValue(){returnid;}
}
Further, a DatagramPacket is created, and the command and when is the case, the command parameters too is provided
as an array of bytes as required by the DatagramPacket constructor. The UDP packet is then sent to the Weather Station
sensor node. In response, the sensor node provides a JSON object containing the sensor data required to update the user
interface. Since the UDP communication is asynchronous we don't know how long it takes for the request to reach the sensor
node and how long it takes until a response is received, a thread is used to continuously listen for incoming UDP packets.
Hide Shrink
Copy Code
publicvoidonCreate(BundlesavedInstanceState){
(newThread(newRunnable(){
@Override
publicvoidrun(){
while(true){
DatagramPacketudpPacket=receiveUdpData(udpPort);
if(udpPacket==null)continue;
StringudpPacketData=newString(udpPacket.getData());
try{
JSONObjectjsonObj=newJSONObject(udpPacketData);
updateUserInterface(jsonObj);
}catch(JSONExceptione){
e.printStackTrace();
}
}
}
})).start();
}
DatagramPacketreceiveUdpData(intport){
try{
byte[]data=newbyte[1024];
DatagramPacketpacket=newDatagramPacket(data,data.length);
if(socket==null)returnnull;
socket.receive(packet);
returnpacket;
}catch(IOExceptione){
e.printStackTrace();
returnnull;
}
}
The received UDP data stream of bytes is converted to a JSON object and passed to updateUserInterface method
which is responsible to extract the sensor values and show them in the user interface. We show only the code which deals with
the temperature value, but the same applies also for humidity, voltage, and the other values see the full source code.
Hide Copy Code
voidupdateUserInterface(finalJSONObjectjsonObj){
try{
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
17/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
finaldoubletemperature=jsonObj.getDouble("temperature");
temperatureValueTextView.post(newRunnable(){
publicvoidrun(){
temperatureValueTextView.setText(String.valueOf(temperature)+"°C");
}
});
}catch(JSONExceptione){
e.printStackTrace();
}
}
Due to Android API restrictions, a UI component object can be modified only by the thread who created it. In our case, main
application thread is the one which creates the GUI component objects, while the updateUserInterface is invoked by
the thread which listen for UDP data. In such case, the post method can be used, thus being able to update the sensor values
in the user interface components. Getting reference to the user interface components is made by using the corresponding
implementation class e.g. TextView and invoking the findViewById method, as shown below.
Hide Copy Code
publicclassMainActivityextendsActivity{
//someotherproperties...
TextViewsensorsDataReceivedTimeTextView;
publicvoidonCreate(BundlesavedInstanceState){
sensorsDataReceivedTimeTextView=(TextView)findViewById(R.id.sensorsDataReceivedTimeTextView);
}
//someothermethods...
}
One special requirement in our application is to provide a "disable autosleep feature" for the Android device, as long as the
application runs. This means, the device screen stays on as long as the application is active. To obtain this behavior, we use the
addFlags method of the window object inherited from the Activity super class, and provide the corresponding
parameter. In our case, these parameters are defined as literalos of the WindowManager.LayoutParams enumeration.
Hide Copy Code
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Remember, this requires to enable the android.permission.WAKE_LOCK permission, by editing the
AndroidManifest.xml file as shows earlier on this tutorial.
Further improvements
We can extend our project by considering the following improvements:
SMS alerts by using a GSM module costs about 15. We can receiveSMS alerts on a mobile phone if some measured
parameters are not in the predefined limits. For example, if the temperature goes below 0C, we like to receive an SMS,
because this may indicate an issue with the home heating system.
Improve the code by considering various problematic cases:
WiFi module does not respond check the module periodically and perform a hardware reset when needed.
DHT22 sensor errors provide a robust code which alert us if the temperature and humidity sensor becomes
unstable or is damaged.
Use the Arduino EEPROM memory to store configuration parameters.
Improve the hardware design so it allows to be battery powered. This includes to replace our linear voltage regulator for
the 3.3V line with a more power consumption efficient one a switch mode based one.
Allow to use solar energy to charge the batteries for Weather Station nodes specially for the ones used outside, under
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
18/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
direct sunlight.
Add soil moisture sensors, providing indication about the right moment to water our plants.
Add a light intensity sensor, providing a better way to create statistics related to temperature values with respect to day
and night. Altough this can be done in the Android software, it requires to have your phone connected with the node for
most of the time, which is general is not the case.
Add a real time clock RTC for our node, further improving the various statistics about measured environment
characteristics.
Stay tuned! All these improvements are discussed in our further tutorials.
License
This article, along with any associated source code and files, is licensed under The Code Project Open License CPOL
Share
EMAIL
Mircea Diaconescu
Instructor / Trainer
Germany
Researcher, developer, WoT/IoT enthusiast
Cofounder of http://webengineering.info.
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
Go
First Prev Next
31Mar16 18:54
Re: My vote of 5
Mircea Diaconescu
20/22
4/2/2016
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
My vote of 5
csharpbd 31Mar16 11:40
Doubt regarding CH_PD and RESET pins of the ESP8266...
Member 12426909 30Mar16 13:23
Re: Doubt regarding CH_PD and RESET pins of the ESP8266...
Mircea Diaconescu 30Mar16 22:14
Re: Doubt regarding CH_PD and RESET pins of the ESP8266...
Member AndroidF 31Mar16 6:47
My vote of 5
raddevus 10Mar16 8:01
Re: My vote of 5
Mircea Diaconescu
10Mar16 8:08
My vote of 5
D V L 9Mar16 7:17
Re: My vote of 5
Mircea Diaconescu
good
NIHS das
9Mar16 22:21
25Feb16 21:48
Nice project
Christian Hack
24Feb16 2:21
24Feb16 2:28
24Feb16 2:47
My vote of 5
AJSON 20Feb16 11:45
Re: My vote of 5
Mircea Diaconescu
22Feb16 0:14
19Feb16 7:18
Refresh
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
1 2 Next
21/22
4/2/2016
General
ArduinoWiFiConnectedWeatherStationwithAndroidUserInterfaceCodeProject
News
Suggestion
Question
Bug
Answer
Joke
Praise
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160329.1 | Last Updated 31 Mar 2016
Select Language
Layout: fixed | fluid
http://www.codeproject.com/Articles/1079298/ArduinoWiFiConnectedWeatherStationwithAndroi
22/22