Cold frame monitoring with an ESP8266 WebServer

In this post I will describe a monitor for a Coldframe (that is sort of a small unheated greenhouse).

It has the following functions/uses the following sensors:

  • A HTU21D to measure humidity and temperature inside the coldframe. The HTU21D is a very stable easy to use sensor….but after it has been exposed to 100% humidity for a while, it starts to behave funny, it may give you readings of over 100% or even negative readings. Not sure if this will leave longterm damage but I understand it can be ‘cured’ by  putting it in a 120 degree celsius oven for about an hour.
  • Four DS18B20’s to check temperature in the soil, the air outside the coldframe, the electronics as well as a reservoir.
  • A soil moisture sensor, consisting of  2 carbon rods (those are resistant against electrolysis). Though I could have used the A0 pin of the ESP8266 I am using, I found that one to be unreliable, so I am using a PCF8591 ADC for that. The PCF8591 is a reltively slow 8 bit ADC, but it suffices for the goal. If you want a fast one, consider the ADS1015.
  • A BH1750 to measure the incoming light.
  • A leaf wetness sensor (actually it is cheap chinese webshop ‘rainsensor‘). When used upside down it measures condensation, which is a measure for leaf wetness. I use the pcf8591 ADC to read it.
  • A solar panel as a backup power source. I use one channel of the pcf8591 to measure the voltage.
  • A rain meter (outside the cold frame of course) that I read with yet another channel of the pcf8591.
  • Time is set by a time server and after that kept by the ESP8266
  • A Switch, checking if the lid is open.

There are also three outputs:

  • A fan for ventilation. I have the fan blowing out air from the coldframe -in case it got too hot- but I probably will just put it in another position and use it simply for circulation. The fan is driven through a transistor driver.
  • A fan circulating hot air through an underground heat sink. This fan is autonomous, so there is no switch on the webserver-interface. It does two things: if the coldframe is getting too hot, it will blow that air through the heatsink, thus storing it. If the coldframe gets too cold and the  temperature of the heatsink is higher, it will push the warmth of the heatsink into the coldframe. The heatsink is an underground space filled with stones, throughwhich I have led a pipe.
  • A motor to open the lid of the cold frame. The motor is driven through a MOSFET
    Credit where credit is due, the code around the outputs ‘I stole’ from randomnerdtutorials and modified it for my own use

The reporting and control is done as follows:

  • A webserver connected to the home network (ESP8266 in STA mode)
  • A stand-alone webserver (ESP8266 in AP mode)
  • Thingspeak
  • A MySQL/MariaDB database on a separate computer (e.g. a raspberry). This is also  based on some articles by randomerdtutorials.
  • Googlesheet.
  • Telegram messages: I use Telegram to report the min and max temperature every day at 6 a.m.  It also sends me a message once the temperature goes over a set value. In future I may start to use it to control the Outputs described above

The processor used is a Wemos D1 mini, It might be wise though to get a Wemos D1 mini Pro or an ESP8266-07 board as that has an antenna. Could come in handy, depending where in the garden you place the coldframe.
One more remark about the HTU21D, both the sparkfun library and the adafruit library are rather ‘spartan’ in the use of the HTU21D sensor. It has the possibility of heating up the sensor to prevent condensation. I have added some code to switch that on when the sensor is close to 100% humidity, but only during a few hours in the night. When that internal heating is switched on the temperature is shown in red, like shown below

HTU21D Heated
HTU21D Heated

Construction.
it is not my intention to fully describe how to make a coldframe (I may in future on ‘instructables’), as I presume everybody can make a box with a lid from glass. The one I made is not perfect as it only lets in light from above. I built it during the corona lockdown and had to make do with what I had. But i do want to point out a few details: I put all the electronics in a wooden box with plastic lid, that I just hung in the Coldframe. It has the BH1750 (cover temporarily removed for the picture) on top of it

For the back and one side I used polystyrene, covered with duct tape. In my experience that holds up quite long against the elements.
The construction to open the lid took a lot of pondering. Most of the linear actuator solutions required me to attach the push rod  to the lid…which would impede manual opening. In the end I decide for an egg shaped disc that is eccentrically connected to a motor so when it turns it opens and lowers the lid. make sure to apply some grease on the turning part.

For those not familiar with cold frames: The main ‘danger’  of a cold frame is that it gets too hot during the day. Opening the lid is essential then. It is easy to automate that: insert a line that checks the temperature against a set value and start the motor. As I have chosen to let the motor turn one direction that would mean let it turn for a few seconds and then stop it. I could fine-tune that by adding a position switch,  or even use an H-bridge (requiring an extra pin), but as I have not been on holiday much during the lockdown, I have chosen to keep it manual.

To measure the outside temperature I put a DS18B20 in a piece of conduit pipe sprayed black  on the top half. the idea behind that is that the top will heat more than the bottom, causing an updraft, so the DS18B20 that is located in the bottom will always get fresh outside air

The code:
The core of the code is an Asynchronous webserver that presents the sensordata via server events, every 10 seconds. To prevent the ‘on-start’ values being empty I do an initial replace of the placeholders with the freshly read sensordata. and to make sure I also start with a negative number for the timer so the first 10sec update comes almost immediately.

If one wants to fill a webpage with data there are several approaches: 1. build the webpage, then read the sensors and fill them in; 2. Read sensors while building the webpage and fill them in step by step; 3 read all the sensors first.
I have chosen for the latter.

The webserver contains several icons. I have used 3 ways to put those icons there: 1. from the fontawesome library; or of not available there: 2. directly inserted with base64 codes; or 3. from SPIFFS.
I did that mainly to play around with different techniques, but to use SPIFFS just for 1 picture might be a bit silly and you may consider to not do that. (Edit: I did away with the SPIFFS picture, just picked another one from fontawesome)

The code keeps track of max and min temperature during a 6 a.m to 6 a.m. 24 hr timeslot. Should you lose power or update the code in between via OTA, or if for whatever reason the processor resets, the kept min and mac temperatures are lost. It is easy to prevent that by storing them in SPIFFS (but you will rapidly wear  out the EEPROM), or RTC memory (in a 4 byte per value block). The RTC memory survives reset but not a power outage. I just did not find it important enough to bother with and it introduces some other problems. Mind you that rtcData stored in the first 32 blocks will be lost after performing an OTA update, because they are used by the core internals.

Thingspeak
The thingspeak code is very straightforward. You will need to open a Thingspeak account though and note the channel number and write API code to insert in the program.

coldframe-thingspeak

When using Thingspeak, one can install one of the many Thingspeak apps (such as Thingshow, Thingview or Thingviewer)on one’s phone for easy acces to the data.

Thingshow

MySQL
In order to use this you will need to setup MySQL or MariaDB on a server somewhere. A raspberry Pi would be suitable for that. Earlier I referenced to two articles on randomnerd tutorials that describe how to set up a MySQL  database, no need to reinvent the wheel here, although I did adapt the code a bit.
coldframe-mysql

Googlesheet
You wil need to setup Googlesheet for that as I have described here. You will find an example here too.

Telegram
You will need to setup a Telegram account and create a bot. I describe the process here.

InfluxDB
I did not put my data in influxDB, but if you want it is rather easy to do that with a POST statement.
Add code like this:

#include <ESP8266HTTPClient.h>
HTTPClient ifhttp;
const char* influxUrl = "http://localhost:8086/write?db=mydb";
const char* influxUser = "username";
const char* influxPassword = "password";
String influxData = "";

void (influxDB()
{
influxData ="........" ---> add your fields and data here


// Create POST message
ifhttp.begin(influxUrl);
ifhttp.addHeader("Content-Type", "application/x-www-form-urlencoded");
ifhttp.setAuthorization(influxUser, influxPassword);

// The first attempt to send returns -1
int httpCode = -1;
while(httpCode == -1){
httpCode = ifhttp.POST(influxData);
http.writeToStream(&Serial);
}
ifhttp.end();
}

There is also a library for InfluxDB. The program below fills a database ‘garden’ and a set called ‘bed’ with (random) values for moisture, temperature, light and barometric pressure

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <InfluxDb.h>
#define INFLUXDB_HOST "YourInfluxdbIP" //Enter IP of device running Influx Database
#define WIFI_SSID "YourSSID" //Enter SSID of your WIFI Access Point
#define WIFI_PASS "YourPW" //Enter Password of your WIFI Access PointESP8266WiFiMulti WiFiMulti;
Influxdb influx(INFLUXDB_HOST);

void setup() {
Serial.begin(115200);
WiFiMulti.addAP(WIFI_SSID, WIFI_PASS);
Serial.print("Connecting to WIFI");
while (WiFiMulti.run() != WL_CONNECTED) {
Serial.print(".");
delay(100);
}
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
influx.setDb("garden");
Serial.println("Setup Complete.");
}
void loop() {
InfluxData row("beds");// measurement name
row.addTag("bedname", "bed1");//tag
row.addValue("moisture", random(500,800));
row.addValue("temperature", random(10, 40));
row.addValue("light", random(1100,1400));
row.addValue("pressure", random(980, 1023));
influx.write(row);
delay(20000);
}

These can be viewed in Grafana (full explanation on how to do this here)

grafanadas

Carriots
Carriots, now called Altair Smartworks is an IoT data collection and processing site. It allows you to store your data and have it processed and attach specific actions to it. It might be useful and is fairly easy to add. Check here.

The code can be updated via website OTA. For development serial OTA is the easiest, so if that is what you prefer: I left the original serial OTA statements in so it is easy to convert back.

Download
You can download the code here. A remark though: it is my ‘as is’ working code and while developing it, I may have put in some unnecessary things and comments and also my variables might not have been grouped logically. Normally i clean up code before publishing it….but that means I have to retest it again and i just did not have the time for that right now. I may in future. But as said, it is a working code. You do need to add your own data such as passwords and API’s though. I am in the process of rewriting the code from the ground up,based on experience gained with the using the  ColdFrame for some time

————————————————————

 

Experience after a few weeks:
In general the system functions well. The cooling/heating system was able to keep the temperature above 0 degrees celsius when the temperature outside dropped to minus 6 at night for a few hours. It had a bit more trouble when it was freezing minus 6 the entire day. Mind you though that a relatively small object is harder to keep warm because of the unfavorable volume vs. surface ratio.

The HTU21D was a bit of a disappointment. According to the datasheet, the humidity operating range is 0-100% and I have no reason to doubt that. However, after continued exposure to 100% RH, condensation within the sensor can play havoc on the results. RH values above 100% or below 0% are possible then. Robert Smith in fact mentions this in his excellent comparison of various humidity sensors. He though sees it as a possibility to “do your own calibration”. I think though that if the HTU21D jumps from say 114% to -3% within 10 secs, there is more at large than the calibration not being fine tuned.

The question though is whether the condensation also influences the temperature readings. I do not think so, but I might add another DS18B20 just to make sure. I doubt if another humidity sensor would do better. Measuring near the upper limit of the range for a prolonged period seems to be problematic for all. The problem is the condensation in the sensor and no doubt other sensors, like the BME280 would suffer the same fate (eventhough the BME280 seems to use different type of sensor (resistive vs capacitive)). Also here, the relatively small size of the box may play a role as a relatively low amount of water will easily raise the potential humidity.
Ventilation can help, but it is a 2 edged sword: ventilation will generally also drop the temperature, which will make the relative humidity go up. Also the 100% humidity would normally occur when the temperature would go down to 6-7 degrees or lower, i.e. usually at night, and that is the moment you do not want the temperature to drop any lower.
Alternatives: BME280, Sensirion SHT4x or SHT71, HDC1080, AHT20 (datasheet mentions in fact a drift if subject to prolonged >80%RH). The Si7021 is practically identical to the HTU21D (in fact you may get the one if you order the other at less than reputable shops). They are only distinguishable by the serialnumber that supposedly is 60 for the HTU21D and 57 for the Si7021.

The BH1750 functioned well, it provided good information on what hours were most sunny on the spot the coldframe was standing.. It had one quirk though, occasionally (though very rarely), it would display the default value of 56412 Lux for a while and then it would be OK again ( did not find any fault in the wiring). A full reset would normally ‘cure’ it as well.

Obviously not a matter of just ‘finetuning’

The reporting through Telegram worked fine. Only 2 little ‘annoyances’ When the temperature ‘hoovers around 0 degrees or 25 degrees celcius (the lower and upper limit warning levels), I could get a couple of warnings in a row: I get a warning when the temparature dropped below zero, then when it would briefly rise above zero again the warning flag would be reset and subsequently if the temperature would drop below half a minute later I would get a warning again. It is basically the system doing what it was told to do. I could ‘solve’ that but not allowing a second warning within say 5 minutes, but I really did not find it important enough.

The leaf wetness sensor functioned ‘moderately’. Somehow the surface was not as appealing to condensation as the glass top (or the HTU21D sensor for that matter). As I still consider it important info, I will try to find another solution for it.

The combination of the webserver info that is basically à la minute (every 10 secs to be precise) and Thingspeak/MySQL/GoogleSheet that gives an historic overview worked very well.

Improvements
Apart from the HTU21D and leaf wetness sensor I have to look at/reconsider, there are a few things I may add: currently experimenting with a TCS34725 sensor to see if I can monitor ‘green development’.
I am considering if I should add a moveable setpoint for the cooling fan to set in, but it may not be important enough.
Currently I have 4 ADC channels through the PCF8591. I use one of those channels for soil moisture. If I want to use the system in a larger coldframe, or a greenhouse, I may need to add some ADC’s.
The current soil sensor I use (carbon rods) works fine, albeit that the thickness and bluntness of the rods can make it hard to stick it in a pot, so I may decide for a slightly leaner and sharper capacitive sensor, or just use metal nails. The latter though would require a transistor to switch off the current when not used (in order to minimize electrolyses), which takes an extra pin of the ESP8266.
I may expand the function of the lid opener to automatically stop when the lid is open or the lid is closed.
Also considering to add Tweets for notification next to Telegram


If you have a Thingspeak account, tweets can be sent either from your ESP via “thingtweet” or directly from Thingspeak.

I did add an emergency heating in the mean time. It is set to kick in if the temperature drops below 0 degrees, in spite of the underground heatsink providing heat. It is basically a relay that can switch on a heater. In my cold frame it is a resistor heater, if used in a greenhouse it could be a dedicated electrical heater. With seemingly only 2 projected frost days remaining till mid May, I will need to wait with proper testing.

Coldframe Aircon

When the Coldframe is getting too hot, the fan will pull hot air through the underground heatsink that has a rather steady temperature 0f 8-12 degrees Centigrade. When it is getting too cold, the same fan will pull cold air through the underground heatsink which then will warm the air. If that is not enough to prevent coldframe temperature to stay above zero, a heater above the fan wil kick in. I made the heater from 24 half-Watt resistors that are pushed to their limit, producing 12 Watt in heat. The main aim is to keep the temperature above freezing, not to heat the coldframe to say 20 degrees. As said, this is still experimental stage.
It happened to me once that the 6 a.m. telegram message was not received. Checking my SQL database and Thingspeak showed the connection was briefly dropped around 6 a.m. As I do not do any error checking on the connection with Telegram (or MySQL for that matter), the program is not aware of the message not being received.
If it is important to you, the result of bot.sendMessage(chat_id, bottext, "HTML"); is “0” if the transmission failed and “1” if it succeeded. You could do a check on that and resend if necessary. I am using an insecure connection with Telegram by specifying “setInsecure” in the setup. That’s easier and I am not sending top secret info. If you want the connection to be secure, you can do that by stating:

X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure botclient;
UniversalTelegramBot bot(BOT_TOKEN, botclient);

Experience after a few months
When summer came, I had trouble loading the coldframe’s website on my network. As I still could load the the AP website when I was close to the coldframe, I was suspecting something was blocking the connection to the router. The most likely suspect was a row of potato filled containers between the coldframe and my house. When those grew into firm plants it isn’t unlikely to think these walls of moisture blocked the signal. Yet the connection to Thingspeak as well as my mySQL server seemed not to suffer.

Granted, I do not really use the coldframe in the summer, yet it might be wise to use a Wemos Pro (or ESP8266-7) with external antenna and place a router or WiFi extender in a room directly facing the garden (currently it connects to a router on the opposite side of the house, 1 floor up).

Also, when I will build another coldframe, I will try to find a way to remove the electronics from the box in an easier way, e.g.by making external plug connections with the ventilators, motors and some of the sensors. and I will start streamlining the code a bit more.

Strange behaviour in ESP8266 AccessPoint was password related

In my previous article, I made a skeleton program for a tutorial about the various ways of WiFi connection of an ESP8266, I ran into an odd problem that turned ourt to be related to the password.
the code aimed to include both STA and AP connection and I set up the credentials like this.

#define WIFI_SSID "YOURSSID"
#define WIFI_PASS "YOURPASSWORD"

// Set AP credentials
#define AP_SSID "YOUR_DESIRED_AP_NAME"
#define AP_PASS "YOUR_DESIRED_AP_PW"

After uploading the acces point ofcourse identified itself as ‘YOUR_DESIRED_AP’ and I quickly set to correct my mistake of not filling out my credentials and I changed it to:

// Set AP credentials
#define AP_SSID "Pond"
#define AP_PASS "1234"

After uploading again, I was surprised to see that instead of the expected AP SSID ‘Pond’, I now saw ESP-859C2F, with the numbers being the last 3 bytes of my ESP’s MAC-number. Chosing that accespoint made me connect to the ESP without asking for a password.
what the heck was going on? I knew the code was allright as on myinitial upload I had seen the SSID of the AP when it was still called “YOUR_DESIRED_AP_NAME”.
To make a long story short: I found out the problem was with the password: apparently there is a problem with a password that is too short, or contains numbers.
1234–> no proper AP_SSID visible
abcd–>works well
abcd1234 –>no proper AP SSID visible
abcd123–> works well.
So initially I thought that perhaps the amount of letters needed to be bigger than the amount of numbers in th epassword.
but ‘1234567’ worked fine….till I tried ‘123456’ which did not work, and then ‘1234567’ did not work either anymore and i had to go to ‘12345678’ to make it work.
Note: I uploaded the sketches with the “Tools-erase all flash content set”.
So I am still not entirely sure the exact problem, but I do know that numbers in the password apparently can cause problems with the AP

The HTU21D on an ESP8266-01, with MQTT and graphics

Limited as the ESP8266-01 might seem regarding the number of pins, it is still a very capable little device that is sometimes wrongfully underrated.

It is perfect however for projects that demand little I/O, such as reading a single sensor.

I am using the HTU21D temperature and humidity sensor. The ESP01 needs constructing a small board that contains the connectors and a small 1117-33 voltage regulator (soldered on the bottom) so the circuit can be fed with 5 Volt. As I am using an ESP8266-01S -that already has 10k pullups on GPIO0 and GPIO2, I do not have to add resistors for an undisturbed startup and use of I2C. If you are using the ‘old’  ESP8266-01, you have to add 4k7 -10k pullups to GPIO0 and GPIO2. If your HTU21 module already contains pullups, those will function as proper startup resistors as well.

The software (download here) is not too complicated, it first connects to your LAN, but it chooses the strongest of two LANs if available.

It then connects to an MQTT server and sends the sensor readings via MQTT every minute.

I also find it convenient when the software tells me what program it is, so I have added that too.

Finally, as in future I may want to include some time dependent signaling, I included a clock that is being synchronized through the internet.

Should you check your DHCP list, the device identifies as “HTU21”

MQTT Output:

Update
If you like a graphical presentation of your data, I have made another file that will exactly do that. It is based on code by Rui and Sara Santos from (randomnerdtutorials) that I discussed in an earlier  post. It will work with a 512k/32k SPIFFS setting as well as with a 1M/64k setting.
Beware though that many ESP8266-01 (and especially the ESP8266-01S) modules now come with a PUYA memory chip that has been causing some issues when using SPIFFS. The userdata.h file contains 2 defines that need to be set or commented out depending on whether you have or do not have the PUYA chip (2 defines to cover different cores). If you are still on the 2.4.1 core, you will need a patch. That you will have to put here: C:/Users/your.name/AppData/Local/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266.

Using the ESP8285 M3

Use of the ESP8285 M3

Chinese webshops sell the ESP-M3. This is a tiny module containing an ESP8285. In short, an ESP8285 is like an ESP8266 but with 1Mb memory on chip. It is for instance the chip that has been used in the SonOff basic till now. The M3 is not a new module,it surfaced in 2016 and was primarily meant for wearables I think.

Sadly it is not really breadboard friendly. 6 pins have a 0.1″ pitch with throughholes, but 6 other pins have a 0.1″ pitch with edge-pads. The alignment between the three rows of  pins is a stretch to fit a standard 0.1″ pitch grid.
The module has the following pins.

ESP-M3 Compares with Wemos/NodeMCU
GPIO0 D3
GPIO1 Tx
GPIO2 (Tx1)(apparently connects to an onboard blue LED D4
GPIO3 Rx
GPIO4 (VSDA) D2
GPIO13 (Mosi) D7
GPIO14 (SCK) D5
GPIO16 D0
EN CH_PD
RST RST
Vcc Vcc
Gnd Gnd

The function of the pins is equal to that of the ESP8266. In comparison with the Wemos D1/ESP8266 (11 I/O pins, one ADC pin) the ESP-M3 has only 7 I/O pins, and no ADC. The ESP8285 HAS more pins than that, but these are not all broken out on the ESP-M3 module. All in all that is still 3 pins more than the ESP8266-01.

As the GPIO16 pin is broken out, the M3 board is more flexible in DeepSleep applications.

The use of the ESP-M3 is similar to that of the ESP8266. In order to go into Flash mode, the GPIO0 pin has to be made LOW. For ‘normal use’ the GPIO0 has to be pulled HIGH. The EN pin has to be pulled high. Choose 8285 board for upload. An ESP8266-01 programmer can quickly be repurposed to program the M3.

void setup() {
pinMode(2, OUTPUT);
}

void loop() {
digitalWrite(2, HIGH); // turn LED on 
delay(500);
digitalWrite(2, LOW);
// turn LED off
delay(500);
}

There is a Wiki with user manual.

A minimal system is built like this:

Simple WiFi relay board (3): A 1 relay Chinese Website module


In an earlier post, I discussed how to quickly  make  a one channel WiFi relay with a relay module an ESP8266-01 and some Dupont cables.
In a later post, I showed how to make a 4 channel WiFi relay with an ESP8266-01 and a 4 channel relay board.

Both posts were a consequence of 2 videos by Ralph Bacon, discussing his slightly disappointing adventures with 2 commercially available Wifi relay boards, based on an ESP8266-01.
Out of interest I bought one of those boards -knowing the shortcomings Ralph pointed out- that I presumed I could fix.

The board comes with an ESP8266-01s. It has a Reset button, which isn’t really useful. The GPIO0 drives the relay through a 7002 FET, GPIO2 drives an LED and TX and Rx are not connected to anything.

The crux of this board is that it is really designed for the ESP8266-01S, although it can be made to work with the regular ESP8266-01. The ESP8266-01S is a version that already has pull-ups on GPIO0 and GPIO2, albeit that one of those pullups is through an onboard  LED. The regular ESP8266-01 does not have these pull ups and the relay board  does not provide them.

The relay module uses only one pin, GPIO0. It is connected to the gate of a 2007 FET that switches the relay and that is exactly where the problem starts. During startup, the ESP needs GPIO0 to be HIGH, unless you want to go to flash mode, when it needs to be LOW.
But as the ESP8266-01S correctly pulls pin GPIO0 HIGH, the relay will immediately be activated at startup. Hence he designer added a pull down resistor. Due to the presence of the Pull up on GPIO0 on the ESP8266-01 board, that needed to be a very strong pull down resistor and a 2k resistor was chosen. But now the GPIO0 pin is pulled LOW at startup, putting it in flash mode.

There are some simple solutions for this:

  • remove the 2k resistor. However this will activate the relay at start up.
  • reroute the triggersignal to  come from pin GPIO1 (Tx) or GPIO3 (Rx) (but you still need to remove the 2k resistor)

The latter solution is fairly simpel because of the long PCB trace going from GPIO0 to the gate of the FET

 

 

Simple WiFi relay board (2): A 4 channel DIY WiFi relay board with ESP8266-01

Driving a 4 channel relay board with ESP8266-01 through MQTT or Webserver


In a previous post I discussed making a WiFi relay inspired by the trouble  Ralph Bacon had with a single relayboard from Aliexpress. Given the fact that the Sonoff SV is relatively cheap (don’t forget the shipping cost though), and the WiFi relay at AliExpress even cheaper, it is a nickle and dime question whether it is wise to DIY such a project yourself. However, if you already have an unused ESP8266-01 and a relay lying around, basically all you need are some DuPont cables to connect the two (as shown in my previous post).

It becomes more interesting to use all 4 pins of an idle lying ESP8266-01 and add a 4 channel relay board.
The ESP8266-01 however is a bit particular with the pins it has,as two of the 4 I/O pins are the pins that need to be pulled HIGH on startup whereas the remaining two pins are the UART. Those UART pins can be used as GPIO, but the problem is that they do not know that, they need to be told that they are no longer UART but in fact GPIO. We do that with a special pinMode command (more about that later).

The relayboard I had in mind is a bit peculiar. I discussed the full workings of this board in an earlier post.

For now however suffice to say the inputs need an active LOW to  close the relays, while in rest, the inputs are HIGH.
That is in fact quite handy when using an ESP8266-01, as two of the 4 pins, GPIO0 and GPIO2, need to be pulled high on start-up, something this circuit actually does. It is necessary though to feed the board, including the optocoupler with 5Volt. The connections between the ESP8266-01 and the relay board are made as follows:

If you are using a different relay board that does not have it’s inputs pulled high in rest and you are using the ‘old’ ESP8266 module, then you need to add 10k pull-ups on GPIO 0 and GPIO2. Not necessary if you are using the ESP8266-01S.

A reminder: the relayboard needs 5Volt and the ESP-01 needs 3.3Volt.  You could use an LDO like the AMS1117 3.3 to drop the 5Volt to 3.3 however,do not connect the two Vcc’s directly. Wait, let me emphasize that: DO NOT CONNECT THE Vcc OF THE ESP TO THE VCC OF THE RELAY BORD, JUST DONT!!!!

The full board

The ESP8266-01 adapter board

Finally, put it in a nice enclosure

4 Channel relay housing
4 Channel relay housing

Software

MQTT
For theMQTT  program I followed the structure that is used by computourist with regard to the use of MQTT messages.
The idea behind that is that commands going from MQTT broker to the node are called ‘southbound’  (‘sb’), while the ones going to the broker (so usually the ‘ state’) are called ‘northbound’ (‘nb’). (with ‘southbound being a command and northbound being the status). The specific functions in the node are addressed as numbered devices.
This has advantages and disadvantages. The disadvantage being that you get codes like: “home/sb/node01/dev17” rather than something like: “home/cmd/wifirelay/relay1“.
Also the handling of the incoming MQTT is bound to a specified length, so altering it needs to be done with some consideration.
The advantages are that the handling of the code is easier and in fact extending the code with more functions is fairly easy.
What happens in fact is that once a subscribed MQTT code comes in, it is stripped to a its last two digits. These digits define the function it fulfills.
The Payload can be “ON”, “OFF”, “READ”, or a number, depending on the function chosen. The “READ”  payload reads and returns the state of the specific function (‘device’)  that is being read. Some ‘devices’ -as for instance the IP number or the MAC address, can only be read and not ‘set’.

The full list of devices is as follows:
00 uptime: read uptime in minutes
01 interval: read/set transmission interval for push messages
02 RSSI: read WiFi signal strength
03 version: read software version
05 ACK: read/set acknowledge message after a ‘set’ request

10 IP: Read IP address
11 SSID: Read SSID
12 PW: Read Password

16 read/set relay1 output
17 read set relay2 output
18 read set relay3 output
19 read set relay4 output

92 error: tx only: device not supported
91 error: tx only: syntax error
99 wakeup: tx only: first message sent on node startup

As I mentioned earlier, the UART pins need to be told that they should behave like GPIO pins. That can be done with the statement:
pinMode(1,FUNCTION_3);
pinMode(3,FUNCTION_3);

However, this will not work when there are any hardware serial statements left (such as Serial.print, Serial.begin).

Also, the device will not boot if you happen to pull pin 1 (Tx) down.
So in order to control the relays from e.g. OpenHAB, this is what you add to your itemsfile:

Switch rel1 "WiFi relay 1 [%s]" (GF_Corridor) { mqtt="[mosquitto:home/sb/node01/dev17:command:*:default]" }
Switch rel2 "WiFi relay 2 [%s]" (GF_Corridor) { mqtt="[mosquitto:home/sb/node01/dev18:command:*:default]" }
Switch rel3 "WiFi relay 3 [%s]" (GF_Corridor) { mqtt="[mosquitto:home/sb/node01/dev19:command:*:default]" }
Switch rel4 "WiFi relay 4 [%s]" (GF_Corridor) { mqtt="[mosquitto:home/sb/node01/dev16:command:*:default]" }

this will render the following menu:

The program can be downloaded here. FYI, I trimmed down an existing, bigger program of mine. I left a bit of code here and there that might not be of immediate use in this project, but may come in handy if you want to use the code on a Wemos.

WebServer

If you do not want to use MQTT, then a webserver might be what you are looking for. I adapted a program from Rui Santos (Original can be found here). to be suitable for use on an ESP8266-01.

Cost:

  • relayboard 1.80 euro
  • ESP8266-01 1.45 euro
  • 5 and 3.3Volt module 0.40ct

Simple WiFi relay board (1): an overview of two popular modules on Chinese Websites

In his video nr 107 youtuber Ralph Bacon describes his ‘frustration’ with an ESP8266-01 based wireless relay he got from AliExpress.

Wifi relay with ESP8266-01 and STC15F104 microprocessor

His frustration is understandable as that particular module is needlessly complicated. It seems the ESP8266-01 is mainly there to make the WiFi connection, while the relay is triggered by yet another microprocessor, the STC15F104. Communication between the two is via the serial port of the ESP8266, as if the designers thought, how can we make this in the dumbest way possible.
If you want to use this relay, this is how to do it:

Set the serialport to 9600 with : Serial.begin(9600);

To enable the Relay send the proper command bytes to serial port:

const byte ReBufferON[] = {0xA0, 0x01, 0x01, 0xA2};
Serial.write(ReBufferON, sizeof(ReBufferON));

To disable the Relay send the following bytes to the serial port:
const byte reBufferOFF[] = {0xA0, 0x01, 0x00, 0xA1};
Serial.write(ReBufferON, sizeof(ReBufferOFF));

Apparently it will also work with AT commands.

The circuit looks like this

###

An even simpler board

The ‘simple’ relay board

In his follow up video # 110  Ralph describes another, simpler relay board (pictured), that also frustrated him as the manufacturer apparently had not included the necessary pull-up resistors on the Chip Enable and on GPIO0 and GPIO2. (Edit: this turned out not to be entirely true as the board comes with an ESP8266-01S that has the necessary pullups on board)

Both videos came in my focus again, when i discussed the ‘simpler’ board with a diy mate and frequent commenter. It is very cheap to buy and once you add the resistors (to make it start up correctly) factually you have a Sonoff SV.
Ofcourse the Sonoff SV is less than 5 Euro (plus shipping), as opposed to the ‘brandless’ relay board only costing some 2.60 euro, so you might as well get the real thing, but it opens some interesting perspectives, especially as I had most of the stuff laying around namely an ESP8266-01 a relay module and a 3.3Volt power module, all fairly cheap. Just a couple of DuPont cables to connect the three, and it should be fine. I know it is all nickles & dimes stuff but lets do a quick calculation.

Total 2.08 euro as opposed to 2.62 euro (in a nicer package), so not really cost effective to ‘DIY’  but if you have the stuff laying around, better to use it than for it gather dust. It also allows you to choose another pin than GPIO2 to drive the relay.
Ralph also offers a program to replace the existing firmware in the ESP8266, as well as a phone app (all found in the description of his video). Ofcourse it is also possible to replace the firmware with MQTT responsive firmware. For that you could e.g. use my Sonoff Touch program, albeit that in line 17, you have to change “TouchLED=12;”  to “TouchLED=2;

But why stop there? the ESP8266-01 has 4 I/O pins, if we ad a small 220->5V power module and a 4 channel relay board, we could make a sonoff 4ch. These cost about 22 Euro. So that would be more rewarding to build.
That however will be for part 2.

Flashing Sonoff Touch – No soldering

Although it is not really a big thing to solder an angled header in a SonOff Touch in order to reprogram it, one also has to solder a wire to the GPIO-0 pin of the ESP8285 chip as the SonOff Touch has no button that can be used to get it into flash mode.
I therefore wondered if it wouldn’t be possible to flash the Sonoff Touch without any soldering. Spoiler: yes it is possible, but you need some dexterity.
First open the Sonoff Touch. This is easiest done with cautiously prying a screwdriver on between the casing and the frontplate at the side.
once that is done you can see a small board that you can just pull-out.
On that board there are 4 in line holes that we need to connect an FTDI programmer to. On the bottom side of the board is also a 2×2 male header. That is the one that we just pulled out of its header in the housing. We are going to need that header a bit later as well.

indicated  the function of the 1×4 header in the image. You are going to need an FTDI to USB module  THAT YOU CAN SET TO 3.3 VOLT. You also will need a 1×4  straight pinheader and 4 female to female DuPont wires.
Now make the following connection between the 1×4 male header and the FTDI to USB connector:

header FTDI module
Ground Ground
Tx Rx
Rx Tx
Vcc Vcc

To make clear, if it already wasn’t, this is a connection to a loose, 4 pin male header.
The next thing you need is a female to male DuPont cable. Connect the female end to the ground connection on the 2×2 header.

Also, you need to identify GPIO0 on the ESP8285 chip:

 

For the final flashing you need a bit of dexterity but this is what you do:

  • Have your Arduino IDE available with the  required program loaded.
  • Under tools-boards choose the generic 8285 module
  • Flash size 1 Mbyte 16k SPIFFS
  • Make sure the FTDI module is not connected to the USB port of your computer.
  • Now press the 4 pin male header that is connected to your FTDI module in the proper holes. Make sure it is the right way around, so Ground connects to ground, Vcc to Vcc, Rx to Tx and Tx to Rx. If there is a bit of slack between the header and the holes. push against the pins with  the mouse of yr thumb or with your little finger, so it makes  poper connection.
  • Now take the male pin of the DuPont cable that you connected to the ground on the 2×2 pin header and push it against GPIO 0.
    Keep it in place with your thumb.
  • You still should have one hand free. Use that to push the FTDI module in the USB connection of your computer.
  • Once that is done, you can let go of the male pin pressed against GPIO0
  • In the IDE chose the right port and press ‘upload’.

That’s it.

So, what program should you upload to make the Sonof Touch work?
Of course there is Tasmota and many people are very happy with it. Truthfully, I found it cumbersome and couldn’t even compile it. Considering all we need to do is switch 1 pin, it shouldn’t be so hard to write something simple.
Given the fact that the Sonoff Touch will most likely disappear in the wall and you don’t want to have to take it out and flash it again, two things come in very handy in the program:

  • OTA (Over The Air) flashing
  • WiFiManager

The code also gives MQTT feedback about the

  • MAC
  • IP
  • Filename
  • SignalStrength

It can be downloaded here

Battery fed Deepsleep Weatherstation revisited

After my previous publication of a battery fed weatherstation, I exchanged ideas with one of the commenters about ways the improve the energy efficiency of the circuit.

One doesn’t need to be a rocketscientist for that:
Ditch the batteryshield as it is very inefficient
Ditch the DHT22 as that constantly uses 2.5mA
Ditch the Wemos as even while it is in deep sleep the CH340 chip on the board isn’t. (it drains 200uA)
Ditch the voltage divider used to monitor the battery voltage (it drains 10uA).
Also ditch the BMP280 as it cannot measure humidity.

So what we will be doing is use a bare ESP8266-12F  and a BME280 as that can measure humidity as well as temperature and airpressure.
Feed with alkaline cells, omitting the need for an LDO. That way the voltage can be measured directly from Vcc/Vbatt without the need of a voltage divider

So, a new circuit starts to evolve:

Obviously that needs a bit more soldering than just using a Wemos and battery shield, but in essence one only needs to add the resistors to put the necessary pins HIGH (pins 0, 2 and CH_PO) or LOW (pin 15). There are however  various baseplates  for the ESP8266-12F that have these resistors already present. The  capacitor is  there to give some extra boost when the ESP is busy connecting to a network.

In order to minimize the poweruse of the BME280, one has to use some special settings. Normally the BME280 constantly is taking readings of its sensors. Not only does that take more power, but I noticed it can also drive up the temperature of the chip, influencing the temperature reading.
The mode to use it in is  the so called Forced Mode: it will only take a reading when told to do so.
Now mind you, even if you don’t tell it to take a reading, the library will still give you a result as that gets its values from a register, but it will always be the same value, you will need to tell the chip it has to store a new value in that register.

The datasheet suggests 4 different possibilities of ‘Forced mode’:

  • Weather station scenario
  • Humidity scenario
  • Indoor Navigation
  • Gaming

We obviously will be taking the first one.
The software can be downloaded here

While in sleep this should draw 80uA
Now suppose we have a 2000mAh battery then the circuit could run 25000 hour=1042 days=2.85 years =2 years, 10 months and a week
Now obviously that is a bit of a simplification as the full power of the battery might not be available within the 4.2<->3.0 Volt slot and ofcourse the circuit is using more current when not asleep, so lets recalculate:
Though larger peaks exist, the average current drawn during connection is some 85mA. So suppose that we have a 3 second connection and 15 (900sec) min of sleep
The current consumption is then as follows 3x85mA+900x80uA=255+72=327mAs, so over an hour it consumes 1308mAs and during a day 31392mAs. So every day that is 8.72mAh. A 2000mAh battery then gives 229 days=7.6 months.
(Edit: more energy savings can be made. Check out the ‘very deep sleep series

A battery fed MQTT weatherstation

(Note: if you consider building this… I am working on a similar station with a bare ESP12 and a BME280 for even better energy efficiency) (Actually, check here)

Weatherstations are a popular build for DIY-ers and with the ESP8266 WiFi capabilities that has become very easy.
Here I will present a simple weatherstation (DHT sensor BMP sensor for temperature, humidity and atmospheric pressure) that can be battery fed or mains fed.
It will send the info by MQTT and in order to save batteries, go to sleep most of the time.
Components needed are:

  • A wemos mini D1
  • A DHT11 or DHT22
  • A BMP280
  • A 100k resistor for the battery
  • A small switch or jumper
  • A LithiumIon charger module

Just a word for the wise… the Wemos D1 is not the best option to battery feed, as it has some peripheral components (such as the CH340 chip) that draw current. A better choice would be the bare ESP8266, but it is not for everybody to solder that.

The application has OTA. Using OTA together with deep sleep is always a bit of a tricky situation as you cannot do OTA when the ESP8266 is in deep sleep.
basically there are 3 solutions for that:

  1. Include a pause in which you can do OTA. Problem with that is that you would need some indication of when that pause starts (e.g. once the MQTT messages have come in). Another problem is that that pause in which the processor is not in deep sleep, it wil consume more energy.
  2. Make the deepsleep dependent on the state of a pin. With a jumper or Switch you could make one pin high or low and thus allow deepsleep or not.
  3. By having the software check on a seperate website whether or not there is an update for the software and then download that software. Obviously that requires some more organization and if the Wemos will do that check whenever it awakes, it will do that say every 15 minutes for something that may never happen.

Considering the above, Option 2 seemed the best, so I added a small switch to tell the software whether or not to go into deepsleep.

Software

The program once loaded (get it here) has several tabs in the IDE.
The main program “esp8266_weatherstation” is quite straightforward, it sets up all the usual parameters, variables and the sensors.
It reads the sensors and sends these via MQTT to a broker.
Once that is done, it goes into deepsleep, depending on two parameters:

  • the “FORCE_DEEPSLEEP” variable: if present there will be a 15 min deepsleep. If not set, the deepsleep will be determined by the battery voltage.
  • the state of the ‘SLEEPPIN (D6):  if LOW there will be deepsleep, if HIGH, there will be no deepsleep
    [Edit: DeepSleep can be made more effective See the series “Very Deep sleep and energy saving” that starts here.]

If there is no deepsleep, a pause of 30 secs is added to avoid the MQTT messages being send in a frenzy.

You may be puzzled by the following code section:

float h = dht.readHumidity();
float t = dht.readTemperature();
delay(2000);
float h = dht.readHumidity();
float t = dht.readTemperature();

The reason for this is the response time of the DHT22. If you  start a reading, the results you get are from a reading that was started 2 secs before. Usually that is not an issue, but if you put the processor to sleep for 15 minutes, that first reading will give you 15 min old values. If that is not a problem, by all means remove the delay and second reading. It will not make a difference on your battery life as your  DHT22 is not put to sleep.
technically ofcourse it is possible to feed the DHT22 from one of the I/O pins and switch it off when not needed, but the DHT22 also needs a warm-up time of about 2 secs, so you would need to take that into account. No doubt that warm up time could be catered for with the delay(2000) command mentioned above.

The “OTA” section sets up the OTA function. As explained before, OTA and DEEPSLEEP is a bit of an uneasy combination. In order to use OTA, tou would need to put the switch on D6 in the right position (HIGH) and either reset  the WEMOS or wait till the next wake up. Mind you that when DEEPSLEEPing the OTA port  can disappear, but it should come back once the processor is out of DEEPSLEEP.

the “config.h” file defines some variables

the “webconnect” file connects to WiFi. If for some reason that connection cannot be made after 10 times trying, the processor is going back to sleep for 30 more seconds and then tries again.

Libraries

The libaries used are quite standard, with the exception of the PubSubClient library. This is not the well known PubSubclient library from Nick O’Leary, but a fork made by Ian Tester. The reason for using that one is that it is easier to send variables in the MQTT payload.
The DHT library is the DHT sensor Library from Adafruit. If you prefer another DHT library (there are many) you will probably only need to make minor changes.
The BMP280 library is also from Adafruit.

The sensors

DHT22

The DHT22 is the more accurate sibling of the DHT11, but both have a tendency of failure. generally the DHT22 needs a pull up resistor, but one can also use the internal pullup of the I/O pin for that.

There are two specification where the DHT11 is better than the DHT22. That’s the sampling rate which for the DHT11 is 1Hz or one reading every second, while the DHT22 sampling rate is 0,5Hz or one reading every two seconds and also the DHT11 has smaller body size.

If you are using this sensor outside, you can protect it against dirt and  creepy crawlies by covering it with a single layer of teflon tape. Supposedly this is fully permeable for humidity.

The DHT sensors do not have eternal life. they give up working alltogether (and usually permanently) when the humidity is 100%

Properties DHT11 DHT22
Voltage 3-5 Volt 3-5 Volt
Operating current 2.5mA 2.5mA
Temperature range 0 t/m 50 ºC -40 t/m 80 ºC
Temperature accuracy ±2 ºC ±0,5 ºC
Humidity range 20-80% RH 20-95% RH
Humidity accuracy ±5% RH ±2-5% RH
Sampling rate 1Hz 0.5Hz

BMP280

The BMP280 is the successor of the BMP085, BMP 180 and BMP183

Ofcourse it is possible to use one of the above predecessors, but these older sensors are generally more expensive than the BMP280.
The BMP280 can measure barometric pressure with ±1 hPa absolute accuraccy, and temperature with ±1.0°C accuracy. It can be controlled both by SPI and I2C.

Do not mix it up with the BME280. That sensor can also read humidity, but it is slightly more expensive.
The BME280 ofcourse would be a perfect chip to go to if you want to avoid the DHT22 sensor. It can read temperature, humidity and barometric pressure. I just didnt have it lying around, thus couldnt try.

If you are no fan of the DHT11/22 consider the I2C HTU21D, or theSi7021 (replaced by the HTU21D).
If you are only interested in say temperature and not in humidity, the BPM280 is the best choice and you can omit the DHT22. If you only want temperature, the DS18B20 is probably the best choice.

The battery

Lipo Charge module

It is hard to give recommendations for what battery to use. I am using the battery shield to which I connect a LiPo battery. That makes it all very simple but it is not the most efficient way of using the energy from a battery as the battery shield first boosts it up to 5 Volt after which the Wemos makes 3V3 Volt from it.
Another easy way is to use a Lipo battery with a lowdrop 3V3 regulator and a cheap charging module (pictured top). You could combine the charging module with a small solar cell (with a 5-6 Volt max output). The 100k resistor in the  circuit sketch should go directly to the V+batt, to monitor the battery voltage. The choice for the 100k resistor is explained here.  If for power efficiency you decide to use a bare ESP8266 instead, one has the opportunity to increase the resistors of the voltage divider to come to a smaller current through these resistors