IoT - First Test of ESP8266 WiFi Module

To try out the ESP8266 module I connected an USB-to-serial adapter which I ordered via the bay (“USB RS232 Serial TTL PL2303HX UART”).

Pinout

It was possible to reconnect the 5V power supply from USB within the module (just opened it) to the 3.3 Volt needed for the module.

Re-connection

I wired up the module with the USB adapter; connected PIN CH_PD to VCC (3.3 Volt) and connected to PC. Red light goes on, blue flashes shortly.

Pinout

Label Signal
VCC 3.3V (max 3.6V)
GND Ground
TXD Transmit Data (3.3V)
RXD Receive Data (3.3V)
CH_PD Chip Power down: (LOW = Power down active)
GPIO0 General Purpose I/O 0
GPIO2 General Purpose I/O 2
RST Reset (LOW = Reset active)

Connection The picture is not the best - the yellow bounded cable connects CH_PD with VCC. The green connector from the USB-Serial-Converter goes to RXD, and the white to TXD.

After connecting the USB-Serial-Converter, my Linux shows following dmesg log:

[23081.471573] usb 1-3: New USB device found, idVendor=067b, idProduct=2303
[23081.471575] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[23081.471576] usb 1-3: Product: USB-Serial Controller
[23081.471577] usb 1-3: Manufacturer: Prolific Technology Inc.
[23081.471957] pl2303 1-3:1.0: pl2303 converter detected
[23081.472510] usb 1-3: pl2303 converter now attached to ttyUSB1

I installed GtkTerm via

sudo apt-get install gtkterm

I made sure the config file of gtkterm: “.gtktermrc” in my home folder contains the right config for my setup (in fact I needed to change the port and speed config):

[default]
port	= /dev/ttyUSB1
speed	= 115200
bits	= 8
stopbits	= 1
parity	= none
flow	= none
wait_delay	= 0
wait_char	= -1
rs485_rts_time_before_tx	= 30
rs485_rts_time_after_tx	= 30
echo	= False
crlfauto	= False
font	= "Nimbus Mono L, 14"
term_transparency	= False
term_show_cursor	= True
term_rows	= 80
term_columns	= 25
term_scrollback	= 200
term_visual_bell	= True
term_foreground_red	= 43253
term_foreground_blue	= 43253
term_foreground_green	= 43253
term_background_red	= 0
term_background_blue	= 0
term_background_green	= 0
term_background_saturation	= 0,500000

Now I was ready to play around with gtkterm. Actually my terminal was showing nothing, until I typed the first command (AT). For details about the below mentioned commandos (all starting with AT) - please visit: https://nurdspace.nl/ESP8266#AT_Commands or this website

AT

OK
AT+RST

OK

 ets Jan  8 2013,rst cause:4, boot mode:(3,7)

wdt reset
load 0x40100000, len 24444, room 16 
tail 12
chksum 0xe0
ho 0 tail 12 room 4
load 0x3ffe8000, len 3168, room 12 
tail 4
chksum 0x93
load 0x3ffe8c60, len 4956, room 4 
tail 8
chksum 0xbd
csum 0xbd

ready

AT+GMR
00160901

OK
AT?
no this fun
AT+CWMODE?
+CWMODE:2

OK
AT+CWMODE=3

OK
AT+CWMODE?
+CWMODE:3

OK
AT+CWLAP
+CWLAP:(0,"",0)
+CWLAP:(4,"wifi1",-86)
+CWLAP:(3,"wifi2",-72)
+CWLAP:(3,"wifi3",-83)
+CWLAP:(3,"mywifi",-63)

OK
AT+CWJAP="mywifi","mypass"

OK
AT+CIFSR
192.168.1.20

After above commandos the module is connected with my home wifi (“mywifi”) which is secured with a password. The IP adress of the module is “192.168.1.20” (automatically received by the DHCP of the wifi router). Now I will start a TCP server listening on Port 8001 on the module (timeout is set to 180 sec because the module handles only a limited number of connections; we might free some long running idle ones):

OK
AT+CIPSERVER=1,8001

OK
AT+CIPSTO=180

On the linux box I open a terminal; started a telnet connection; entered the message “Helo” and pressed >enter<:

telnet 192.168.15.20 8001
Trying 192.168.15.20...
Connected to 192.168.15.20.
Escape character is '^]'.
Helo


In the serial monitor (gtkterm) I can see the terminal receiving the message:

Link

+IPD,0,6:Helo

OK

That’s it!

Next step is to have an arduino react/respond on tcp messages.


After consulting some forums in the internet I have read, that some additional preparation of the module is needed to talk with arduino (downgrade baudrate of the module). By the way - some alternative firmware exists for running LUA and/or even a webserver on the module using the GPIOs directly. But I want to talk to the Arduino Nano, so I need the following steps.

Clone the flash utility:

git clone https://github.com/themadinventor/esptool.git

Get the firmware esp8266.9.2.2.bin or here and unzip it to the folder of the esptool.

Now connect GPIO0 to low and restart the module (with GPIO0 to low it boots to flashable mode).

Trying to run the flash utility gave me an error (note that my serial converter sits on USB1, your setup might be different!):

./esptool.py -p /dev/ttyUSB1 write_flash 0x000000 v0.9.2.2\ AT\ Firmware.bin 
Traceback (most recent call last):
  File "./esptool.py", line 22, in <module>
    import serial
ImportError: No module named serial

So I had to install the python serial modul via pip:

sudo pip install pyserial
Downloading/unpacking pyserial
  Downloading pyserial-2.7.tar.gz (122kB): 122kB downloaded
  Running setup.py egg_info for package pyserial
    
Installing collected packages: pyserial
  Running setup.py install for pyserial
    changing mode of build/scripts-2.7/miniterm.py from 644 to 755
    
    changing mode of /usr/local/bin/miniterm.py to 755
Successfully installed pyserial
Cleaning up...

After that I was able to flash the firmware:

 ./esptool.py -p /dev/ttyUSB1 write_flash 0x000000 v0.9.2.2\ AT\ Firmware.bin
Connecting...
Erasing flash...
Writing at 0x0007ef00... (100 %)

Leaving...

Now we have to change the baudrate for gtkterm (see above for the details) and restart gtkterm:

[default]
port	= /dev/ttyUSB1
speed	= 9600
bits	= 8
stopbits	= 1
parity	= none
...

One thing has changed for the communication with the module after the upgrade: after every command entered in gtkterm, not only Return has to be hit, but additionally Ctrl + J as well (CR+LF). So what do we get? Let’s change the baudrate to 57600:


AT

OK
AT+GMR
0018000902

OK
AT+CIOBAUD?
+CIOBAUD:9600

OK
AT+CIOBAUD=57600
BAUD->57600

OK
R

-> reconfigure & restart gtkterm!

As the new firmware changed some settings, we need to issue some more commands to get our tcp server back online (this time on ip 192.168.1.25….):

AT+CIPMUX?
+CIPMUX:0

OK
AT+CIPMUX=1

OK
AT+CIPMUX?

+CIPMUX:1

OK
AT+CIPSERVER=1,8001

OK
AT+CIFSR

192.168.4.1
192.168.1.25

OK
Link

+IPD,0,6:helo

OK

Now I will be ready to connect the Arduino Nano to my wifi module!


Connecting Arduino Nano is done really easily, with one level shifter (a resistor should work as well). I connected additionally the USB-Serial-Converter to the SoftSerial Arduino to see debug messages.

The Arduino is powered through the USB connection to the PC. During upload of the Arduino Sketch, the serial connection to the Wifi module has to be removed and reconnected afterwards.

I have pulled the CH_PD Pin to VCC, first with resistor (10k) then without. Without it was working more stable for me. Here the big picture:

Schematic

What we now need is the corresponding Arduino Sketch. I will upload it soon to my GitHub repo - here the first draft, inspired by Ray Wang @ Rayshobby LLC

/* ====== ESP8266 TCP Demo ======
 * Receive & Respond via TCP
 * (Updated Dec 30, 2014)
 * ==========================
 *
 * Change SSID and PASS to match your WiFi settings.
 * The IP address is displayed to soft serial upon successful connection.
 *
 * Inspired by
 * Ray Wang @ Rayshobby LLC
 * http://rayshobby.net/?p=9734
 * http://raysfiles.com/arduino/ESP8266a_arduino.ino
 */

#include <SoftwareSerial.h>

#define BUFFER_SIZE 512
#define esp Serial
#define SSID  "mywifi"      // change this to match your WiFi SSID
#define PASS  "mypassword"     // change this to match your WiFi password
#define PORT  "8001"          // using port 8001 by default

char buffer[BUFFER_SIZE];

// Software Serial for debug
SoftwareSerial dbg(10,11);  // use pins 10, 11 for software serial 

// By default we are looking for OK\r\n
char OKrn[] = "OK\r\n";

// LED Pin
const int LED = 13;


byte wait_for_esp_response(int timeout, char* term=OKrn) {
  unsigned long t=millis();
  bool found=false;
  int i=0;
  int len=strlen(term);
  // wait for at most timeout milliseconds
  // or if OK\r\n is found
  while(millis()<t+timeout) {
    if(esp.available()) {
      buffer[i++]=esp.read();
      if(i>=len) {
        if(strncmp(buffer+i-len, term, len)==0) {
          found=true;
          break;
        }
      }
    }
  }
  buffer[i]=0;
  dbg.print(buffer);
  return found;
}

void setup() {

  // assume esp8266 operates at 57600 baud rate
  // change if necessary to match your modules' baud rate
  esp.begin(57600);
  
  dbg.begin(9600);
  dbg.println("begin.");
  
  // Setup LED PIN as output
  pinMode(LED, OUTPUT);
  
  // blink test
  digitalWrite(LED, HIGH); // LED on
  delay(500); // 500 ms delay
  digitalWrite(LED, LOW); // LED off
    
  setupWiFi();

  // print device IP address
  dbg.print("device ip addr:");
  esp.println("AT+CIFSR");
  wait_for_esp_response(1000);
}

bool read_till_eol() {
  char incomingByte = 0;   // for incoming serial data
  static int i=0;
  if(esp.available()>0) {
    incomingByte = esp.read();
      buffer[i++]=incomingByte;
      if(i==BUFFER_SIZE)  i=0;
      if(i>1 && buffer[i-2]==13 && buffer[i-1]==10) {
        buffer[i]=0;
        i=0;
        dbg.print(buffer);
        return true;
    }
  }
  return false;
}

void loop() {
  int ch_id, packet_len;
  char *pb;  
  if(read_till_eol()) {
    dbg.println("----------------------------------");
    if(strncmp(buffer, "+IPD,", 5)==0) {
      // request: +IPD,ch,len:data
      sscanf(buffer+5, "%d,%d", &ch_id, &packet_len);
      if (packet_len > 0) {
        // read serial until packet_len character received
        // start from :
        pb = buffer+5;
        while(*pb!=':') pb++;
        pb++;
        dbg.print("Message received: ");
        dbg.println(pb);
        send_Response(ch_id, "ACK");
        if (strncmp(pb, "LEDON", 5) == 0) {
          digitalWrite(LED, HIGH); // LED on
        }
        if (strncmp(pb, "LEDOFF", 6) == 0){
          digitalWrite(LED, LOW); // LED on
        }
      }
    }
  }
}


void send_Response(int ch_id, String content) {
  esp.print("AT+CIPSEND=");
  esp.print(ch_id);
  esp.print(",");
  esp.println(content.length());
  if(wait_for_esp_response(2000, "> ")) {
    esp.print(content);
  } else {
    esp.print("AT+CIPCLOSE=");
    esp.println(ch_id);
  }
}


void setupWiFi() {
  // try empty AT command
  esp.println("AT");
  wait_for_esp_response(1000);

  // set mode 1 (client)
  esp.println("AT+CWMODE=1");
  wait_for_esp_response(1000);  

  // reset WiFi module
  esp.print("AT+RST\r\n");
  wait_for_esp_response(1500);
 
  // join AP
  esp.print("AT+CWJAP=\"");
  esp.print(SSID);
  esp.print("\",\"");
  esp.print(PASS);
  esp.println("\"");
  // this may take a while, so wait for 5 seconds
  wait_for_esp_response(5000);
  
  esp.println("AT+CIPSTO=30");  
  wait_for_esp_response(1000);

  // start server
  esp.println("AT+CIPMUX=1");
  wait_for_esp_response(1000);
  
  esp.print("AT+CIPSERVER=1,"); // turn on TCP service
  esp.println(PORT);
  wait_for_esp_response(1000);
  
    
}

A little success: Arduino sends correctly the AT commands to connect to the network! It receives an IP adress, I even can telnet to it!

I can see (on the debug serial) following commands running through:

begin.
AT

OK
AT+CWMODE=1
no change
AT+RST

OK
AT+CWJAP="mywlan","mypassword"
B�
  r�Ĥ���HB߬!{�����1�!�+!��B(�C)����B�B1�c+&ƅ��"�C�*�B����!(��9*)%�DŽ�b�c����Cx��B)�!���r�,%��D��c����C�!愆D
[System Ready, Vendor:www.ai-thinker.com]
AT+CIPSTO=30

ERROR
AT+CIPMUX=1

OK
AT+CIPSERVER=1,8080

OK
device ip addr:AT+CIFSR
192.168.1.30

OK

What does not work?

I wanted to switch the on-board LED of the Arduino via TCP commands (“LEDON” / “LEDOFF”) but at the moment I am struggling with the communication from the esp8266 to the Arduino. Sending the message “Hello” through a telnet terminal, I can see that the Wifi module is sending the complete message: “+IPD,0,7:Hello” but only a crippled message is received by the Arduino “+0lloOK”.

….to be continued….


If you run into problems or if you have any suggestions for the mistakes I have made, please leave a comment!

w