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.

Connect ESP8266 with Thingspeak through LUA: Analog pin and Internal ReferenceVoltage

esp8266-thingspeakluaConnecting your ESP to Thingspeak with a program written in your Arduino IDE is quite easy and those programs come a dime a dozen.
However, when I went to look for a program that did the same in LUA I came a cross a number of programs that simply didn’t work.
So I had to give it a go myself.
The below program is more or less a skeleton for thingspeak connection. It reads two values and posts those on Thingspeak. As it was just for testing I didnt want to add a lot of sensors, so th eonly two values read are the Internal reference voltage and the analog value from ADC0.
To make the program easily adaptable, I readthe sensors in a seperate function.
If you want to add a variable resistor to test the ADC, mind you that it can only take 1 Volt input so you need a voltage divider that limits it to 1 volt instead of 3.3 Volt.
When using the program dont forget your network credentials and  Thingspeak API Key

WRITEKEY="T3I6T9YF67JE527" -- set your thingspeak.com key
wifi.setmode(wifi.STATION)
wifi.sta.config("YourSSID","YourPW")
wifi.sta.connect()
tmr.delay(1000000)
volt=0 --Internal reference voltage
ana=0 -- analog port A0 Mind you, this one has a 1 Volt max

--read sensor
function ReadSensor()
volt = node.readvdd33()
ana=adc.read(0) -- 1V=1023
print("Internal Ref.Voltage: " ..(volt/1000).."."..(volt%1000).." Volt")
print("Analoog: "..ana)
end 

-- send to https://api.thingspeak.com 
function sendTS() 
conn = nil
conn = net.createConnection(net.TCP, 0)
conn:on("receive", function(conn, payload)success = true print(payload)end)
conn:on("connection",
   function(conn, payload)
   print("Connected")
   conn:send('GET /update?key='..WRITEKEY..'&field1='..(volt/1000)..'.'..(volt%1000)..'&field2='..ana..'HTTP/1.1\r\n\
   Host: api.thingspeak.com\r\nAccept: */*\r\nUser-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n\r\n')end)
conn:on("disconnection", function(conn, payload) print('Disconnected') end)
conn:connect(80,'184.106.153.149')
end

ReadSensor()
sendTS()
tmr.alarm(1,6000,1,function()ReadSensor()sendTS()end)

Now I haven’t been completely honest here, as it isnt really good practice to read the internal Voltage and the A0 port as it reads either the one or the other.
When using the  A0 to read internal voltage  in the Arduino IDE rather than in LUA ADC_MODE(ADC_VCC); in combination with ESP.getVcc() is now the correct way to do it. Using readvdd33 causes problems

Adding a PCF 8591 ADC/DAC to ESP8266-01

ad-da-converter-moduleThe ESP8266-01 is a great WiFi enabled  microcontroller but it only has 4 I/O pins broken out. Fortunately it does support I2C protocol so in spite of  the low number of pins, there still is a lot of hardware that can be added.
As the ESP8266-01 has no analog inputs at all, adding an ADC to it is something I wanted to do. After all,  sensors as LDR or NTC are still analog.
The PCF8591 is such an ADC: it is  a single-chip, single‑supply low‑power 8‑bit CMOS data acquisition device with four analog inputs, one analog output and a serial I²C‑bus interface. Three address pins A0, A1 and A2 are used for programming the hardware address, allowing the use of up to eight devices connected to the I²C‑bus without additional hardware. I doubt whether I need more than 8 of those chips. Lets just start with one. Although one can get the individual chip, I have chosen for a module that actually already has some sensors on it:

  • AIN0 – Jumper P5 – Light Dependent Resistor (LDR)
  • AIN1 – Jumper P4 – Thermistor
  • AIN2 – Not connected
  • AIN3 – Jumper P6 – Potentiometer

pcf8591-circ
The I2C address of the PCF8591 is determined by the pins A0-A2. As they are close to the Ground pin, let’s start with grounding them (as they are on the module).
pcf8591adresThe address is 1001A2A1A0. With A2-A0 being LOW, that is 1001000=0x48.

base A2A1A0 Hex Dec
1001 000 48 72
1001 001 49 73
1001 010 4A 74
1001 011 4B 75
1001 100 4C 76
1001 101 4D 77
1001 110 4E 78
1001 111 4F 79

In some programs you will see the address as “0x90>>1” Which is 48 as well. The “0x90” counts the LSB of the 8 bit address, which is the R/W bit. With the Write Bit Low (=active) the full address is 10010000=0x90, but the rightshift 1 removes the LSB again, making it 0x48.
As it is not my intention to explain the full innerworkings of the PCF8591, but just to show it is working with the ESP8266-01, I will skip a full technical discussion. For now it is enough to know that the PCF8591 can be read byte for byte, but it can also be read in ‘burst mode’, in which we read the 4 analog values all at once. The program I present is burstmode with autoincrement of the address. The reason we read 5 bytes instead of 4 is because the first byte contains old data. As the datasheet states in paragraph 8.4: “The first byte transmitted in a read cycle contains the conversion result code of the previous read cycle.”

#include "Wire.h"
int PCF8591=0x48; // I2C bus address
byte ana0, ana1, ana2, ana3;
void setup()
{
 Wire.pins(0,2);// just to make sure
 Wire.begin(0,2);// the SDA and SCL
}
void loop()
{
 Wire.beginTransmission(PCF8591); // wake up PCF8591
 Wire.write(0x04); // control byte: reads ADC0 then auto-increment
 Wire.endTransmission(); // end tranmission
 Wire.requestFrom(PCF8591, 5);
 ana0=Wire.read();// throw this one away
 ana0=Wire.read();
 ana1=Wire.read();
 ana2=Wire.read();
 ana3=Wire.read();
}

Obviously when you have these values read you will need to do something with them: print them out, put them on yr own webpage or upload them to e.g. Thingspeak
we can do that as follows:

#include  // ESP8266WiFi.h library
#include "Wire.h"
int PCF8591=0x48; // I2C bus address
byte ana0, ana1, ana2, ana3;

const char* ssid     = "YourNetworkSSID";
const char* password = "YourPassword";
const char* host = "api.thingspeak.com";
const char* writeAPIKey = "YourWriteAPI";

void setup() {
  // Initialize sensor
 Wire.pins(0,2);// just to make sure
 Wire.begin(0,2);// the SDA and SCL

//  Connect to WiFi network
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

void loop() {
 Wire.beginTransmission(PCF8591); // wake up PCF8591
 Wire.write(0x04); // control byte: reads ADC0 then auto-increment
 Wire.endTransmission(); // end tranmission
 Wire.requestFrom(PCF8591, 5);
 ana0=Wire.read();
 ana0=Wire.read();
 ana1=Wire.read();
 ana2=Wire.read();
 ana3=Wire.read();

// make TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    return;
  }

  String url = "/update?key=";
  url+=writeAPIKey;
  url+="&field1=";
  url+=String(ana0);
  url+="&field2=";
  url+=String(ana1);
  url+="&field3=";
  url+=String(ana2);
  url+="&field3=";
  url+=String(ana3);
  url+="\r\n";
  
  // Request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
    delay(1000);
}

Writing to the DAC is as follows:

#define PCF8591 (0x48) // I2C bus address
void setup()
{
 Wire.pins(0,2);// just to make sure
 Wire.begin(0,2);
}
void loop()
{
 for (int i=0; i<256; i++)  { Wire.beginTransmission(PCF8591);  Wire.write(0x40); // control byte b1000000  Wire.write(i);  Wire.endTransmission(); }  for (int i=255; i>=0; --i)
 {
 Wire.beginTransmission(PCF8591); // wake up PCF8591
 Wire.write(0x40); // turn on DAC b1000000
 Wire.write(i); 
 Wire.endTransmission();
 }
}

Calculations
A the board normally uses the 3.3v supply as the reference voltage:
The input voltage is determined with:
vIn = value * (3.3 / 255)
and the output voltage is:
vOut = (value / 255) * 3.3
or to find the value for a given voltage:
value = (vOut / 3.3) * 255

So if for instance I would write  the value of 50 to the DAC. The voltage would be: 0.64V
In order to test that, I hooked up Aout to the A0 of an ESP 8266-12 and found a value of 192.
To calculate that to a voltage that is  (192/1023)*3.3=0.162V. I guess that is close enough.
Oddly though when I hooked up the Aout to AIN2 or AIN1 that didn seem to give reliable readings. A value of 50 written to Aout should give a value of 50 on AIN, but oddly it didnt

In my version of the board the NTC channel only varied between 255 and 254, changing the temperatuur didnt seem to have any influence, but removing jumper P4 made the value go all over the place so i presume the channel id ok, and only the NTC might not be OK.

Using the 4 pins of the ESP8266-01

esp8266_henhouseThe limited number (4) of GPIO pins on the ESP8266-01 may seem like an obstacle, for any serious application.

Yet if one uses the pins in a smart way it is very well possible to do a lot with only those 4 pins.
In some of my recent postings, I have shown the use of a DHT11 a DS18B20, an OLED, an RTC and a BMP180 with the ESP8266-01.
In this posting I set out to use 4 sensors and a display, while also uploading the acquired data to Thingspeak. It actually is expanding on a project of monitoring the atmosphere in and around my chicken coop. Yes, you could call this a weatherstation, but it is just to illustrate the use of the 4 pins, you could easily make something else this way

I will be using 2 pins for I2C (BMP180 and OLED)
1 pin for 2 DS18B20 sensors via the OneWire protocol
1 pin for the DHT11
Although the ESP8266-01 now has all its pins used, I can still add more sensors (or actuators) through the OneWire protocol and/or via the I2C protocol.

So, what do we need:
BOM

  • ESP8266-01
  • 2x DS18B20
  • 1x DHT11
  • 1x BMP180
  • OLED (optional)

and ofcourse a breadboard, a 3.3 V PSU and some breadboard wires and a Thingspeak acount

Just some remarks regarding the BOM:

  • ESP8266-01
    Obviously the project is about utilizing the limited pins of the ESP8266-01, but if you still need to buy one, you could consider an ESP8266-12 that has more pins
  • DHT11
    A cheap all purpose humidity and temperature sensor. It is not hugely accurate but it will do. If you still need to buy one, you could opt for the DHT22 that is supposedly more accurate, but you could also opt for the AMS2321. That is a sort of DHT22 that is suitable for I2C, thus freeing another pin
  • BMP180
    measures temperature and Airpressure. It is the successor of the BMP085, but it also now has some suvessors itself. There is the (cheaper) BMP280, but you could also opt for the BME280 that measures temperature, airpresure AND humidity. That way you can save on the DHT/AMS sensor
  • OLED
    I just used that so I quickly could see whether the sensors were read, but you could just as well check it on Thingspeak. The OLED is too small anyway to print all the read values

The circuit

weerstationThe 4 pins of the ESP8266 are not indicated as such on the PCB, and most images only clearly state GPIO0 and GPIO2.
However the ESP826-01 has a a GPIO1 pin (the Tx pin) and a GPIO3 pin (the Rx pin).
i will be using those pins as follows

  • GPIO0 -> SDA pin of the I2C port
  • GPIO1 ->DHT11
  • GPIO2-> SCL pin of the I2C port
  • GPIO3-> OneWire Bus

As my I2C modules already have pull up resistors, I will not add any I2C pullup resistors there. The DS18B20 still needs a pull up resistor for which I used a 4k7, but it is really not that critical, a 10k is also good. The DHT11 supposedly also needs a pull-up resistor but I found it to work without one as well. adding a 4k7 resistor didnt change any of the readings, so I left it out. Many of the 3 pin DHT11 modules, already have a 10 k soldered onto the module.

I just realized that I didnt draw the connections for the OLED. That is because I only hooked it up for a quick check, but should you want to add it, it is just a matter of connecting SDA to SDA and SCL to SCL… and ofcourse the ground and Vcc pins to their counterparts

The program is quite straightforward. First it sets up the libraries and the sensors.
It attaches the DHT11 to pin 1 (Tx) and the OnWire bus for the DS18B20 to pin 3 (Rx). In order to use more than 1 DS18B20 sensor on the OneWire bus, you need to know their ‘unique adress’. If you do not have that then you need a program to read those addresses. Do that on an arduino for ease.

In the program you still have to provide your WiFi credentials as well as the write API for your Thingspeak Channel

 

/*
   Field 1 temp roost (DHT11)
   Field 2 humidity roost (DHT11)
   field 3 Coop temperature (DS18B20)
   field 4 soil temperature (DS18B20)
   field 5 Airpressure (bmp180)
   field 6 Outside temperature (bmp180)
 * */
#include <DHT.h>
#include  <OneWire.h>//  http://www.pjrc.com/teensy/td_libs_OneWire.html
#include <DallasTemperature.h> //   http://milesburton.com/Main_Page?title=Dallas_Tem...
#include <Adafruit_BMP085.h>
#include <ESP8266WiFi.h>
#include "SSD1306.h"
SSD1306  display(0x3c, 0, 2);

#define DHTPIN 1  //GPIO1 (Tx)
#define DHTTYPE  DHT11
#define ONE_WIRE_BUS 3 // GPIO3=Rx

const char* ssid     = "YourSSID";
const char* password = "YourPassword";
const char* host = "api.thingspeak.com";
const char* writeAPIKey = "W367812985"; //use YOUR writeApi

//DHT11 stuff
float temperature_buiten;
float temperature_buiten2;
DHT dht(DHTPIN, DHTTYPE, 15);

//DS18b20 stuff
OneWire oneWire(ONE_WIRE_BUS); //oneWire instance to communicate with any OneWire devices
DallasTemperature sensors(&oneWire);// Pass address of our oneWire instance to Dallas Temperature.
DeviceAddress Probe01 = { 0x28, 0x0F, 0x2A, 0x28, 0x00, 0x00, 0x80, 0x9F};
DeviceAddress Probe02 = { 0x28, 0x10, 0xA4, 0x57, 0x04, 0x00, 0x00, 0xA9};

// bmp180 stuff
Adafruit_BMP085 bmp;

void setup() {
  //I2C stuff
  Wire.pins(0, 2);
  Wire.begin(0, 2);
  // Initialize sensors
  //dht 11 stuff
  dht.begin();
  //ds18b20 stuff
  sensors.begin();//ds18b20
  // set the resolution to 10 bit (Can be 9 to 12 bits .. lower is faster)
  sensors.setResolution(Probe01, 10);
  sensors.setResolution(Probe02, 10);
  //bmp180 stuff
  if (!bmp.begin()) {
    //   Serial.println("No BMP180 / BMP085");
    //   while (1) {}
  }

  //OLED stuff
  display.init();
  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_10);
  delay(1000);

  //  Connect to WiFi network
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

void loop() {
  //ds18b20stuff-------------------
  sensors.requestTemperatures(); // Send the command to get temperatures
  temperature_buiten = sensors.getTempC(Probe01);//
  temperature_buiten2 = sensors.getTempC(Probe02);//
  //dht11 stuff--------------------
  float humidity = dht.readHumidity();
  float temperature = dht.readTemperature();
  if (isnan(humidity) || isnan(temperature)) {
    return;
  }
  //bmp stuff-------------------------
    String t= String(bmp.readTemperature());
    String p=String(bmp.readPressure());
  //OLED stuff--------------------------
  display.clear();
  display.drawString(0,10,p);//bmp pressure
  display.drawString(0,24,String(temperature_buiten));//ds18b20
  display.drawString(0,38,String(humidity));//dht11
  display.display();

  // make TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    return;
  }

  String url = "/update?key=";
  url += writeAPIKey;
  url += "&field1=";
  url += String(temperature);// roost (DHT1)
  url += "&field2=";
  url += String(humidity);// roost (DHT11)
  url += "&field3=";
  url += String(temperature_buiten);//coop temperature (DS18B20 nr 1)
  url += "&field4=";
  url += String(temperature_buiten2); //soil temperature (DS18B29 nr 2)
  url +="&field5=";
  url +=String(bmp.readTemperature());Outside temperature (BMP180)
  url +="&field6=";
  url +=String(bmp.readPressure());// Airpressure (BMP180)
  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");

  delay(1000);

}

Currently this program only monitors, but what is to stop you from adding a BH1750 I2C light sensor to measure if it is evening or morning or an RTC to know the time of day and to open and close the door of the coop automatically with aid of a PCF8574 I2C I/O expansion card, or as it is already in the garden, add a PCF8591 or ADS1115 AD converter to measure soil humidity and activate a pump when necessary. Or maybe switching on the water basin heater when the temperature falls below zero
if there is an I2 C chip for it, the ESP8266 can probably use it.

NOTE: the Adafruit DHT library contains an error that may show up in bigger progrms on an 8266. If the majority of readings result in “failed to read”, it is time to comment out two erroneous lines in the DHT.cpp file as in the picture below:
adafruiterror

Adding a BMP180 to an ESP8266-01

esp8266-01-bmp180After I added an RTC and an OLED to the ESP8266-01 through I2C, I presumed it should not be too difficult to add a BMP180 as well, in spite of coming across some postings on Internet of people not succeeding.

My BMP180 module -from my Arduino days- was a 5 Volt module, which made me think I may need a level shifter, which would be a pity as the BMP180 is in fact a 3.3V chip.

bmp180-5-33The circuit of my BMP180 module shows that the I2C pull up resistors (4k7) are in fact connected to the 3.3 V line that is provided by a 662k voltage regulator (as was to be expected). This meant that even if I fed the module with 5 Volt, I would not need a level shifter. And as the 662K is a low drop regulator and the BMP 180 also works with voltages lower than 3.3 (1.8-3.6 in fact), I presumed I didn’t need 5 Volt whatsoever.
The connection of the BMP180 is simple Vcc to Vcc, Ground to ground, SDA to SDA and SCL to SCL. On the ESP8266 I am using GPIO0 as SDA and GPIO2 as SCL

BOM

Just some remarks on the BOM

  • ESP8266-01: If you still have to buy this, consider an ESP8266-12. it isn’t much more expensive and has more pins. Some modules like Wemos D1 even have an USB added
  • BMP180: If you still need to buy this, consider a BMP280 that is more precise and cheaper or even a BME280 that can also measure humidity. The BME280 is slightly more expensive. I have not been able to test it, but the BMP280 needs a different library and the BME280 needs a different library.
  • Adafruit BMP_085 Library: This is the ‘Old’ library. Adafruit has a newer one that I found less pleasant to work with and I seem to remember it also needed the Adafruit ‘unified sensor’ library. There is a Sparkfun library as well
  • The female and male headers and the piece of veroboard are used to make a breadboard friendly adapter for the ESP8266-01
  • If you dont have a 3.3 Volt USB-TTL adapter yet and are only planning to work with the ESP8266-01, consider this handy device.
  • The OLED is just used to display the values. Ofcourse you may use an LCD as well, or forget about the display and send it off to a website or Thingspeak

esp8266-01-bmp180-circuitThe connections couldn’t be simpler:
I used GPIO0 as SDA and GPIO2 as SCL. The BMP180 and OLED have the pin nominations clearly stamped on them so you only need to connect as follows All Vcc-s together All Grounds together BMP180 and OLED SDA pins to GPIO0 BMP180 and OLED SCL pins to GPIO2 Finally connect the CH_PD pin with Vcc Make sure you identify the proper pins. Your modules may have a pin sequence that differs from mine. As my BMP180 module already had pull up resistors, I didnt need to add those. If your module does not, add 4k7 resistors as pull up on the SDA and SCL lines.

I presume you do know how to program the ESP8266. In short:
Connect Tx<->Rx (meaning the Tx of your ESP to the Rx of your USB-TTL converter)
Connect Rx<->Tx
Connect CH_PD<->Vcc
Connect GPIO0 <->Grnd
Connect Vcc <-> Vcc (Only if you have a 3.3 volt Vcc)
Connect Grnd <-> Grnd

#include <Wire.h>
#include <Adafruit_BMP085.h>
#include "SSD1306.h"
Adafruit_BMP085 bmp;
SSD1306  display(0x3c, 0, 2);

void setup() {
  Serial.begin(9600);
  Wire.pins(0, 2);
  Wire.begin(0, 2);
  if (!bmp.begin()) {
    //   Serial.println("No BMP180 / BMP085");// we dont wait for this
    //   while (1) {}
  }
  display.init();
  display.flipScreenVertically();// I turn the screen coz easier in my setup
  display.setFont(ArialMT_Plain_10);
}

void loop() {
  display.clear();
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.setFont(ArialMT_Plain_16);


  String t = "T=" + String(bmp.readTemperature()) + " *C";
  String p = "P=" + String(bmp.readPressure()) + " Pa";
  String a = "A=" + String(bmp.readAltitude(103000)) + " m";// insert pressure at sea level
  String s= "S="+ String(bmp.readSealevelpressure(30))+" Pa";// or insert your atltitude 
  display.drawString(0, 10, t);
  display.drawString(0, 24, p);
  display.drawString(0, 38, a);
  //display.drawString(0, 38, s);// if you want to calculate sealevelpressure
  // write the buffer to the display
  display.display();
  delay(2000);
}

As you can see, one of the parameters is the Altitude. This value is only correct if you supply the program with the pressure at sea level for your location. As that pressure can change, it is not of real value. On the other hand, as the altitude or elevation is much less likely to change (unless you are mobile), you could provide the known elevation for your location and then back calculate the pressure at sea level. Or… given the fact you have a WiFi processor available, read the current pressure at sea level from a web site and then calculate your altitude.

The temperature readings of the BMP180, though precise, still can be off (too high) if the sensor is mounted too close to the ESP8266. Whether this is a result of the HF radio waves or just direct heat of the processor is still being argued. I think it is the latter

Adding an RTC and OLED to ESP8266-01

dsc_0024Adding an RTC and OLED to ESP8266-01 is fairly easy with I2C. The ESP8266-01 has 4 I/O pins that can be used for  I2C. using the GPIO0 and GPIO2 for sda resp scl is more or less standard.

esp8266-rtcoledI presume you do know how to program the ESP8266. In short: Connect Tx<->Rx (meaning the Tx of your ESP to the Rx of your USB-TTL converter)
Connect Rx<->Tx Connect CH_PD<->Vcc Connect GPIO0 <->Grnd
As both modules already had pull up resistors, I didnt need to add those. If your modules do not, add 4k7 resistors as pull up on the SDA and SCL lines.

/* ************************************
 Read the time from RTC and display on OLED
 with an ESP8266<br> sda=0, scl=2
* *************************************/

// Libraries
#include <Wire.h>
#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
#include "RTClib.h" //  Lady Ada
//Object declarations
RTC_DS1307 rtc;            // RTC
SSD1306  display(0x3c, 0, 2);//0x3C being the usual address of the OLED

//Month and Day Arrays. Put in Language of your choice, omitt the 'day' part of the weekdays
char *maand[] =
{
  "Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"
};
char *dagen[] = {"Zon", "Maan", "Dins", "Woens", "Donder", "Vrij", "Zater" };


// date and time variables
byte m = 0;    // contains the minutes, refreshed each loop
byte h = 0;    // contains the hours, refreshed each loop
byte s = 0;    // contains the seconds, refreshed each loop
byte mo = 0;   // contains the month, refreshes each loop
int j = 0;     // contains the year, refreshed each loop
byte d = 0;    // contains the day (1-31)
byte dag = 0;  // contains day of week (0-6)

void setup() {
  Wire.pins(0, 2);// yes, see text
  Wire.begin(0,2);// 0=sda, 2=scl
  rtc.begin();

// reading of time here only necessary if you want to use it in setup
  DateTime now = rtc.now();
  dag = now.dayOfTheWeek();
  j = now.year();
  mo = now.month();
  d = now.day();
  h = now.hour();
  m = now.minute();
  s = now.second();
  DateTime compiled = DateTime(__DATE__, __TIME__);
  if (now.unixtime() < compiled.unixtime())
  {
    Serial.print(F("Current Unix time"));
    Serial.println(now.unixtime());
    Serial.print(F("Compiled Unix time"));
    Serial.println(compiled.unixtime());
    Serial.println("RTC is older than compile time! Updating");
    // following line sets the RTC to the date & time this sketch was compiled<br>   // uncomment to set the time
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  // Initialise the display.
  display.init();
  display.flipScreenVertically();// flipping came in handy for me with regard 
                                                                // to screen position
  display.setFont(ArialMT_Plain_10);

}


void loop() {
  display.clear();
  DateTime now = rtc.now();
  dag = now.dayOfTheWeek();
  j = now.year();
  mo = now.month();
  d = now.day();
  h = now.hour();
  m = now.minute();
  s = now.second();

  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.setFont(ArialMT_Plain_16);
  String t = String(h) + ":" + String(m) + ":" + String(s);
  String t2 = String(d) + ":"  + String(mo) + ":" + String(j);
  display.drawString(0, 10, t);//
  display.drawString(0, 24, t2);
  display.drawString(0, 38, maand[mo - 1]);
  String d = dagen[dag];
  d = d + "dag";//adding the word 'dag' (=day)  to the names of the days
  display.drawString(0, 52, d);
  // write the buffer to the display
  display.display();
  delay(10);
}

The code is fairly straightforward but it does contain some peculiarities.
I make a call to ‘Wire.pins(sda,scl)’. That seems redundant and in fact the call was deprecated, but apparently if any other library would make a call to ‘Wire()’ the proper definition of the pins for the sda and scl can get lost. So I left them both in for safety.
If you still have an old RTCLib you may get an error on ‘dayOfTheWeek’. That is because it used to be called ‘dayOfWeek’ but it got changed: update your library.

The last line, with the day on it, may be just a bit too much size for your OLED: set the font smaller (say ‘Plain_10’) and alter the print positions (the second digits in the display.drawString(0, x, string); statements)

Adding 433MHz RC to ESP8266-01

esp266-433Currently I have a homeautomation system on an Arduino. It uses 433 Mhz to switch lamps and stuff. It works fully automatic and if i want to intervene I use bluetooth to give commands.
It works well, but if I am away from home, I cannot intervene or check anything anymore. So I started to transfer the entire Arduino based system to an ESP8266.
Obviously that is a big overhaul and one of the first things I wanted to check is how well my 433 Mhz switches could be integrated with an ESP8266.
As such code might be beneficial to others, I thought I’d publish it here.
The 433 Mhz library I use is the enhanced RemoteSwitch library. I find that a bit more pleasant than the RCSwitch library because for many (not for all) remote switch sockets you do not need to sniff any code. Just knowing what type of Switch you have is enough.
The example below switches 4 sockets. I have explained the use of those switches with the RemoteSwitch library in another post. Obviously I switch many more in my house, but I wanted to keep things in this example simple. I am using an ESP8266-01, the simplest of the ESP8266 modules. I use GPIO2 to connect to the signal pin of a 433 MHz transmitter and feed everything with 3.3 Volt. As the ESP8266 is working on 3.3Volt, the transmitter is also working on 3.3Volt. I didnt notice any problem with that, but it is better to use a decent antenna that is easy to make, rather than just a 1/4 wavelength rod. Under no circumstance put 5 volt on any of your ESP8266 pins. If for whatever reason you need or want to feed the transmitter with a higher voltage, then I presume it is ok to still connect the GPIO2 pin to the data pin of the transmitter, as I presume that doesnt carry a voltage (but better do not risk it), but the transmitter may not recognize the ESP8266 output as HIGH. Adding a levelconverter may be necessary then, but to be clear: It works well with 3.3 Volt for the transmitter
The Sketch is quite straightforward. I included 4 switches as example. Therefore there are 8 buttons defined (ON and OFF for each channel.
If you want to add more switches, add the names for these in the Array. The program will automatically generate the required buttons. Add the On and Off codes for yr switch to code for the pages via a Switch /case statement.
When you start the program the relevant connection data is printed in the serialmonitor but the IP that you need can also be checked in the DHCPclient list of your router

/*
    This Sketch demonstrates the use of the Extended RemoteSwitch Library  with an ESP8266-01 WiFi module
    The setup is as follows:
    Supply module with 3.3 Volt
    Attach  pin GPIO2 with the signal pin of a 433 Mhz transmitter module
    The names you want to attach to the Buttons are defined in  the array "socketnames"
    the number of sockets can be extended. Pages are dynamically generated based on the
    size of the array as calculated by "ARRAY_SIZE"
    The use of  4 different modules is demonstrated:
    ELRO AB440
    Blokker /SelectRemote 1728029
    EverFlourish EMW203
    Eurodomest 972080
    Basic idea from Alexbloggt
    23-09-2016 DIY_bloke
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <RemoteSwitch.h> //FuzzyLogic extended lib

/************************************************
            Object Declarations
 ***********************************************/
ElroAb440Switch ab440Switch(2);
BlokkerSwitch3 blokkerTransmitter(2);// SelectRemote 1728029
EverFlourishSwitch everswitch(2);  // EverFlourish EMW203
Ener002Switch enerswitch(2);      // Eurodomest 972080
//  Fill out the base address of YOUR Eurodomest switch
const unsigned long euro  = 823149;  // base adres eurodomest  : 11001000111101101101  Supply the baseaddress of YOUR Eurodomest
#define ElroAAN ab440Switch.sendSignal(29, 'A', true)
#define ElroUIT ab440Switch.sendSignal(29, 'A', false)
#define BlokkerAAN blokkerTransmitter.sendSignal(1, true)
#define BlokkerUIT blokkerTransmitter.sendSignal(1, false)
#define EverFlourishAAN everswitch.sendSignal('A', 1, true)
#define EverFlourishUIT everswitch.sendSignal('A', 1, false)
#define EnerAAN enerswitch.sendSignal(euro, 1, true)
#define EnerUIT enerswitch.sendSignal(euro, 1, false)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
MDNSResponder mdns;
// Replace with your network credentials
const char* ssid = "YourSSID";
const char* password = "YourPassword";
ESP8266WebServer server(80);
// Define names of your buttons here, number of buttons will be  automatically adapted
char* socketnames[] = {"ELROAB440", "Blokker", "EverFlourish", "ActionSwitch"};
int numofsockets = ARRAY_SIZE (socketnames);//bevat de grootte van het Array
// sample css and html code
String css = "body {background-color:#ffffff; color: #000000; font-family: 'Century Gothic', CenturyGothic, AppleGothic, sans-serif;}h1 {font-size: 2em;}";
String head1 = "<!DOCTYPE html> <html> <head> <title>RemoteSwitch Demo</title> <style>";
String head2 = "</style></head><body><center>";
String header = head1 + css + head2;
String body = "";
String website(String h, String b) {
  String complete = h + b;
  return complete;
}
void setup(void) {
  // adapt body part of html if necessary
  body = "<h1>RemoteSwitch Demo</h1>";
  // socket names and buttons are created dynamical
  for (int i = 0; i < numofsockets; i++) {
    String namesocket = socketnames[i];
    body = body + "<p>" + namesocket + " <a href=\"socket" + String(i) + "On\"><button>ON</button></a> <a href=\"socket" + String(i) + "Off\"><button>OFF</button></a></p>";
  }
  body += "</center></body>";
  delay(1000);
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // serial output of connection details
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  if (mdns.begin("esp8266", WiFi.localIP())) {
    Serial.println("MDNS responder started");
  }
  // this page is loaded when accessing the root of esp8266´s IP
  server.on("/", []() {
    String webPage = website(header, body);
    server.send(200, "text/html", webPage);
  });

  /************************************************
                        Dynamically creating pages
   *********************************************** */
  for (int i = 0; i < numofsockets; i++) {
    String pathOn = "/socket" + String(i) + "On";
    const char* pathOnChar = pathOn.c_str();
    String pathOff = "/socket" + String(i) + "Off";
    const char* pathOffChar = pathOff.c_str();
    //content ON page
    server.on(pathOnChar, [i]() {
      String webPage = website(header, body);
      server.send(200, "text/html", webPage);

      switch (i)
      {
        case 0:
          ElroAAN;
          break;
        case 1:
          BlokkerAAN;
          break;
        case 2:
          EverFlourishAAN;
          break;
        case 3:
          EnerAAN;
          break;
        default:
          break;

      }
      delay(500);
    });
    //content OFF page
    server.on(pathOffChar, [i]() {
      String webPage = website(header, body);
      server.send(200, "text/html", webPage);

      switch (i)
      {
        case 0:
          ElroUIT;
          break;
        case 1:
          BlokkerUIT;
          break;
        case 2:
          EverFlourishUIT;
          break;
        case 3:
          EnerUIT;
          break;
        default:
          break;

      }
      delay(500);
    });
  }
  server.begin();
  Serial.println("HTTP server started");
}
void loop(void) {
  server.handleClient();
}