ESP8266 WiFi – Universal I/O bridge Firmware
This is a project that attempts to make all (or at least most) of the I/O on the ESP8266 available over the network. Currently this includes GPIO’s (as GPIO or PWM), I2C, the UART and external displays (currently only SAA1064).
The GPIOs can be selected to work as “normal” input, “normal” output, “timer” mode (this means trigger once, either manually or at startup, or “blink” continuously) or “pwm” mode (16 bits PWM mode, running at 330 Hz, suitable for driving lighting).
The “normal” UART lines (TXD/RXD) are available and are bridged to the ESP8266’s ip address at port 25. This is unless the UART lines are re-assigned as GPIOs, which is also possible.
GPIOs can also be selected to work as i2c lines (sda, scl). You can use the “raw” i2c send and receive commands to send/receive arbitrary commands/data to arbitrary slaves. For a number of i2c sensors there is built-in support, which allows you to read them out directly, where a temperature etc. is given as result.
The firmware also listens at tcp port 24, and that is where the configuration and commands go to. Type
telnet <ip_address> 24 and type
? for help.
The project is still in development, expect more features in the future.
About the UART bridge
The UART bridge accepts connections on tcp port 23, gets all data from it, sends it to the UART (serial port) and the other way around. This is the way to go to make your non-networking microcontroller WiFi-ready. If you add an RS-232C buffer (something like a MAX232 or similar), you can even make your non-networking peripherals like printers etc. available over the wireless lan.
The UART driver is heavily optimised and is completely interrupt driven, no polling, which makes it very efficient.
This code is very loosely based on the work of beckdac, which I used as a starting point, although there hasn’t been any original code left for some time ;-)
This is how it works:
- Attach your microcontroller’s UART lines or RS232C’s line driver lines to the ESP8266, I think enough has been written about how to do that.
- Load a generic “AT-command” style firmware into the ESP8266. Exactly how to do that should be on the page you’re downloading the firmware from.
- Setup the wlan parameters (SSID and password) from this firmware, using a terminal emulator. Check it’s working and write to flash (if the firmware doesn’t do that automatically).
- Now flash this firmware, for example with the esptool.py command, something like this:
esptool.py --port /dev/pl2303 --baud 460800 write_flash 0x00000 fw-0x00000.bin 0x40000 fw-0x40000.bin. Replace /dev/pl2303 by the proper device node. The ESP8266 can indeed be flashed at this high speed, it’s autoprobing the baud rate. If it doesn’t succeed immediately, try again, sometimes the ESP8266 gets the baud rate wrong initially. If it still doesn’t work, try a lower baud rate.
- After flashing restart. In theory this is not necessary, but I found the UART won’t start if you leave out the reset.
- Start a
telnetsession to port 24 of the ip address, type
- You will now see all commands.
- Use the commands starting with baud to setup the UART. After that, issue the
config-writecommand to save and use the
resetcommand to restart.
- After restart you will have a transparent connection between tcp port 23 and the UART, tcp port 24 is always available for control.
To work with i2c, first select two GPIO’s as sda and scl lines using the
gm .. mode sda and
gm .. mode scl commands. Besides the “normal” GPIOs, it should be possible to use GPIO0 and GPIO2 for i2c (boot selection), just as GPIO1 andGPIO3 (normally connected to the UART) using a proper pull-up resistor, but I didn’t try it myself.
The selected GPIO’s are set to open drain mode without pull-up, so you will have to add them yourself. The proper value of the resistors should be calculated but 4.7 kOhm usually works just fine.
i2c-write commands to read/write raw data to/from i2c slaves.
For a selection of well-known i2c sensors, there is built-in support. Use the
i2c-sensor-readcommands for these.
Currently supported i2c sensors are:
- digipicco (temperature and humidity)
- lm75 (and compatible sensors) (temperature)
- ds1621/ds1631/ds1731 (temperature)
- bmp085 (temperature and pressure) (untested for now)
- htu21 (temperature and humdity) (untested for now)
- am2321 (temperature and humidity)
- tsl2560 (light intensity)
- bh1750 (light intensity).
Currently only the SAA1064 is supported, it’s a 4×7 led display multiplexer, controlled over i2c.
In the future I plan to add “bare” LCD text displays using the well-known Hitachi LCD controller and Orbital Matrix i2c-controlled VFD/LCD screens.
The system consists of multiple “slots” of messages that will be shown one at a time. You can set a timeout on a message and it will be deleted automatically after that time. If no slots are left, it show the current time (rtc). Use 0 as timeout to not auto-expire slots.
All displays have 8 slots for messages that can be set using the ds (display-set) command: ds . Use dd (display-dump) to show all detected displays, add a verbosity value (0-2) to see more detail. Finally the db (display-bright) command controls the brightness of the display. Valid values are 0 (off), 1, 2, 3, 4 (max). Use: db
Please note the saa1064 runs at 5V or higher. It cannot be connected to the esp8266 directly. It must have it’s own 5V power supply and may or may not need i2c level shifters. I am using level shifters, but it may not be necessary in the end. YMMV.
Needless to say it will only work if i2c is up and running.
|ub||uart-baud||baud rate||Any baud rate you like, forget the 300-600-1200-2400-etc. list, the ESP8266 can freely use any baud rate you like. Don’t forget to config-write and reset.|
|ud||uart-data||5, 6, 7, or 8||The number of data bits, usually 8.|
|us||uart-stop||1 or 2||The number of stop bits, usually 1.|
|up||uart-parity||none, evenor odd||The parity, usually none. Don’t forget to set data bits to 7 if you want to use any parity.|
|cd||config-dump||none||Shows the complete configuration as stored in non volatile memory.|
|cw||config-write||none||Writes config to non volatile memory.|
|gd||gpio-dump||none||Dump GPIO configuration and current status.|
|gg||gpio-get||gpio||Read GPIO. For example gg 2 reads the GPIO 2 as input.|
|gs||gpio-set||gpio [value]||Set the GPIO if it’s set as output, if set as timer, trigger the timer, if it’s set as pwm, set the duty cycle (default startup value is taken if it’s missing).|
|gm||gpio-mode||mode[mode parameters]||Without mode/parameters: dump all GPIOs and their mode. See the table below for available modes and their syntax when parameters are supplied. After making changes, use reset to enable the changes.|
|disable||none||Dont’ use the GPIO (leave completely untouched).|
|input||none||Set GPIO to input.|
|counter||[reset_on_get[debounce_time]]||Set GPIO to counter. Set reset_on_get to 1 to have the counter reset when read. Set debounce to set debounce time in milliseconds (default is 100 ms).|
|output||startup-state||Set GPIO to output. Set startup-state to 0 or 1 to configure the state of the output directly after start.|
|pwm||[startup-duty-cycle]||startup duty cycle is the duty cycle after boot, default 0. The duty cycle can be 0 (off) to 65535 (continuously on).|
|i2c||sda or scl||configure this GPIO for i2c operation. Specify two GPIOs to assign to sda and scl.|
|ia||i2c-address||address||set i2c slave’s client address for subsequent read and write commands.|
|ir||i2c-read||bytes||Read (raw) this amount of bytes from the i2c slave. The bytes returned are in hex.|
|iw||i2c_write||byte [byte …]||Write (raw) bytes to i2c slave. Format is hex bytes separated by a space, e.g. 1 2 a b cc.|
|irst||i2c-reset||none||Reset the i2c bus. Required whenever a read or write failed.|
|isd||i2c-sensor-dump||[verbose]||Dump all detected sensors on the i2c bus. Set verbose to 1 to list all known sensors, including those that are not detected, set verbose to 2 to get even more verbose output, including i2c bus errors.|
|isr||i2c-sensor-read||sensor-id||Get the value of the sensor with id sensor id. Obtain sensor id’s with i2c-sensor-dump.|
|isc||i2c-sensor-calibrate||sensor-idscale offset||Set calibration of the sensor with id sensor id. The result from the sensor is multiplied by scale and then offset is added. Both values may be negative and are floating point types. Don’t forget to write the config afterwards.|
|db||display-brightness||brightness||Sets display brightness. Use brightness = 0 (off), 1,2,3,4|
|dd||display-dump||Dumps all detected displays.|
|ds||display-set||Displays text on display. Slots with text are shown in turn, after timeout (in seconds) the slot is discarded, 0 for permanent, need to replace manually.|
|?||help||none||Shows list of commands.|
|s or u||set/unset||[option]||Sets / unset options. Add option to set/unset option, leave out the option to list all options.
Currently known options are:
print-debug, shows debug info on the UART (wlan, dhcp etc).
strip-telnet, disable / enable stripping initial “garbage” from telnet at the UART bridge.
tsl-high-sens, set tsl2550 and tsl2561 sensors to “high sensitivity mode”, recommended unless operated outdoors in sunlight.
bh-high-sens, set bh1750 sensor to “high sensitivity mode”, recommended unless operated outdoors in sunlight.
To activate, write config and restart.
|q||quit||none||Disconnect from the control channel.|
|r||reset||none||Reset the ESP8266, required if you make changes to the UART parameters or to the GPIOs mode.|
|S||stats||none||Shows some statistics (timers, wlan, memory). These may change over time.|
|rs||rtc-set||hoursminutesseconds||Set “real time clock”. It’s a real time clock in the sense that it counts hours, minutes, seconds. It may not be that precise. YMMV.|
|wl||wlan-list||none||View results of access point / ssid scan from wlan-list|
|ws||wlan-scan||none||Initiate access point / ssid scan. Use wlan-list to view the results|
Release 11: Uart bridge tcp port and access point scanning.
- tcp port the uart bridge listens at is now configurable (see btp command)
- add wlan / access point scanning (see wlan-scan and wlan-list commands)
- optimisation (speed and memory usage, both ram and flash)
- some small bug fixes
Release 10: Add display framework, combine firmware files
- add missing display.c and display.h files
- added display framework
- added support for i2c SAA1064 4x7 led segment driver
- move to a single firmware file with padding between the iram and the irom region, flash on 0x00000
- updated documentation
Release 9: Add sensor calibration, pwm modulation feature, fix some i2c sensors
- add i2c sensor calibration, you can specify a correction offset and factor per sensor (isc command)
- change irom_text offset from 0x40000 to 0x10000, this frees up about 200 kbyte of flash memory
- add pwm modulation for all your "flashy" effects, see below for usage
- fixes to the tsl2550, tsl2561, bh1750, digipicco and am2321 i2c sensors
- add realtime clock (sort of)
This makes the duty go up and down automatically between configured boundaries, with a configured speed. Convenient for "slow" flashlights or "glowing" christmas lights.
- For normal pwm use:
- For modulated pwm use:
Speed is actually slowing down factor, 1 is fastest.
Release 8: Keep WLAN config when possible and add the last few GPIO's
- i2c sensors: improve ds1621/ds1631/ds1731 vs lm75/tmp275 and tsl2550 vs. tsl2561
- don't touch GPIO's AT ALL if we don't configure them
- add GPIO16 (restricted to modes input/output/timer, due to hardware/sdk restrictions)
- reduce stack and bss size
- introduce major/minor versioning scheme, if only minor config change, keep most of the configuration
- add option to disable the wlan bootstrap mode (thus making the tcp<->uart bridge completely transparent again
- add GPIO14 and GPIO15, note that GPIO15 needs to be pulled to ground for programming but don't use a link, use a resistor (or a led plus a resistor, etc.)
- change "bounce" mode name to "timer", which I feel is more appropriate
- add GPIO1 and GPIO3 to the list of GPIO's, these are normally the UART TX and UART RX pins, so be careful; you can still use the UART for programming though.
Release 7: Add wlan bootstrap mode, add tsl2560, generic option support (set/unset), add gpio counter support
- Add GPIO asynchronous counter support. Just like it says, it counts the input going low or high. Unfortunately we can't specify which edge to count, the SDK code doesn't allow us to. Add a debouncing time in milliseconds.
- UART settings default to 115200N8, as the system also spits out messages at this setting.
- Add WLAN SSID and password to our own config, for some reason we can no longer use the settings from the system.
- Add WLAN bootstrap mode, after power-on you have 10 seconds to type (or even better: copy&paste) the SSID name, a space, the password and a linefeed (0x0a, ^J) to the UART and it will be used to connect WLAN.
- Several i2c robustness improvements
- Add TSL2550 sensor
- Enhance sensor dump command: parameter = 0 or absent: short dump, only detected sensors parameter = 1: longer dump, show all known sensors parameter = 2: longer dump, show all known sensors with verbose error
- Replace lineair (float) calculations for some i2c sensors by integer or simplified float code, saves on iram usage
- Replace commands print-debug and strip-telnet by a generic "set" and "unset" option command interface, add tsl-high-sens option to make the tsl i2c sensors work in a higher sensibility mode (recommended unless in direct sunlight, where it will overflow).
- Add some stuff to prevent the tsl2550 and tsl2561 to be confused (same i2c address), similarly the lm75/tmp versus ds1621/ds1631/ds1721 which on the same address but not alike.
Release 6: Add i2c, raw, and including support for some sensors.
Release 5: Add more GPIO's, small fixes.
Release 4: Add PWM to GPIO's
Release 3: includes gpio bounce mode.
Release 2: First release with precompiled binaries. Basic wlan<->serial functionality is working now.
Release 1: Initial release