Electronics project notes/ESP notes
See also Electronics project notes/Microcontroller and computer platforms
Hardware, and the minimal boards
WiFi-capable microcontrollers.
You can run code on the microconroller, alongside the wifi code.
It is also sometimes used standalone, with another microcontroller using it for the wifi.
See Electronics_project_notes/Microcontroller_and_computer_platforms#ESP_series for wider context.
ESP8266
ESP8266
- Based on Xtensa LX106 microprocessor (a 32-bit RISC CPU)
- ~160KB SRAM
- often at 80 MHz (can be run faster at 160MHz though people report this breaks code that didn't expect that)
- WiFi b/g/n (no bluetooth)
- apparently people have got it to send on the order of ~10mbit/s but don't count on that
- The given SDK effectively shares the CPU cooperative-multitasking style, and you must yield time to the wifi code at least every few hundred ms and preferably more often(verify)
- 17 GPIO, 2 SPI, 2 I2S, 2 UART, 1 I2C, and a 10-bit ADC (pin overlap)
- no hardware PWM (though you get a decent rate out of via timers)
ESP8266 itself is a SMD IC and you probably want to get it on a board helping you along, (see e.g. http://esp8266.net/ for details), because at the least you'll want it connected to flash. It's hard to get it without unless you buy just the chip in bulk, though.
Initially from espressif, who had board variants called ESP-WROOM-something.
More common are the Ai-Thinker ones, and derivatives, often one of:
- ESP-01 - exposes little useful IO, used mostly as a "add WiFi to existing project" board
- ESP-05 - also exposes little IO. Allows better antenna than 01. Discontinued?(verify)
- ESP-12 - exposes more things, making it more useful as a standalone uC
- though physically it's not so easy to use by itself, it is the core of various larger PCBs
- ESP-201 - easier to use on a breadboard
- ...and yeah, a bunch more of these exist.
You now may prefer more complete prototyping boards, such as the NodeMCU or WeMOS or HUZZAH
Most build on the ESP-12, and add things like USB-to-serial and voltage regulation. (see below)
The size of flash will vary.
ESP8285
Compatible with ESP8266, but smaller because it has flash integrated (1MiB for ESP8285N08, 2MiB for ESP8285H16).
There seem to be some variant boards here too, at least:(verify)
https://www.espressif.com/sites/default/files/documentation/0a-esp8285_datasheet_en.pdf
ESP32
The earlier variants we saw (no particular signifier(verify))
- CPU: dual or single-core Tensilica Xtensa LX6 (verify)
- WiFi
- Bluetooth 5 LE
- often at 160MHz (can be run faster), ~20% CPU used for wireless (verify)
- https://www.espressif.com/en/products/hardware/esp32/overview
- https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
- ~520K SRAM
- Four timers
- more IO than a ESP8266: thirty-six GPIO, four SPI, two I2S, 3 UART(verify), 2 I2C, a 12-bit ADC, two 8-bit DACs
- but note: pin overlap, and boards may not break out everything
- because they use things internally, like GPIO used to access flash
- because they are smaller
- because there are just a bunch of boards out there. Also makes finding pinouts slightly interesting.
- but note: pin overlap, and boards may not break out everything
ESP32-S2
- CPU: single-core Tensilica Xtensa LX7, up to 240MHz
- 320 KB SRAM
- WiFi
- (no Bluetooth (verify))
- USB OTG
- some variants have 2MByte(verify) embedded PSRAM (R2 in ESP32 model name, e.g. ESP32-S2R2, ESP32-S2FN4R2, but it's less obvious to tell by the board)
- https://www.espressif.com/en/products/socs/esp32-s2
- https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf
ESP32-C3
- CPU: single-core RISC-V, up to 160 MHz
- Bluetooth 5 LE
- WiFi
- 400KB SRAM
- https://www.espressif.com/en/products/socs/esp32-c3
- https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf
ESP32-S3
- CPU: dual-core Tensilica Xtensa LX7, up to 240MHz
- Bluetooth 5 LE
- WiFi (b/g/n)
- variants with 2, 8, or 16MB internal PSRAM
- USB OTG (verify)
- 512KB SRAM
- https://www.espressif.com/en/products/socs/esp32-s3
- https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf
ESP32-C6
- Bluetooth 5 LE
- WiFi 802.11ax (also b/g/n support)
- 802.15.4
- CPU: RISC-V core (up to 160MHz) and low-power RISC-V core (up to 20MHz)
- 512KB SRAM
- https://www.espressif.com/en/products/socs/esp32-c6
- https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf
ESP32-H2
- Bluetooth 5 LE
- 802.15.4 (zigbee)
- (no wifi)
- CPU: RISC-V, up to 96MHz
- 320KB SRAM
- https://www.espressif.com/en/products/socs/esp32-h2
- https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf
See also:
- https://en.wikipedia.org/wiki/ESP32
- http://esp32.net/
- https://www.espressif.com/en/products/hardware/esp32/overview
- https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf
see also
Some DIYer-geared ESP8266 boards
May add
- breakout into something easier to solder
- exceptions include the Huzzah
- Regulator from 5V input -- particularly if it has USB, to be powered off it
- Reset button, GPIO (boot related) button
Huzzah
Adafruit huzzah:
Based on ESP-12
Power:
- The board has a 500mA LDO regulator that you should feed 4-6V
- V+ and Vbat both go to this LDO, separated via Schottky diodes
- and V+ is also on FTDI header, so that you stably can power the chip while programming it (...from a powered hub / port)
- if you have your own regulation, you can bypass the LDO regulator by connecting the LDO pin to ground
IO:
- TX and RX are used for bootloading, and for serial control (exposed in two places on this board, to make FTDI plug easier)
- RX is 5V safe (and Vcc goes to the regulator) so you can use a generic 5V serial cable
Note: no USB
- https://www.adafruit.com/product/2471
- https://learn.adafruit.com/adafruit-huzzah-esp8266-breakout?view=all
WeMOS ESP8266
WeMos D1 is a Arduino-sized board, partially compatible
- and a revision "D1 R2", with minor difference in pins between the two.
- https://wiki.wemos.cc/products:d1:d1
Wemos D1 Mini are smaller boards, specifically:
- D1 Mini Lite
- ESP-8285 based,
- 1MB Flash
- PCB antenna
- https://www.wemos.cc/en/latest/d1/d1_mini_lite.html
- D1 Mini
- ESP-8266EX based
- 4MB Flash
- PCB antenna
- https://www.wemos.cc/en/latest/d1/d1_mini.html
- D1 Mini Pro
- ESP-8266EX based
- 16MB Flash
- Lithium battery pin, charger chip
- PCB antenna + Antenna connector
- https://www.wemos.cc/en/latest/d1/d1_mini_pro.html
Power
NodeMCU devkit
NodeMCU itself refers to the firmware. It'll run on any ESP based board, really.
For clarification, there is also a breadboardable piece of hardware called the The 'NodeMCU Devkit' is the name of a specific board [1],
There seem to be three board that carry this name. Image on the right from this post:
[2].(verify)
Other
Some DIYer-geared ESP32 boards
Wemos ESP32
D32, based on ESP32
- D32
- Lithium battery pin, charger chip
- https://www.wemos.cc/en/latest/d32/d32.html
- D32 Pro
- Lithium battery pin, charger chip
- MicroSD socket
- 4MB PSRAM
- https://www.wemos.cc/en/latest/d32/d32_pro.html
(with some revisions)
Huzzah32
https://www.adafruit.com/product/3405
ESP32 DevKit-C
https://www.espressif.com/en/products/devkits/esp32-devkitc/overview
No-name
There's a bunch of ebay/aliexpress boards that are perhaps best distinguished by some physical things like pin count, (lack of) antenna overhang, and such
Consider e.g. these: https://www.studiopieters.nl/esp32-pinout/
LOLIN32 ESP32
D1 Mini ESP32
https://www.az-delivery.de/products/esp32-d1-mini
M5Stamp
https://shop.m5stack.com/products/m5stamp-pico-diy-kit
On firmware
Flashing new firmware
nodemcu pyflasher
- basic GUI that is a wrapper around esptool.py
- easier to use
- you need to install wxpython and pyserial (e.g. through pip install wxpython pyserial)
- https://github.com/marcelstoer/nodemcu-pyflasher
esptool.py
- came from the community, now also adopted by espressif
- you need to install python
ESP Flash Download tool
- in theory more flexible, but the interface is hard to understand
- https://www.espressif.com/en/support/download/other-tools
See also:
On flash mode
Apparently [3]
- ESP8266 ESP-12 boards uses DIO
- most other ESP8266 board (e.g. ESP-01 and ESP-07) use QIO
- ESP8285 uses DOUT
- ESP32 uses DIO
Since this is about wiring, you can't be entirely use until something fails to flash.
Is this just about upload speed or also about execution speed?(verify)
On some bare-bones boards you may need to manually get it into programming mode.
e.g. on ESP8266-01 you need to tie GPIO0 to Gnd (verify) at reset time. Various boards will have two buttons to make this easier.
What's this address stuff?
In basic cases you put the firmware at the start of flash (0x0),
If you have distinct blocks to go to specific addresses, you'll probably get instructions for it.
Firmware alternatives
Everything shares the same SDK underneath,
but what is added on top, and the thing you interact with, varies.
AT commands firmware
The AT commands firmware (Espressif?) is useful if you want to use the ESP as a separate board that does WiFi for you.
You communicate over it via serial (RX and TX serial pins), and controlling how it communicates.
You'll still need to manage how it connects to access points, and set up TCP and UDP connection.
https://room-15.github.io/blog/2015/03/26/esp8266-at-command-reference/
https://www.electrodragon.com/w/ESP8266_AT-Command_firmware
https://bbs.espressif.com/viewtopic.php?f=10&t=362 - for espressif firmware?
https://tttapa.github.io/ESP8266/Chap07%20-%20Wi-Fi%20Connections.html
NodeMCU firmware (Lua)
The NodeMCU firmware wraps Espressif's SDK (and primarily for the ESP8266) with a Lua interpreter, which hooks into a bunch of C libraries and pure-lua libraries.
There is now also an RTOS variant for the ESP32 (and not ESP8266, because of the higher memory use) which
There are a whole bunch of C libraries you can add.
- A little more controlled, but more work, is https://github.com/nodemcu/nodemcu-firmware
- The easier way for tinkerers is to use the online build service: https://nodemcu-build.com/
Including more modules will increase the flash size (you usually don't care) but often also the RAM size
Lua coding for that firmware
You can use one of various tools to upload lua files, which itself is (relatively basic) serial-port stuff. Options include:
ESPlorer
- java based IDE, fiddly but it works
- https://esp8266.ru/esplorer/
- https://github.com/4refr0nt/ESPlorer
luatool [4]
- CLI
- uploads Lua files to ESP8266 modules running nodemcu firmware
nodemcu-tool
- CLI
- up/down lua files, manage filesystem
esp8266 lualoader [5]
...and various other tools people have built.
See also:
- https://nodemcu.readthedocs.io/en/master/en/modules/net/
- https://github.com/nodemcu/nodemcu-firmware
- https://nodemcu.readthedocs.io/en/master/
- https://nodemcu.readthedocs.io/en/dev/lua-developer-faq/
Other interpreters people have built onto the SDK
this page lists variants on idea of the interpreting firmware but for other languages, like python, JS, Basic, Forth, Lisp, and support from some other embedded platforms.
The idea ends up being the same - flash its firmware, later upload code via the serial port (and possibly over the air)
Arduino
PlatformIO
Lua firmware notes
Some lowish level notes
Keep in mind that some standard Lua modules (e.g. io, os, debug) are removed, and others provide similar function (e.g. node, file).
- So some Lua code you find around (e.g. for raspberry Pi) will need changes, with some specific knowledge of the argument differences.
- And since debug is missing, debug mostly consists of print statements.
- There are other practical differences, like that print(string) is mainly just uart.write(0, string)
Running code off flash is done with cached memory mapping, which is basically why there is one SPI interface you cannot use
The event/tasking system is roughly three queues, a high priority one (for hardware related tasks), medium (for timer and event stuff), and low (everything else)
- no task can pre-empt others (priority isn't relevant once it's started),
- so ideally no task should run longer than a dozen milliseconds
- if you want things like wifi (or any other code-mediated hardware) to work smoothly
- and sometimes less so that your own tasks work smoothly but this can be less critical
- so ideally no task should run longer than a dozen milliseconds
- if a task takes over 500ms it'll trigger the watchdog (unless you explicitly feed it, but in most cases that is bad design)
(there are also ISRs in C for time-critical stuff but you probably don't want to touch that. They can interrupt tasks, but only up to ~10usec)
Calling various functions in net, tmr, wifi, and some others will (in part because they are C) amount to queueing their code as tasks. So
- They will not run until after the current lua task is done.
L They will not necessarily be the next task (but many will be high priority so this is moderately likely)
- being in that queue uses a little RAM until they actually execute
- (which is one of a few reasons why event/callback style coding is recommended)
Errors will trigger a panic, which then leads to triggering the watchdog, and a reboot
- this is useful for recovery
- but not always for debugging because even just a typo may cause a reboot before any error gets printed
Flash not used for firmware is provided via file
- classically SPIFFS, now moving to LittleFS
- (Confusingly, LFS, Lua Flash System, is a different thing https://nodemcu.readthedocs.io/en/release/lfs/ )
- note that file can also be used to read/write SD cards
- https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html
The float versus int builds:
- working in float is more to specs, and generally recommended
- working in integers is faster but breaks the specs a little, so also some code.
The SDK triggers startup code,
- which initializes lua,
- runs init.lua
- listens interactively to UART0
- defaults to 9600 baud. ESPlorer changes speed by sending a uart.setup() command, then attempting to reconnect (verify)
Coding using events, timers, and coroutines
Tasks run to completion and cannot be pre-empted.
Running too long will trigger the watchdog, and before that will make wifi code break or be choppier.
So it's suggested to try keeping tasks under 10ms, also for the responsiveness of responding to events.
In general, try to do things event-based, using callbacks.
It's generally useful to put code in a timer, or use a timer as an event loop checker
Note that since timers and callbacks are tasks that don't pre-empt (and that timers are software timers), they may get scheduled later than you think. Also, don't set timers faster than they'll take.
Longer calculations are probably best done in smaller chunks
Can you use coroutines?(verify)
Keep ISRs under 10us, or wifi will break.
I2S canbe DMA'd, no other peripherals can(verify)
"Waiting answer from ESP - Timeout reached. Command aborted"
(in ESPlorer)
This can be
- a bug related to use of CR-style newlines[6] (where the firmware expects CRLF(verify)), but only on specific commands.
- It's particularly file transfers that will be broken.
- This could be fixed on both sides, but the easier may be to get a newer firmware build (verify)
- https://github.com/nodemcu/nodemcu-firmware/issues/784
- the serial connection crapping out for some reason (verify)
- I seemed to have it one one board, possibly power problems?
modules, packages, and compilation
On reboots
boot/reset cause
If you catch enough of the next boot's output, you'll see something like:
rst cause:2, boot mode:(3,6)
boot mode
The last part, the boot mode is rarely very interesting. It indicates
- where we booted from (which is based on GPIO pin state at boot), and
- how exactly.
ESP8266:
- In most cases this will be 3 (Flash), (rather than SD or UART)[7]
- ...and if it's not, and not booting as expected, chances are the relevant GPIO pins (GPIO15, GPIO0, GPIO2(verify)) are not in the state they should be. (If you put hardware on these pins, this needs extra care to not affect boot)
- ...or it's the first watchdog reset after a firmware download and soft reboot(verify), which can trigger it trying to do a firmware download again (e.g. 1,7) (verify), once.(verify)
ESP32:
- 0x13 seems to mean SPI_FAST_FLASH_BOOT, which seems typical
- 0x03 seems to mean programming mode (specific variant?)
rst cause
While the rst cause seems to be the list from
0 unknown reason 1 'Reset due to power-on event', which is effectively normal boot 2 External reset using reset pin (not for ESP8266?) 3 Software reset (esp_restart?) 4 Hardware watchdog (WDT) reset /
...there is a slightly more informative value you get via node.bootreason(). It returns
rawcode, reason [, exccause, epc1, epc2, epc3, excvaddr, depc ]
That is, it usually returns two values:
- the first as above(verify)
- the second is the extended reset cause, which is one of:
0 power-on 1 hardware watchdog reset 2 exception reset 3 software watchdog reset 4 software restart 5 wake from deep sleep 6 external reset
..but in the case of exception reset, it also returns more exception information, the first of which is tells you exception cause and the rest of which may be useful to for an actual debugger (if you built the image yourself).
I mostly run into 2 4 where 4, software reset, which seems to include the software watchdog(verify) (confusingly enough).
4 1 is the hardware watchdog(verify)
https://riktronics.wordpress.com/2017/10/02/esp8266-error-messages-and-exceptions-explained/
Solving and avoiding reboot loops
If you manage to get an exception in early code, or trigger the hardware watchdog fairly early, then you may not be able to get the control you need to fix that.
There's always flashing the firmware again, and then wiping the flash. But that's a bunch of work, annoying during coding/debugging.
One way around that I like is to have init.lua contain something like:
abort = 0
function load_main()
if abort ~= 0 then
print("aborting startup")
else
if file.exists('main.lua') then
print("startup")
dofile('main.lua')
else
print("main.lua does not exist")
end
end
end
print("send abort=1 to stop boot")
_start_timer = tmr.create()
_start_timer:register(1500, tmr.ALARM_SINGLE, load_main)
_start_timer:start()
...and put your real code in main.lua.
That way, you have a little over a second before anything happens, in which time you can stop startup by sending abort=1 via serial
https://bigdanzblog.wordpress.com/2015/04/24/esp8266-nodemcu-interrupting-init-lua-during-boot/
On watchdogs
There is both a
- hardware watchdog
- on by default, can be disabled (but there is rarely good reason to disable it)
- part of the ESP's hardware
- configured at approximately 6 seconds(verify)
- software watchdog
- on by default
- C code that digs into the SDK, and amounts to a timer that decrements a counter and, if that counter reaches zero, calls system_restart()
- accessible in Lua via tmr.softwd() to set a time, and tmr.wdclr() to feed it
- apparently a value like 0.5 sec [8], 1.5 sec, or 3.2 sec (reports are mixed; TODO: figure out)
It seems that the SDK's system_soft_wdt_feed() feeds both.
- tmr.wdclr() in Lua, and ESP.wdtFeed() in arduino(verify), mostly call system_soft_wdt_feed()
- tmr.delay calls system_soft_wdt_feed while it is counting down (but is otherwise a wait loop, so long ones will mess with wifi{{verify||)
- some libraries will also reset the watchdog in some places
The short version is that if code does not
- call tmr.wdclr(), OR
- call something that implies tmr.wdclr(), OR
- returns to let the ESP idle
...for a significant time (between 0.5 or 6 seconds, see above), it will cause a reset.
Which makes sense. If you have code that takes more than 500ms without yielding in any way, you are likely breaking other things, not least of which the WiFi code, which can stutter (in smaller ways) if any task takes longer than approx 15ms.
If you do need to do a lot of processing, just make sure you yield occasionally so that that housekeeping can happen.
This may mean rewriting to do small chunks at a time.
In Lua this is sometimes simple, because when you code in an event/callback style the idle task gets control regularly (and its feeds the dog(verify) and does the necessary housekeeping(verify)).
Keep in mind that it's not too hard to defeated the watchdog (e.g. feed it each loop but get into your own infinite loop) and can make things hang forever, and/or break wifi and other library code.
The likeliest problems that trigger the watchdog seem to be
- an exception in the code
- if you're me, largely variable typos and nil values you should be checking
- presumably stops the current task so the watchdog
- to avoid hanging forever, this is cause for reset (via watchdog?)
- triggering a watchdog by having code hang, or take too long to complete
- running out of heap space
Your own watchdogs
I have found reasons to have code like "if we didn't manage to do a HTTP fetch in a minute, for any reason, we probably want to reset"
...just because there are more reasons for that (that I can't easily check), and most of them will be rare enough that a reset is the easiest clean slate.
You will want to decide which method of reset you prefer.
manual reset
If you have an ESP with USB, it probably has its DTR/RTS wired to GPIO0 and RST, there so you can get it into flash programming mode. [9], but you could also self-reset by wiring a GPIO pin to RST and do the same.
In some ways it's the cleanest, because apparently there are a few issues around some internal registers not being reset unless it's a hardware reset.(verify). But check that you don't get stray signals.
If you're not bothered by said register problems, then software resets probably using node.restart() is also an option.
Networking
TCP server
UDP server
HTTP requests
The http module is quite convenient.
Example:
http.get(posturl, "", -- headers function(code, data) if (code < 0) then print("HTTP request failed") else print(code, data) end end )
Note that concurrent requests are not supported.
(I think an issue of mine (reported as HTTP client: DNS error code -1, I think) was that I was effectively doing this.)
On HTTPS
The http module can use the tls module which is basically mbed TLS.
That means you can give it https links and it'll do the TLS part too. (Alternatively, you can do a TLS connection, and e.g. do a bare HTTP 1.0 request over it. See examples using tls.createConnection())
However, you basically don't have enough RAM to guarantee that large certificates, or large chains, can be processed properly - the process may easily need 30KByte or 40KByte of heap, which is usually most of what you have. Also, there is no real SNI support.
So you cannot guarantee all HTTPS requests to arbitrary servers will work, and the best workaround is to only ever send to a server you have precise control over the certificates being send, and possibly self-sign.
Arduino firmware notes
Some notes
Current draw and sleep
(this is broadly true for ESP8266, ESP32, just get get a sense of the ballpark. When specifics matter, look them up for a specific board)
Estimates:
- Startup might be up to ~400mA for ~40ms[10] (RF calibration maybe?)
- just once and short
- ~200mA actively transmitting radio (though Tx power can be lowered)
- CPU but no RF on (i.e. modem sleep)
- 15mA to 70mA, depending on core frequency, amount of cores, ESP variant, readymade board you bought (often on the lower, 25mA end of that?(verify))
- ~1mA with light-sleep (varying a little with DTIM interval)
- wakeup takes a few milliseconds
- ~0.1mA with deep-sleep, which roughly amounts to 'everything off, waiting to be rebooted from a pulse on RST pin'
- takes regular boot time, and note that a cold connect to wifi tends to take a few seconds
Note that the ESP32 variants vary on CPU use and sleep details,
but RF power is basically just determined by range.
On the sleep modes:
- no sleep / active mode
- ESP32: ~200mA if transmitting, ~100mA if not
- modem sleep
- keeps the CPU on, keeps the wifi on but only listening, and can be woken by DTIM
- since it times the sleep between AP beacons, this applies only once connected to an AP
- should average maybe ~20mA when not transmitting
- going to modem sleep is automatic once set (and possible), so firmware seems to enable this by default(verify)
- NodeMCU: seems to apply automatically once we're connected to an AP(verify)
- light sleep - pauses modem, system clock, CPU
- ~1mA ? (verify)
- cannot enter light sleep if wifi suspended
- woken via configured GPIO or timer(verify)
- ESP32 can wake up via touch sensitive GPIO(verify)
- modem and CPU are sleeping but can be woken by GPIO, or DTIM(verify)
- wakeup takes ~3ms
- NodeMCU: node.sleep()
- deep sleep leaves on the RTC and almost nothing else
- ~0.01mA or 0.2mA ? (verify)
- can apply when not maintaining a WiFi connection.
- you can only explicitly tell it to go to deep sleep (not an automatic thing)
- only the RTC is still powered (and can be used to wake up),
- woken up a pulse on RST, which can come from our own RTC (if GPIO16/WAKE/D0 is wired to RST)
- so the call is "deep sleep for this many microseconds" (in an uint32, which implies a 71 minute maximum [11]
- there are flags controlling
- whether wifi will be initialised after such a sleep (you can avoid a current spike if you don't need it)
- whether a calibration will be done (which you want after longer sleeps(verify))
- NodeMCU: node.dsleep()
- hibernation (ESP32)
- ~3uA ? (verify)
- deep sleep on the ESP32 leaves on a low-power coprocessor and the oscillator it needs, hibernation does not. (verify)
Note that
- I need to look up the difference between ESP8266, ESP32
- these currents are the ratings of the ESP itself, things like regulators will add to this.
- These figures are often the use of the raw circuit. If powered via a linear regulator, your will waste more energy. Battery users will care.
https://bbs.espressif.com/viewtopic.php?t=133
https://www.espressif.com/sites/default/files/9b-esp8266-low_power_solutions_en_0.pdf
https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/
Voltage and damage
Power should be 3.3V. (Powering from 5V power won't fry it immediately, but is likely to shorten lifespan, some people report sooner rather than later (and seemingly it's the flash that often fails first)
The ADC gets damaged by voltages above 1V, so you probably always want a voltage divider. And possibly a diode to protect it.
"Are ESPs 5V tolerant?"
Officially, no.
Can you get away with it?
Probably?
There is transient higher-voltage detection - basically ESD above 6V - quoth the datasheet" "All digital IO pins are protected from over-voltage with a snap-back circuit connected between the pad and ground. The snap back voltage is typically about 6V, and the holding voltage is 5.8V. This provides protection from over-voltages and ESD. The output devices are also protected from reversed voltages with diodes."
However, 5V tolerance is more about continuous current/heat the entire structure can deal with. There's no mention of it, so the short answer is no.
The ESD protection diodes will probably help a little, and people have experimentally determined that putting 5V on these inputs only sinks a few microamps,
Perhaps the simplest halfway-decent solution is a voltage divider. Though it comes with 'assuming it does not affect your use' footnote. Particularly high-speed communication often needs a little more care, so when you're prepared to throw some components at it, there are also other options - see level shifting.
Note that using our 3.3V GPIO to output to things expecting 5V levels can be safe -- but note it's not great if the 5V side engages a pullups (rather than pulldown).
(As in general, it may not always work due to voltage levels -- 5V TTL is high is above 2V so fine. 5V CMOS is high above 3.7V so won't work. Thresholds can vary a little per device anyway, so check datasheets.).
On WiFi
Having it be stable
For wifi to be stable, task should yield after ~15ms or so (quoth the SDK(verify)).
More may still work because it'll recover, but wifi will be choppier.
When you think tasks may take longer, think some more about event, timer, and corouting style programming.
I also tend to add a "can I DNS-resolve things" test, so that it can reconnect, or switch APs, when one does not work for some reason.
(...which I can still mess up by spamming the ESP with UDP packets)
How to tell it about APs
The basic way to do credentials is hardcoding one, or maybe a few that code loops through a few stored APs. This works until you move it, or replace your AP, at which point you have to put in new credentials, probably via usb-serial.
The fancier thing to do is a wifi manager that, if it can't find one of the previously configured AP's, puts the ESP into soft AP mode with a webserver, and lets you set AP via a simple web interface.
For NodeMCU: https://github.com/gfnord/lua_wifimanager
For arduino: https://github.com/tzapu/WiFiManager (slightly nicer)
Wifi current draw
https://nodemcu.readthedocs.io/en/release/modules/wifi/#wifisetphymode
On PWM
On SPI
Errors
serial.serialutil.SerialException: Cannot configure port, something went wrong. Original message: PermissionError(13, 'A device attached to the system is not functioning.', None, 31)
...when uploading a sketch.
For me this seemed caused by esptool not finding the device in the right state - presumably because I had selected the wrong board variant?
I did get it to work by holding the boot button.
Which is a problem and solution possibly very specific to my case.