- By limpkin - My Projects -

As mentioned in my previous blog post I was very optimistic when designing my ESP8266-03 development board and didn't even prototype it before launching a batch in production. As I just received a few of these boards in the mail today and given that information about this module is scattered all over the internet, I'll detail here my first steps with it...





Configuring the FT230X







The onboard USB to UART adapter has 4 CBUS pins that can be configured as GPIOs or status pins. Three of them (CBUS0/1/3) are connected to green LEDs so if you want to change the default settings, you can download the FT Prog utility [here|http://www.ftdichip.com/Support/Utilities/FT Prog_v3.0.56.245.zip|en|FT Prog utility], program your new settings, disconnect/reconnect the dev board.





Playing with the default firmware





This part is inspired by this awesome web page.

Connect the development board to your computer using a micro-usb cable, launch your favorite terminal program (in my case Realterm), set a 9600 baudrate, head to the "Send" tab, tick the +CR & +LF boxes, enter these different commands and click "Send ASCII".



Testing the communication



>AT

OK



Getting the firmware version:



>AT+GMR

0018000902-AI03



Setting Wifi mode as AP+STA and listing nearby Access Points (APs):



>AT+CWMODE=3

OK

>AT+CWLAP

+CWLAP:(3,"mysuperwifi",-76,"90:xx:xx:xx:xx:xx",1)

+CWLAP:(4,"zak-52122",-79,"a4:xx:xx:xx:xx:xx",3)

+CWLAP:(3,"ZyXEL_133A",-80,"cc:xx:xx:xx:xx:xx",2)

+CWLAP:(3,"somewifi",-81,"e0:xx:xx:xx:xx:xx",4)

+CWLAP:(0,"HP-Print-0C-Photosmart",-82,"6c:xx:xx:xx:xx:xx",4)

+CWLAP:(4,"anotherwifi",-83,"fc:xx:xx:xx:xx:xx",1)



As you can see you'll find the APs names together with their MAC addresses and RSSIs. The first digit is the encryption type (0:open, 1:wep, 2:wpa psk, 3:wpa2 psk, 4:wpa wpa2 psk).

Connecting to your access point:



>AT+CWJAP="mysuperwifi","mypassword"

OK



Checking that you're actually connected:



>AT+CWJAP?

AT+CWJAP:"mysuperwifi"

OK



Download and run this TCP server/terminal made by tomeko: Bcbserver, send data to your main computer:



> AT+CIPMUX=0

OK

>AT+CIPSTART="TCP","your computer IP",7778

OK

Linked

+IPD,24:Connection established

OK



Here the TCP connection is established, you need to specify how many bytes you want to send (here 4)



>AT+CIPSEND=4

> (type your 4 bytes long text here)

SEND OK



You should see your text displayed in BCBcostam.

Finally, stop your TCP connection:



>AT+CIPCLOSE

OK

Unlink



You'll find a lot more AT commands here and here.





Building the Espressif toolchain





Until now we've used the ESP8266 as a peripheral, meaning that we need a computer/phone/microcontroller to operate it. However, since the ESP8266 manufacturer released the chip SDK we can reprogram it with our own code so it can work as a standalone device. To do so, we first need to build the Espressif toolchain.

This will unfortunately take quite a while... so only do it when you have some time to spend! I highly recommend following the great guide that can be found here. It is a tutorial for linux but you'll also find a Windows tutorial here.

Please note that in the Linux tutorial, at the time of writing I had to run "mv esp iot sdk v0.9.3/* ESP8266 SDK" and not "mv esp iot sdk v0.9.3 ESP8266 SDK".





Making our own program





Let's learn by example. In 4-5 hours I managed to make this fun setup:







The Doppler station





First, we need to setup one ESP8266 pin as input with its internal pull-up enabled so we can just connect our button between this IO and our platform ground:



PIN FUNC SELECT(PERIPHS IO MUX MTCK U, FUNC_GPIO13); // Set GPIO13 function

gpio output set(0, 0, 0, BIT13); // Set GPIO13 as input

PIN PULLDWN DIS(PERIPHS IO MUX MTCK U); // Disable pulldown

PIN PULLUP EN(PERIPHS IO MUX MTCK U); // Enable pullup



Given that we don't have access to the ESP8266 english datasheet and want to use all its already included features, we are forced to use the SDK. Have a look for "ESP8266EX SDK Programming Guide" on your favorite search website.

As a given pin can be driven by several controllers inside the ESP8266, the first line specifies that we want to use the GPIO controller on GPIO13. The three others.... well read the comments . This is a simple and non energy-saving way to use a button as you'll need to poll its state rather than having an interrupt based readout:



ETS GPIO INTR_DISABLE(); // Disable gpio interrupts

ETS GPIO INTR ATTACH(doppler int_handler, 12); // GPIO12 interrupt handler

PIN FUNC SELECT(PERIPHS IO MUX MTDI U, FUNC_GPIO12); // Set GPIO12 function

gpio output set(0, 0, 0, GPIO ID PIN(12)); // Set GPIO12 as input

GPIO REG WRITE(GPIO STATUS W1TC_ADDRESS, BIT(12)); // Clear GPIO12 status

gpio pin intr state set(GPIO ID PIN(12), 3); // Interrupt on any GPIO12 edge

ETS GPIO INTR_ENABLE(); // Enable gpio interrupts



The doppler sensor has a 5 volts frequency output (don't forget the voltage divider!) meaning that it'll toggle its pin several times per second at a frequency proportional to an object speed. In the simple firmware you can download below we're using a very simple strategy: everytime the HB-100 FOUT pin toggles, an interrupt is generated on the ESP8266 which will increment a counter. Every 0.5s we read this counter value and broadcast it to our computer and other ESP8266-03 module.

The interesting part above is the second line that registers doppler int handler as the GPIO12 interrupt function. Every time this function is called we increment our counter.



PIN FUNC SELECT(PERIPHS IO MUX GPIO2 U, FUNC_GPIO2); // Set GPIO2 function

gpio output set(0, BIT2, BIT2, 0); // Set GPIO2 low output



These two lines set GPIO2 as an output to drive the red LED. Given that the ESP8266-03 board already includes current limiting resistors you can directly connect your LED. As you can see in the video, this red LED blinks every 0.5sec:



os timer disarm(&led_timer); // Disarm led timer

os timer setfn(&led timer, (os timer func t *)led_timerfunc, NULL); // Setup led timer

os timer arm(&led_timer, 500, 1); // Arm led timer, 0.5sec, repeat



The ESP8266 'operating system' allows you to specify timers (functions) that will be fired at a pre-defined frequency. Here we specify that the led_timerfunc function should be called every 0.5sec indefinitely.



char ssid32 = "mywifissid"; // Wifi SSID

char password64 = "mywifipassord"; // Wifi Password

struct station_config stationConf; // Station conf struct

wifi set opmode(0x1); // Set station mode

os_memcpy(&stationConf.ssid, ssid, 32); // Set settings

os_memcpy(&stationConf.password, password, 64); // Set settings

wifi station set_config(&stationConf); // Set wifi conf

//wifi status led install(13, PERIPHS IO MUX MTCK U, FUNC GPIO13); // Wifi LED status



Having your board connect to your home Wifi is so simple! The last line allows you to specify an LED dedicated to Wifi status indication. It will blink when trying to connect/having an error, it will switch off when everything is ok.



void ICACHE FLASH ATTR network check ip(void)

{

struct ip_info ipconfig;



os timer disarm(&network_timer); // Disarm timer

wifi get ip info(STATION IF, &ipconfig); // Get Wifi info



if (wifi station get connect status() == STATION GOT IP && ipconfig.ip.addr != 0)

{

network_start(); // Everything in order

}

else

{

os_printf("Waiting for IP...

\r");

os timer setfn(&network timer, (os timer func t *)network check ip, NULL);

os timer arm(&network_timer, 1000, 0);

}

}



This 1sec timer is called until the platform gets an IP from your home's DHCP server (usually your router). Once it has an IP address, you can start establishing connections to you computer and other devices.



global tcp connect.type=ESPCONN_TCP; // We want to make a TCP connection

global tcp connect.state=ESPCONN_NONE; // Set default state to none

global tcp connect.proto.tcp=&global_tcp; // Give a pointer to our TCP var

global tcp connect.proto.tcp->local port=espconn port(); // Ask a free local port to the API

global tcp connect.proto.tcp->remote_port=7778; // Set remote port (bcbcostam)

global tcp connect.proto.tcp->remote_ip0=ip1; // Your computer IP

global tcp connect.proto.tcp->remote_ip1=ip2; // Your computer IP

global tcp connect.proto.tcp->remote_ip2=ip3; // Your computer IP

global tcp connect.proto.tcp->remote_ip3=ip4; // Your computer IP

espconn regist connectcb(&global tcp connect, tcpNetworkConnectedCb); // Register connect callback

espconn regist disconcb(&global tcp connect, tcpNetworkDisconCb); // Register disconnect callback

espconn regist reconcb(&global tcp connect, tcpNetworkReconCb); // Register reconnection function

espconn connect(&global tcp_connect); // Start connection



Setting up a TCP connection is not so complex. You specify your destination IP/port together with functions to call if the connection is made, disconnected or reconnected.



global udp connect.type=ESPCONN_UDP; // We want to make a UDP connection

global udp connect.state=ESPCONN_NONE; // Set default state to none

global udp connect.proto.udp=&global_udp; // Give a pointer to our UDP var

global udp connect.proto.udp->local_port=2222; // Set local port

global udp connect.proto.udp->remote_port=2222; // Set remote port

global udp connect.proto.udp->remote_ip0=ip1; // The other ESP8266 IP

global udp connect.proto.udp->remote_ip1=ip2; // The other ESP8266 IP

global udp connect.proto.udp->remote_ip2=ip3; // The other ESP8266 IP

global udp connect.proto.udp->remote_ip3=ip4; // The other ESP8266 IP

if(espconn create(&global udp_connect) == 0) // Correctly setup

{

os_printf("UDP connection set

\r");

udp conn ok = TRUE;

}



UDP connection are much simpler given that there's strictly no added logic on the data sending part like with TCP. The ESP8266 is just sending bytes to a given IP address.



I think I covered most of the low level stuff. I'll summarize what the firmware does in case you want to have a look at the source code:

- setup the input/outputs

- register a 0.5sec timer in charge of toggling the red LED, reading the doppler frequency, sending it to your computer and other ESP8266

- register a 1sec timer that will check the ESP8266 connection status. Once it has an IP, start making a TCP connection to the computer and a UDP one to the ESP8266





The indicating platform





The code here is much simpler:

- Connect to your Wifi

- Set 3 pins as outputs for the green/orange/red LEDs

- Create a UDP connection

- Parse the incoming data to know which LEDs to turn on/off.



Want the files? Here they are: doppler sensor code esp8266 client code

If you want more examples have a look at this github repository and don't hesitate to come to #esp8266 on freenode!

Thanks zarya for the help and code!