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();
}

A capacitive soil humidity sensor: Part 1

An automated plant/garden watering system is a popular application for  the Arduino and other microcontrollers. The humidity sensor that is often used is  often a resistance meter: 2 probes in the soil form a resistor and as part of a voltage divider that gives info on the amount of water in the soil.
The major shortcoming of these sensors is that since there is a current flowing, the probe is sensitive to electrolytic corrosion. Another shortcoming is that it doesnt really give information on the soil humidity, but more on the  ion concentration in the soil. Remember: pure water is a bad conductor, It are the ions in the water that make it a conductor.

To get around the corrosion, people have started to feed the probe with AC rather than DC current, but at best the circuits for this supply a pulsating DC current. Another  possibility to minimize corrosion is to  switch off  the current to the probe and only switch it on when a measurement is taken, say every 5  minutes.

All these measures help but even then, just due to the contact with moist soil, the metal on the probe will corrode and weather.
Another method is to encase the probes in plaster. Some people swear by it but I  think it is bothersome. Also the plaster encased probe has a lag as it will retain water  for some time after the  soil is already dry and it will still be dry for some time after the soil is already moist.

Capacitive measuring is a way to avoid these problems. With capacitive measurement the ‘plates’ of the capacitor can be electrically isolated from the soil and the soil in fact forms the dielectrum of the capacitor. Water makes a good dielectrum, whereas ions dont. Capacitive measuring therefore will have a better correlation with the actual amount of water in the soil than resistive measuring and, as said, ideally there will not be any corrosion.

Although the Arduino can measure capacity, it needs 3 pins for that. Also, it isnt really practical to have a long wire as part of your soil probe capacitor go to your Arduino as the wire and whether it is  straight or curly or in a loop, will act as a parasitic capacity and affect the measurement.
Putting your Arduino right onto your plantbed might also not be the best solution.

capacitive74hc14
RC Oscillator With 74HCT14

A better way to do this is to introduce an RC oscillator in which the soil functions as a capacitor and the Arduino measures the frequency that comes out of the oscillator. More water  will increase the value of the ‘capacitor’ which usually will lower the frequency (or increase the cycle time) and that can be measured with the arduino.

An easy RC oscillator can be seen in the figure to the right. A 74HC14 or 74HCT14 Inverter Schmitt-trigger is all you need. For the HC version the Frequency is:
f=1/T=1/(0.8*R*C)
for the HCT version it is:
f=1/T=1/(0.67*R*C)

But in fact the frequency isn’t really that important because we are not making a frequency meter. We are only interested in changes of the frequency that relate to  dry, moist or wet soil. The workings of this type of Oscillator are explained here. and here. The theory behind the frequency calculation is explained here.

leydenjarI tested my set-up initially with a sort of Leyden Jar as a capacitor. Simply put I taped two pieces of alufoil on the outside of a glass jar, attached wires to it and tried if I could measure a change between an empty and a full jar. I started out using a 100k resistor, but only got a decent range after using a 2M2 resistor: an empty jar gave me 1uSec (maybe less, but I guess that was my lower limit) a half full jar around 50uS and a full jar about 100uS (measured with PulseIn). From using a known capacitor I knew I had to use the formula f=1/T=1/(0.67*R*C), but as said, neither the frequency or the actual capacitor value are of much importance as we are just looking for  changes.

Nevertheless the capacity of this jar (when full) could be calculated from
100*10⁻⁶=0.67*2.2*10⁶*C
C=(100*10⁻⁶)/(1.47*10⁶)
C=68*10⁻¹²
C=68pF
Now ofcourse this isn’t entirely correct as with PulseIn We only measured half a cycle, so in fact the Capacity is more likely to be 136pF, provided the dutycycle is 50% (some sources say it is 50% others say it is 33% with the space  2*mark).

byte pin = 8;
unsigned long duration;

void setup()
{
  pinMode(pin, INPUT);
  Serial.begin(115200);
}

void loop()
{
  duration = pulseIn(pin, HIGH);
  Serial.print("Time ");
  Serial.print(duration);
  Serial.print(" usec ");
  Serial.print(500/duration);
  Serial.print(" kHz ");
  Serial.print(500000/duration);
  Serial.println(" Hz");
  delay(500);
}

Then it was time to do some garden field tests. There are several ways to construct a probe: two pieces of PCB at a distance from eachother, One piece of PCB with two plates etched onto it, or a piece of double sided PCB. With regerd to the latter, we tend to think of a capacitor as two plates with a dielectrum in between, but in fact it can also be two  plates with a dielectrum around it.

capacitive probe-textMy garden field test, using two insulated plates of PCB (picture) kinda gave similar results as with the Leyden Jar so I knew I had a decent design.

Yet, two plates is not really very handy: you have a loose wire connecting the plates and as that forms part of the capacitor it introduces stray capacitance, so I decided to go for either a double sided PCB, or a single sided PCB with two plates etched onto it and then place the oscillator on that PCB as well. Frankly, that idea isnt new as many of the (semi)DIY (e.g. the ‘Chirp’) or commercial capacitive probes follow that design as well.

Now it is always good  that before you make a PCB to think through what you want. As I was using only 1/6th of the 74HCT14, I was thinking maybe I could use the other gates as RC oscillators as well  for e.g. an LDR or NTC. Now ofcourse I immediately dismissed that again as I could just as well use an analog read of those and I would have to run extra cables that would all carry a frequency signal, no doubt those would interfere, but it got me thinking. The ‘Chirp’ has a big brother that has an I2C interface, if I would add that, I could add some other sensors (light, temperature)  to my probe. With just the capacitive sensor I would have to run 3 wires (+Vcc, signal, ground). With I2C 4 wires (+Vcc, SDA, SCL, Ground) would be enough for a number of sensors on my probe. Also, as I have various plantbeds, having a number of I2C probes wouldnt require  more inputs on my Arduino.

Obviously, adding I2C meant adding a microcontroller, preferably a cheap one, which easily brings one to the attiny25/45/85 series. If you have good eye sight and a steady hand, you could consider the soic version that is available from 30-70 cts. If you go for a DIP version, that is around 0.9-1 euro. Considering one can get an entire Pro Mini for about 1.20, obviously that is a narrow gap and I (or you) could consider giving each plantbed a totally dedicated  Pro Mini microprocessor that could take care of the irrigation as well.
Having said that, in the past, I have made a self contained system for plantbeds, just using 1 Opamp, so maybe I should just consider this I2C excercise a ‘learning excercise’

capacitive74HC14_attinyI came up with the following circuit. It is easy to recognise the RC oscillator. The cycle signal is fed to PB1 whereas the analog inputs on PB3 and PB4
A3= PB3=physical pin2;A2=PB4=physical pin3.
Pin PB2 is used as SCL signal and PB0 as SDA signal for the I2C interface.

If for any reason you do not have a 74HCx14 in your toolbox, there are other ways of constructing an RC generator. E.g. a 555 or a 74HC00. Even a single transistor could be used. With this type of oscillator the dutycycle approaches 50%
rc-osc

555-oscillator-probe

In a next article I will discuss how to implement the I2C software.

Sending sensor data wireless (433MHz) with an Attiny85 or Attiny45 with Manchestercode

Sending sensor data wireless (433MHz) with an Attiny85 or Attiny45 with Manchestercode

P1060016
instructables-transmitter

In an earlier article I described how to send RF/wireless data between two Attiny85 chips with a 433 MHz transmitter/Receiver pair.
Now I will  give a more practical program that sends  3 variables from an LDR and a DHT11 sensor.
The connections are simple
The transmitter is connected to D0 (pin 5). The DHT11 sensor is connected to D4 (pin 3) and an LDR connected to A1 (pin 7), with the other end connected to Vcc and a corresponding pull down resistor.
The big photo shows a test circuit on stripboard, The smaller picture shows the final PCB. The huge amount of  cables at the top doesn’t mean much, I just use a few

/*
Pin 2 =A3 D3
pin 3 = A2 D4
pin5 =D0
Pin 6=D1
Pin7= D2 A1

LDR=A1
PIR= D1
RF433=D0
DHT11=D4
LED=D3
*/
// libraries
#include <dht11.h> //Rob Tillaert
#include <Manchester.h>
dht11 DHT11;
#define DHT11PIN 4
#define TX_PIN 0  //pin where your transmitter is connected
//variables
float h=0;
float t=0;
int transmit_data = 2761;
int transmit_t = 0; // temperature
int transmit_h = 0; // humidity
int transmit_l=0; // lightlevel
int transmit_p = 0; //PIR
int transmit_s = 0; /Station identifier
byte ledPin=3;
int light=0;

void setup() {
pinMode(1, INPUT);
pinMode(ledPin,OUTPUT);
man.setupTransmit(TX_PIN, MAN_1200);
}

void loop() {
int chk = DHT11.read(DHT11PIN);
h=DHT11.humidity;
t=DHT11.temperature;
transmit_h=2000+h;
transmit_t=2100+t;
transmit_l=2200+(analogRead(A1)/10);
transmit_p=2300+digitalRead(1);
transmit_s=2500;
digitalWrite(ledPin,HIGH);
man.transmit(transmit_h);
delay(200);
man.transmit(transmit_t);
delay(200);
man.transmit(transmit_l);
delay(200);
digitalWrite(ledPin,LOW);
delay(1000);
}

The idea of adding a number, in this case in the 2000 range is to be able to identify what (which station) is sending the data: any 2000 number I know is humidity, any 2100 number I know is temperature, etc. Variables h and t are floats that can have decimals. As I am only interested in 2 digit accuracy, I just add them to an integer and thus turn them into integers. WIth regard to the lightlevel as it is an analog read it might be as high as 1023 (theoretically), so when it is divided by 10, the range will usuallu be 99 max a two digit number. If by any chance it would be 100, the transmitter will send a number as 24xx. The receiving software then knows it is a more than 2 digit value, but that will be very rare I then send 5  values: Humidity, temperature, light PIR and a station identifier ending the data. The receiving station then can identify where it came from and process the incoming signals (starting by dividing subtracting  the first two digits).
WIth regard to the lightlevel as it is an analog read it might be as high as 1023 (theoretically), so when it is divided by 10, the range will usually be 99 max a two digit number. If by any chance it would be 100, the transmitter will send a number as 24xx. The receiving software then knows it is a more than 2 digit value, but that will be very rare

It takes 3374 bytes so I could compile it in an Attiny45.

See also: DHT11 on Attiny85
Attiny DHT 11 & 433 MHz (with Oregon code)