iTranslated by AI
Using Custom TensorFlow Lite Models on Raspberry Pi Pico
Introduction
Raspberry Pi Pico is a lot of fun, isn't it? The other day, I made a button that uses the Raspberry Pi Pico to automatically input if err != nil {...} in Go.
Recently, I've been trying to run TensorFlow Lite on the Raspberry Pi Pico, and yesterday I finally solved a problem where my custom model just wouldn't work no matter what I did.
What I Built
I embedded a model that performs inference for an XOR gate, which turns an LED on or off based on input from the serial port.
First, Create the Model
There's nothing particularly difficult here; it's just a standard training process.
import tensorflow as tf
from tensorflow import keras
import numpy as np
x_train = np.array([[0, 0],
[1, 0],
[0, 1],
[1, 1]]).astype(np.float32)
y_train = np.array([0,
1,
1,
0]).astype(np.float32)
model = tf.keras.Sequential()
model.add(keras.layers.Dense(16, activation='relu', input_shape=(2,)))
model.add(keras.layers.Dense(16, activation='relu'))
model.add(keras.layers.Dense(1))
model.compile(optimizer='adam', loss="mse", metrics=["mae"])
history = model.fit(x_train, y_train, epochs=500, batch_size=4)
model.save('saved_model')
def representative_dataset():
for i in range(4):
yield([x_train[i]])
converter = tf.lite.TFLiteConverter.from_saved_model("saved_model")
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.float32
converter.inference_output_type = tf.float32
converter.representative_dataset = representative_dataset
model_tflite = converter.convert()
with open('xor_model.tflite', 'wb') as f:
f.write(model_tflite)
The only thing to watch out for is creating it without quantization.
Writing the Code
Convert the resulting tflite model file into a C language byte array using a tool called xxd.
$ xxd -i xor_model.tflite > model.c
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#define TF_LITE_STATIC_MEMORY
#include "tensorflow/lite/micro/all_ops_resolver.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "tensorflow/lite/version.h"
alignas(8) const unsigned char xor_model_tflite[] = {
0x20, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x12, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00,
0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x12, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x8c, 0x0b, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00,
0x00, 0x03, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x0b, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x6d, 0x69, 0x6e, 0x5f,
0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xb8, 0x02, 0x00, 0x00,
0xa4, 0x02, 0x00, 0x00, 0x48, 0x02, 0x00, 0x00, 0xe4, 0x01, 0x00, 0x00,
0xd0, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
0x64, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe6, 0xfd, 0xff, 0xff,
0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x35, 0x2e,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xfd, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x36, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x81, 0xb8, 0x46, 0x3e, 0xfd, 0x20, 0x1f, 0xcc,
0xbb, 0xd8, 0x5a, 0xde, 0x19, 0xf2, 0xe1, 0xc4, 0x00, 0x00, 0x00, 0x00,
0x56, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0xf1, 0x30, 0xd2, 0x18, 0x0c, 0xb8, 0x14, 0x99, 0xcc, 0xdb, 0x4e, 0x08,
0x1d, 0xea, 0x7f, 0xfc, 0x3b, 0x10, 0xb0, 0x0a, 0x24, 0xe4, 0xdb, 0x1a,
0x4c, 0xc9, 0xd1, 0x00, 0x4a, 0xb0, 0xaf, 0x1f, 0x40, 0x17, 0x48, 0x4c,
0x34, 0x3c, 0x24, 0x20, 0x20, 0xd2, 0x5a, 0x5a, 0x49, 0x59, 0x08, 0xb3,
0x98, 0xdc, 0x67, 0x4f, 0xbb, 0xeb, 0x39, 0xcb, 0xb7, 0x10, 0x93, 0x39,
0x12, 0x29, 0xd5, 0x19, 0x0f, 0xba, 0xeb, 0xd3, 0xdb, 0x04, 0xdc, 0x25,
0x4a, 0x3b, 0xe7, 0xed, 0xad, 0xb7, 0xae, 0x43, 0x3b, 0x1c, 0x25, 0x19,
0x4e, 0xd0, 0xb6, 0x53, 0xfa, 0xf2, 0xbd, 0xde, 0x27, 0x1a, 0x0d, 0x4b,
0x56, 0x17, 0x67, 0xee, 0xf4, 0x04, 0xf8, 0x71, 0x03, 0xe4, 0x1c, 0xdf,
0xe9, 0x3a, 0x0c, 0x4e, 0xeb, 0xf0, 0x30, 0xbd, 0x42, 0x39, 0xec, 0xf9,
0x4b, 0x49, 0x22, 0xc1, 0xbe, 0x21, 0xf5, 0xcd, 0xf3, 0xe6, 0x12, 0x18,
0xe5, 0xc8, 0xd9, 0xbb, 0xef, 0x05, 0x4d, 0x07, 0x45, 0xff, 0xb5, 0xc5,
0x29, 0x26, 0x1a, 0xd8, 0x38, 0xb9, 0xec, 0x09, 0xf9, 0xb2, 0x2f, 0xf7,
0xd5, 0xb0, 0xff, 0x44, 0x41, 0x5d, 0x23, 0x47, 0xc8, 0x33, 0xdb, 0x16,
0x1c, 0xd0, 0x5c, 0x3e, 0xe5, 0x4e, 0xfe, 0xc2, 0x42, 0xad, 0xd3, 0x35,
0x48, 0xc9, 0xf4, 0x42, 0xf2, 0x1f, 0x43, 0xad, 0x2f, 0xbb, 0x15, 0xc0,
0x0f, 0xef, 0x06, 0x53, 0x29, 0xef, 0xe5, 0x55, 0x11, 0xe5, 0x3c, 0x19,
0xee, 0x1b, 0xda, 0x1e, 0xe3, 0x0a, 0xb0, 0xd1, 0xe8, 0xe9, 0x1a, 0x20,
0xb1, 0xba, 0x4b, 0xd3, 0xaf, 0x14, 0xd9, 0x33, 0x19, 0xf7, 0xfd, 0x2a,
0xbe, 0x40, 0x19, 0x35, 0x02, 0xae, 0xce, 0x15, 0xf8, 0x12, 0xab, 0xb3,
0x2c, 0x3e, 0x34, 0xa4, 0x1a, 0x0e, 0x26, 0x1f, 0x37, 0xc4, 0x0d, 0x01,
0x1c, 0xf1, 0x9b, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x66, 0xff, 0xff, 0xff,
0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x99, 0x72, 0x97, 0x59,
0x55, 0xb2, 0x35, 0xef, 0x2b, 0x32, 0xa9, 0x58, 0xaf, 0x07, 0x9b, 0x5b,
0xaf, 0x9c, 0x16, 0x47, 0xc6, 0x23, 0xab, 0x54, 0xd8, 0xe1, 0x68, 0x9b,
0xe6, 0x14, 0x81, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x96, 0xff, 0xff, 0xff,
0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x49, 0x09, 0x00, 0x00,
0xa6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0xc7, 0x27, 0x00, 0x00, 0xfc, 0xe8, 0xff, 0xff, 0x1a, 0x14, 0x00, 0x00,
0xf8, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x14, 0x00, 0x00,
0xbf, 0x11, 0x00, 0x00, 0x53, 0xdb, 0xff, 0xff, 0x97, 0xe8, 0xff, 0xff,
0xef, 0xee, 0xff, 0xff, 0xdf, 0x21, 0x00, 0x00, 0xcb, 0x33, 0x00, 0x00,
0xf2, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xe3, 0xff, 0xff,
0x0a, 0xe7, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0xe6, 0xf5, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xc9, 0x12, 0x00, 0x00, 0xfc, 0xed, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x3a, 0xf6, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0xea, 0xff, 0xff, 0x95, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x1a, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x50, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0xff, 0xff,
0x0f, 0x00, 0x00, 0x00, 0x4d, 0x4c, 0x49, 0x52, 0x20, 0x43, 0x6f, 0x6e,
0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x04, 0x00,
0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x58, 0x01, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x04, 0x01, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1a, 0xff, 0xff, 0xff,
0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0xca, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x08,
0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x10, 0x00,
0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xba, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
0x08, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x68, 0x06, 0x00, 0x00, 0xf4, 0x05, 0x00, 0x00, 0x8c, 0x05, 0x00, 0x00,
0x38, 0x05, 0x00, 0x00, 0x8c, 0x04, 0x00, 0x00, 0xd8, 0x03, 0x00, 0x00,
0x24, 0x03, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00,
0x90, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0xc8, 0xff, 0xff, 0xff, 0x28, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x49, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x74, 0x79, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x60, 0xfa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x6c, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x01, 0x00, 0x00, 0x00, 0x4c, 0xfa, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x01, 0x00, 0x00, 0x00, 0x76, 0x80, 0x80, 0x3b, 0x01, 0x00, 0x00, 0x00,
0xe6, 0xff, 0x7f, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0xb4,
0x0d, 0x00, 0x00, 0x00, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79,
0x5f, 0x69, 0x6e, 0x74, 0x38, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xfa, 0xff, 0xff,
0x00, 0x00, 0x00, 0x09, 0xf4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
0x50, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
0xcc, 0xfa, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
0x41, 0x32, 0x38, 0x3b, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x7a, 0x37, 0x3f,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00,
0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64,
0x65, 0x6e, 0x73, 0x65, 0x5f, 0x31, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b,
0x53, 0x74, 0x61, 0x74, 0x65, 0x66, 0x75, 0x6c, 0x50, 0x61, 0x72, 0x74,
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, 0x61, 0x6c, 0x6c, 0x2f,
0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64,
0x65, 0x6e, 0x73, 0x65, 0x5f, 0x31, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b,
0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64,
0x65, 0x6e, 0x73, 0x65, 0x5f, 0x31, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41,
0x64, 0x64, 0x3b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x66, 0x75, 0x6c, 0x50,
0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, 0x61,
0x6c, 0x6c, 0x2f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61,
0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x31, 0x2f, 0x42, 0x69,
0x61, 0x73, 0x41, 0x64, 0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe8, 0xfb, 0xff, 0xff,
0x00, 0x00, 0x00, 0x09, 0xec, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x50, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
0xd4, 0xfb, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
0x6b, 0x57, 0xed, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x14, 0x6a, 0xec, 0x3e,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00,
0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64,
0x65, 0x6e, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b, 0x53, 0x74,
0x61, 0x74, 0x65, 0x66, 0x75, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, 0x61, 0x6c, 0x6c, 0x2f, 0x73, 0x65,
0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e,
0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b, 0x73, 0x65, 0x71, 0x75,
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65,
0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, 0x64, 0x64, 0x3b, 0x53, 0x74, 0x61,
0x74, 0x65, 0x66, 0x75, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69,
0x6f, 0x6e, 0x65, 0x64, 0x43, 0x61, 0x6c, 0x6c, 0x2f, 0x73, 0x65, 0x71,
0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73,
0x65, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, 0x64, 0x64, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x52, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x9c, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0xc4, 0xfc, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x14, 0xcb, 0xef, 0x3b, 0x01, 0x00, 0x00, 0x00,
0x10, 0xf1, 0x28, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xeb, 0x6d, 0xbf,
0x4b, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69,
0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x32, 0x2f, 0x4d,
0x61, 0x74, 0x4d, 0x75, 0x6c, 0x3b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x66,
0x75, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65,
0x64, 0x43, 0x61, 0x6c, 0x6c, 0x2f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e,
0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x32,
0x2f, 0x4d, 0x61, 0x74, 0x4d, 0x75, 0x6c, 0x00, 0x02, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0xfe, 0xff, 0xff,
0x00, 0x00, 0x00, 0x09, 0x9c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x74, 0xfd, 0xff, 0xff,
0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x1d, 0x80, 0xaa, 0x3b, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x2b, 0x29, 0x3f,
0x01, 0x00, 0x00, 0x00, 0x36, 0xab, 0x11, 0xbf, 0x4b, 0x00, 0x00, 0x00,
0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64,
0x65, 0x6e, 0x73, 0x65, 0x5f, 0x31, 0x2f, 0x4d, 0x61, 0x74, 0x4d, 0x75,
0x6c, 0x3b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x66, 0x75, 0x6c, 0x50, 0x61,
0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, 0x61, 0x6c,
0x6c, 0x2f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x31, 0x2f, 0x4d, 0x61, 0x74,
0x4d, 0x75, 0x6c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xb2, 0xfe, 0xff, 0xff,
0x00, 0x00, 0x00, 0x09, 0x94, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x24, 0xfe, 0xff, 0xff,
0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x01, 0x92, 0x3b,
0x01, 0x00, 0x00, 0x00, 0xdf, 0xc6, 0x01, 0x3f, 0x01, 0x00, 0x00, 0x00,
0x26, 0xdd, 0x10, 0xbf, 0x47, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75,
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65,
0x2f, 0x4d, 0x61, 0x74, 0x4d, 0x75, 0x6c, 0x3b, 0x53, 0x74, 0x61, 0x74,
0x65, 0x66, 0x75, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f,
0x6e, 0x65, 0x64, 0x43, 0x61, 0x6c, 0x6c, 0x2f, 0x73, 0x65, 0x71, 0x75,
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65,
0x2f, 0x4d, 0x61, 0x74, 0x4d, 0x75, 0x6c, 0x00, 0x02, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x5a, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x4c, 0xff, 0xff, 0xff,
0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x09, 0x89, 0xac, 0x37, 0x09, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e,
0x6f, 0x77, 0x6e, 0x5f, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0xaa, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02,
0x44, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0xd4, 0x12, 0x1e, 0x37, 0x09, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e,
0x6f, 0x77, 0x6e, 0x5f, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x08, 0x00,
0x07, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x34, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0xbc, 0x93, 0x92, 0x37, 0x09, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e,
0x6f, 0x77, 0x6e, 0x5f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x07, 0x00,
0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x7c, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00,
0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x01, 0x00, 0x00, 0x00, 0x81, 0x80, 0x80, 0x3b, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x69, 0x6e,
0x70, 0x75, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x38, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x07, 0x00,
0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00,
0x06, 0x00, 0x00, 0x00, 0x00, 0x72, 0x0a, 0x00, 0x0c, 0x00, 0x07, 0x00,
0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
0x04, 0x00, 0x00, 0x00
};
namespace {
tflite::ErrorReporter* error_reporter = nullptr;
const tflite::Model* model = nullptr;
tflite::MicroInterpreter* interpreter = nullptr;
TfLiteTensor* input = nullptr;
TfLiteTensor* output = nullptr;
constexpr int kTensorArenaSize = 2000;
uint8_t tensor_arena[kTensorArenaSize];
}
int main() {
stdio_init_all();
gpio_init(25);
gpio_set_dir(25, GPIO_OUT);
// NOLINTNEXTLINE(runtime-global-variables)
static tflite::MicroErrorReporter micro_error_reporter;
error_reporter = µ_error_reporter;
model = tflite::GetModel(xor_model_tflite);
if (model->version() != TFLITE_SCHEMA_VERSION) {
TF_LITE_REPORT_ERROR(error_reporter,
"Model provided is schema version %d not equal "
"to supported version %d.",
model->version(), TFLITE_SCHEMA_VERSION);
return 1;
}
// This pulls in all the operation implementations we need.
// NOLINTNEXTLINE(runtime-global-variables)
static tflite::AllOpsResolver resolver;
// Build an interpreter to run the model with.
static tflite::MicroInterpreter static_interpreter(
model, resolver, tensor_arena, kTensorArenaSize, error_reporter);
interpreter = &static_interpreter;
// Allocate memory from the tensor_arena for the model's tensors.
TfLiteStatus status = interpreter->AllocateTensors();
if (status != kTfLiteOk) {
TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
return 1;
}
input = interpreter->input_tensor(0);
output = interpreter->output_tensor(0);
while (true) {
int c1 = getchar();
printf("%c\n", c1);
int c2 = getchar();
printf("%c\n", c2);
input->data.f[0] = c1 == '1' ? 1.0f : 0.0f;
input->data.f[1] = c2 == '1' ? 1.0f : 0.0f;
status = interpreter->Invoke();
if (status != kTfLiteOk) {
TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
continue;
}
int on = output->data.f[0] > 0.5 ? 1 : 0;
printf("XOR(%d, %d) = %d\n",
c1 == '1' ? 1 : 0,
c2 == '1' ? 1 : 0,
on);
gpio_put(25, on);
}
return 0;
}
One thing to note here: when creating a model embedded in the source, make sure to define TF_LITE_STATIC_MEMORY. It seems that without this, an unintended delete operator gets embedded, causing the application to fail to run correctly.
// C++ will automatically create class-specific delete operators for virtual
// objects, which by default call the global delete function. For embedded
// applications we want to avoid this, and won't be calling new/delete on these
// objects, so we need to override the default implementation with one that does
// nothing to avoid linking in ::delete().
// This macro needs to be included in all subclasses of a virtual base class in
// the private section.
#ifdef TF_LITE_STATIC_MEMORY
#define TF_LITE_REMOVE_VIRTUAL_DELETE \
void operator delete(void* p) {}
#else
#define TF_LITE_REMOVE_VIRTUAL_DELETE
#endif
Build and Transfer
To build it, create a directory called tflite/tflite_xor directly under pico-examples, and create one CMakeLists.txt directly under tflite.
if (NOT PICO_NO_HARDWARE)
add_subdirectory(tflite_xor)
endif ()
Then, create another one under tflite_xor.
link_directories(${CMAKE_SOURCE_DIR}/lib)
add_executable(tflite_xor
main.cxx
)
set_target_properties(
tflite_xor
PROPERTIES
COMPILE_FLAGS -fno-rtti
COMPILE_FLAGS -fno-exceptions
COMPILE_FLAGS -fno-threadsafe-statics
COMPILE_FLAGS -nostdlib
)
# Pull in our pico_stdlib which aggregates commonly used features
target_link_libraries(tflite_xor pico_stdlib pico-tflmicro)
pico_enable_stdio_usb(tflite_xor 1)
pico_enable_stdio_uart(tflite_xor 0)
pico_add_extra_outputs(tflite_xor)
# add url via pico_set_program_url
example_auto_set_url(tflite_xor)
target_include_directories(tflite_xor
PRIVATE
"c:/dev/pico-tflmicro/src"
"c:/dev/pico-tflmicro/src/third_party/flatbuffers/include"
)
Since I'm developing on Windows, full paths are included; please correct them according to your own environment. If you're using the serial port, don't forget to set pico_enable_stdio_usb to 1.
Transfer the generated pico-examples/build/tflite/tflite_xor/tflite_xor.uf2 to your Raspberry Pi Pico, and you're done!
Conclusion
I wasted about half a day because I didn't notice TF_LITE_STATIC_MEMORY, but I finally got it working. If we can connect a camera, display, or Wi-Fi, we might even be able to perform image inference via HTTP.
Well, since it's also possible to achieve something like that by pouring a mime/multipart body into the serial port and having it respond with JSON, I'll try that if I have time.
Discussion