MQTT with the W5100 Ethernetshield

In a previous post I discussed the use of an old ENC28J60 ethernetshield for an MQTT node. The biggest setback of the ENC28J60 shield is that it uses a lot of memory. When using the newer W5100 Ethernetshield, there is a bit more room to play with. So here is a simple framework  for an MQTT node that doesnt’t only publish, but also reacts to simple commands that come in with a subscription.

MQTT-Spy output
MQTT-Spy output
          Arduino UNO with W5100 Ethernetshield or  W5100 Ethernet module, used as MQTT client
          It will connect over Wifi to the MQTT broker and controls a digital output (LED, relay)
          and gives the Temperature and Humidity, as well as the state of some switches
          The topics have the format "home/br/sb" for southbound messages and  "home/nb" for northbound messages
          Southbound are messages going to the client, northbound are messages coming from the client
          As the available memory of a UNO  with Ethernetcard is limited, I have kept the topics short
          Also, the payloads  are kept short
          The Northbound topics are
          home/br/nb/temp  for temperature
          home/br/nb/humid  for humidity
          home/br/nb/deur  for a door switch
          home/br/nb/l for  the lightintensity
          home/br/nb/pr  for the status of a PIR sensor
          home/br/nb/ip showing the IP number of the client
          home/br/nb/relay showing the relaystate

          There is only one southbound topic:
          The payload here determines the action:
          0 -Switch the relay off
          1-Switch the  relay on
          2-Publish the IP number of the client
          3 Ask for the relaystate REMOVED

          On Startup, the Client publishes the IP number

#include "PubSubClient.h"
#include "DHT.h"
//kennelijk  geeft update van DHT sensor library boven 1.2.1 een fout
#define CLIENT_ID       "Hal"
//#define TOPIC           "temp"
#define PUBLISH_DELAY   3000
#define PUB_TOPIC "my_username/f/temperature" //Adafruit dashboard
#define PUB_TOPIC_h "my_username/f/humidity" //Adafruit dashboard
#define DHTPIN          3
#define DHTTYPE         DHT11
#define ledPin 13
#define relayPin 8
String ip = "";
bool statusKD = HIGH;
bool statusBD = HIGH;
bool statusGD = HIGH;
bool relaystate = LOW;
bool pir = LOW;
bool startsend = HIGH;
int lichtstatus;
uint8_t mac[6] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x06};

EthernetClient ethClient;
PubSubClient mqttClient;

long previousMillis;

void setup() {
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT);
  pinMode(relayPin, OUTPUT);

  // setup serial communication

  while (!Serial) {};
  Serial.println(F("MQTT Arduino Demo"));

  // setup ethernet communication using DHCP
  if (Ethernet.begin(mac) == 0) {
    //Serial.println(F("Unable to configure Ethernet using DHCP"));
    for (;;);

  Serial.println(F("Ethernet configured via DHCP"));
  Serial.print("IP address: ");
  ip = String (Ethernet.localIP()[0]);
  ip = ip + ".";
  ip = ip + String (Ethernet.localIP()[1]);
  ip = ip + ".";
  ip = ip + String (Ethernet.localIP()[2]);
  ip = ip + ".";
  ip = ip + String (Ethernet.localIP()[3]);

  // setup mqtt client
  //mqttClient.setServer(mqttServer, 1883);
  // mqttClient.setServer("", 1883);
  //  mqttClient.setServer( "raspberrypi.local",1883);
  mqttClient.setServer( "", 1883);
  //Serial.println(F("MQTT client configured"));
  // setup DHT sensor
  Serial.println(F("DHT sensor initialized"));

  Serial.println(F("Ready to send data"));
  previousMillis = millis();
  mqttClient.publish("home/br/nb/ip", ip.c_str());

void loop() {

  statusBD = digitalRead(4);// FrontdoorSwitch
  statusGD = digitalRead(5);// Garagedoor Switch
  statusKD = (digitalRead(6));//LivingRoom Switch

  lichtstatus = analogRead(A0);//Reads an LDR
  pir = digitalRead(7);//Reads a PIR sensor
  relaystate = digitalRead(relayPin);// Reads the state of a relay

  // it's time to send new data?
  if (millis() - previousMillis > PUBLISH_DELAY) {
    previousMillis = millis();



void sendData() {

  char msgBuffer[20];
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  Serial.print("Temperature: ");
  Serial.print("Humidity: ");
  Serial.print("Relay is: ");
  Serial.println((relaystate == LOW) ? "OPEN" : "CLOSED");
  if (mqttClient.connect(CLIENT_ID)) {
    mqttClient.publish("home/br/nb/temp", dtostrf(t, 6, 2, msgBuffer));
    mqttClient.publish("home/br/nb/humid", dtostrf(h, 6, 2, msgBuffer));
    mqttClient.publish("home/br/nb/deur", (statusBD == HIGH) ? "OPEN" : "CLOSED");
    mqttClient.publish("home/br/nb/garage", (statusGD == HIGH) ? "OPEN" : "DICHT");
    mqttClient.publish("home/br/nb/bel", (statusKD == HIGH) ? "OPEN" : "CLOSED");
    mqttClient.publish("home/br/nb/l", dtostrf(lichtstatus, 4, 0, msgBuffer));
    mqttClient.publish("home/br/nb/p", (pir == HIGH) ? "OPEN" : "CLOSED");
    mqttClient.publish("home/br/nb/relay", (relaystate == LOW) ? "OPEN" : "CLOSED");
    if (startsend) {
     // mqttClient.publish("home/br/nb/relay", (relaystate == LOW) ? "OPEN" : "CLOSED");
      mqttClient.publish("home/br/nb/ip", ip.c_str());
      startsend = LOW;

void callback(char* topic, byte* payload, unsigned int length) {
  char msgBuffer[20];
  // I am only using one ascii character as command, so do not need to take an entire word as payload
  // However, if you want to send full word commands, uncomment the next line and use for string comparison
   //payload[length] = '\0';            // terminate string with '0'
  //String strPayload = String((char*)payload);  // convert to string
  // Serial.println(strPayload); //can use this if using longer southbound topics
  Serial.print("Message arrived [");
  Serial.print("] ");//MQTT_BROKER
  for (int i = 0; i < length; i++) {

  // Examine only the first character of the message
  if (payload[0] == 49)             // Message "1" in ASCII (turn output ON)
    digitalWrite(LED_BUILTIN, HIGH);    //
    digitalWrite(relayPin, HIGH);
  } else if (payload[0] == 48)      // Message "0" in ASCII (turn output OFF)
    digitalWrite(relayPin, LOW);     //
    digitalWrite(LED_BUILTIN, LOW);
  } else if (payload[0] == 50)
    mqttClient.publish("home/br/nb/ip", ip.c_str());// publish IP nr
  } else {
    Serial.println("Unknown value");
    mqttClient.publish("home/br/nb", "Syntax Error");


You will find the full code for download here.

Setting up a local MQTT broker on the Raspberry Pi

On the web there are a ton of instructions and how to’s on how to do this, but I found  it easiest to just  issue two commands on Raspian Jessie:
sudo apt-get update
sudo apt-get install mosquitto mosquitto-clients python-mosquitto

then to test if it was all working, I opened 2 ssh terminals to my raspberry with:
ssh pi@  (the latter being the ip nr from my raspberry)
and then in one of those terminals I entered:
mosquitto_sub -d -t hello/world
this made the terminal I will call Terminal 1 subscribe to the topic “hello/world”
in the other ssh terminal window (Terminal 2) I entered
mosquitto_pub -d -t hello/world -m "Greetings from Terminal2"
and immediately I got that message published in Terminal 1
(actually you don’t need the ‘-d’ option. That is just for diagnostics)
So I knew my local Mosquitto broker was working, at least within one machine, the raspberry on which it was installed. Time to check if it also worked on other machines. To do that I opened a third terminal on my desktop that didnt ssh to the raspberry but just gave a command line to the machine I was working on (a regular Linux desktop).

Before I could have that machine subscribe to an MQTT topic, I first had to install the MQTT client with:
sudo apt-get install mosquitto-clients

when that was done I entered:
mosquitto_sub -h -t hello/world

mosquitto-terminalNow when I published a message on terminal2 (thats the raspberry) it got published on terminal1 (that same raspberry) and on terminal3 (a regular desktop), so now I knew everything was hunky dory.
However, having to use terminal command lines to check your MQTT broker is not the most convenient. I can advise everybody who works with MQTT to install MQTT-spy. That is a jar file that basically is a publisher and a client that keeps track of MQTT messages on your network.

It comes pre-configured with 3 public brokers but adding your local broker is very simple:
mqtt-localAfter starting MQTT-spy go to  ‘Connections-New Connection” Fill out a name for your connection and under the ‘connectivity tab’ add (in my case):  with 1883 being the  standard MQTT port.
Then go to the ‘other’tab and check ‘auto subscribe when opened’.
Now in the main window add a subscription tab called ‘hello/world’ and republish  the messagemqttspy-3 from Terminal2: it should appear in the receive window of mqtt-spy. Vice versa, if  you publish a message from within mqtt spy, it will appear on terminal 1 also

Sending data to Carriots IoT platform with ESP8266

carriots is a flexible IoT platform that can connect to a variety of devices and can collect data in XML or JSON format. It can process that data and on the basis of that send out data, e.g. to mail or SMS and I believe it can even Tweet. Apparently it is quite popular to attach a PIR sensor that then can send you a mail id it detects motion

Carriots does have free accounts. Those are limited in the number of devices one can connect (only 2), the number of emails (max 100/day) and the number of SMS’ (max 5/day) but it is enough for the average hobby use.

For now, I will focus  on how to get the data into Carriots, so i will not go into detail about the inner workings  of carriots, that in fact can be a bit overwhelming for those used to ‘simple’ Thingspeak, but I think it took me about 10-15 minutes to figure it all out and set up  my account. One warning though, one of the setting screens does have some info in a non scrolling sidebar. If you have set your screen to zoom in (Ctrl +) you may not see that info unless you zoom out with Ctrl-. Therefore I advise to take the quick tour after signing up so you have some quick orientation about the various screens.
Anyway after signing up most of the work is done from the cpanel, but it comes down to “connecting” a device that then defines a datastream. Don’t be put off, once you are there, it becomes quite clear. The ESP8266 is not between the default devices so just take “Other”. Once you are done you need to go the API screen to get your API and you need to make note of your DeviceID. The latter is often said to be “streamname@userid”, but in my case it was “streamname@userid.userid”.
You need the API Key and the DeviceID to send data to Carriots.
The below code reads the Analog port of the ESP8266 and uploads that to your Carriot datastream

#include "ESP8266WiFi.h"
const char* ssid     = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
const char* server = "";
// Replace with your Carriots apikey
const String APIKEY = "47777777777778c98cbb";
const String DEVICE = "xxxxx@yyy.yyy"; // your deviceID
WiFiClient client;

int val = 0;

void setup() {
  // start wifi
  Serial.print("Connecting to ");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {

  Serial.println("WiFi connected");
  Serial.println("IP address: ");
// Send data to  Carriot

void sendStream()
  //const int httpPort = 80;
  if (client.connect(server, 80)) {   // If there's a successful connection

    // construct the data json
    String json = "{\"protocol\":\"v2\",\"device\":\"" + DEVICE + "\",\"at\":\"now\",\"data\":{\"moisture\":\"" + val + "\"}}";

    // Make an HTTP request
    client.println("POST /streams HTTP/1.1");
    client.println("Accept: application/json");
    client.println("User-Agent: Arduino-Carriots");
    client.println("Content-Type: application/json");
    client.print("carriots.apikey: ");
    client.print("Content-Length: ");
    int thisLength = json.length();
    client.println("Connection: close");
  else {
    // If server connection failed:
    Serial.println(F("connection failed"));
void loop() {
  val = analogRead(A0);
  Serial.println(F("Send Data"));

People who want to do this with an Arduino and Ethernetcard can use this library.

Reviewing the Wemos Battery Shield

wemosb3The Wemos battery shield seems an easy way to start battery feeding your Wemos D1 mini, but after using one for a while, it became obvious it is not for any serious battery use, mainly for two reasons: It is not efficient in using the battery power and the Wemos D1 itself is not efficient to be used with batteries.

The battery shield like all shields is to be plugged onto the Wemos D1 mini. It has two jacks: one for a battery and one for an USB plug that can be used to charge the battery. The charging circuit is built around a TP5410 Lipo charger. One therefore would expect a standard LiPo cell connector on the board but the LiPo cell connector on the board is an XH2.54 connector, whereas most LiPo cells come with a JST-PH connector. Another disappointment was that it came with male headers only. Apparently it is thought this shield should come on top of every other possible shield

Apparently he 5410 cranks up the battery voltage to 5 Volt and feeds this to the 5 Volt pin of the Wemos D1. Though this makes the Shield handy to use in combination with other shields that may rely on the voltage coming from the 5 Volt pin, it is likely a less efficient way of using the battery power as opposed to bringing it to 3.3 Volt directly via an LDO.

wemosbatteryshieldcircuitThere is not much technical information on the battery shield, but I did find a circuit that seems to almost come right out of a chinese datasheet of the TP5410, in which several configurations are shown.
Studying the circuit it seems that the 5 Volt coming from the USB, is connected to the 5 Volt pin of the shield, only through an SS32 Skottky diode. In itself that is no problem, unless one decides to use another input to that connector, e.g. a solar cell. The Wemos D1 mini has an RT9013 LDO regulator that has a max input of 5.5 Volt with an absolute Max rating of 6 Volt.
Considering that the SS32 Skottky diode has a forward voltage of 200 mV@200mA, a voltage of > 6.2 on the USB connector of the battery shield (say a 6 Volt solarpanel on a bright day) could already kill the RT9013 LDO on the Wemos D1 board, Eventhough Wemos states the shield can be supplied with 10 Volt, but maybe that is without it being connected to the Wemos D1 mini

Anyway, I hooked up a 720mAh Lipocell to the battery shield and uploades a sketch that measures the battery voltage (through a resistor on A0) and did an upload to Thingspeak every minute, being in deep sleep in between, just to see how long it would last.

My first observation was that the shield apparently does not fully charge the LiPo cell. It came to a max of 4.05 Volt before it switched to ‘Standby’. I made sure by using a Multimeter and indeed, only 4.05-4.1 volt on the cell.
shield5-6It worked pretty well after that, uploading the voltage to Thingspeak for 5 days and 5 hrs, when suddenly it stopped, with the battery voltage at 3.56 Volt, far above the 3 Volt minimum charge of a LiPo. Strange. The RT9013 has a drop of 250mV at 500mA, so even at 500mA the voltage on the ESP8266 still would have been 3.31 Volt. I have fed the 8266 with as low as 2.9 Volt and it was still working, so this was a strange finding. Resetting the Wemos did not bring it back to life… which was not so surprising because when i measured the LiPo (this was almost a day after the sketch stopped working… I was busy shopping for Newyears Eve), it was at 1.3 Volt. A quick connection to a USB port brought it back to life. A very strange finding indeed that warranted me to repeat the test (See below). But for now it doesnt seem like the battery shield is  the best solution for a serious battery dependend project.

As said before, the Wemos D1 Mini, also is not the most suitable for a battery operated project. True, the ESP8266 can be put to deepsleep and will only use around 77uA, but the Wemos board also has the CH340 FTDI to TTL chip on board. As that is directly connected to the 3.3 Volt line, it will always be active, drawing around 50uA which is sort of in the same ballparc as the ESP8266 itself. Without that CH340 it could operate 1.6 times longer.

Battery Voltage Wemos battery shield
Battery Voltage Wemos battery shield

The repeated test showed similar results: Charge to 4.05 V (should be 4.2 Volt) and apparently shuts off at 3.5 volt (should be 2.7 Volt)





batterijspaning10minA final test, in which the Wemos was put to sleep for 10 minutes, the battery lasted 18 days before it was shut off at 3.59 Volt

Apparently Harald has a more positive experience with the shield.

Sending mail with an ESP8266

Sending mail with an ESP8266 can be handy for a variety of things. I use it to occasionally have a remote ESP8266 send me a message it is still ok and functioning.
Though it is possible to have the ESP8266 directly access your mail server and send a message through that, that is usually not a good idea as many mailservers will refuse mail that is being sent from a different domain (your ip) than the mailserver’s.
it is therefore safer to use a service like As long as you stay below a certain limit of emails, one can get a free account.

After signing up  for smtp2go, you will need to choose a user id and password for your smtp log in. You thus have two sets of id and password: one for your user account and one for the mails you send.
The latter, you need to encode in base 64 to use  from your ESP8266. You can do that with an online encoder.
As there is no need to re-invent the wheel, I used this program as a basis and reworked that to my needs, but as your needs might be different from mine, I will just give a general example.
In order to send something more useful than ‘Hello World’, we are going to send the supply voltage and the chip ID. In real life I do not send the suply voltage as that is not so useful, but I send the battery voltage. But to keep it simple in this example we will stick to the supply voltage, which we get with ESP.getVcc().
The program is like this: (NOTE: the code might be badly formatted by wordpress, make sure you copy it completely)

#include <ESP8266WiFi.h>  // the ESP8266WiFi.h  lib
const char* SSID = "YourSSID";
const char* PASS = "YourPW";
char server[] = "";

WiFiClient client;
void setup()
  Serial.print("Connecting To ");
  WiFi.begin(SSID, PASS);
  while (WiFi.status() != WL_CONNECTED)
  Serial.println("WiFi Connected");
  Serial.print("IP address: ");
  byte ret = sendEmail();

void loop()

byte sendEmail()
  byte thisByte = 0;
  byte respCode;

  if (client.connect(server, 2525) == 1) {
  } else {
    Serial.println(F("connection failed"));
    return 0;
  if (!eRcv()) return 0;

  Serial.println(F("Sending EHLO"));
  if (!eRcv()) return 0;
  Serial.println(F("Sending auth login"));
  client.println("auth login");
  if (!eRcv()) return 0;
  Serial.println(F("Sending User"));
  // Change to your base64, ASCII encoded user
  client.println("ZV83MTAwMEBnbWFljC5jb31="); // SMTP UserID
  if (!eRcv()) return 0;
  Serial.println(F("Sending Password"));
  // change to your base64, ASCII encoded password
  client.println("X5pqVU9vYlJjY7Bq");//  SMTP Passw
     if (!eRcv()) return 0;
    Serial.println(F("Sending From"));   // change to your email address (sender)
   client.println(F("MAIL From:"));// not important 
   if (!eRcv()) return 0;   // change to recipient address
    Serial.println(F("Sending To"));
    client.println(F("RCPT To:"));
    if (!eRcv()) return 0;
    Serial.println(F("Sending DATA"));
    if (!eRcv()) return 0;
    Serial.println(F("Sending email"));   // change to recipient address
   client.println(F("To:"));   // change to your address
 client.println(F("Subject: Emails from ESp8266\r\n"));
    client.print(F("Power is: "));
    client.print(F("Device Chip ID: "));
    Serial.print(F("Voltage is: "));
    if (!eRcv()) return 0;
    Serial.println(F("Sending QUIT"));
    if (!eRcv()) return 0;
    return 1;
  byte eRcv()
    byte respCode;
    byte thisByte;
    int loopCount = 0;
    while (!client.available())
      loopCount++;     // if nothing received for 10 seconds, timeout
      if (loopCount > 10000) {
      return 0;

  respCode = client.peek();
  while (client.available())
    thisByte =;

  if (respCode >= '4')
    //  efail();
    return 0;
  return 1;

In the example I use “gmail” but ofcourse this can be any other mailservice>
In the program you will also see a line with “"));// not important“. I may be wrong but it is not that important what that says. It is the identity under which your mails are grouped in the smpt2go dashboard. Maybe it is easiest to make that equal to the sender address, but it isnot important for the functioning of the program.

The strings that are send are rather flexible. Instead of
client.println(F("Subject: Emails from ESp8266\r\n"));
On can also do:
client.print(F("Subject: "));
if (condition == met)

Monitoring LiPo battery voltage with Wemos D1 minibattery shield and Thingspeak

There are a million reasons why you would want to monitor the Battery voltage of  your Battery fed ESP8266. I will illustrate it with a Wemos D1 mini and the Battery shield

Wemos D1 Mini Battery shield

I am using a small 720 mAh LiPo cel. If I just leave the Wemos access the internet continuously it will last 6.5 hours, but for this example I will put the Wemos in Deepsleep for a minute, then read the battery voltage and upload that to Thingspeak.
You only need to make a few connections:
First, connect RST with GPIO16 (that is D0 on the Wemos D1 mini). This is needed to let the chip awake from sleep.
Then connect the Vbat  through a 100k resistor to A0.

So why a 100 k resistor?

Well the Wemos D1 mini already has an internal voltage divider  that connects the A0 pin to the ADC of the ESP8266 chip. This is a 220 k resistor over a 100 k resistor

Wemos D1 Internal Voltage divider
Wemos D1 Internal Voltage divider

By adding a 100k , it will in fact be a total resistance  of 100k+220k+100k=420k.
So if the Voltage of a fully loaded Cell would be 4.2 Volt, the ADC of the ESP8266 would get 4.2 * 100/420= 1 Volt

1 Volt is the max input to the ADC and will give a Raw reading of 1023.

The True voltage  then can be calculated by:
raw = AnalogRead(A0);voltage =raw/1023;
voltage =4.2*voltage;
Ofcourse you could also do that in one step, but I like to keep it easy to follow.

Wemos Battery monitoring
Wemos Battery monitoring

If you do use this possibility, do realise that the resistors drain the battery as well with a constant 10uA (4.2V/420 000ohm). The powerconsumption of an ESP8266 in deepsleep is about 77uA. With the battery monitor this would be 87uA, which is a sizeable increase. A solution could be to close off the Vbat to the A0 with a transistor, controlled from an ESP8266 pin

A program could look like this:


 * Wemos battery shield, measure Vbat
 * add 100k between Vbat and ADC
 * Voltage divider of 100k+220k over 100k
 * gives 100/420k
 * ergo 4.2V -> 1Volt
 * Max input on A0=1Volt ->1023
 * 4.2*(Raw/1023)=Vbat

// Connect RST en gpio16 (RST and D0 on Wemos)
#include <ESP8266WiFi.h>
unsigned int raw=0;
float volt=0.0;
// Time to sleep (in seconds):
const int sleepTimeS = 60;

void setup() {
  Serial.println("ESP8266 in normal mode");
  const char* ssid     = "YourSSID";
  const char* password = "YourPW";
  const char* host = "";
  const char* writeAPIKey="YourAPIkey";
  // put your setup code here, to run once:
  pinMode(A0, INPUT);
  raw = analogRead(A0);
//  Connect to WiFi network
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
  String v=String(volt);// change float into string
  // make TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
  String url = "/update?key=";
  url += writeAPIKey;
  url += "&field6=";// I had field 6 still free that's why
  url += String(volt);
  url += "\r\n";
// Send request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" +
                 "Connection: close\r\n\r\n");

   Serial.println("ESP8266 in sleep mode");
   ESP.deepSleep(sleepTimeS * 1000000);              

void loop() {
  //all code is in the Setup

So your touch sensor is not working?

sensorWe have all experienced it, you buy something at Aliexpress. It arrives and you confirm receipt before you have time to test everything and then when you finally get around to that… there is a problem.
That happened to me with a TTP223B capacitive touch sensor. Whatever I tried, the output remained low. Slightly frustrated I was looking at the rather simple board and thought that there really couldn’t be much wrong with it.
ttp223-icFound a datasheet of the TTP223B ic that is on this module and started measuring. Well to make a long story short, the input pin (pin 3) seemed to have no connection with the sensorplate. When I would just touch the input pin, it switched very well. According to an application note in the datasheet capacitor C1 should be between  the input and  the ground and as it should be connected it also should be connected to the  sensorplate, which in fact it was. Turns out pin 3 was not connected to anything. A small wire that I soldered between the top of C1 and  pin 3 remedied everything and after that the sensor worked wonder well.
On checking the feedback of people who ordered this sensor, I noticed many experienced the same problem. No doubt the manufacturer (not perse the seller) must have known about this.