TinyML: artificial intelligence on small boards
In the previous lessons small models – a tree and k-NN – ran on the ESP32 and micro:bit. But can a neural network that recognizes words or images also fit on a board? This field is called TinyML (from tiny and machine learning). In this lesson we calculate how much “intelligence” fits into a small chip and get to know the tools that are used.
How much memory our chips have
| Board | Working memory (RAM) | Program memory (flash) | What it can do |
|---|---|---|---|
| Arduino Uno | 2 KB | 32 KB | rules and very small models (a threshold, a small tree) |
| micro:bit V2 | 128 KB | 512 KB | k-NN, small trees, small networks (gestures, sounds) |
| ESP32 | 520 KB | usually 4 MB | trees, small neural networks (gestures, words) |
| ESP32-S3 | 512 KB + often an extra 2–8 MB | usually 8–16 MB | word recognition, simple image recognition from a camera |
| laptop | 8–32 GB | hundreds of GB | large models, training |
A laptop has hundreds of thousands of times more memory than a micro:bit. That is why models are trained on a computer, and only finished, “shrunk” models are moved to a small chip.
Let's calculate: how big is a network
Each connection between two neurons has a weight, and each neuron also has a threshold. For layers with a and b neurons that is a · b + b numbers. A decimal number (float) takes 4 bytes; if we “shrink” it to a whole number from –128 to 127 (int8), it takes 1 byte.
# How much memory does a model take? We calculate the number of weights of a neural network
def count_weights(layers):
"""layers: the number of neurons in each layer, for example [64, 64, 10]."""
total = 0
for n_in, n_out in zip(layers, layers[1:]):
total += n_in * n_out + n_out # weights + one threshold for each neuron
return total
networks = {
"our network for digits (64-64-10)": [64, 64, 10],
"a network for 96 × 96 images (9216-128-10)": [96 * 96, 128, 10],
"a bigger network (9216-512-256-10)": [96 * 96, 512, 256, 10],
}
chips = {"Arduino Uno": 2, "micro:bit V2": 128, "ESP32": 520} # working memory (RAM) in KB
for name, layers in networks.items():
n = count_weights(layers)
kb_float = n * 4 / 1024 # a decimal number (float) takes 4 bytes
kb_int8 = n * 1 / 1024 # a “shrunk” model: one byte per weight
print(f"{name}: {n} weights = {kb_float:.0f} KB (float) or {kb_int8:.0f} KB (int8)")
for chip, ram in chips.items():
print(f" {chip:12} ({ram:3} KB RAM): {'fits' if kb_int8 < ram * 0.7 else 'does NOT fit'}")
Program output:
our network for digits (64-64-10): 4810 weights = 19 KB (float) or 5 KB (int8)
Arduino Uno ( 2 KB RAM): does NOT fit
micro:bit V2 (128 KB RAM): fits
ESP32 (520 KB RAM): fits
a network for 96 × 96 images (9216-128-10): 1181066 weights = 4614 KB (float) or 1153 KB (int8)
Arduino Uno ( 2 KB RAM): does NOT fit
micro:bit V2 (128 KB RAM): does NOT fit
ESP32 (520 KB RAM): does NOT fit
a bigger network (9216-512-256-10): 4853002 weights = 18957 KB (float) or 4739 KB (int8)
Arduino Uno ( 2 KB RAM): does NOT fit
micro:bit V2 (128 KB RAM): does NOT fit
ESP32 (520 KB RAM): does NOT fit
- Our network for digits from module 3 has 4810 weights – it fits on both the micro:bit V2 and the ESP32.
- An ordinary network for 96 × 96 pixel images is too big. That is why special convolutional networks are used for images; they “slide” the same small group of weights over the whole image – they have far fewer weights, so they can fit on an ESP32-S3.
- This calculation is simplified: the weights can be kept in flash memory, and RAM is also needed for intermediate results. But it shows the key thing – the number of weights decides whether a model fits.
How a model is “shrunk”
| Method | What it does | Price |
|---|---|---|
| quantization | weights from float (4 bytes) to int8 (1 byte) – the model is 4 times smaller | accuracy drops a little |
| fewer neurons and layers | a smaller network from the start | the model may be less accurate |
| pruning | weights that are almost zero are removed | a more complex process |
| better features | instead of raw data, the model gets cleverly chosen numbers (like the spread with the micro:bit) | you need to know what is important |
Tools that are used
- TensorFlow Lite for Microcontrollers (Google; since 2024 the library has been part of a project called LiteRT) – runs small neural networks on microcontrollers, including the ESP32. The network is trained in Python, then converted into an array of bytes that is inserted into the program.
- Edge Impulse – a website where you record data from a board or phone, train a model and get a ready library for the Arduino IDE. It requires an account (for students – with a teacher and parents).
- ESP-DL and ESP-SR (Espressif) – libraries for recognizing faces, objects and voice commands on ESP32-S3 chips.
- micro:bit CreateAI – gesture recognition on the micro:bit, without programming.
For school, the easiest path is to start with trees and k-NN (as in this module), and only then move on to tools for neural networks.
Examples of TinyML devices
| Device | Sensor | Model |
|---|---|---|
| recognizing the words “on” / “off” | microphone | a small neural network on sound |
| a repetition counter in the gym | accelerometer | k-NN or a small network, like in the micro:bit lesson |
| a doorbell that recognizes whether a person or a cat is at the door | camera | a convolutional network on an ESP32-S3 |
| a warning that a machine is vibrating “strangely” | accelerometer | a model that knows what normal operation looks like |
Students calculate the number of weights for several networks (task 1) and decide which board they would fit on. Then, in groups, they design a TinyML device for the school.
Common misconceptions
- “TinyML is the same as a chatbot on a board” – large language models have billions of weights and don't fit on a microcontroller; TinyML means small models for one task.
- “A model on a chip is trained on the chip” – it is almost always trained on a computer, and the finished model is moved to the chip.
Practice tasks
Try it yourself first, and only then open the solution.
- How many weights does a network with layers of 64, 16 and 10 have? How many kilobytes is that as float, and how many as int8?
- For a “smart doorbell” that recognizes the faces of the people living in the house – would the model run in the cloud or on the device? Give your reasons.
- Why are models almost always trained on a computer and not on a microcontroller?
Solution 1: the calculation
64 · 16 + 16 = 1040 and 16 · 10 + 10 = 170, a total of 1210 weights. As float: 1210 · 4 = 4840 bytes ≈ 4.7 KB; as int8: 1210 bytes ≈ 1.2 KB.
Solution 2: one possible answer
Better on the device (for example an ESP32-S3 with a camera): photos of faces are personal data and it is better if they don't leave the house, and the doorbell should work even when there is no internet. Disadvantage: the model has to be small, so it may make mistakes more often – that is why it is good if the people in the house can also unlock the door by hand.
Solution 3: explanation
Training needs a lot of memory (all the examples, intermediate results) and a lot of computation, while a microcontroller has little RAM and a slow processor. Using a finished model is much easier: just a few multiplications and additions per measurement.
What's next
You have finished the module AI and the Internet of Things. Next is the module AI and society, which starts with the lesson Is artificial intelligence conscious? In it we talk about big questions: does artificial intelligence think, how can it be fair and safe, and what is its future.
Check your knowledge
Open the quiz
Quiz: TinyML
1. How many weights does a network with layers of 4, 3 and 2 have?
2. What does quantization do?
3. Where are TinyML models usually trained?
4. Which board has the most working memory?
