I wanted to try my hand with ESP8266 modules, so I got a witty cloud development board. It's running a proprietary firmware from gizwits which I backed up if anyone wants to look at it.
The board is in two parts: programming board("cape") with ch340g usb serial and 3.3V converter (plus flash and reset buttons); and main board with the esp module, ams1117 3.3V voltage regulator, a button, a blue led, an rgb led, and a light sensor(photo resistor). All this for the price of a nodemcu board, but in a smaller form factor.
One of the greatest things of the ESP8266 ecosystem is nodemcu-firmware, an environment allowing you to program the microcontroller in lua, greatly simplifying the prototyping and familiarization.
After backing up the flash with esptool (see esptool read_flash
), I flashed the latest release of nodemcu-firmware. Then, using nodemcu-uploader, one can access the lua REPL (nodemcu-uploader terminal
) and uploads lua scripts (nodemcu-uploader --baud 9600 upload init.lua
); init.lua
being the first script being run at powerup.
Quick doc
I reverse-engineered the various goodies that are on board, since I didn't find any documentation on this specific board online:
Blue LED: use the PWM 4. High duty cycle = OFF.
-- Use a LED with a 500Hz PWM
function led(pin, level)
pwm.setup(pin, 500, level)
pwm.start(pin)
end
-- Control the Blue LED: 0 -> 1023 higher means light off
function blueLed(inverted_level)
led(4, inverted_level)
end
blueLed(10) -- test at high intensity
RGB LED: use PWMs 8, 6, 7. High duty cyle = ON.
-- Control an RGB LED: three 0->1023 values; higher means more light
function rgb(r, g, b)
led(8, r)
led(6, g)
led(7, b)
end
rgb(500, 0, 0) -- test RED
Button: GPIO 2. button pressed = 0 level.
-- launch connect() on button press
gpio.mode(2, gpio.INPUT)
gpio.trig(2, "down", connect)
Light sensor: use the ADC.
-- Print light sensor value
print(adc.read(0))
Going further
I then discovered the official nodemcu-firmware documentation currently points to the dev branch; which has many new modules and functions I wanted to use (like the wifi event monitor or http module) that weren't available in master yet. I used the nodemcu cloud builder, a service provided by a kind community member to build a custom version of nodemcu-firmware on the dev branch and the modules I needed enabled.
This allows to do this kind of code, that connects to wifi on a button press, and reacts with a simple HTTP request:
function connect()
-- if wifi is already connected (config saved), launch job directly
if wifi.sta.status() == wifi.STA_GOTIP then
doOnlineJob()
return
end
rgb(1000, 50, 0) -- turn orange
for event=wifi.STA_IDLE,wifi.STA_GOTIP do
wifi.sta.eventMonReg(event, monCallback)
end
wifi.sta.config("mynetworkssid", "mynetworkpassword")
wifi.sta.eventMonStart(100) --the event mon polls every 100ms for a change
end
function monCallback(prevState)
state = wifi.sta.status()
if prevState == nil then
prevState = "unknown"
end
print("Wifi status " .. prevState .. " -> " .. state)
blueLed(state*204) -- led intensity depends on status, with success = OFF
if state == wifi.STA_GOTIP then
rgb(0, 200, 150) --blue/green-ish, wifi OK
print("Got IP " .. wifi.sta.getip())
wifi.sta.eventMonStop("unreg all") -- stop event monitor
doOnlineJob()
end
if state == wifi.STATION_NO_AP_FOUND or state == wifi.STATION_CONNECT_FAIL then
rgb(150, 0, 0) -- red/fail
wifi.sta.eventMonStop("unreg all") -- stop event monitor
end
end
function doOnlineJob()
rgb(150, 0, 150) -- working, purple
http.post("http://example.invalid/api/pushed", nil,
'{"hello": "from_esp_witty_42"}', function(status_code, body)
if status_code == nil or body == nil then
print(status_code)
print(body)
rgb(200, 0, 0) --fail red
return
end
print("Got code " .. status_code .. " answer " .. body)
if status_code == 200 then
rgb(0, 0, 200) --success, blue
end
end)
end
This is reproducing the software function of the DASH/IoT Button, Netflix Switch or Flic.
There are a few projects that will guide you through the hardware part of building a button with an ESP module.
PS: Be careful of big https cert chains, there's a hardcoded limit of 5120 bytes for the SSL buffer in the firmware, that might make the handshake fail.