ESP8266 Wi-Fi Module Revisited

A while back I posted some information about the ESP8266 Wi-Fi Module. You can view that post here. I mentioned that for testing it, an Arduino with multiple hardware serial ports would be ideal. Well, I just got an Arduino Leonardo which matches that criteria.

Here is how I hooked it up:

 

ESP8266 Fritzing Diagramyou can get the Fritzing file here. (The Fritzing part for the ESP8266 can be found here.)  Notice that the TX and RX serial connections ‘crossover’. Not crossing over is a common mistake when first hooking up a serial communications device.

The Arduino sketch I used was chosen via

Examples->04.Communication->MultiSerialMega

 

void setup()  {
  Serial.begin(9600);
  Serial1.begin(115200);
}
void loop()  {
   if (Serial1.available()) {
      int inByte = Serial1.read();
      Serial.write(inByte);
   }
 
  if (Serial.available()) {
     int inByte = Serial.read();
     Serial1.write(inByte);
  }
}

You only need to change the serial BAUD rate for Serial1 (the ESP8266) from the default of 9600 to 115200. Once you upload the sketch to the Arduino, run the serial monitor and the commands you type will be sent to the ESP8266. Any response from the ESP8266 will be ‘echoed’ in the serial monitor.

Testing the ESP8266 on an Arduino with two hardware serial ports is much easier than my original way. Now I can add sensors to this circuit and send the information they gather through the ESP8266 to the WEB.

 

UPDATE: 12/29/2014

 

I ran into a common problem with the ESP8266. Sometimes the ESP8266 will return ‘busy’ when you enter a command. The ESP8266 is essentially locked up (i.e. frozen) at this point. To recover you can power off the device and power back on. However that is not a programatic solution. Fortunately there is a way to ‘RESET’ the ESP8266 from code if this situation occurs.

 

Here is how to wire the ESP8266:

 

ESP8266 Reset Circuit

 

 

 

 

 

 

You can download the Fritzing diagram source here.

 

Here is a sketch showing the Reset function.

 

/*
Arduino Leonardo <--> ESP8266
Eamil:  earl@microcontrollerelectonics.com
*/

#define SSID "your_SSID"
#define PASS "your_password"
#define DST_IP "192.168.0.100"
#define CONNECT_ATTEMPTS 5
#define RST 8
#define CHP 9
#define LED 13

void setup() {

  pinMode(RST, OUTPUT);
  pinMode(LED, OUTPUT);
  pinMode(CHP, OUTPUT);

  reset();

  Serial.begin(9600);
  Serial1.begin(115200);

  delay(5000);

  Serial1.println("AT+RST");
  delay(1000);

  if (Serial1.find("ready")) Serial.println("Module is ready");
  else {
    Serial.println("ESP8266 Module did not respond.");
    Serial.println("Enter Commands Manually.");
    while (1) chk_serial_io();
  }
  delay(1000);
  boolean connected = false;
  for (int i = 0; i < CONNECT_ATTEMPTS; i++) {

    if (connectWiFi()) {
      connected = true;
      break;
    }
  }
  if (!connected) {
    Serial.println("Enter Commands Manually.");
    while (1) chk_serial_io();
  }
  delay(5000);
  Serial1.println("AT+CIFSR");
  Serial.println("ip address:");
  while (Serial1.available()) Serial.write(Serial1.read());
  Serial1.println("AT+CIPMUX=0");
}

void reset() {
  digitalWrite(LED,HIGH);
  digitalWrite(CHP,HIGH);
  digitalWrite(RST,LOW);
  delay(100);
  digitalWrite(RST,HIGH);
  delay(1000);
  digitalWrite(LED,LOW);
}

void loop() {
  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += DST_IP;
  cmd += "\",80";
  Serial1.println(cmd);
  Serial.println(cmd);
  if (Serial1.find("Error")) return;
  cmd = "GET / HTTP/1.0\r\n\r\n";
  Serial1.print("AT+CIPSEND=");
  Serial1.println(cmd.length());
  if (Serial1.find(">")) {
    Serial.print(">");

  } else {
    Serial1.println("AT+CIPCLOSE");
    Serial.println("connect timeout");
    delay(1000);
    return;
  }
  Serial1.print(cmd);
  delay(2000);
  while (Serial1.available()) {
    char c = Serial1.read();
    Serial.write(c);
    if (c == '\r') Serial.print('\n');
  }
  Serial.println("====");
  delay(1000);
}

void chk_serial_io() {
  if (Serial1.available()) {
//    if (Serial1.find("busy")) {
//      Serial.println("Resetting...");
//      reset();
//    }
    int inByte = Serial1.read();
    Serial.write(inByte);
  }
  if (Serial.available()) {
    int inByte = Serial.read();
    Serial1.write(inByte);
  }
}

boolean connectWiFi() {
  Serial1.println("AT+CWMODE=1");
  String cmd = "AT+CWJAP=\"";
  cmd += SSID;
  cmd += "\",\"";
  cmd += PASS;
  cmd += "\"";
  Serial.println(cmd);
  Serial1.println(cmd);
  delay(2000);
  if (Serial1.find("OK")) {
    Serial.println("OK, WiFi Connected.");
    return true;
  } else {
    Serial.println("Can not connect to WiFi.");
    return false;
  }
}

 

 

Explaindio Video Creator

You may not think this post has a lot to do with MicroController Electronics, however, read on before you formulate an opinion.

There is a new Windows and Mac Video Creator program called Eplaindio that recently became available. I am using it to create training, educational and advertising videos for various projects. It is very powerful yet simple to use.

Basically you can take images, SVG graphics, video backgrounds, optional audio files and create scenes which you put together in sequences to make a video. Additionally, slides created in Adobe Flash can be imported to provide additional animation like capabilities.

I made a sample demo video to demonstrate its potential use (especially in electronics)  which you can view below.

All of the electronic SVG images in the sample demo are from fritzing.org. I took those (~6,500) SVG files (which are distributed under the Creative Commons license) and put them into folders and then created a PNG image for each SVG. (The PNGs are used by Explaindio to present a view of the SVG for selection / inclusion into a ‘sketch’.)  I used Inkscape in non-gui batch mode (-z)  to take the SVGs and save them as  PNG images.  (You can download the python script I used to do that HERE.) Contact me if you want a copy of the Fritzing.org electronics SVG/PNG library for use with Explaindio.

If you are interested in that library you might also be interested in the (~8000) SVG graphic files from OpenClipart.org.The SVGs from there can be freely used commercially. I converted them also into folders (with PNGs) for use in Explaindio. Contact me if you want a copy of that library.

It is interesting to note that the Explaindio project files ([.explaindio] used to create the videos) are XML like. That opens possibilities to generate them ‘programatically’.  For example, when I browse through an SVG library looking for ideas or specific images that I need, I can drag/drop them into a folder with my project/scene creator script (add optional text files for adding text slides) and when done, click on the creator script for it to create the project and/or scenes. It saves me a bit of time. Contact me if you are interested in it. (You’ll need to download and install Python in order to use it.)

All in all, I think Explaindio can be taken advantage of to teach Electronics (and other things).

What do you think? Leave a comment and buy your copy of Explaindio here.

 

Prototyping Circuits using a Breadboard

When I first heard the term ‘breadboard’ when reading about electronic circuits, I thought about bread of course and some great bread making recipes. I must have been hungry!

For electronic recipes 🙄 (i.e. circuits), originally a smooth piece of wood (literally a breadboard with nails and wiring) was used as a surface for assembling/wiring  electronic components. We still use the term breadboard today although the synonym protoboard  is also used.

The breadboard of today is reusable and does not use solder which makes it a good experimental tool to prototype circuits. It consists of a perforated block of plastic with numerous metal spring clips under the holes and comes in various colors and sizes (i.e. number of holes):

BreadBoard_170_red BreadBoard_170_green BreadBoard_170_blue

 

 

 

 

BreadBoard

BreadBoard

 

My favorite one is transparent so you can see the spring clips. It has 400 holes and looks like this:

BreadBoard

On this breadboard there are two identical sides separated by the middle notch. Each side has 200 holes ( each divided into two ‘strips’). One strip is called the terminal strip and the other is called a bus strip (which contains two columns:  one for ground – and one for a supply voltage +.)  The clips on the right and left of the middle notch are each connected in a radial way;  five clips (i.e., beneath five holes) in a row on each side of the notch are electrically connected. On the bus strip the whole row (+ or -) is electrically connected.

Breadboards usually have an adhesive backing and can be interlocked for larger projects. The spacing between the holes is typically 0.1 in (2.54 mm). Integrated circuits (ICs) in dual in-line packages (DIPs) can be inserted to straddle the centerline/notch of the block. Interconnecting wires and the leads of components (such as capacitors, resistors, and inductors) can be inserted into the remaining free holes to complete the circuit. Connecting wire should be 22 AWG (0.33 mm2) solid copper. If you have any CAT5 cable around, that is perfect.

Cat5_Cable

Just cut to the length you need unravel the wire  and straighten it out. The wire ends should be stripped 316 to 516 in (4.8 to 7.9 mm).

Arduino Weather Station

With just a few sensors, one can determine a lot about the weather.

 

BMP085 Barometric Sensor

BMP085

DHT11 Humidity and Temperature Sensor

DHT11

 

 

 

 

 

 

 

The BMP085 can be used to sense barometric pressure and temperature and the DHT11 can be used to sense humidity and also temperature.

Here is what they look like attached to a mini breadboard:

Weather_Station

Arudino Breadboard Weather Station

An FTDI cable (not shown in the above image) can be plugged in at the top left of the breadboard to power this circuit and collect the data.

To collect data in an arduino sketch. the DHT library and the Wire Library will be needed. Both of which are included in the Aruduino IDE.

Here is the arduino sketch (code) to display barometric pressure, humidity and temperature (from both devices) :

// Weather Station DHT11 & BMP085
// from earl@microcontrollerelectronics.com

#include "DHT.h"
#include <Wire.h>

#define DHTPIN 8
#define LED    9
#define DHTTYPE DHT11
#define BMP085_ADDRESS 0x77

const unsigned char OSS = 0;
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;
long b5;

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  dht.begin();
  pinMode(LED, OUTPUT);
  Wire.begin();
  bmp085Calibration();
}

void loop() {

  float h = dht.readHumidity();
  float t = dht.readTemperature();
  float f = t * 1.8 + 32.0;

  digitalWrite(LED, HIGH);

  Serial.println("--start-\n");

  Serial.println("Sensor: DHT11");
  if (isnan(t) || isnan(h)) {
    Serial.println("Failed to read from DHT");
  } else {
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.println(" %");
    Serial.print("Temperature: ");
    Serial.print(t);
    Serial.println(" °C");
    Serial.print("Temperature: ");
    Serial.print(f);
    Serial.println(" °F");
    Serial.println("");
  }

  float temperature   = bmp085GetTemperature(bmp085ReadUT()); //MUST be called first
  float pressure      = bmp085GetPressure(bmp085ReadUP());
  float atm           = pressure / 101325; // "standard atmosphere"
//  float altitude      = calcAltitude(pressure); //Uncompensated caculation - in Meters
  float temperature_F = (temperature * 1.8) + 32;

  Serial.println("Sensor: BMP085");
  Serial.print("Temperature: ");
  Serial.print(temperature, 2); //display 2 decimal places
  Serial.println(" °C");

  Serial.print("Temperature: ");
  Serial.print(temperature_F, 2); //display 2 decimal places
  Serial.println(" °F");

  Serial.print("Pressure: ");
  Serial.print(pressure, 0); //whole number only.
  Serial.println(" Pascals");

  Serial.print("Standard Atmosphere: ");
  Serial.println(atm, 4); //display 4 decimal places

//  Serial.print("Altitude: ");
//  Serial.print(altitude, 2); //display 2 decimal places
//  Serial.println(" M");

  Serial.println("");
  Serial.println("--end-\n");

  delay(250);
  digitalWrite(LED, LOW);    

  delay(5000);
}


// Stores all of the bmp085's calibration values into global variables
// Calibration values are required to calculate temp and pressure
// This function should be called at the beginning of the program
void bmp085Calibration()
{
  ac1 = bmp085ReadInt(0xAA);
  ac2 = bmp085ReadInt(0xAC);
  ac3 = bmp085ReadInt(0xAE);
  ac4 = bmp085ReadInt(0xB0);
  ac5 = bmp085ReadInt(0xB2);
  ac6 = bmp085ReadInt(0xB4);
  b1 = bmp085ReadInt(0xB6);
  b2 = bmp085ReadInt(0xB8);
  mb = bmp085ReadInt(0xBA);
  mc = bmp085ReadInt(0xBC);
  md = bmp085ReadInt(0xBE);
}

// Calculate temperature in deg C
  float bmp085GetTemperature(unsigned int ut){
  long x1, x2;

  x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
  x2 = ((long)mc << 11)/(x1 + md);
  b5 = x1 + x2;

  float temp = ((b5 + 8)>>4);
  temp = temp /10;

  return temp;
}

// Calculate pressure given up
// calibration values must be known
// b5 is also required so bmp085GetTemperature(...) must be called first.
// Value returned will be pressure in units of Pa.
  long bmp085GetPressure(unsigned long up){
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;

  b6 = b5 - 4000;
  // Calculate B3
  x1 = (b2 * (b6 * b6)>>12)>>11;
  x2 = (ac2 * b6)>>11;
  x3 = x1 + x2;
  b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;

  // Calculate B4
  x1 = (ac3 * b6)>>13;
  x2 = (b1 * ((b6 * b6)>>12))>>16;
  x3 = ((x1 + x2) + 2)>>2;
  b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;

  b7 = ((unsigned long)(up - b3) * (50000>>OSS));
  if (b7 < 0x80000000)
    p = (b7<<1)/b4;
  else
    p = (b7/b4)<<1;

  x1 = (p>>8) * (p>>8);
  x1 = (x1 * 3038)>>16;
  x2 = (-7357 * p)>>16;
  p += (x1 + x2 + 3791)>>4;

  long temp = p;
  return temp;
}

// Read 1 byte from the BMP085 at 'address'
char bmp085Read(unsigned char address)
{
  unsigned char data;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  Wire.requestFrom(BMP085_ADDRESS, 1);
  while(!Wire.available());

  return Wire.read();
}

// Read 2 bytes from the BMP085
// First byte will be from 'address'
// Second byte will be from 'address'+1
int bmp085ReadInt(unsigned char address)
{
  unsigned char msb, lsb;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  Wire.requestFrom(BMP085_ADDRESS, 2);
  while(Wire.available()<2);
  msb = Wire.read();
  lsb = Wire.read();

  return (int) msb<<8 | lsb;
}

// Read the uncompensated temperature value
unsigned int bmp085ReadUT(){
  unsigned int ut;

  // Write 0x2E into Register 0xF4
  // This requests a temperature reading
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x2E);
  Wire.endTransmission();

  // Wait at least 4.5ms
  delay(5);

  // Read two bytes from registers 0xF6 and 0xF7
  ut = bmp085ReadInt(0xF6);
  return ut;
}

// Read the uncompensated pressure value
unsigned long bmp085ReadUP(){

  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;

  // Write 0x34+(OSS<<6) into register 0xF4
  // Request a pressure reading w/ oversampling setting
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x34 + (OSS<<6));
  Wire.endTransmission();

  // Wait for conversion, delay time dependent on OSS
  delay(2 + (3<<OSS));

  // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
  msb = bmp085Read(0xF6);
  lsb = bmp085Read(0xF7);
  xlsb = bmp085Read(0xF8);

  up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);

  return up;
}


void writeRegister(int deviceAddress, byte address, byte val) {
  Wire.beginTransmission(deviceAddress); // start transmission to device
  Wire.write(address);       // send register address
  Wire.write(val);         // send value to write
  Wire.endTransmission();     // end transmission
}

int readRegister(int deviceAddress, byte address){

  int v;
  Wire.beginTransmission(deviceAddress);
  Wire.write(address); // register to read
  Wire.endTransmission();

  Wire.requestFrom(deviceAddress, 1); // read a byte

  while(!Wire.available()) ; // waiting

  v = Wire.read();
  return v;
}

float calcAltitude(float pressure){

  float A = pressure/101325;
  float B = 1/5.25588;
  float C = pow(A,B);
  C = 1 - C;
  C = C /0.0000225577;

  return C;
}

Update 11/5/2020, things have changed in the Arduino IDE and libraries since this was first posted. Here is an updated sketch:

// Weather Station DHT11 & BMP085
// from earl@microcontrollerelectronics.com
 
#include <DHT11.h>
#include <Wire.h>
 
#define DHT11PIN 8
#define LED      9
#define BMP085_ADDRESS 0x77

DHT11 dht11(DHT11PIN);
const unsigned char OSS = 0;
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;
long b5;
float t, h, f;
int err;

void setup() {
  Serial.begin(9600);
  pinMode(LED, OUTPUT);
  Wire.begin();
  bmp085Calibration();
}
 
void loop() {
  
if ((err=dht11.read(h, t))==0){
  float f = t * 1.8 + 32.0;

  digitalWrite(LED, HIGH);
 
  Serial.println("--start-\n");
 
  Serial.println("Sensor: DHT11");
  if (isnan(t) || isnan(h)) {
    Serial.println("Failed to read from DHT");
  } else {
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.println(" %");
    Serial.print("Temperature: ");
    Serial.print(t);
    Serial.println(" °C");
    Serial.print("Temperature: ");
    Serial.print(f);
    Serial.println(" °F");
    Serial.println("");
  }
 
  float temperature   = bmp085GetTemperature(bmp085ReadUT()); //MUST be called first
  float pressure      = bmp085GetPressure(bmp085ReadUP());
  float atm           = pressure / 101325; // "standard atmosphere"
//  float altitude      = calcAltitude(pressure); //Uncompensated caculation - in Meters
  float temperature_F = (temperature * 1.8) + 32;
 
  Serial.println("Sensor: BMP085");
  Serial.print("Temperature: ");
  Serial.print(temperature, 2); //display 2 decimal places
  Serial.println(" °C");
 
  Serial.print("Temperature: ");
  Serial.print(temperature_F, 2); //display 2 decimal places
  Serial.println(" °F");
 
  Serial.print("Pressure: ");
  Serial.print(pressure, 0); //whole number only.
  Serial.println(" Pascals");
 
  Serial.print("Standard Atmosphere: ");
  Serial.println(atm, 4); //display 4 decimal places
 
//  Serial.print("Altitude: ");
//  Serial.print(altitude, 2); //display 2 decimal places
//  Serial.println(" M");
 
  Serial.println("");
  Serial.println("--end-\n");
 
  delay(250);
  digitalWrite(LED, LOW);    
 

}
  delay(5000);
} 
 
// Stores all of the bmp085's calibration values into global variables
// Calibration values are required to calculate temp and pressure
// This function should be called at the beginning of the program
void bmp085Calibration()
{
  ac1 = bmp085ReadInt(0xAA);
  ac2 = bmp085ReadInt(0xAC);
  ac3 = bmp085ReadInt(0xAE);
  ac4 = bmp085ReadInt(0xB0);
  ac5 = bmp085ReadInt(0xB2);
  ac6 = bmp085ReadInt(0xB4);
  b1 = bmp085ReadInt(0xB6);
  b2 = bmp085ReadInt(0xB8);
  mb = bmp085ReadInt(0xBA);
  mc = bmp085ReadInt(0xBC);
  md = bmp085ReadInt(0xBE);
}
 
// Calculate temperature in deg C
  float bmp085GetTemperature(unsigned int ut){
  long x1, x2;
 
  x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
  x2 = ((long)mc << 11)/(x1 + md);
  b5 = x1 + x2;
 
  float temp = ((b5 + 8)>>4);
  temp = temp /10;
 
  return temp;
}
 
// Calculate pressure given up
// calibration values must be known
// b5 is also required so bmp085GetTemperature(...) must be called first.
// Value returned will be pressure in units of Pa.
  long bmp085GetPressure(unsigned long up){
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;
 
  b6 = b5 - 4000;
  // Calculate B3
  x1 = (b2 * (b6 * b6)>>12)>>11;
  x2 = (ac2 * b6)>>11;
  x3 = x1 + x2;
  b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
 
  // Calculate B4
  x1 = (ac3 * b6)>>13;
  x2 = (b1 * ((b6 * b6)>>12))>>16;
  x3 = ((x1 + x2) + 2)>>2;
  b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
 
  b7 = ((unsigned long)(up - b3) * (50000>>OSS));
  if (b7 < 0x80000000)
    p = (b7<<1)/b4;
  else
    p = (b7/b4)<<1;
 
  x1 = (p>>8) * (p>>8);
  x1 = (x1 * 3038)>>16;
  x2 = (-7357 * p)>>16;
  p += (x1 + x2 + 3791)>>4;
 
  long temp = p;
  return temp;
}
 
// Read 1 byte from the BMP085 at 'address'
char bmp085Read(unsigned char address)
{
  unsigned char data;
 
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();
 
  Wire.requestFrom(BMP085_ADDRESS, 1);
  while(!Wire.available());
 
  return Wire.read();
}
 
// Read 2 bytes from the BMP085
// First byte will be from 'address'
// Second byte will be from 'address'+1
int bmp085ReadInt(unsigned char address)
{
  unsigned char msb, lsb;
 
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();
 
  Wire.requestFrom(BMP085_ADDRESS, 2);
  while(Wire.available()<2);
  msb = Wire.read();
  lsb = Wire.read();
 
  return (int) msb<<8 | lsb;
}
 
// Read the uncompensated temperature value
unsigned int bmp085ReadUT(){
  unsigned int ut;
 
  // Write 0x2E into Register 0xF4
  // This requests a temperature reading
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x2E);
  Wire.endTransmission();
 
  // Wait at least 4.5ms
  delay(5);
 
  // Read two bytes from registers 0xF6 and 0xF7
  ut = bmp085ReadInt(0xF6);
  return ut;
}
 
// Read the uncompensated pressure value
unsigned long bmp085ReadUP(){
 
  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;
 
  // Write 0x34+(OSS<<6) into register 0xF4
  // Request a pressure reading w/ oversampling setting
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x34 + (OSS<<6));
  Wire.endTransmission();
 
  // Wait for conversion, delay time dependent on OSS
  delay(2 + (3<<OSS));
 
  // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
  msb = bmp085Read(0xF6);
  lsb = bmp085Read(0xF7);
  xlsb = bmp085Read(0xF8);
 
  up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
 
  return up;
}
 
 
void writeRegister(int deviceAddress, byte address, byte val) {
  Wire.beginTransmission(deviceAddress); // start transmission to device
  Wire.write(address);       // send register address
  Wire.write(val);         // send value to write
  Wire.endTransmission();     // end transmission
}
 
int readRegister(int deviceAddress, byte address){
 
  int v;
  Wire.beginTransmission(deviceAddress);
  Wire.write(address); // register to read
  Wire.endTransmission();
 
  Wire.requestFrom(deviceAddress, 1); // read a byte
 
  while(!Wire.available()) ; // waiting
 
  v = Wire.read();
  return v;
}
 
float calcAltitude(float pressure){
 
  float A = pressure/101325;
  float B = 1/5.25588;
  float C = pow(A,B);
  C = 1 - C;
  C = C /0.0000225577;
 
  return C;
}

 

 

HC-SR04 Distance Sensing

Animals such as bats and porpoises use ultrasound for locating prey and obstacles.  If you have an electronic device that needs to sense distances from objects (like a robot or an automatic door opener) you might consider using an HC-SR04 Sensor Module.

HC-SR04 Ultrasonic Sensor

HC-SR04

No one can sneak up on you with a couple of these and a buzzer attached to your favorite Arduino board. 🙄

The HC-SR04 module sends out an ultrasonic ‘PING’ and then detects its return after ‘bouncing off’ something in the distance. By measuring the round trip time (and knowing the speed that sound travels), a calculation can be made to determine the distance of the object from the HC-SR04.

Here is a public domain Ardunio sketch (the comments show the math involved to calculate the distances, they also show how the HC-SR04 is wired):

 

/* HC-SR04 Sensor

https://www.dealextreme.com/p/hc-sr04-ultrasonic-sensor-distance-measuring-module-133696
This sketch reads a HC-SR04 ultrasonic rangefinder and returns the
distance to the closest object in range. To do this, it sends a pulse
to the sensor to initiate a reading, then listens for a pulse
to return. The length of the returning pulse is proportional to
the distance of the object from the sensor.
The circuit:

* VCC connection of the sensor attached to +5V
* GND connection of the sensor attached to ground
* TRIG connection of the sensor attached to digital pin 7
* ECHO connection of the sensor attached to digital pin 6


Original code for Ping))) example was created by David A. Mellis
Adapted for HC-SR04 by Tautvidas Sipavicius

This example code is in the public domain.
*/


const int trigPin = 7;
const int echoPin = 6;

void setup() {
// initialize serial communication:
Serial.begin(9600);
}

void loop() {
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration, inches, cm;

// The sensor is triggered by a HIGH pulse of 10 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(trigPin, OUTPUT);
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(15);
digitalWrite(trigPin, LOW);

// Read the signal from the sensor: a HIGH pulse whose
// duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);

// convert the time into a distance
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(500);
}

long microsecondsToInches(long microseconds) {
// According to Parallax's datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second). This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
// See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds) {
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}

Measuring Light Intensity

Any camera buffs out there? Sometimes it is handy to be able to measure the amount of light at a particular spot. This is needed sometimes so you can adjust your camera to take the ‘perfect’ picture. Or perhaps you are calculating the amount of solar energy your solar panels will be producing given the amount of light available.

In any case, there  are a couple of components that are very useful for this, the TSL235R light to frequency converter and the BH1750 digital light sensor.

 

TSL235R

TSL235R

BH1750

BH1750

 

 

 

 

 

 

 

 

 

Here are both components on a DIY Arduino breadboard (click on the image to enlarge it):

Arduino LUX Meter

Arduino LUX Meter

Here is the Arduino sketch (code) to get the readings from these components. (Note: the code comments show how these components are wired.) Two libraries are need for this sketch (Wire and BH1750).  The BH1750 library can be downloaded here.  The Wire library is included in the standard Arduino IDE.

 

/*
Arduino Lux Meter
From earl@microcontrollerelectronics.com

BH1750 Connection:
 VCC-5v
 GND-GND
 SCL-SCL(analog pin 5)
 SDA-SDA(analog pin 4)
 ADD-NC or GND

TSL235R Connection:
 PIN 1 - GND
 PIN 2 - VDD - 5V
 PIN 3 - SIGNAL IRQ 0

*/

#include <Wire.h>
#include <BH1750.h>

BH1750 lightMeter;

#define led 9

volatile unsigned long cnt = 0;
unsigned long oldcnt = 0;
unsigned long t = 0;
unsigned long last;

void irq1()
{
 cnt++;
}
void setup(){
 pinMode(led, OUTPUT); 
 Serial.begin(115200);
 Serial.println("START");
 pinMode(2, INPUT);
 digitalWrite(2, HIGH);
 attachInterrupt(0, irq1, RISING);
 lightMeter.begin();
}

void loop() {
 if (millis() - last >= 1000) {
 last = millis();
 t = cnt;
 unsigned long hz = t - oldcnt;
 digitalWrite(led, HIGH);
 Serial.print("FREQ: ");
 Serial.print(hz);
 Serial.print(" = ");
 Serial.print((hz+50)/100); // +50 == rounding last digit
 Serial.print(" mW/m2");
 oldcnt = t;

 uint16_t lux = lightMeter.readLightLevel();
 Serial.print(" Lux: ");
 Serial.println(lux);

 delay(500);
 digitalWrite(led, LOW);

}

ESP8266 Wi-Fi Module

My children bought a present for me recently (yes, another birthday, I really am getting older 🙁 ). It is an ESP8266 Module which is a self-contained [IoT] Wi-Fi networking solution. Here are pictures (with the pins labelled):

 

ESP8266

ESP8266 Wifi Transceiver Module

 

 

 

 

 

 

 

 

 

My module comes from Elecrow.com. Since this module is rather new there is not much documentation nor sample code for it, however there is a WEB site dedicated to these devices here :  esp8266.com.

The SDK is here. The Cross-Compiler is here. A very handy ESP8266 ROM Bootloader utility is here.

The module I have takes 5 pins (3.3V, GND, TxD, RxD and CH_PD). The CH_PD pin on my module needs 3.3V. The default BAUD rate for my module is 115200. I connected to it using an FTDI cable and Minicom. (For 3.3V I used an Arduino Nano.)

Here is a good article on hooking it up similar to how I did it with links to new firmware, sample code, newer SDK and other tools.

I plan on eventually attaching mine to an Arduino and using it to send sensor data to a WEB site for data collection.

Since the ESP8266 is a serial device and the debugging ‘view’ to what is going on with it (USB to the Arduino)  is also using a serial connection (FTDI probably), two serial connections are needed. I probably should explain this (especially if you are new to using Arduinos). All Arduino boards have at least one serial port (also known as a UART or USART). The  serial port communicates using digital pins 0 (RX) and 1 (TX) as well as communicating with the computer via USB. So,  if you use USB to communicate with the Arduino, you cannot also use pins 0 and 1 for digital input or output and thus you need to another serial port to both communicate with the Arduino and the ESP8266.

One might be tempted to try the Arduino software serial library to connect to the ESP8266, however the software serial library is too slow to keep up. Two hardware serial connections are therefore needed. An Arduino Leonardo, Due or Mega 2560 have at  least two hardware serial interfaces and would work fine for this purpose.

DIY Dual Relay Circuit

It is sometimes very handy to be able to control mains electric via an arduino to turn things like lights on and off.  [warning]BE VERY CAREFUL hooking up any mains electricity. [/warning]

I built a dual circuit so that two things can be controlled from one board. Here is the fritzing graphic:

 

DIY Dual Relay CircuitOnce built, here is what it looks like:

Dual Relay Circuit TopDual Relay Circuit Back

Click on the above images to enlarge them and see the parts used.

Input (3 pins) comes from a simple arduino circuit (GND, 5V Power and another pin to control the relay state). A simple arduino sketch can toggle the relay off/on.

Here is the fritzing source so you can modify it yourself.

3 PIN HD44780 LCD

One of the problems of connecting an HD44780 LCD

HD44780 LCDto an arduino is the number of pins taken up (usually 6). There is an older article here for hooking up an HD44780 LCD to an arduino with only 3 pins.  (Note: There is an alternate link here as the original link may be down.)

The circuit uses the 74HC595 shift register IC.  I liked the idea and have built several of these circuits.

 

LCD_Shift_Register

 

LCD_Shift_register_1

 

 

 

 

 

Thus I have a handy way of attaching an LCD to arduino projects without taking too many pins.

 

You will need a library for controlling the LCD (attached via the 74HC595 shift register) which you can get here. (Updated:  here)  A sample sketch is shown below. It is the same one here from the original author but I modified it via:

lcd.setLED2Pin(HIGH);

to turn the backlight on. Here is the sketch:

 

/*
 * 3-pin Arduino interface for HD44780 LCDs via 74HC595 Shift Register
 *     by Rowan Simms   code@rowansimms.com
 *     License: Creative Commons - Attribution.
 *     Full Documentation and Description:  http://rowansimms.com/article.php/lcd-hookup-in-seconds
 *
 * This sketch allows Arduinos to use a shift register to control an LCD, allowing
 * a reduction in pins it requires from 6 to 3 while still retaining full control
 * including backlight on/off.
 * This requires the use of the LiquidCrystal595 library
 * available at: http://code.google.com/p/arduino-lcd-3pin/
 */

#include <LiquidCrystal595.h>    // include the library
LiquidCrystal595 lcd(7,8,9);     // datapin, latchpin, clockpin

void setup() {
    lcd.init(7,8,9);
    lcd.setLED2Pin(HIGH);        // Backlight On
    lcd.begin(16,2);             // 16 characters, 2 rows
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Wow. 3 pins!");
    lcd.setCursor(0,1);
    lcd.print("Fabulous!"); 
}

void loop() {
    // not used.
}

DIY Arduino Circuit Board

Shown below is one of my DIY Arduino circuits.

DIY Arduino Circuit FrontDIY Arduino Circuit (Back View)

 

 

 

 

 

 

 

 

The circuit does not have the FTDI chip built in. The FTDI circuit is only needed for programming and cutting out un-necessary components saves a bit of money. The ICSP connection (6 pins comming out the side) on this circuit is perfectly connected to the SparkFun FTDI breakout board:

 

FTDI Breakout 5V

FTDI Breakout 5V

 

 

 

or an FTDI cable:

 

FTDI Cable

 

Here is the Fritzing graphic:

DIY Arduino Circuit Board

DIY Arduino Circuit Board

If you’d like to modify the Fritzing source, get it by clicking here.

Here is the parts list:

 

Quantity Description
 connecting wire
1 AVR Atmega328P
1 16Mh Crystal
2 22pf Capacitor
1 fiber protoboard
1 5mm Red LED
1 0.1 uf Capacitor
1 Base 28 Dip .3 inch
1 1/2 Watt 10K Ohm Resistor
1 1/2 Watt 220 Ohm Resistor
2 16 Pin Header Connector
1 6 Pin Connector 90 degrees

 

If you’d like to experiment on a breadboard before building (soldering) the circuit, here is the breadboard view:

Arduino on a BreadboardYou can  get the Fritzing source here if you’d like to modify it.

Load more