Monday, January 30, 2017

Temperature Controlled Relay

Like many people who enjoy seeing birds, we have feeders and a bird bath in our yard. In the winter the bath requires a heater to keep it from freezing. However, it only gets below freezing here a few dozen days a year, so the heater is usually just wasting electricity. Also, it makes the water evaporate much faster when it's on. What if we could automatically turn it on only when needed?

All it takes to do this is a temperature sensor, a relay, and of course, an Arduino. An enclosure holds these along with an old cell phone charger for power. An extension cord runs through the enclosure and is spliced into the relay. This device could also be used to control heating tape for protecting exposed pipes.

Enclosure with sensor visible through small hole

ds18b20 sensor is soldered
and insulated














One channel relay module

The final setup with the bird bath













You must provide good insulation for all the AC lines in the enclosure. I used wire nuts for all of the connections except the relay. The relay had screw terminals and the bottom of the PCB was exposed, so all of that was wrapped heavily with electrical tape. The keep the enclosure waterproof, I sealed the sensor and the extension cord holes with epoxy.

Circuit Diagram for temperature Controlled Relay

And, finally, here is the code I used.

/*
 *  Temperature Controlled Switch
 *  by ted.b.hale@gmail.com
 *  29-Jan-2017
 *
 *  read a ds18b20 temperature sensor and turn a relay on 
 *  when temperature is below freezing
 */

#include 
#include 
#include 

#define RELAY 0                     // relay control pin
#define ONE_WIRE_BUS 2              // one-wire bus pin
OneWire oneWire(ONE_WIRE_BUS);      
DallasTemperature sensors(&oneWire);
DeviceAddress thermo;               // address of ds18b20

//*****************************************************************************
// One time setup
void setup() 
{
  pinMode(RELAY,OUTPUT);            // relay pin is OUTPUT
  digitalWrite(RELAY,0);            // start with relay OFF

  sensors.begin();                  // initialize one-wire system
  sensors.getAddress(thermo, 0);    // get device address of sensor
}

//*****************************************************************************
// Main loop
void loop() 
{
  sensors.requestTemperatures();    // get the current temperature
  float tempC = sensors.getTempC(thermo);

  if (tempC<1.0)                    // if it's near or below freezing
  {
    digitalWrite(RELAY,1);          // then turn relay on
  }
  else
  {
    digitalWrite(RELAY,0);          // else turn relay off
  }
  delay(2000);                      // wait 2 seconds

}

Friday, January 20, 2017

ESP8266-01 Prototyping PCB

I have been working a lot lately with the ESP8266-01 WiFi module. This module can be used to add wireless network capability to an Arduino, but it is also capable of being programmed directly. They are great for Internet of Things devices since they are cheap (less than $2 each) and they have WiFi support built in. They can also run reasonably on batteries if you use sleep mode properly.

Unfortunately, they are not at all breadboard friendly. To make my life easier, I am developing a small prototyping board specifically to support the -01 version of the ESP8266. There are a few prototyping boards that support the -01 as well as other versions but I found them to be too large and more complex than what I wanted. Here is a view of my first few versions.

Here is the latest version with a few parts soldered on. I already have a few improvements for the next version, but that's the reason I only get 5 or 10 manufactured at a time. I paid just over $30 for 10 of these PCBs but if you are willing to wait a month for a shipment from China, you can get them for less than $15. You can compare prices at http://pcbshopper.com/ but be sure to note the total days and the total cost with shipping.

Once I settle on my design I will make the Gerber files available for download. If there is huge interest I might even start selling them.  On that note - How much would you pay for a kit that includes the PCB, the ESP, voltage regulator, capacitor, and headers?

A Word About PCB Design Software

I have tried numerous programs for designing Printed Circuit Boards (PCBs) and would like to share some info. There are lots of free programs available to create PCBs and some of them are quite good. However, they often provide output in a proprietary format to lock you into using their PCB manufacturing service. If you want more freedom, then you have very few options. What you need is a program that will output standard Gerber file format.

Rather than re-hash what has already been done, here is an excellent review of the various options.
https://www.sfcircuits.com/pcb-school/pcb-design-software-comparison-guide

One option that is not included is Fritzing. I did try this and did not find it well suited for PCB design. The software that I eventually went with is DipTrace. The free version will create PCBs up to 300 points and the lowest paid level is only $75.

Please leave your opinions and experiences with PCB design software in the comments.


Monday, January 16, 2017

WiFi Temperature Display

Recently my indoor/outdoor thermometer died and I was tired of paying $35 or more for something that would just die again after a year (and was terribly inaccurate to boot!) My solution was to just make a small display that gets the temperature from my personal weather station.

This blog post describes how I built my weather station based on a Raspberry Pi. I added to that software the capability for a network client to connect and request data. My remote display is powered by an ESP8266-01 module which has a processor and a WiFi interface. The -01 version only provides two GPIO pins, but that is enough for an I2C bus interface.

The only complication I ran into is that the LED display requires 5V but the ESP is 3V only. I solved that by powering the display directly from the power adapter and powering the ESP using a voltage adapter. This is the converter that I used, but I don't recommend it. It provides an adjustable output of 0.8 to 20V but is larger than a simple 3V regulator would be. It was also very difficult to adjust accurately. If you use one of these, be sure to adjust the voltage down before connecting it to the ESP or it will kill it.





The other parts I used were pretty straight-forward:
- a 7-segment LED display with I2C backpack https://www.adafruit.com/products/878
- a 6 pin header for connecting a serial interface for programming the device
- a small bit of prototyping board
- a project case from Radio Shack
- an old cell phone charger (very few amps required, so any would work)


Here is a look at the inside and the circuit diagram.



The code could be modified to display any data that you could get from the internet or local network. There is likely a web site (Weather Underground maybe) that will provide real-time weather data by zip code that could be used to display current outdoor temperature.

Here is my code. I used the Adafruit LED backpack library but had to make one change. The GPIO pins used for the I2C bus are hard-coded and these had to change to match the capabilities of the ESP.
This also can serve as a simple socket client program.

#define WIFINAME "Put Your SSID Here"
#define PASSWORD "Put Your Passwor Here"
#define HOSTNAME "IP address of host"
#define HOSTPORT 33333

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiClient.h>
#include <Wire.h>

#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"

Adafruit_7segment matrix = Adafruit_7segment();

WiFiClient client;


void setup() {
  matrix.begin(0x70);
  matrix.print(0x1111, HEX);
  matrix.writeDisplay();

  WiFi.mode(WIFI_STA);                        // WiFi client mode
  WiFi.begin(WIFINAME,PASSWORD);              // connect to WiFi
  while (WiFi.status() != WL_CONNECTED) {     // wait for wifi connection
    delay(500);
  }  
}


void loop()
{
  unsigned long t1;
  char resp[100];
  char c;
  int i;
  float ot;

  if (client.connect(HOSTNAME, HOSTPORT))
  {
    client.println("ot\n");
    t1 = millis();
    i = 0;
    memset(resp,0,100);
    while (true)
    {
      if (client.available())
      {
        c = client.read();
        if (c<' ') break;
        resp[i] = c;
        i++;
      }
      if (i>98) break;
      if ((millis()-t1)>5000) break;
    }
    ot = atof(resp);
    matrix.print(ot,1);
    matrix.writeDisplay();
  }
  else
  {
    matrix.print(0xEEEE, HEX);   
    matrix.writeDisplay();
  }

  client.stop();
  delay(10000);
}