ESP8266: part I
By Ricardo
Ah, microcontrollers. Man, I missed playing with those. Seriously. Who here who has ever played with one doesn’t miss countless hours of programming and weird debugging? It’s always so much fun… mostly.
Note: I wrote this post to describe my experience with ESP8266 modules. This is not really a tutorial, but if might help young players, so… go for it!
ESP what?
A few months ago I’ve bought some ESP8266 modules from China. Since I’m very lucky, the customs stopped me at the time and charged me for that. Paying the taxes they imposed on that package was worth it: it was still cheaper than buying them online here. No reason to complain there. Anyway, a while has passed since they arrived and they were inside a box in my room. Today, I decided to give it a try and maybe think about redesigning a project I did (and used) while I was still in Berlin. The project will be discussed later in the future.
The ESP8266 is a really cool module. For those who had no idea what is that, it’s a very tiny wireless-enabled system-on-chip. It’s one of those Internet of Things little devices. You know, the future! You can write code and reprogram the thing to do anything you want (within its limitations, of course). It has an ARM CPU running at 80 MHz and has only a few kilobytes of RAM. I won’t go into details of its specifications since you can find pretty much everything online (like here and here). I’m going to describe here my experience so far with it.
We need power!
(Source: http://teslamania.delete.org/frames/longarc.htm)
First of all, I’m an idiot 1. I didn’t read the full documentation on how to power the thing up, so I smashed the keyboard for 30min until I felt like I really needed to RTFM. Oh well.
Ok, so we know that this thing runs at 3.3v. Of course all my power supplies are 5v, or even 12v. That’s fine: all you need is a voltage regulator for that. Ironically, I had one stolen from another device around here, so I just used one 5v supply with that and I had a good and solid 3.3v output. For the 5v I used one of those 2A units that come with small TP-Link routers and gives you an USB port at the end of it. Meh, it works. Also, 2A is overkill for this device - really!
So now let’s take a look at the pinout of my ESP8266 board. There are many variations of it, but I’ll discuss only the one I have, which is, as far as I know, the oldest one. Here’s it:
(Source: http://uzebox.org/wiki/index.php?title=ESP8266)
As you can see, we have our VCC
and GND
pins, which is where you connect the power. And that’s what I did, and, of course, nothing happened. Actually, a very cute and small red LED powered on, showing that the device had power. That’s cool. But nothing blinked or something, which was weird for me: embedded devices like this usually blink something on boot. Go figure. Anyway, after that, I attached my USB-to-serial board that accepts 3.3v (since the UART on this device is also 3.3v) and tried to communicate with it using picocom
. And, of course, nothing happened! I double-checked the wiring again and again and nothing was happening. I took a look at the documentation and a blue LED should blink when there was serial data passing around it but nothing changed. Hm, I did something wrong. This where I should have read the documentation. Duh!
Turns out this device is a bit harder2 to power on. You need to pull-up the RST
and CH_PD
pins to 3.3v, so that the device would actually go on and boot. By leaving the RST
floating, it would stay forever resetting (aka no boot). Adding a few resistors to the breadboard and more wires to the thing, it worked: blue LED blinked and something was printed on my screen! Yey!
Oh, regarding the RTFM, here is “manual” I used.
We have serial!
Ok, so now we have communication. Blue LED is blinking and we have a string on our terminal: ready
. Good, so am I (haaaa). By reading a bit more I saw that it has a default firmware that accepts AT commands - yes, just like old modems! Oh, that’s nostalgic! And yes, I honestly like that. It’s so cool and old-school-ish.
I typed my first commands… and, of course, it didn’t work. It never does. Turns out this default firmware requires Windows-like CR: CRLF (0x13 0x10
). Nothing a --omap crcrlf
can’t fix. Easy.
Anyway, I played a bit with that default firmware. You can’t really do anything cool with it. I mean, sure, it allows you to connect to networks, maybe even transmit data, but not really in the way I plan to use this thing. So let’s take it off and burn something else on it. Maybe even our own code? We’ll see.
Well, for the project I want to use this, I need 3 PWM (pulse-width modulation) pins. This is my way of emulating a lower voltage, so that the device I’ll attach this to reads a voltage between 0 and 3.3v, according to what I set as my PWM configuration. This is nothing new to me: I’ve done that with Arduino for quite a while now and it works really well. However, remember that I need 3 PWM pins, but my board is the small version, so it has only 2 GPIO (General Purpose I/O). pins I could use for that. That’s a problem.
My not-so-long-but-yet-extremely-useful experience with microcontrollers showed me that I can use their pins for whatever I want, as long as I have enough low-level access to change their configuration. On AVR microcontrollers, for example, I was able to select which pins I wanted for UART3. So, in theory, I could use the UART pins on the ESP8266 as GPIO pins and have PWM configured on them. After all, I won’t need serial on my project at all, since all the communication will be done by the network. Debugging? Nah, I can do that with the built-in LED on the board. I call this “the classic debugging”. This is nothing new to me as well: I’ve debugged the Die Datenkrake by turning LEDs on and off, so that should be enough for me on the ESP8266 as well. I hope.
However, every project I had looked so far (essentially only NodeMCU (Lua-based firmware) and MicroPython) needed a serial port to work, or at least to play with it. They are terminal-like firmwares. I don’t want that. I mean, I want, but for this project I can’t use that. I need one pin of that UART port. Also, I don’t want to program the device like that: I want to directly write my code to the damn thing - even if it’s harder to do so. For that, all we need is the SDK, right?
Yes and no. Well, there’s a SDK for the ESP8266 which is the esp-open-sdk. It took a while to fully install on my laptop, but while it was doing that I actually found a better way of playing with it - at least for now. However, yes, I will play with its SDK one day. I still want to compile and upload my code like I used to do with AVR: make image upload
. Oh, the good days: all I needed was a terminal and a good bottle of Club-Mate. Oh yeah.
So, what I’ve found was Arduino IDE. Yes, you’re not crazy. Think about it: for prototyping, why not use an Arduino-based environment? After all, we know how to use Arduino, and it has good libraries that help us a lot when coding tricky stuff or complex timings. And someone added support for the ESP8266 on it…. so, why the hell not? Let’s play with it!
It’s alive!
After properly updating my Arduino IDE and adding support for that board, I thought: why not doing the Hello World of microcontrollers - the blinking LED on the ESP8266 as well? After all, it doesn’t matter if it’s a dumb code or not, all I want is to make sure I can reprogram the damn thing to run my own code! So here’s what I came up with:
void setup() {
// I want to use the built-in blue LED on the board now.
pinMode(BUILTIN_LED, OUTPUT);
}
void loop() {
// LED on.
digitalWrite(BUILTIN_LED, HIGH);
delay(500);
// LED off.
digitalWrite(BUILTIN_LED, LOW);
delay(500);
}
Easy, no?
Once compiled, it’s time to program the board, right? Well… not so fast. First we need to reset it into a mode where it allows you to upload your code. Following partial instructions from the esptool
programming script, I pulled GPIO0
down and left CH_PD
floating4, as well as GPIO2
(which was already floating anyway). Even though most of the documents online say to do something else, this combination worked pretty well for me. It was more of a try-and-error approach, but in the end I was able to boot into programming mode.
Once in the bootloader, I just hit Upload on the Arduino IDE and left it do its job… and done. After a few seconds, the image of a simple code that blinks the built-in blue LED on the board was flashed. The board rebooted itself into to normal execution mode and… YES, it’s blinking!
Oh, and yeah, if you disconnect power or reset the board somehow, I’ll have to undo your programming mode wiring and go back to the normal execution wiring. That is kinda annoying. That means reconnecting the CH_PD
back to its 3.3v pull-up resistor and disconnecting GPIO0
from GND. But, hey, nothing is perfect!
I want more!
I wanted to connect to my wireless network at home! I wanted to have a HTTP server listening for requests changing the pins on the board! I wanted to listen on an UDP port and change pins according to the packets I receive there! Well…
There’s a lot of cool stuff we can do using the libraries available on Arduino’s IDE. And also without them, coding straight from the SDK. But let’s walk this road step by step, reading the documentation before coding (haha, like that’s gonna happen!) and enjoying every step we take towards the future, making sure we don’t release the magic smoke on it!
And I actually have it already on my wireless network, as well as a HTTP server running on it. But I’ll leave this to a next post, since there’s a lot to discuss as well. And in case you’re curious, here’s a photo of my dirty setup:
Good luck!
-
No, I did not run it at 5v. I know what I’m doing. Sort of. ↩︎
-
Well, that’s not really harder. It’s more like annoyingly annoying. I’ve played with other devices that require such things to power up, and it’s usually nothing really hard. All it takes is a few resistors and we’re good to go. What is annoying is that it could be somehow embedded on that board. Also, it’s extra wiring, and the thing is already really small. All that wiring is… well, confusing. ↩︎
-
Well, at least which serials, which changed the pins. I didn’t really try to use random pins for UART, but it should, in theory, be possible. At least with software UART. Hardware UART seems unlikely to me. I might be wrong. ↩︎
-
I’m not sure if the technical term is correct here. What I mean by floating is leaving the pin disconnected. ↩︎