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.

Advertisements

Using the ESP8285 M2, with a warning

Next to the previously discussed M3, there is also an ESP8285 M2 (in fact, there is also an M1). Like the M3 it is based on an ESP8285 that has 1Mb on board.
It has 11 I/O pins (including Rx and Tx) as well as an ADC.

An advantage though is that it is available on a development board that has a Vcc and Grnd connection per I/O pin (but read the caveat below), whereas e.g. the Wemos D1 mini only has 1 ground and 3V3 pin.
The board can be programmed directly from the Arduino IDE, but it does not have a circuit present that puts it automatically in flash mode. Therefore it is necessary to push the Flash button, hold it and then press the Reset button and only then release the Flash button.

There is a big caveat with this board though: The row of positive pins opposite the I/O pins, is connected to the INPUT voltage, so even if you feed this board via USB, you get 5Volt on the “V” pins. If you feed your board 3.3 Volt via the 3V3 connector……there is no voltage at all on the ‘V’ pins. Whether this is a design flaw or intentional I do not know.

Using 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 through-hole and edge pins is hwoever not a standard 0.1″ pitch.
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.

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.

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

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

Showing ESP8266 battery voltage in a graph

In a previous post, I dabbled around with presenting sensor readings with the Highcharts graphic library, based on a post on the randomnerdtutorials website.

It might be educational to add another channel to it that reads battery voltage and presents that in a graph as well.
In the picture above there are two colours: when the voltage is above 3.3Volt, the colour is green, when it goes below 3.3Volt the colour turns red.

This is how to do it:
First, grab the Arduino Sketch file from the randomnerdsturorial website. Open it up and add two procedures:

1 locate the procedure called readBME280Humidity() and right above that, add the following lines:

String readBatt(){
float v=analogRead(A0);
v=4.2*(v/1023);
return String(v);
}

2 locate the section that says // Start server.
right above that add:

server.on("/voltage", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readBatt().c_str());
  });

That’s all we need to do in the Arduino Sketch. Now get the index.html file from the randomnerdstutorial website.
Open up the file in an editor like Notepad++ and find the </script> tag.
Right above that tag, add the following code.

var chartV = new Highcharts.Chart({
chart:{ renderTo:'chart-voltage' },
title: { text: 'LipoVoltage' },
series: [{
showInLegend: false,
name: 'Voltage',
data: [],

zones: [{
value: 0,
color: '#0000ff'
}, {
value: 3.3,
color: '#ff0000'
}, {
color: '#00ff00'
}]

}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
}
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: { second: '%H:%M:%S' }
},
yAxis: {

title: { text: 'Voltage (V)' },
min: 0,
max:5
},
credits: { enabled: false }
});

setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartV.series[0].data.length > 40) {
chartV.series[0].addPoint([x, y], true, true, true);
} else {
chartV.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open("GET", "/voltage", true);
xhttp.send();
}, 30000 ) ;

Next, locate the following section in the file, and add the indicated line

Save the html file in the data folder of your Arduino sketch.

Now we have to take care of the hardware section.
The ADC of the ESP8266 chip can only read a maximum of 1Volt, whereas a lipo battery will have a max voltage of 4.2 Volt. So we need a voltage divider that makes 1 Volt uit of 4.2 Volt. If you are using the Wemos D1 mini, that already has a voltage divider in place. It connects the A0 of the Wemos with the ADC of the ESP8266 chip.

A 220k over 100k however will not be giving the required ratio. We will need to add an extra 100k resistor between the battery and the A0 pin. That gives us a ratio of 100/(100+220+100)=100/420=1/4.2.
If you happen to use the new, version 1.3 battery shield, I think that already has an extra 130k in place, which gives a slightly different division factor of 100/(130+220+100)=1/4.5.

Upload the Arduinosketch to an ESP8266 and upload the HTML file to the SPIFFS. Open up your IDE terminal window to check the ip nr and open a browser to that ip nr.

ESP8266 Plot Sensor Readings in Real Time Charts on a Web Server

Until recent, I had not bothered much about adding graphics to my ESP8266 programs, as I was using Openhab and Influx/Grafana for graphical presentation of data. In fact I never fully realized what was possible on an ESP8266. Then I saw some great graphics for a BME280 on the randomnerdtutorials site from Rui and Sara Santos.
Their approach is to use the ‘Highcharts’ graphic javascript library that is available on line on cloudflare, something that in all honesty I had never thought of.
Anyway, they create 3 separate graphs, for each of the modalities (temperature, humidity and pressure) of the BME280. That works wonder well. I however was more interested in having various (temperature) results in one graph. Before I go further, the fact that Sara and Rui make 3 requests, makes the program easy to follow. They could ofcourse have made one request, receive the temperature, humidity and air pressure in one json message and parse that. Anyway, back to my adaptation of the code.
I found some examples that were using a different library: Chart.js, but I found the program that Sara and Rui presented cleaner and clearer. Also, they fully separate the HTML file from the ino sketch (storing the HTML in SPIFFS) and that was something I wanted too, so I set about to adapt their program to my needs. I must confess that I am not an expert on javascript, asynchronous websites, websockets and AJAX programming, but this seemed like a great way to dive deeper.
I started with identifying where in the program the data was sent and where it was further processed
In the BME280 program 3 separate calls are made in which subsequently temperature, humidity and pressure are sent to the server.
For the temperature this goes as follows:

server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readBME280Temperature().c_str());

The request->send_P is a way to send an entire webpage from PROGMEM, but in fact, only the result of the temperature reading is being sent. It seemed to me the best way to add temperature readings (from several DS18B20’s) they needed to be added here somehow. It seemed most sensible to do that with a JSON format.

I found the data was received/processed in the HTML file by the setInterval(function ( ) in the line y = parseFloat(this.responseText);. Obviously I needed to add one or more variables here and instead of using parsefloat, I would need to parse the JSON like this:

var myObj = JSON.parse(this.responseText);
var y=myObj.Temp[0];
var z=myObj.Temp[1];

OK, so that seemed covered, now the Highcharts library needed some further digging in to for me in order to actually add the values to a second and third line in the chart. There are some examples on the cloudflare and jsfiddle website, but those seemed to have little in common with the structure I already had, so obviously this needed some trial and error.

To keep things manageble as an example, I will add 1 channel to the temperature chart that Sara and Rui Santos made and will leave the Humidity and AirPressure graphs untouched.

So first lets adapt the ino file.
Go to the server.on("/temperature" procedure and replace that one by:

server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
     String payload = "{\"Temp\":[" + String(readBME280Temperature()) + "," + String(readDS18B20()) + "]}";
    Serial.println(payload);
    request->send(200, "text/plain", payload.c_str());

The readDS18B20() should be your procedure to read the result of a DS18B20 (or any other sensor). and yes, I am using ‘send‘, not ‘send_P.’
The result -i.e. the JSON, can be checked on /temparature20190807_200243.jpg

The HTML file needs various changes,not only in the AJAX-serverrequest section, but also in the Highcharts definitions, so I best just post that here in totality.
You could play around with the various Highchart settings. You may have noticed that the colors of both lines are the same. Might be a good excercise for you to try and define a different color . A hint: in the index.html file, as far as I understand Highcharts, the color statement that Rui&Sara use (series: { color: '#059e8a' }) under ‘plot options’ is a general one for the entire graph (1 of the 3). That is a possibility with more than one line too, but you can also define colors per line. Try it, it is not so hard. (I believe that if you do not define any color at all, Highcharts will use default colours, but I did not try that.)

BME3

It is also easy to change the line markers,BME4

or make a dotted line, give it a try.

BME5

or display negative results in a different color:

bme6

(Yes, I know I am not giving you the exact code for that, trying to stimulate, and really, only takes minutes. You may find this link of interest)

Turning LED OFF and ON on the ESP32 camera module, using bluetooth.

The popular ESP32 camera module that I discussed in my previous post has a large build in LED.
In the standard build in camera program, that LED is always on. In the ESP32 camera example that comes with the ESP32 core in the Arduino IDE, that LED is OFF, both programs have no possibility to toggle the state of the LED, which is a pity.
I had a glance at adding a button, that would be visible in the UI, but that seemed quite an undertaking, and I thought it would be easier to use bluetooth for that.
In order to do that, we need to do the following:
Open the Camera example in the IDE and add the below statements to your declaration section (say right above the “// WARNING!!! Make sure that you have either selected ESP32 Wrover Module”)

#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
int incoming;
#define LED_BUILTIN 4

Once you have done that, go to the setup() section and add:

Serial.begin(115200);
  SerialBT.begin("ESP32Camera"); //Bluetooth device name
  Serial.println("The device started, now you can pair it");
  Serial.setDebugOutput(true);
  Serial.println();
  pinMode (LED_BUILTIN, OUTPUT);//Specify that LED pin is output

Subsequently go to the “loop” section. That should only have a delay(10000); statement. Replace the entire ‘void loop() by:

void loop() {
  // put your main code here, to run repeatedly:
   if (SerialBT.available()) //Check if we receive anything from Bluetooth
  {
    incoming = SerialBT.read(); //Read what we recevive 
    Serial.print("Received:"); 
    Serial.println(incoming);

    if (incoming == 49)
        {
        digitalWrite(LED_BUILTIN, HIGH);
        SerialBT.println("LED turned ON");
        }
        
    if (incoming == 48)
        {
        digitalWrite(LED_BUILTIN, LOW);
        SerialBT.println("LED turned OFF");
        }     
  }
  delay(20);
}

Upload that program and check if the camera functions as normal. Then you need some kind of Bluetooth application on your phone. There are various options, but I like “Serial Bluetooth Terminal“.
To pair the Camera, open the Serial Bluetooth Terminal and tap the 3 horizontal bars in the top left.
Then choose ‘Devices’, make sure you are in the Bluetooth Classic tab, and tap the cogwheel in the top right. There you can scan for available devices and once found pair with ESP32Camera.

Then go back to the ‘Devices’ menu you were before and choose ESP32Camera (it is likely the only one there). Tap the back arrow, so you are in the main terminal menu and tap the ‘connect’  icon in the top right (it is just left of the ‘delete bin’.


The terminal window will show you the connection status.
Then tap in the command window (the one at the bottom), your keyboard comes up and press 1, to turn on the LED and 0 to turn off the LED, press ‘send’ on yr keyboard, or the right arrow in the terminal to send yr command.


Full software found here.