WWW.DUMAIS.IO
ARTICLES
OVERLAY NETWORKS WITH MY SDN CONTROLLERSIMPLE LEARNING SWITCH WITH OPENFLOWINSTALLING KUBERNETES MANUALLYWRITING A HYPERVISOR WITH INTEL VT-X CREATING YOUR OWN LINUX CONTAINERSVIRTIO DRIVER IMPLEMENTATIONNETWORKING IN MY OSESP8266 BASED IRRIGATION CONTROLLERLED STRIP CONTROLLER USING ESP8266.OPENVSWITCH ON SLACKWARESHA256 ASSEMBLY IMPLEMENTATIONPROCESS CONTEXT ID AND THE TLBTHREAD MANAGEMENT IN MY HOBBY OSENABLING MULTI-PROCESSORS IN MY HOBBY OSNEW HOME AUTOMATION SYSTEMINSTALLING AND USING DOCKER ON SLACKWARESYSTEM ON A CHIP EMULATORUSING JSSIP AND ASTERISK TO MAKE A WEBPHONEC++ WEBSOCKET SERVERSIP ATTACK BANNINGBLOCK CACHING AND WRITEBACKBEAGLEBONE BLACK BARE METAL DEVELOPEMENTARM BARE METAL DEVELOPMENTUSING EPOLLMEMORY PAGINGIMPLEMENTING HTTP DIGEST AUTHENTICATIONSTACK FRAME AND THE RED ZONE (X86_64)AVX/SSE AND CONTEXT SWITCHINGHOW TO ANSWER A QUESTION THE SMART WAY.REALTEK 8139 NETWORK CARD DRIVERREST INTERFACE ENGINECISCO 1760 AS AN FXS GATEWAYHOME AUTOMATION SYSTEMEZFLORA IRRIGATION SYSTEMSUMP PUMP MONITORINGBUILDING A HOSTED MAILSERVER SERVICEI AM NOW HOSTING MY OWN DNS AND MAIL SERVERS ON AMAZON EC2DEPLOYING A LAYER3 SWITCH ON MY NETWORKACD SERVER WITH RESIPROCATEC++ JSON LIBRARYIMPLEMENTING YOUR OWN MUTEX WITH CMPXCHGWAKEUPCALL SERVER USING RESIPROCATEFFT ON AMD64CLONING A HARD DRIVECONFIGURING AND USING KVM-QEMUUSING COUCHDBINSTALLING COUCHDB ON SLACKWARENGW100 MY OS AND EDXS/LSENGW100 - MY OSASTERISK FILTER APPLICATIONCISCO ROUTER CONFIGURATIONAASTRA 411 XML APPLICATIONSPA941 PHONEBOOKSPEEDTOUCH 780 DOCUMENTATIONAASTRA CONTACT LIST XML APPLICATIONAVR32 OS FOR NGW100ASTERISK SOUND INJECTION APPLICATIONNGW100 - DIFFERENT PROBLEMS AND SOLUTIONSAASTRA PRIME RATE XML APPLICATIONSPEEDTOUCH 780 CONFIGURATIONUSING COUCHDB WITH PHPAVR32 ASSEMBLY TIPAP7000 AND NGW100 ARCHITECTUREAASTRA WEATHER XML APPLICATIONNGW100 - GETTING STARTEDAASTRA ALI XML APPLICATION

LED STRIP CONTROLLER USING ESP8266.

2016-03-02

I recently installed an RGB led string under my kitchen cabinet. I wanted to way to control it using any web browser on a cell phone, tablet or desktop computer. There are many ways I could have achieved this but this time, I wanted to do it all by myself and design my first PCB. This is how I did it.

ESP8266

The ESP8266 is small cheap wifi microcontroller. It is a 32bit microcontroller with and external 1024kb or flash memory. There are tons of information out there about this chip so I won't dig too much into the basics.

When I discovered this board, I realized the potential it could bring to my home automation projects. I can now have multiple devices that talk to my central software (New Home Automation system) wirelessly.

Firmwares

The ESP8266 usually comes with a pre-loaded "AT" firmware. If it isn't, you can download it for free and upload it, using an FTDI cable, to your chip. The AT firmware is a simple firmware that lets you send "AT" style commands, like in the old days with modems, to control the chip. There's an AT command to connect to an access point, another to start a TCP server, another to send a packet, etc.

A lot of people use the AT firmware. This allows you to connect a another microcontroller to the ESP8266 using the UART pins and send commands to the device. But you can also write your own firmware and take advantage of the the 1024kb of flash on the chip. You have a few GPIOs and 2 UARTs. You don't need an external microcontroller.

Environment

To upload a firmware, whether it is the AT firmware or your own, you will need the flash tool. To build your firmware, you will need a complete toolchain. The esptool can be found at https://github.com/themadinventor/esptool/. Once you have downloaded the file, just copy it somewhere like in /usr/bin so that it is in your exec path. To upload a firmware, you must obviously obtain one or build one. The firmware is separated in a couple of file. If you are uploading the AT firmware, this should work (change /dev/ttyUSB8 for the serial port where your FTDI cable is attached):

esptool.py --port /dev/ttyUSB8 --baud 9600 write_flash 0x00000 boot_v1.1.bin 0x01000 v0.20/user1.bin 0x7c000 esp_init_data_default.bin 0x7e000 blank.bin

Programming

Keep in mind that the chip must be reset while GPIO0 is pulled low in order to enter the bootloader to accept a firmware update. To create your own firmware, you will need to download the toolchain. The following should get you going:

git clone --recursive https://github.com/pfalcon/esp-open-sdk make STANDALONE=y mv xtensa-lx106-elf /opt/

Now add /opt/xtensa-lx106-elf/bin in your PATH. Next, you will need a Makefile. I've created the following:

all: firmware TTY=/dev/ttyUSB8 SRC = main.c OBJECTS=$(SRC:.c=.o) CC = xtensa-lx106-elf-gcc CFLAGS = -I. -mlongcalls LDLIBS = -nostdlib -Wl,--start-group -lmain -lnet80211 -lwpa -llwip -lpp -lphy -Wl,--end-group -lgcc LDFLAGS = -Teagle.app.v6.ld .c.o: $(CC) -c $(CFLAGS) $< -o $@ firmware: $(OBJECTS) $(CC) $(LDFLAGS) $(LDLIBS) $(OBJECTS) -o firmware.elf esptool.py elf2image firmware.elf install: firmware esptool.py --port $(TTY) --baud 115200 write_flash 0 firmware.elf-0x00000.bin 0x40000 firmware.elf-0x40000.bin clean: rm *.bin rm *.elf rm *.o

Again, remember to reset the chip with GPIO0 pulled low before invoking 'make install'. Here is a basic source file to build a firmware

#include "ets_sys.h" #include "gpio.h" void ICACHE_FLASH_ATTR user_init() { gpio_init(); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO5); gpio_output_set(BIT5, 0, BIT5, 0); }

Notice how the entry function is called user_init() instead of main(int argc, char** argv). This is because you are not running your firmware bare-metal on the board. There is an OS running in there and it will invoke user_init(). This is an event-based system. You cannot make an infinite loop like you would on another microcontroller. Instead, you let the OS run and hook your app to some events with callback functions. There is a way to create a timer and give the OS a pointer to your timer callback function. You can also give the OS a function pointer to a message handler and post messages to your app in order to receive messages in your message handler. If your code takes too much time inside a callback, the OS watchdog will reset your chip. So you cannot make infinit loops nor complex functions that do massive computations. You have to build your architecture around a single-threaded event-based system. Kindof like a javascript application.

The SDK, included in the toolchain, is pretty easy to use. For examle, to connect to a wireless access point, all you need to do is:

void ICACHE_FLASH_ATTR init_wifi(char ssid[32], char password[64]) { struct station_config station_config; wifi_set_opmode(1); // station mode. will connect to AP os_memcpy(&station_config.ssid, ssid, 32); os_memcpy(&station_config.password, password, 64); wifi_station_set_config(&station_config); wifi_station_set_auto_connect(true); wifi_station_set_reconnect_policy(true); } void ICACHE_FLASH_ATTR user_init() { init_wifi("SSID","PASSWORD"); }

If you want to create an infinite loop, as I said previously, you cannot do this within a callback since it will block the os thread and the watchdog will reset your board. Instead, you need to post your self a message so that the OS will call your function everytime. For example:

#define TASK_QUEUE_SIZE 64 #define MAIN_LOOP_TASK_PRIORITY 1 os_event_t main_loop_task_queue[TASK_QUEUE_SIZE]; // handle a message static void ICACHE_FLASH_ATTR main_loop(os_event_t *events) { // do something with the message ... // now post a message again to our self, creating an infinit loop system_os_post(MAIN_LOOP_TASK_PRIORITY, 0, 0); } void ICACHE_FLASH_ATTR user_init() { system_os_task(main_loop, MAIN_LOOP_TASK_PRIORITY, main_loop_task_queue, TASK_QUEUE_SIZE); // post a message to ourself system_os_post(MAIN_LOOP_TASK_PRIORITY, 0, 0); }

The Board

I'm not going to show my board diagram, because frankly, I'm a little ashamed of the work I did. This is my first PCB design and I'm still learning basic electronics. Bascially, I made a PCB with 3 mosfets, a step-down voltage regulator (12V to 3.3V) and a ESP-03 chip.

PWM

The chip supports software PWM for all GPIOs but I never was able to make it work properly. So I ended up writing my own software PWM. It's pretty straight forward, I just setup a timer and toggle GPIOs according to a duty cycle set by the user application. You can get my source code here:

DWN protocol

For each of my new Wifi devices to talk to my home automation server, I had to invent a new protocol. I could have used MQTT but I felt like my idea was even more simple. I created what I call the DWN protocol (DHAS Wifi Nodes).

The protocol is very simple. The wifi node broadcasts a JSON message containing its name and unique ID every 5 seconds on a multicast address at port 242. Whenever my home automation server sees such an advertisement, it will detect the source IP address of the broadcasting device and connect to the device's TCP server listening on port 242. Once the wifi device has a TCP client connected, it continue to send advertisements every 5 seconds and also sends heartbeats to the connected client. The DWN protocol does not define the format of payloads being exchanged between the home automation server and the wifi device. The DWN protocol is just a protocol that allows wifi nodes discovery.

Using such a system, my home automation can detect any wifi devices that gets turned on in my house and it will connect to it. Since the devices broadcast their name (ie: "IRRIGATION_CONTROLLER"), the server loads the appropriate "driver" or "module" for that device and starts communicating with them. This allows me to have a plug-and-play architecture. If I want to add a second led controller device, I just build one, turn it on and the home automation server automatically detects it and starts using it.

Future projects

This was my led controller board. I am planning on making a sprinkler controller with a esp-03 board with 4 relays, using the DWM protocol with my home automation server. I will also make a small device with a ESP-01 board with 2 input GPIOs to monitor my alarm system's relays. I currently monitor my alarm system's relay with an arduino setup as an ACM device plugged in the USB of my computer. I'd rather go wifi now. I would also like to build a device that would stay connected in my car. Onces I park my car in the garage, because of the DWN protocol, my home automation server will know when my car is at home and when it isn't. So as you can see, these esp8266 chips can be used for many things in the home automation world.