Character Recognition
Handwriting recognition that runs entirely on a microcontroller. No cloud, no network connection. We trained two neural networks on 70,000 handwritten digits, compared them head to head, and our library runs this same task live on an STM32H7.

- accuracy on 7,000 handwritten digits it had never seen
- 98.24%
- parameters, small enough for a microcontroller
- 100,254
- of weights, and about a quarter of that once quantized to 8 bits
- 392 KB
- the microcontroller in our live demo
- STM32H7
Where it's used
A small image in, an answer out, all on the device
Lots of products need to turn a small picture into an answer on the spot. When the network runs on the device itself, it works without a connection, it answers right away, and the data never has to leave the product.
Reading handwritten digits is a great example of that kind of model, and it’s the same approach behind products like these.
- A smart pen digitizing handwritten forms
- A point-of-sale device reading a handwritten amount
- A meter reader recognizing a dial
- A postal sorter reading a ZIP code
The data
70,000 handwritten digits
We trained on MNIST, the classic handwriting benchmark: 70,000 digits written by about 500 different people. Each one is a 28 × 28 image, and we cut every pixel down to a single bit, black or white, to keep the input as small as possible for the microcontroller.
- Training · 80%, 56,000 digits
- what the networks learn from
- Validation · 10%, 7,000 digits
- checked after each round of training, so we keep the best model
- Test · 10%, 7,000 digits
- kept aside until the very end. The 98.24% comes from these.

How we built it
Two networks, one test
Instead of training one network and reporting a number, we built two different kinds, trained them on identical data and graded them with the same test, so the comparison is a fair one.
Convolutional network train_cnn.c
This one scans the image with small 5 × 5 filters that pick out strokes, combines those into shapes, and then hands the result to a few final layers that decide which digit it is. Only 3,424 of its 100,254 parameters sit in the filter layers, but that’s where most of the arithmetic happens, about 880,000 multiply-adds per digit in total.
Fully-connected network train_fc.c
The classic alternative wires every one of the 784 pixels straight into a layer of 128 units, then 64, then the answer. It’s a similar size at 109,386 parameters and needs only about 109,000 multiply-adds per digit, but it has no sense of which pixels sit next to each other. It’s the network a convolutional design has to beat to earn its place.
We graded both strictly. A digit only counts as right if the network gives the correct answer at least 50% confidence and no other digit gets that much. That’s a tougher bar than simply taking the network’s top guess.
Results
Fewer mistakes, same memory
| Network | Parameters | Multiply-adds per digit | Epochs | Training time | Train accuracy | Test accuracy |
|---|---|---|---|---|---|---|
| Convolutional train_cnn | 100,254 | ~880K | 11 | 8 min 25 s | 99.17% | 98.24% |
| Fully connected train_fc | 109,386 | ~109K | 10 | 15 s | 99.44% | 97.26% |
Training times are on a single desktop CPU core. The convolutional network came out ahead in both pairs of runs we measured: 98.24% against 97.26% here, and 98.49% against 96.13% in an earlier pair.
Why it wins
With slightly fewer parameters, the convolutional network makes about a third fewer mistakes on digits it’s never seen: 123 out of 7,000, against 192. The fully-connected network actually scores higher on its own training data, but that’s memorization, and its error on new digits starts climbing after the fifth round of training. Convolutional filters look for strokes wherever they appear, so what the network learns carries over to handwriting it hasn’t met before.
What it takes
The extra accuracy comes from arithmetic, not memory. Each digit takes about eight times the multiply-adds, and training took about 8½ minutes instead of 15 seconds. On a device reading one digit at a time, it still works out to just milliseconds.
Mistakes a person could make
Many of the digits it gets wrong are hard to read for anyone. Think 4s closed at the top that look like 9s, 8s and 9s whose loops run together, and 2s and 3s with a straight tail that pass for 7s.

On the device
Small enough for a microcontroller
The trained network needs 392 KB for its weights. An STM32H743 has 2 MB of flash and 1 MB of RAM, so there’s plenty of room left for the rest of the product’s firmware. Our library can also convert the model to 8-bit integers, which cuts it to about a quarter of the size, and store it in a format that runs straight out of flash without copying anything into RAM.
The code on the device is short. It takes the image from the touch panel or camera, scales it to 28 × 28, hands it to the network and reads off the answer. At about 880,000 multiply-adds per digit, that works out to a few milliseconds on a Cortex-M7 running at several hundred megahertz.
Ready to build your next intelligent device?
Let's discuss your project and how Cole Design & Development can bring your idea to life.
Founded in 2008 · Hudson, Ohio · info@coledd.com