1. Grant Young
  2. esp8266-wifi-test-class

Overview

HTTPS SSH

README

A "first principles"/ground up attempt at getting a stable AT commands implementation working with an Arduino Uno + Nano, using the ESP8266 chip, to connect to the Thingspeak API using the POST HTTP method.

NOTE: I've been so far unsuccessful in achieving a working/stable form.

What is this repository for?

I've provided for review/suggestions by participants at the OzBerryPi IoT meetup group.

See the companion "flat" implementation (i.e. bare-bones, non-class based, with all commands in procedural style), which was the (semi-)working code attempt at achieving a stable version of AT commands (see Background below).

This class-based library is an attempt at refactoring this "flat" (semi-)working code into a library/class-based format. The code is generally cleaner in that version, and the comments are more complete.

However, in moving to a library, the code is no longer working, causing what appear to be out-of-memory–related errors.

Background

I'm aware of a number of libraries attempting to do the same thing, especially the WeeESP8266, the ESP8266_Simple libraries. These libraries did not work "out of the box" for me, probably due to firmware differences. I was unable to find firmware versions for previous/stable versions of the firmware that could be installed using the esptool (see How do I get set up below). Other libraries designed for specific shields etc. (e.g. the SparkFun ESP8266 Shield library) exhibited similar issues when applied to generic ESP8266 chip configurations.

Due to various aspects of what I'm trying to achieve, it's not suitable to run Arduino on the ESP8266. I assume that this code is not suitable for running using serial comms to the device (and couldn't see any easy/ready references in that direction).

After spending a lot of time troubleshooting with these libraries, I decided to start from first principles to review the response for each AT command and build up a library based on the latest firmware (see How do I get set up below). My starting point was to keep things as absolutely basic as possible, resulting in this implementation.

I then began refactoring into classes, and continue to run into issues (see Issues below)

How do I get set up?

Download the .ino file and open in the Arduino IDE (I have built this using v1.6.5 of the IDE).

Note that I have enabled compiling with C++11, so some syntax that I'm using may require this flag to be enabled. Details of how to enable C++11. On Mac OS X:

  1. Find app in Applications folder
  2. Ctrl click choose “Show package contents"
  3. Navigate to and open Contents > Java > hardware > arduino > avr > platform.txt
  4. Find the line starting with "compiler.cpp.flags="
  5. Add "-std=gnu++11" at the end

You will need to have an ESP8266 chip of some description connected to the digital pins 8 (Arduino Receive-->ESP Transmit) and 9 (Arduino Transmit-->ESP Receive) using a logic level converter (or equivalent) for 5v-based Arduinos.

Note that this code is tested with the latest ESP8266 AT firmware available at the time of writing. The github notes identified as being for SDK 0.9.4. The firmware string returned by AT+GMR:

AT+GMR

0020000903

OK

Installing the ESP8266 firmware

Download AT firmware from the Espressif github repository and flash using the Python-based esptool.

Drop GPIO0 to ground, and hardware reset the device (by dropping RST to ground temporarily), and you are connected using an FTDI interface (or similar). I'll leave it to you to search how to do this (there's lot's of tutorials around). REMEMBER the ESP8266 is 3v3, so make sure your FTDI interface is 3v3, or use a logic level converter.

On Mac/Terminal, the following worked for me (once you have navigated to the ESP8266_AT-master directory).

esptool.py --port /dev/tty.usbserial-XXXXXXX write_flash 0x00000 boot_v1.1.bin 0x01000 v0.20/user1.bin 0x7C000 esp_init_data_default.bin 0x7E000 blank.bin

where "tty.usbserial-XXXXXXX" is the name of your serial port (use ls /dev/tty.* to determine). (Hat tip: rappa)

Sorry the above is a little light on detail. I'll hopefully have time to do a proper write-up soon.

NOTE: once you've updated the firmware, the baud rate is likely to be set to 1152000. This is too fast for the SoftwareSerial implementation on Arduino.

On Mac, once you've successfully connected to the device using CoolTerm or similar. Set line endings to CLRF (both), and baud rate to 1152000.

Screen Shot 2015-12-02 at 11.17.09 AM.png

Then send the command "AT+IPR=9600" (Hat tip: Andrew Rapp). This will (persistently) set the baud rate of the ESP to 9600. Change the baud rate in CoolTerm to this lower figure to continue working with the device, and set your SoftwareSerial baud rate in your Arduino code using "yourSerial.begin(9600)".

Syntax/Usage

The general gist of the library is to abstract the AT commands into something more friendly to use. Look at the .ino file as the primary, hopefully "self-documenting" example of how the library is intended to be used/work.

There are three classes:

  1. WifiConnection: the stuff you need to use to connect/disconnect etc. to a wifi network. This is working just fine, albeit a bit brittle. I'd like for it to be more robust in terms of retries and error checking etc.
  2. WifiHTTPRequest: a rough attempt at creating a class for constructing well-formed request strings based on required parameters (like hostName, endPoint etc.). Once all the parameters are provided, calling render() will output the well-formed HTTP string (POST method only supported presently). The idea would be you could call response.send() and have this string sent via AT commands. This is the bit that isn't working correctly (seem to get out of memory errors).
  3. WifiHTTPResponse: not implemented as yet. The idea behind this is that the object creates an in-memory string from the response and parses for HTTP status. Once this info is available, it would provide key info (like status) in a simple interface (e.g. if (response.isReady()) { if (response.status == 200)) { }} etc.

(The WifiBase class is an abstract class supporting the other classes, but contains a lot of the underlying/utility methods.)

The example attempts to connect to the Thingspeak API using POST method. I wanted to use correct HTTP verbs (i.e. not GET for posting data), and eventually pass JSON strings. But this example just does the bare minimum to get a "working" version.

Issues

See notes above on the WifiHTTPRequest and WifiHTTPResponse classes.

Calling send() fails after one or two attempts. Sometimes the ESP8266 becomes unresponsive (which is most likely the Arduino running out of memory and not handling send/return correctly, rather than the ESP itself). Other times, the Serial.println() debug statements just stop showing up, also suggesting a memory issue.

I am also at a loss as to what to do with the returned data (i.e. in the WifiHTTPResponse class). Even a basic HTTP response from Thingspeak weighs in at over 700 bytes, which is problematic in the Arduino environment. Suggestions on how to work in a stream-based manner (to at least detect the HTTP status in the response) would be appreciated.

Some command calls, with this version of the firmware, return malformed responses. For example, the CIPSEND response starts with a bunch of gibberish. The AT+CIPSTART command also seems to often return a mix of correct and malformed characters. The visual appearance of this gibberish is similar to what you get with a baud rate discrepancy, but this shouldn't be the case.

Contribution guidelines

This code is provided primarily for illustrative purposes.

If you have notes/suggestions/would like to connect/contribute, please contact Grant Young via http://zum.io/contact/