by Floris Wouterlood – the Netherlands –
Introduction
The Internet of Things (IOT) is a wonderful place where devices can be accessed via internet connectivity and where all kinds of data exchange is possible. In this project I am exploiting the IOT to read on my smartphone data provided by a sensor located somewhere else in the world. There are many ways to make this possible. In this project an Arduino compatible BH1750 photosensor measures incident light. Values are processed by a microcontroller board carrying an ESP8266 chip: a Lolin NodeMCU ESP8266 (further abbreviated as NodeMCU). This device is particularly interesting because it is recognized and supported by the Arduino programming environment. Because of this sensors originally designed to be used with an Arduino can be used as well with a NodeMCU. Sensor data are transmitted by the NodeMCU via wifi to a router connected to the internet. A server at ThingSpeak (https://thingspeak.com) provides a timestamp and stores the data. Via a smartphone (or any computer, tablet) the internet server can be accessed, with a browser interface. The main web page at ThingSpoeak produces cool graphs. A separate page in the user interface allows data downloading, e.g., for import in a spreadsheet.
The BH1750 photometric light sensor
Light, in this project sunlight, is a form of electromagnetic energy. Light as it is perceived by the human eye can be measured with an appropriate device: a photometric sensor. The BH1750 is such a sensor available for the Arduino microcontroller programming environment. A treatise on photometry can be accessed at wikipedia (https://en.wikipedia.org/wiki/Photometry_(optics). In the ‘Bare Basics’ section of my website www.zonnepanelen.wouterlood.com a BH1750 is discussed, connected to an Arduino Nano. Measuring sunlight is important for me because it provides data correlated with the output of my solar panels. The latter data is private, the former is public. Sunshine is free for everyone, after all. A ‘Bare-Basics‘ application of the BH1750 with an Arduino microcontroller is available in the Bare Basics section of the Arduinohoekje
The NodeMCU ESP8266 microcontroller board
If a BH1750 is connected to an Arduino board the measured photometric data can be displayed on a computer via Serial Monitor and from here copy-pasted into a spreadsheet. Alternatively, some display (LCD, OLED, TFT) can be connected to the Arduino. When a memory card shield is stuck on the Arduino the data can be stored on the card for later import in a spreadsheet and processing. However it is attractive to have real time graphic display on a smartphone or tablet. This type of connectivity is possible via the IOT. A IOT solution discussed here is to use a microcontroller board with wifi capability that connects to the home wifi network. The NodeMCU is a very suitable and economic platform for this purpose. The attractiveness lies within the fact that this microcontroller board can be programmed via the Arduino IDE with familiar Arduino instructions.
The combination of a BH1750 photometric sensor and a NodeMCU microcontroller board is shown in Figure 1. The BH1750 uses the I2C protocol which means that the connection between sensor and microcontroller needs four wires: power (3.3V, GND, SCL and SDA). On an Arduino SCL is connected to pin A4 while the NodeMCU has pin D1 for this purpose. SDA on the Arduino is supported by pin A5 while on the NodeMCU this function is supported by pin D2. Note that the NodeMCU is a 3.3V device.
Figure 1. A BH1750 photometric sensor wired to a NodeMCU ESP8266 microcontroller board. Note that the sensor is actually smaller compared with the NodeMCU board than in this picture. With a short distance between the BH1750 and the NodeMCU board a 4.7 kΩ pullup resistor between SCL and 3.3V, and between SDA and 3.3V is sufficient to support flawless I2C transmssion.
As a photometric sensor needs light it is obvious to place this sensor in full sunlight. As I do not favor placing electronic equipment all day basking in sunlight I wanted to mount the NodeMCU in a sun protected spot at some distance from the sensor, at least in a shady position. Here I was challenced by the circumstance that I2C connectivity is designed for use over very short distances.
Figure 2: Wiring scheme of a BH1750 photometric sensor to a NodeMCU via a cat 5 twisted pair cable connection . Note the 10 kΩ pull up resistors at both end of the cable.
With some experimenting with several kinds of cable the best solution in the current situation was to bridge a distance of approximately 50 cm with category 5
twisted pair LAN cable. With such a length of cable it is necessary to apply 10 kΩ pullup resistors to the SDA and SCL lines at both ends of the cable. This is visible in the wiring (figure 2).
Electronic components needed
1x BH1750 sensor, 1x 70×30 soldering board, 1x 70×50 soldering board, NodeMCU ESP8266 microcontroller board, 4x 10 kΩ resistor, 50 cm cat 5 twisted pair network cable, red, black, green and yellow jumper wire, 1x 4-pin male pin header, 1x female 5-pin header,
Wiring
Figure 2 shows the wiring of the BH1750 to the NodeMCU board The photometric sensor sticks into a female pin header mounted on a 70×30 universal printed circuit board (PCB) that also contains the 10 kΩ pullup ‘sender end’ resistors attached to the SDA and SCL lines. On the board is another, five-pin male pin header that receives the wires from the cat 5 LAN cable. The assembled board is shown in figure 3.
Cat 5 LAN cables carry four (twisted) pairs of wires. Numbers and colors are listed in the table below. See also Figure 2.
wire number —- wire color ——————- Function
—- 1 ———— orange-white —————- GND
—- 2 ———— orange ———————– SDA
—- 3 ———— green-white —————- 3.3V
—- 4 ———— blue ————————– not used
—- 5 ———— blue-white ——————- not used
—- 6 ———— green ————————- not used
—- 7 ———— brown-white —————- SCL
—- 8 ———– brown———————— GND
The NodeMCU board sticks two parallel female 15-pin headers soldered on a 70×50 PCB. This is done as a replacement for the more luxurious ready-to-use, commercially available NodeMCU base. The same PCB is used to solder the 10 kΩ pullup resistors for the ‘receiver end’ SDA and SCL lines. Without these pullup resistors the I2C protocol will not reliably work and data will not be properly received by the NodeMCU board.
The board with the NodeMCU is mounted in a plastic box with an acrylic, transparent cover (see figure 3).
Figure 3: Final assembled components: center: box with the NodeMCU. From the box a cat5 LAN cable leads to the PCB with the sensor (shown apart in the inset on the right, enlarged).
Sketch
ThingSpeak is a service offered on the internet by MathWorks. According to its developers, “ThingSpeak is an open source IOT application with an AP (application programming interface), enabling the creation of sensor logging applications, location tracking applications, and a social network of things with status updates” (source: wikipedia – search for ThingSpeak). In order to use ThingSpeak, one has to register to obtain an API key / password combination. Next, channels can be named and configured at thingspeak.com to receive and display data. In this example, data are exported from the NodeMCU board to a channel at ThingSpeak named ‘Photometer’
The instructions in the sketch consist of three groups:
1. Connect via wifi to the local area network (SSID, password)
2. Identify the microcontroller to ThingSpeak (API ID, password)
3. Cycle through the routine of aquiring photometric data from the NH1750 sensor, and relaying every minute the value to the ThingSpeak server.
// photometer_nodemcu_01
// public domain
// LoLin nodeMCU v1.0 (black) with Arduino IDE
// stream data BH1750 photometer on ESP8266 ESP12-E (nodeMCU v1.0)
#include <ESP8266WiFi.h>
#include <Wire.h>
// ================== defines and variables ========================
#define myPeriodic 60 // in seconds – ThingSpeak pub is here every 60 sec
int BH1750_Device = 0x23; // I2C address for light sensor
unsigned int Lux, Scaled_FtCd;
float FtCd, Wattsm2;
const char* server = “api.thingspeak.com”;
String apiKey = “aaaaaaaaaaaa”; // subsitute with your API key
const char* MY_SSID = “bbbbbbb”; // subsitute with the SSID of your wifi network
const char* MY_PWD = “cccccccc”; // subsitute with the password of your wifi network
int sent = 0;
void setup() {
Wire.begin ();
Serial.begin (9600);
Wire.beginTransmission(BH1750_Device);
Wire.write (0x10); // set resolution to 1 Lux
Wire.endTransmission ();
delay (200);
connectWifi ();
}
void loop() {
//char buffer[10];
int i;
Lux = BH1750_Read();
FtCd = Lux/10.764;
Wattsm2 = Lux/683.0;
Serial.print (Lux,DEC);
Serial.println (“[lx]”);
Serial.print (FtCd,2);
Serial.println (“[FC]”);
Serial.print (Wattsm2,4);
Serial.println (“[Watts/m^2]”);
Serial.print (String(sent)+” BH1750: “);
Serial.println (Wattsm2,4);
sendWattsm2 (Wattsm2);
int count = myPeriodic;
while(count–)
delay(1000);
}
unsigned int BH1750_Read() {
unsigned int i=0;
Wire.beginTransmission (BH1750_Device);
Wire.requestFrom (BH1750_Device, 2);
while(Wire.available ())
{
i <<=8;
i|= Wire.read();
}
Wire.endTransmission ();
return i/1.2; // Convert to Lux
}
// ================== subroutines =====================================
void connectWifi()
{
Serial.print(“Connecting to “+*MY_SSID);
WiFi.begin(MY_SSID, MY_PWD);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(“.”);
}
Serial.println(“”);
Serial.println(“Connected”);
Serial.println(“”);
} //end connect
void sendWattsm2(float Wattsm2)
{
WiFiClient client;
if (client.connect(server, 80)) { // use ip 184.106.153.149 or api.thingspeak.com
Serial.println(“WiFi Client connected “);
String postStr = apiKey;
postStr += “&field1=”;
postStr += String(Wattsm2);
postStr += “\r\n\r\n”;
client.print(“POST /update HTTP/1.1\n”);
client.print(“Host: api.thingspeak.com\n”);
client.print(“Connection: close\n”);
client.print(“X-THINGSPEAKAPIKEY: ” + apiKey + “\n”);
client.print(“Content-Type: application/x-www-form-urlencoded\n”);
client.print(“Content-Length: “);
client.print(postStr.length());
client.print(“\n\n”);
client.print(postStr);
delay(1000);
}
sent++;
client.stop();
}
Results
After assembling the BH1750 and NodeMCU into a finished device I have now collected an uninterrupted data stream over a period of two months. Via my smartphone, tablet or desktop computer I can see in a private channel at the ThingSpeak website the actual photometric data in a moving graph, I can analyze data on line and I have the possibility to download data in comma delimited (csv) format whenever I want. usually I download every couple of days and store files on hard disk to be imported later in a spreadsheet. A sample spreadsheet graph of a very nice November day is presented in Figure 4. The ThingSpeak web interface allows to analyse data and to display data in different ways, e.g. in the plot visualization shown in Figure 4 as well. For comparison I have included in Figure 4 the graphis crepresentation fo the logfile produced by the logger that keeps track of the production of the photovoltaic panels on the roof of my home. Data points on this logger is one every hour. The solar panel production has a nice correlation (as expected) with the photometric data.
Figure 4: Plot visualization screen capture from ThingSpeak channel (upper) and graph composed after download and import in a spreadsheet of the data feed from the ThingSpeak server (lower). data 22 November 2017, time window between 10 AM and 8 PM. 22 November was a very sunny day, with only some clouds between noon and 1 PM. The graph indicating production of my solar panel installation is shown in the lower right (produced kilowatt hours per hour).
Discussion
The construction of a device that features a BH1750 exposed to full sunlight, with the NodeMCU protected in a box at some distance to avoid sunlight exposure works fine. In the actual situation the box with the NodeMCU is mounted in the space of a double window frame, that is, sandwiched between two glass windows. The wifi signal has to pass the acrylic box cover and the inside glass pane in order to connect to the wifi router which is situated one floow below. This works amazingly well, without problems.
With one transmission per minute to the ThingSpeak server, every 24h period will produce 1,440 data points. In one month, 1,440 x 31 = 44,640 data points will have been accumulated. One year of uninterrupted data collection will result in 525,600 data points. To prevent the accumulation of data to unmanageable amounts it is recommendable handy to download data regularly, say once avery two weeks, and to remove redundant data from the server. Another approach is to reduce the number of readings to, say, one transmission every five minutes. Such a reduction results in 288 data points per 24h period. A disadvantage of the latter ‘data saving’ could be that in a climate like that in the Netherlands where sunny days usually have some cloudy moments a measurement and transmission would occur on a moment when a cloud obscures sunshine. This would results in a kind of false negative reading. I am for this reason working on an improved sketch where every-minute photometric readings are averaged over a five-minute period and then transmitted to the ThingSpeak server.
Finally, although the output of the BH1750 sensor is measured in Watts per square meter units, these numbers must be considered as relative data. This decoiupling from absolute data is caused by the construction: in front of the sensor I had to place as set of grey filters to limit the amount of sunlight reaching the detector. The dynamic range of the BH1750 sensor is limited which means that filtering is necessary on sunny summer days to keep the sensor signal within the dynamic range. To obtain absolute values it is necessary to calibrate the sensor, preferably in the western Europe’s summer season. For my purposes this is relatively unimportant issue. It is the solar power production that counts, ultimately!
sketch: photometer_nodemcu_01.ino