All Posts

Mobile Weather Sensors Using ESP8266

mtbike

Mountain Biking in the local trails in my Southern California home has kept me both reasonably fit while maintaining a close connection with nature. As you roll through many of the trails here, the terrain varies significantly…from the darker shadows of the canyon floors to the wide-open sun exposed ridge-top fire roads. And with these changes there are noticeable variations in the temperature and moisture in the air.

So I got to thinking…

Wouldn’t it be interesting to track these variations as the trail climbs up the mountain face and descends down the other side? Sure, there are gadgets available that do this kind of thing. Like tracking your position, speed, altitude and heart-rate. If you really look around, you might even find one that reports the temperature. Not cheap, but they are available.

Hmmm… Let’s see, can we make a do-it-yourself alternate? A solution that is much cheaper than the cost of a commercially bought product?

This looked like a perfect task for the super low-cost ESP8266 and a few inexpensive sensors. Coupled with a data link to a smartphone, you got a mobile platform tailored to track just about anything. A system that can be tailored to your exact needs. All at a fraction of the cost of a commercially available product, if you can find one meeting the specifications you want.

Here is what I came up with…

My initial design simply collects data samples and saves them to a file on my Android SD Card. This file is then transferred to a PC for visual representation with excel. Later, I intend to add screens to the Android App to display the data on phone. But first, a data collection and storage system was needed.

After thinking about how I wanted to implement these features, the project was broken down into several phases. This post addresses phase 1. Yep, this project is “work-in-progress” and phase 1 is as far as I have gotten…so far. Check back to this blog soon for updates that cover the subsequent elements of this Application as they are developed. Once completed, the “phases” that following will be turned into links.

Phase 1: Mobile Data Collection

Okay, to get started, the scope of the data collection set needed to be defined. First I made a list of the information to collect. While subject to change, initial list includes:

Parameter Units Device
1 Temperature Degrees F ESP8266 Sensor (BMP085)
2 Barometric Pressure in Hg ESP8266 Sensor (BMP085)
3 Humidity Percent ESP8266 Sensor (DHT22)
4 Speed mph Smartphone GPS Sensor
5 Altitude feet Smartphone GPS Sensor
6 Heading Degrees Smartphone GPS Sensor
7 Latitude Degrees Smartphone GPS Sensor
8 Longitude Degrees Smartphone GPS Sensor
9 Heart Rate beats per minute Garmin Ant+ HRM
10 GPS Timestamp ms Smartphone GPS Sensor
11 ESP8266 Run-time seconds ESP8266
12 ESP8266 Heap Bytes ESP8266
13 ESP8266 Iterations Loops ESP8266

The Mobile Smartphone App

The smartphone App is obviously the heart of this project. In this first phase, it must gather data from 3 different sources. But that’s not the only thing to consider. Aside from the Smartphone App, the project also uses an external micro-controller. So the hardware and software design of the ESP8266 system also needs to be developed. But let’s start with the Smartphone App and it’s 3 sources of data.

  1. Phone’s Internal GPS Sensor
  2. ESP8266 Micro-controller
  3. Garmin Heart Rate Monitor

But how do we do it? What do the hardware and software components look like to make this a reality?

GPS Data

My first thought was to add a GPS sensor as an ESP8266 sensor input. But then the obvious hit me… The Smartphone has a built-in GPS Sensor. Why not use it instead of added a redundant capability to the ESP8266 system?

Thanks to the geolocation API included with HTML5, access to the Smartphone GPS data is easy. Starting with the default Native Cordova Android App, the App code (Javascript/jQuery) needed to collect location information from the Phone’s GPS receiver is minimal.

HTML to display the sensor data (simplified, styling excluded):

1. Temperature <p id="tempBaro"></p>
2. Barometric Pressure<p id="presBaro"></p>
3. Humidity<p id="humidity"></p>
4. Speed<p id="Speed"></p>
5. Altitude<p id="Altitude"></p>
6. Heading<p id="Heading"></p>
7. Latitude<p id="Lat"></p>
8. Longitude<p id="Lon"></p>
9. Heart Rate<p id="HeartRate"></p>
10. GPS Timestamp<p id="GpsTimestamp"></p>
11. ESP8266 Run-time<p id="systime"></p>
12. ESP8266 Heap<p id="sysheap"></p>
13. ESP8266 Iterations<p id="sysloop"></p>
Status:<p id="msg">Ok</p>

Javascript/jQuery to collect and update the sensor data display:

 options = {
     enableHighAccuracy: true,
     timeout: 1000,
     maximumAge: 0
 };
 
 //------------------------------------------
 // Functions triggered after page loaded
 //------------------------------------------
 jQuery(window).load(function () {
     navigator.geolocation.watchPosition(onSuccess, onError, options);
 });

 //------------------------------------------ 
 // onSuccess Callback
 //------------------------------------------
 function onSuccess(position) {
     var latt = position.coords.latitude.toFixed(7).toString();
     var long = position.coords.longitude.toFixed(7).toString();
     $("#Lat").html(latt.substring(0, 11));
     $("#Lon").html(long.substring(0, 12));
     $("#Speed").html(position.coords.speed);
     $("#Altitude").html(position.coords.altitude);
     $("#Heading").html(position.coords.heading);
     $("#GpsTimestamp").html(position.timestamp);
     updateWeatherSensorData();
 }
 //-----------------------------------------
 // onError Callback 
 //-----------------------------------------
 function onError(error) {
     //Do nothing (ignore data set) or display message here if an error occurs
     var element = document.getElementById('msg');
     element.innerHTML = 'Failed GPS monitor' + '<br />';
 }

 

The “options” structure sets the GPS configuration. The “enableHighAccuracy” field must be set to true. This tells the geolocation API to use the phones GPS Sensor. If it is set to false, the API will use the 4G or WIFI connection to determine location. Believe me, you do not want that active, it is very slow. It also will not work on the trail when you are out of cell tower range. The timeout is set to 1 second, setting the maximum time to acquire a location from the GPS sensor. Finally, the maximumAge sets the time to use a cached value before acquiring a new location from the sensor. Setting this to zero forces a new acquisition every time a position change is detected.

Once the Cordova web-based App page (index.html) has been loaded, the geolocation “watchPosition” callback is registered. Subsequently, every time the phones’ GPS sensor detects a change in position, the “onSuccess” callback function is executed. The “onError” callback is run if an error is detected.

navigator.geolocation.watchPosition(onSuccess, onError, options);

You can do anything you want with the data in the “onSuccess” callback. This example simply displays the values on the App window by setting the html for the objects by id to the GPS Sensor measured value. As noted, the next phase of this project will log these values to an SD card file on the Smartphone.

ESP8266 Data

The last line of the “onSuccess” callback executes the function “updateWeatherSensorData”.

 //--------------------------------------------
 //Update WeatherSensor Data
 //--------------------------------------------
 function updateWeatherSensorData() {
     requestURL = "http://192.168.22.1:9703/?request=GetSensors";
     if ( typeof updateWeatherSensorData.timeout == 'undefined' ) {
         // It has not... perform the initialization
         updateWeatherSensorData.timeout = 0;
     }
     //Get Weather Sensor Value
     $.ajax({
         url: requestURL,
         error: function(error){
             if(updateWeatherSensorData.timeout++ <10) {
                 setTimeout(updateWeatherSensorData, 1000);
             }
             else {
                 updateWeatherSensorData.timeout = 0;
             }
         },
         success: function(thedata){
             $("#tempBaro").html(thedata.B_Temperature);
             $("#presBaro").html(thedata.B_Pressure);
             $("#humidity").html(thedata.DH_Humidity);
             $("#systime").html(thedata.SYS_Time);
             $("#sysheap").html(thedata.SYS_Heap);
             $("#sysloop").html(thedata.SYS_Loopcnt);
             updateWeatherSensorData.timeout = 0;
         },
         timeout: 7000 // sets timeout to 7 seconds
     });
 }

 

The updateWeatherSensorData() function makes an AJAX request to the ESP8266 to return the current sensor values and status in JSON format. Just as with the GPS Sensor data, these values are simply used to set the html for the applicable displayed objects by id.

Heart Rate Monitor Data

A placeholder has been set in the code to collect heart rate monitor sensor data. While I have used Apps that interface with an external heart rate monitor using ANT+ and therefore know it is possible, I have have not accessed this interface in my own App…yet. So, not to hold up the initial release of this project, the Heart Rate Monitor data is planned to be added in Phase 5 using the ANT+ for Android API.

ESP8266 Configuration

The ESP8266 hardware interfaces to just two sensors for this initial design:

  1. BMP085 – Temperature and Pressure Sensors
  2. DHT22    – Temperature and Humidity Sensors

After many revisions from experience using the ESP8266, the hardware for Phase I of this project is configured as shown in the following schematic:

ESP8266-mobile-schematic - Phase 2
The basic ESP8266 framework is shown on the left side of the schematic with the two sensors on the right. Refer to the following posts for more information about the operation of this circuit:

The ESP8266 code for this project is very straight-forward. It consists of a simple web server, with the module operating in access point (AP) mode. The SSID has a fixed value of “ESP8266N4” and responds to the hard-coded IP: 192.168.22.1 on port 9703. These, of course, can be set to any value or even configured at run-time through the serial or initial web server default value. However, this example sticks with the hard-coded values since this system will only be paired with a single Smartphone.

The web server responds to a request for sensor values and status with a JSON string that can be easily parsed with an AJAX call.

Request URL:

http://192.168.22.1:9703/?request=GetSensors

 

JSON string returned:

{
"B_Pressure":"29.24",
"B_Temperature":"79.34",
"B_Altitude":"555.0",
"DH_Humidity":"34.7",
"DH_Temperature":"69.1",
"SYS_Time":"38",
"SYS_Heap":"32368",
"SYS_Loopcnt":"10",
"SYS_WifiStatus":"255",
"SYS_WifiRecon":"0",
"SYS_WifiMode":"2"
}

 

The code is based on the IoT_Demo example included in the EspressIf SDK. This project uses SDK Version 1.1.1. The latest version as of this post (1.2.0) should also work but I have not tested it with my code yet.  The ESP8266 source code for Phase I of this project is available on GitHub here.

Mobile App Screen Display

The current App GUI display for Phase I of this project exhibits 13 values.

Mobile Sensors

 This GUI includes CSS styling which takes advantage of the responsiveness of bootstrap. The source code for Phase I of this project is available on GitHub here.

Operation

Once the ESP8266 schematic has been built and the SDK based code has been installed, the ESP8266 is ready. The Android Application should also be installed on the target SmartPhone.

First, power up the ESP8266 from a 5 VDC source. The schematic includes a 5V to 3.3V converter, so I typically use a USB wall source or portable battery. Then you go to the phones WIFI configuration screen and select the ESP8266, which has an SSID of “ESP8266N4” in this example. This will connect the SmartPhone to the ESP8266 so sensor data can be read on demand.

Now start up the Android App. The data will update live, typically at a rate of at least once every second. Go ahead, walk around with the phone and observe the GPS Lat and Long values change. You can also put a finger on the barometric pressure sensor and see a change in the temperature value reported on the display.

Conclusion

We now have a working mobile application that collects sensor data and displays it on the smartphone screen. Using a USB battery with 5000 ma-hours or more, the system can easily move with you, secured in a backpack, fanny-pack or even in your pocket. Stay tuned for the next phase – Periodic logging of these data packets to a file; coming soon…

One final note: While this example uses an Android phone, the Cordova platform used is largely platform independent. While I am not familiar with iOS development, it should be a relatively simple task to adapt this application to work with an iPhone with little or no change to the code.

Hope you find this information useful…

 

Loading

Share This:
FacebooktwitterredditpinterestlinkedintumblrFacebooktwitterredditpinterestlinkedintumblr

ThingSpeak Channel Data With More Than 8 Fields

thingspeakchannel

Are you using ThingSpeak to capture and save your IoT device data points? Ever felt constrained by the 8 field channels limit?

I was.

All 8 of my channel fields were in use. None could be deleted. And I needed to save one additional value. But the solution was quite simple and straight-forward. This short post will serve as a reference “note to self”, and perhaps others who may stumble upon this issue…

A Simple Solution

First of all, as noted, I needed more than 8 fields in my channel’s data set. But a ThingSpeak channel is limited to 8 fields.

Hmm, what to do?

While you are limited to 8 data fields, a channel is not constrained by it’s own channel data. So the answer is right there…just add another channel and you get another group of 8 data fields. Since the additional data fields can be accessed from any of the master channel’s “plug-in” webpages, you have just doubled the number of  entries in a single record, from 8 to 16. There is really no limit to how many channels that can be added, scaling the data set upward by 8 fields for each channel added.

// set your channel IDs here
var channel_id1 = 12345;
var channel_id2 = 12346;
var channel_id3 = 12347;
// set your channel read api keys here
var api_key1 = '9XXQ4X79WQJC72SZ';
var api_key2 = '2KJQ2Q82YTPA23CQ';
var api_key3 = '5SWQ9F87UULD86NB';

function getData() {
//Get Data Set 1
$.getJSON('https://api.thingspeak.com/channels/' + channel_id1 + '/feed/last.json?api_key=' + api_key1, function(data1) {
    //Get Data Set 2
    $.getJSON('https://api.thingspeak.com/channels/' + channel_id2 + '/feed/last.json?api_key=' + api_key2, function(data2) {
         //Get Data Set 3
         $.getJSON('https://api.thingspeak.com/channels/' + channel_id3 + '/feed/last.json?api_key=' + api_key3, function(data3) {
             //Do something with the data here

             //Save the maximum of data1.field2 and data3.field4 in data3.field4
             if(data1.field2 > data3.field4) {
                 maxvalURL = "https://api.thingspeak.com/update?key=" + api_key3 + "&field4=" + data1.field2;
                 $.post(maxvalURL);
             }
         });
    });
});

Note the nested jQuery “$.getJSON” to retrieve the ThingSpeak channel data. All processing needs to be performed inside the inner nest in order to keep the values in scope.

And then there was the need to capture a value that could reset, potentially anytime. In my case, one of the requirements was to save a maximum value. This value represents the device run time since it last reset. It provides a measure of the systems reliability. In the above code example:

current-run-time-since-last-reset = data1.field2;

saved-max-time-since-last-reset = data3.field4;

Instead of retrieving a constantly growing array of values from a ThingSpeak field and then evaluating the array for the maximum value, the current max value is compared against the last run time value stored. This simple running “max value” algorithm runs faster and requires minimal code.

Conclusion

Scalable ThingSpeak data sets. This short post should serve as a reference…a reminder of just how simple and obvious it is to expand your sensor data beyond the 8-field limit imposed on a ThingSpeak channel.

I hope you find this information useful…

Loading

Share This:
FacebooktwitterredditpinterestlinkedintumblrFacebooktwitterredditpinterestlinkedintumblr

Native Android App Development Using Only HTML-Javascript-CSS

cordovaHere’s a handy gem for your bag of tricks. Did you know that a native Android App can be developed using only the web familiar html, javascript and css? Without the need to dig deep into the bowels of the OS.

Yep, it is definitely possible – all while still offering control of all your device’s interfaces such as cameras, bluetooth, wifi…you name it. You see, the hardware dependent components are supported with an Apache developed framework called Cordova. And while this article focuses on the Android platform, the same App can easily be ported to ios or Amazon Fire, with little or no change. Making it possible to develop your App once for distribution across several different device types.

Here is how to setup the development environment and install an application on an Android device.


Setting Up The Environment

The trick is using Cordova to provide a platform for building native applications using only HTML. CSS, and Javascript.

What is Cordova?

This is a group of  APIs supporting the development of native Apps without using the language of the device. These APIs provide access to the device’s hardware sensors. And with a few simple steps, you are up and running, developing your unique application.

Step 1:

Install node.js from nodejs.org

This will allow you to run “node” and “npm” from a command line window.

Step 2:

Install a git client from http://git-scm.com/.

This will allow you to invoke “git” from a command line.

Step 3:

Install the Cordova module using npm by entering the following at the command line:

npm install -g cordova

Step 4:

Setup the Eclipse for Android App Development Environment by following the following instructable:

http://www.instructables.com/id/How-To-Setup-Eclipse-for-Android-App-Development/?ALLSTEPS


Creating A New Application

Step 1:

Open a cmd windows.

Step 2:

Change directory to the base directory for your workspaces (your choice).

Cd c:\myworkspace

Step 3:

Create new folder with app name (no spaces):

mkdir mynewapp

cd mynewapp

Step 4:

Create app file structure:

cordova create appfiles com.author.mynewapp MyAppTitle

Where

  • “appfiles” is the folder to create the app file structure
  • “com” is the convention used to start the app filename
  • “author” is the developer or company name or initials
  • “mynewapp” is the bame of the app
  • “MyAppTitle” is the title of the app

Step 5:

Add platform (android or ios)

cd appfiles

cordova platform add android

Step 6:

Add plugins as needed (basic required plugins;device,console,file shown here)

Get plugin names from plugins.cordova.io/#/ Then enter the following for each plugin to be added:

cordova plugins add org.apache.cordova.device

cordova plugins add org.apache.cordova.console

cordova plugins add org.apache.cordova.file

In the future, plugins will be delivered using npm. See the instruction at plugins.cordova.io/#/ for more information regarding npm plugin delivery.


Building the Application

Step 1:

Open Eclipse

Step 2:

Install your USB cable from the PC running eclipse to the Android device.

Step 3:

Select Import from the File menu.

Step 4:

Select the base folder created for the newly created project.

Step 5:

First Select “Clean” from the Project Menu.

Step 6:

Then Click on the “Run” icon to build and launch the new app on your device


Editing The Application

The App starts with the launching of the index.html file located at:

<your base app workspace folder>\iotmobile\appfiles\platforms\android\assets\www

this file should be edited to change the functionality of the App. Javascript/Jquery and css files can similarly be customized. They are located at:

<your base app workspace folder>\iotmobile\appfiles\platforms\android\assets\www\js


Conclusion

There you have it!

A quick reference to setting up the Android Development Environment, creating a blank project, building the App and finally loading running it on your device. Now it’s your turn. What will you create?

I hope you find this information useful…

droid

Loading

Share This:
FacebooktwitterredditpinterestlinkedintumblrFacebooktwitterredditpinterestlinkedintumblr

Compiling ESP8266 Legacy App with SDK 1.1.1

SDK

Have you ever upgraded to a newer version of software or operating system, only to find once working Apps suddenly broken? And now it is not so easy to turn back…

I ran into this sort of thing with the ESP8266 SDK version 1.1.1. It had fixes for the problems I had been experiencing, but my application would no longer compile without error. Yep, this SDK was not compatible with programs developed using my earlier SDK (1.0.1). Some things were added. One item was now required, yet it did not exist before version 1.1.1. Still other features were removed.

Even the IoT_Demo example included with this latest version would not build successfully.

This upgrade started to rub me the wrong way. But finally, through some code review, minor modifications and interaction with EspressIf, the incompatibilities I had encountered were eventually sorted out.

Here is what I discovered and had to change to build an older application (based on the IoT_Demo example) with the improvements offered with SDK 1.1.1. So you can minimize the upgrade challenges and move on. To focus on your latest creation.

Tweaking your application for SDK 1.1.1 compatibility

1. The structure “rst_info” in user_interface.h has changed.

From this:

struct rst_info{
    uint32 <strong>flag</strong>;
    uint32 exccause;
    uint32 epc1;
    uint32 epc2;
    uint32 epc3;
    uint32 excvaddr;
    uint32 depc;
};

To this:

struct rst_info{
    uint32 <strong>reason</strong>;
    uint32 exccause;
    uint32 epc1;
    uint32 epc2;
    uint32 epc3;
    uint32 excvaddr;
    uint32 depc;
};

This will require a change to the structure reference in the function user_esp_platform_init(void) in the file user_esp_platform.c. Change all references from rtc_info.flag to rtc_info.reason.

2. PULLDWN has been removed.

The code statements need to be removed or commented out in the gpio16.c file:

	switch(pull) {
		case GPIO_PULLUP:
			//PIN_PULLDWN_DIS(pin_mux[pin]);
			PIN_PULLUP_EN(pin_mux[pin]);
			break;
		case GPIO_PULLDOWN:
			PIN_PULLUP_DIS(pin_mux[pin]);
			//PIN_PULLDWN_EN(pin_mux[pin]);
			break;
		case GPIO_FLOAT:
			PIN_PULLUP_DIS(pin_mux[pin]);
			//PIN_PULLDWN_DIS(pin_mux[pin]);
			break;
		default:
			PIN_PULLUP_DIS(pin_mux[pin]);
			//PIN_PULLDWN_DIS(pin_mux[pin]);
			break;
	}

NOTE: My application also called “PIN_PULLDWN_DIS” in ds18b20.c. If you are using the ds18b20.c or any other library that calls “PIN_PULLDWN_DIS”, it will need to be removed or commented out.
3. “user_main.c” now is required to include the function “user_rf_pre_init().

void user_rf_pre_init(void)
{
	system_phy_set_rfoption(2);
}

You do not need to include a call to “system_phy_set_rfoption()” in this function, but this is the ONLY function that allows this function to be called. If interested in learning more, refer to the latest SDK programming guide for this new feature.

4. The “Make” file is missing a required library.

Add “pwm” to the LIB line in the Make file for a successful application build:

# libraries used in this project, mainly provided by the SDK
LIBS		= c gcc hal phy pp net80211 lwip wpa <strong>pwm</strong> main json upgrade

And with these minor adjustments, I have successfully built my previously built App using SDK 1.1.1.

This is quite thrilling for me and I hope you too have success using SDK 1.1.1 and beyond. For me, this is the best SDK version yet.

The issues I had in the past with the Wifi server failing to respond to requests (STATION Mode) after about a minute and the AP mode simply not working with Android devices are gone.

Now we can focus on creating amazing things, with all the features of the always improving SDK APIs. From my experience, the SDK is by far the most capable environment to build your IoT visions available for the cheap yet capable ESP8266.

I hope you find this information useful.

Loading

Share This:
FacebooktwitterredditpinterestlinkedintumblrFacebooktwitterredditpinterestlinkedintumblr

ESP8266 WIFI dropout-proof connectivity

How to eliminate ESP8266 WIFI drop-outs

Just when it seemed like the ESP8266 was operating rock-solid, indeed running continuously for days now without resetting, or worse, fatally crashing, a sign that something was wrong appeared…

wifi

Out of the corner of my eye, a flash of light seemed to originate from the up ’till now reliably running ESP8266 based circuit. As my gaze turned directly towards the module, the blue LED started flashing. Not just once, but several times with a silent couple of seconds between illuminations…

“Uh-Ohh”, I thought, “looks like the ESP8266 is once again in a reset loop!” First thing to check was the ESP8266 web server response to a http GET request. The server did respond with a JSON string, just like it was programmed to do. And much to my surprise, the status (seconds running since last reset), indicated the module had been continuously running for days.

So why the flashing blue LED?

I noticed that sending a http GET request around the time the flashing occurs required considerable time (up to 10 seconds) before the ESP8266 returned a JSON response string. This could only mean one thing…

A WIFI Connectivity Check and Recover is Essential

The application firmware had detected a loss in WIFI connectivity and was attempting to reconnect. I had added a WIFI check to the top of the Arduino IDE loop() function. It never seemed to detect a loss of WIFI. That is, until now…

While the following code was developed using the Arduino IDE, the same check should be included for the SDK or NodeMCU code as well.

//connect wifi if not connected
if (WiFi.status() != WL_CONNECTED) {
    delay(1);
    startWIFI();
    return;
}

 

So the setup() function initially establishes the WIFI conection with a call to startWIFI(). The WIFI status is subsequently checked each iteration of the loop() to maintain the connection.

Fortunately, I had included some status messages in the startWIFI() function sent out the serial port just in case some troubleshooting was needed. This came in handy to confirm the root cause of the flashing blue LED.

void startWIFI(void) {
    //set IP if not correct
    IPAddress ip = WiFi.localIP();
    if( ip!= ipadd) {
        WiFi.config(ipadd, ipgat, ipsub); //dsa added 12.04.2015
        Serial.println();
        delay(10);
        Serial.print("ESP8266 IP:");
        delay(10);
        Serial.println(ip);
        delay(10);
        Serial.print("Fixed IP:");
        delay(10);
        Serial.println(ipadd);
        delay(10);
        Serial.print("IP now set to: ");
        delay(10);
        Serial.println(WiFi.localIP());
        delay(10);
    }
    // Connect to WiFi network
    Serial.println();
    delay(10);
    Serial.println();
    delay(10);
    Serial.print("Connecting to ");
    delay(10);
    Serial.println(ssid);
    delay(10);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(500);
    }
    Serial.println("");
    Serial.println("WiFi connected");

    // Start the server
    server.begin();
    Serial.println("Server started");

    // Print the IP address
    Serial.print("ESP8266 IP: ");
    Serial.println(WiFi.localIP());

    // Print the server port
    Serial.print("ESP8266 WebServer Port: ");
    Serial.println(SVRPORT);
    delay(300);
}

 

As I mentioned, the my ESP8266 web server returns status, along with sensor readings in a JSON string upon receiving http GET request. This data is logged to a mySQL database, once every hour. A CRON php script pulls the ESP8266 data and saves it to the database.

The next step

In order to assess how frequent WIFI connectivity is lost and restarted, I am going to add a static counter to my startWIFI() function. This will identify the number of times the WifFi connection was lost and reestablished since the last reset. That value will be recorded to mySQL along with the other values. It will be interesting to see how often this occurs. Once a day? Several times per hour? We shall see…

If you have had any issues maintaining WIFI connectivity, or your server stops responding to request, consider this as a solution.

I hope you find this information useful…

Update: July 5, 2015

The ESP8266 supporting my weather sensor webserver did reset 23 days ago. I took that opportunity to add a static counter to the startWIFI() function. A ThingSpeak channel has also been established to share the live results publicly.  As of this update, the Wifi connectivity was lost 537 times.

Recovery was successful every time as no ESP resets have occurred yet.

This empirical data shows the Wifi connectivity is lost on average 23 times per day.

Loading

Share This:
FacebooktwitterredditpinterestlinkedintumblrFacebooktwitterredditpinterestlinkedintumblr

A cleaner ESP8266-12 hardware setup

ESP8266 packaging issues

One of the first challenges to overcome when you get a bare module ESP8266-12 SoC is how to connect this unit to a circuit. It comes without header pins and the pin pitch is less than the standard 2.54 used on solder-less and copper breadboards. Clearly, it is not ready to use out-of-the-box like, for example, any of the Arduino options.

My first circuit used a 16-pin DIP package with short jumper wires soldered between the ESP8266 pin holes and the DIP. This assembly was then plugged directly on a solder-less breadboard. While this gave me a quick start into the ESP8266 world, the setup was messy and even worse – unstable.

Solder-less Breadboard

Disappointed and often frustrated by the poor performance of the setup, my next setup used a copper plated breadboard. The ESP8266 was mounted to the board using thin (28 AWG) bare wires. These wires were soldered between the ESP8266 through-holes and the breadboard pads. This was a vast improvement in terms of stability. I currently have a system that has been running for over 2 weeks now with no resets or system crashes. The real-time data collected with this system is displayed publicly on ThingSpeak for independent verification.

But with this setup, the tiny interface wires require a lot of time to initially assemble.

That’s where this adapter plate really shines…

Yes, it really made things easier when I stumbled upon a clean and inexpensive adapter for the ESP8266-7/12 modules. For just 28 cents (AliExpress), you get a PWB plate with pre-soldered mounting pads and a 10k pull-up connected to the chip enable (CH_PD).

A 10K resistor is also included that pulls-down GPIO15 to ground. This resistor is way to large to be of any value for that purpose. For proper boot operation, you must add a connection between GPIO15 and ground.

Finally, the fix is in – the pin labels for GPIO4 and GPIO5 have been corrected on this plate. No more confusion for that until now overlooked ESP8266-12 module design error.

ESP8266-12 adapter plate

The circuit has come together quite nicely. So far, it has proven to be a very dependable configuration. Boots without errors and flashes reliably the first time, every time. We shall see if this remains true as more the flash cycles are performed.

Fully assembled ESP8266 with adapter plate

This begs the question… Why not mount all the parts on a plate like this & eliminate the original carrier board?

A few design considerations

  • Notice the 0.1uF decoupling capacitor added close to the ESP8266 assembly. Positioning this essential capacitor there…directly across the ESP8266 VCC and Gnd pins, is absolutely critical for stable operation.

20150519_decouplingcap

  • The header pins were mounted backwards so the longer posts are facing upwards. This will be useful should it be necessary to connect female jumpers directly to any ESP8266 pin.
  • The USB to serial adapter cable connections are split between two terminal sections. The right two terminals connect USB 5V and Ground. The left two terminals, serial transmit and receive, are only used when flashing the firmware. Once deployed, the left two terminals are disconnected and the 5V and ground connections are attached to a USB cable. This supports power sourced from a USB wall or car adapter as well as a USB battery.
  • The ESP serial receive pin has a 100 ohm series resistor included from the serial transmit source. In addition, a 3.3V zener diode clamps the input voltage into the ESP8266. Many ESP8266 users omit these parts. This is not advisable. Exceeding the specified input range will likely degrade the system performance and possibly introduce hard to find latent defects! For long-term reliable operation, these common, readily available components should be included in every interface circuit.

ESP8266-schematic - serial

  • An AMS1117 voltage regulator converts the 5V to 3.3V for the ESP8266 supply. This is mounted on the breadboard copper side of the breadboard so the heat sink built into the regulator can be soldered to the board.

Regulator Heat Sink

  • To minimize instabilities from voltage ripple, two 470 uF capacitors are used, one across the 5V source and one across the 3.3V ESP8266 supply.

ESP8266-schematic - power

In Conclusion

In my experience, while cheap, feature rich and full of promise, unwanted system resets, flash failures and crashes have been the curse when working with the ESP8266.

But there is hope…

This recently introduced adapter plate, along with the hardware interface features presented here will help mitigate these undesirable outcomes.

Hope you find this information useful…

Loading

Share This:
FacebooktwitterredditpinterestlinkedintumblrFacebooktwitterredditpinterestlinkedintumblr

8 ESP8266 analog inputs for 22 cents

Want More Analog Inputs?

Do you have a project needing more than one analog input? If your using an ESP8266, that would seem to be a problem as it only offers a single input. Before you commit to using an Arduino, Spark Core, Raspberry PI or other higher priced micro-controller, one with multiple analog inputs, consider this…

ESP8266image

Adding an 8-1 multiplexer chip to your ESP8266-07 or -12 circuit can expand your system capability from one to eight analog inputs.  I recently tested this out, using a 74HC4051 CMOS analog multiplexer component I got from an AliExpress supplier.

The cost?

$2.19 for 10 chips, or $0.22 per chip.

They are available in a 16-pin DIP package  with 2.54 pitch for easy use with a solder-less breadboard.muxpicSo what’s the downside? Well, selecting one of the 8 analog inputs will require 3 GPIO pins. For many applications, that should not pose a problem when using the ESP8266-07 or -12. These versions have 7 easily accessible GPIO pins available, leaving you with 4 GPIO pins for any digital input or output requirement after adding the 8 analog inputs.

Here is the circuit I used to test this configuration:

ESP8266-schematic - amux-test_rev1

The left side of this drawing is the standard circuit I have been using for all of my ESP8266 projects. A typical USB to serial adapter is used when developing and flashing the circuit. When deployed, I use a USB plug with a wall adapter to provide a 5V source, without the Tx/Rx signals.

The analog multiplexer is controlled by 3 GPIO pins; 14,12 and 13. Setting the states of these 3 digital outputs determine which analog input will be measured.

GPIO14 GPIO12 GPIO13
A0 0 0 0
A1 0 0 1
A2 0 1 0
A3 0 1 1
A4 1 0 0
A5 1 0 1
A6 1 1 0
A7 1 1 1

The sketch used to test this circuit was developed using the ESP8266 Arduino IDE.

The serial output loops through each analog input, setting the multiplexer and reading an input every 2.5 seconds. The sketch also behaves as a web server. All 8 analog values can be retrieved in a single JSON string returned from an http GET request.

ESP8266 ADC Performance Evaluation

Using this circuit and software, I proceeded to collect some data to characterize the ESP8266 analog input range. First, the multiplexer selector was verified by connecting each input to ground and verifying the Analog count returned was 0. Likewise, each input was connected to 3.3V with a reading of 1024 returned when reading the ESP8266 ADC pin.

All good so far…

Then I connected the A0 input to a variable resistor to vary the input voltage voltage.

ESP8266-schematic - amux-Test-Circuit-updated

At the same time, an external Digital Multimeter (DMM) was used to monitor the voltage applied to the ESP ADC input via the multiplexer. For each voltage setting, I recorded the DMM reading and the ADC count returned from the ESP8266. It would have been great to have a calibrated bus controlled DMM to automate this process, but for the purpose of this DIY home project, I simply entered the values into an excel spreadsheet manually.

Thirty-seven voltage settings were applied in the range between 0.2V and 1.2V. Any voltage below 0.2V returned a 0 bit count while voltages above 1.2V returned 1024. I observed approximately 10 values returned from the ESP8266 for each voltage applied and recorded the high and low bit count readings for these measurements. The average of the high and low reading was then used to chart the results.

ESP8266 ADC voltage vs bit count

As you can see, the results were reasonably linear. But there is compression at the voltage extremes. For practical use, I would not use the non-linear ends, limiting the voltage swing from 0.25 to 1.15 V, a 0.9 V range.

The data collected can be reduced to a “best fit” equation. This would provide a method of converting the raw ADC value count to a voltage. Ideally, a data point should be collected for each ADC count value. The equipment I used for this exercise was not calibrated or accurate enough to do this. Given these uncertainties in my test setup, I am not sure if the variances I observed for consecutive readings…and they did vary somewhat…was result of the input voltage source or the ESP8266 ADC.

Still…with the data I had collected, the formula was determined to be:

Vain = (0.94* ADCcount + 200) mV

The slope was determined by dividing the voltage difference by the ADC count  difference at each end of the voltage range. And 200 mV, the intercept, is the voltage when the ADC started reporting 0 for the count.

While there does not appear to be a definitive specification, this is consistent with what I have read regarding the ESP8266. The 10-bit ADC resolution is supposed to be approximately 1 mV with a 1 V range.

Resolving Sensor Incompatibilities

So what can you do if your sensor range is outside the ESP8266 0.2 to 1.2 V window?

Scaling of course.

This can be accomplished passively, using a resistor divider, or actively, with the addition of an op-amp. The interface of choice would be an active op-amp based circuit.

For example, suppose your sensor has a 0-5V range. This would need to be scaled to fit in the ESP8266 0.2 to 1.2 V input range. Obviously, resolution will be compromised as we go from a larger range to a smaller one, but it can be done. And with a single power supply.

ESP8266 Analog Input Voltage Level Shifter

Resistor values calculated here. The 24K/1K resistor divider supplies the 0.2V offset with the gain set for the 1.15 V output with a 5V maximum input applied. This circuit would need to be modified for your specific sensor voltage range.

In summary

So there you have it. Eight analog inputs measured using a single ESP8266 SoC. Possible simply by adding a 22 cent chip.

And I got to mention one more option. Just in case you want even more…

A 16 channel version of the multiplexer is also available (74HCT4067). That’s a whole lot of analog!

I hope you find this information useful.

Loading

Share This:
FacebooktwitterredditpinterestlinkedintumblrFacebooktwitterredditpinterestlinkedintumblr

My ESP8266 Controlled Temperature Sensors now on ThingSpeak

Now that my ESP8266 controlled sensors have been on-line and are now reliably running, the next step was to push some of the data up to ThingSpeak. Up to now, I had been saving the readings exclusively in my host server account’s mySQL database.

And now the temperature readings are also pushed up to ThingSpeak, once every hour.

But not by the ESP8266 micro-controller. No…I have discovered that the stability of the ESP8266, at least at this time, is linked to the frequency of accessing it through http client GET requests. Access to my ESP8266 is tightly controlled. It has to be. I’ve written about structuring a stable ESP8266 Arduino IDE sketch loop() in another post. This may be helpful if you are have issues with the ESP8266 reliability.

The video created to describe the ThinkSpeak channel breaks down the unique methodology I’ve used to move sensor readings up to ThingSpeak.

You can check out the real-time data now visually served to the world on my new ThingSpeak channel. I’m hoping there is something unique about the method used to upload the readings and the eye-catching displays that could be of value to someone. Something not found on any other of the many channels displaying similar data.

Setting up the channel was easy. ThingSpeak is a free platform serving first as a repository database, like mySQL, to store data read from your Internet of Things (IoT) gadgets.

Once you have a periodic data feed to ThingSpeak, the platform can execute actions based on the data. It also provides a simple API to take some of the burden off your micro-controller. Here’s highlights of what ThingSpeak can do for you:

  • ThingTweet – This service provides a simple API for your IoT thing to post Twitter messages.
  • React -Performs whatever action you need when the data in your channel meets your custom set condition. Some obvious examples:
    • Turn light on when proximity sensor detects someone in room
    • Water lawn when moisture detector reaches dry threshold.
    • Turn heater on when temperature drops below certain reading.
  • TalkBack – API that has device execute queued commands. The queue is loaded in ThingSpeak. Then the device request a command, and performs an action based on the command it gets from the ThingSpeak queue. I have not thought of an application for this yet, but I’m sure you might find some from ThingSpeak.
  • TimeControl – Allows you to setup ThingHTTP or ThingTweet requests a a predetermined time. There are many ways to do this, but using ThingSpeak could reduce the burden placed on your device or other element in your IoT ecosystem.

Temp Humidity Baro-Pressure

That’s it for now. Keep your creative juices flowing. I may add my humidity and barometric pressure readings to the initial ThingSpeak soon – in a 3-gauge display window. Like you see above. Being in the US, my temperature is in Fahrenheit and the pressure is inches of mercury. What will you do next?

I hope you find this information useful…

 

 

 

 

Loading

Share This:
FacebooktwitterredditpinterestlinkedintumblrFacebooktwitterredditpinterestlinkedintumblr

What to do when ESP8266 will not flash

Are your ESP8266 flash attempts failing? Or perhaps not working at all anymore? Getting that annoying “Invalid head of packet” exception?

I have. Very frustrating…

And there aren’t many answers to be found on-line. What really got me steaming was the “Fatal error” messages at 115200 baud after I thought the flash completed properly. I have been there.

Over and over again…

Just when I was ready to give up…after many, many flash attempts, a flash will actually succeed. You think everything is good again, but the problem just keeps coming back…

What is wrong? Is this just a cheap Chinese trinket? An illusion of the Holy Grail? The ESP8266 specs look great. With such a cheap price tag that sucked you in? Or is there something your doing wrong?

Here is what I have found to be the problem…

And yes, there is a solution.

What many of us have experienced wit these ESP8266 modules, especially those that like to tinker and flash often, is the very low flash cycle count that the memory chips shipped with many of these modules will tolerate before failing. In my experience, flash failures start after only 20 flash cycles or so.

Then it only gets worse from that point on.

The good news is that the memory chips are not difficult to replace. And they are cheap when you order them with free shipping from the slow boat from China. You should be able to find them on AliExpress or your other favorite source. Here are some recent quotes for the different chips found on ESP8266 modules:

Description Flash ID Size Recent Price (USD)
1 Winbond W25Q40 1340ef 512 KByte 0.32 each 7.85 (per 25)
2 GigaDevice GD25Q40 1340c8 512 KByte 0.32 each 7.85 (per 25)
3 Winbond W25Q32 1640ef 4 MByte 0.42 each 4.14 (per 10)

From looking at the firmware binary header, it looks like the flashes are made for a 512 KByte flash chip (byte 3 upper 4 bits are 0). This would suggest that CURRENTLY, all that is used with the ESP8266 is 512 KBytes.

That is what I am using to replace the flash chip when they start to fail intolerably. I have recently replaced a 4MByte flash chip with a 512 KByte component, it worked flawlessly. With the same amount of space free for the application. You can clearly see that the ESP8266 SDK indicates the maximum firmware size as 512 KBytes.

I have been using the ESP8266-12 modules. The only added step needed for flash chip replacement from an ESP8266-01 is that the golden metal case must be removed to gain access to the SPI memory chip. This is not impossible, you just have to take your time, be patient, and careful.

I use a razor blade to pop the cover off. You just have to score the crease where the metal case meets the PCB. Only do this on the edge that is away from the PCB antenna. This minimizes the risk of damaging something. Eventually, the blade will breach the case bonding. When it starts to give, the rest of the cover will soon separate from the module – cover removed!

Remove ESP8266-12 cover

Take it slow so you do not cut yourself, damage the module, or snap the blade. I use a blade with a safety cover. It only require 5-10 minutes to remove the cover in this manner. I have done it to two modules so far with no damage incurred. I have seen some folks use a heat gun to remove the cover. This is too risky in my opinion.

ESP8266-12 Cover off

The SPI memory chip will be the obvious 8-pin device. Not to worry. While the ESP8266 would be very challenging to remove, not so with the memory chip. The pins are larger than the ESP8266, making them easier to remove. Just spot apply a hot soldering iron tip to each pin with a pointed object used to lift the pin while the heat is applied. One pin at a time. I found that a breadboard jumper to work for this purpose.

ESP8266 flash memory remova

When you have the chip removed and are ready to install the new chip, remember to use the same orientation. A small dot on the chip identifies pin one. Just make a note before removing the old chip for reference. And, obviously, limit the amount of heat applied to each pin.

I am currently using my replacement SPI chips for development and have a decent supply on hand (only 32 cents per chip) to focus on project development, free from the agony of squandering time over recurring flash failures.

I’ll give an update when the replacement chips start to fail to flash. Hopefully, there will be an improvement from the original chips. More flash cycles before the first failure. We shall see. But I can live with it knowing a chip swap will chase this demon away, at least for a while.

Hope that you find this information useful…

Loading

Share This:
FacebooktwitterredditpinterestlinkedintumblrFacebooktwitterredditpinterestlinkedintumblr

Using Javascript AJAX to read ESP8266 data

Okay, so you got your ultra low-cost ESP8266 workhorse setup to read some sensors. And you have an awesome webpage built to visually display the readings. But how do you get the data from the ESP8266 to your website?

PHP and/or Javascript are the two most popular methods. I have used both.

This writing presents a simple Javascript solution. I have also posted an approach to this task using PHP here.

My need came about while developing a mobile app to monitor and control devices in my home. My personal IoTs. Using the Apache Cordova API with the Eclipse IDE. I was developing my App with just HTML, CSS, and JavaScript. Yet it will compile and install onto my Android device like any other application. It is my understanding that the same code can be built into an iOS App as well…but…being strictly a PC user, I have not attempted that.

And let’s get back to using Javascript to pull information from an ESP8266 based web server.

The thing was, I needed to pull my weather, sprinkler, garage and other sensor data from the ESP8266 circuit that monitors these devices to my App. I also wanted maintain control of the data. To be free from a cloud middleman such as ThingsSpeak.

With this in mind, we have two sides to this solution; The micro-controller unit (MCU), which is the ESP8266 in this case, and the client App. The ESP8266 must read all the devices connected to it and then send this data, on request, to the App client. The preferred format is either JSON or XML.

I use JSON strings.

Here is an example of a short function that can be used to create a JSON string in an Arduino IDE sketch. It is critical to include the http header information provided in this example. The header authorizes your domain, allowing the Javascript AJAX to retrieve the ESP8266 http response.

Here is the Javascript with AJAX code used to request a JSON string from the  ESP8266, decode it, and display the values on a webpage.

function updateWeatherSensorData() {
    requestURL = "http://myrouterdomain.com:9999/?request=GetSensors";
    if ( typeof updateWeatherSensorData.timeout == 'undefined' ) {
        // It has not... perform the initialization
        updateWeatherSensorData.timeout = 0;
    }
    //Get Weather Sensor Value
    $.ajax({
        url: requestURL,
        error: function(error){
            if(updateWeatherSensorData.timeout++ &lt;10) {
                setTimeout(updateWeatherSensorData, 1000);
            }
            else {
                updateWeatherSensorData.timeout = 0;
            }
        },
        success: function(thedata){
            $("#baro").html(thedata.B_Pressure + " inHg");
            $("#tempIn").html(thedata.DS_TempInside + " F");
            $("#tempOut").html(thedata.DS_TempOutside + " F");
            $("#tempAttic").html(thedata.DS_TempAttic + " F");
            $("#humidity").html(thedata.DH_Humidity + " %");
            updateWeatherSensorData.timeout = 0;
        },
        timeout: 7000 // sets timeout to 7 seconds
    });
}

 

I am assuming you have a domain name pointed to your router and your router is configured to port forward internet requests. For reference, here is how to set this up.

How this Javascript code works:

First, the URL used to send the http GET request to the ESP8266 is defined. This URL has 3 parts

  1. The domain name: http://myrouterdomain.com
  2. The port your ESP8266 web server is listening on: 9999
  3. The request string recognized by the web server: /?request=GetSensors

Then we need to define a timeout property for this function. The timeout is actually used to store the number of attempts to retrieve the JSON from the ESP8266 before successful.

And now, the AJAX call. As you can see, the code is structured like a JSON string, with 4 keys and 4 values:

  1. url: This defines where to send the request.
  2. error: In case the request fails, the call is repeated, up to 10 times
  3. success: When successful, the webpage elements with the indicated ID are filled with the value retrieved from the ESP8266
  4. timeout: Up to 7 seconds is allowed before a timeout error is declared.

That’s it! This is what I have been using to retrieve JSON strings from my ESP8266 using an AJAX call.

In Summary

Here are a few closing thoughts of my observations for your information…

  • The error handling is essential. This call fails frequently, perhaps every 2 or 3 requests.
  • Most of the time, the error is because a blank string is filled from this call. I do not know if that is an ESP8266 issue or a problem with AJAX.
  • The timeout was set to 7 seconds because I have seen it take up to 4 seconds to get a response.

Hope you find this information useful for your ESP8266, Arduino and other MPU projects.

Loading

Share This:
FacebooktwitterredditpinterestlinkedintumblrFacebooktwitterredditpinterestlinkedintumblr