Now, we need to convert the TF model that we have saved to TF Lite and save it with the tflite file extension. As part of optimizing the workload, we use tf.lite.Optimize.DEFAULT to avoid errors:
loaded_model = tf.keras.models.load_model(‘Model_humidity_predict’)
lite_converter = tf.lite.TFLiteConverter.from_keras_model(loaded_model)
lite_converter.optimizations = [tf.lite.Optimize.DEFAULT]
lite_model = lite_converter.convert()
with open(“predict_humidity.tflite”, “wb”) as file:
file.write(lite_model)
With this, we now have converted the TensorFlow model to a TensorFlow Lite model by loading the model and converting and writing the model to a lite_model file. Now, we will convert the TF Lite model to a C array.
Converting the TF Lite model to a C array
We will then use a Linux command, xxd, to convert the TF Lite model we obtained from the previous step to a C array. This will perform a hex dump, converting the data to its hexadecimal format. We will put the .tflite file as the input for the xxd command, and we then specify the filename with .h as the file extension. We will then be able to predict both values. Thus far, we have been doing the steps for humidity, as with Chapter 1, An Introduction to IoT Architecture, Hardware, and Real-Life Applications, but we can repeat the same steps to get our C temperature array.
We need to convert the result to hexadecimal format by using the xxd command. As xxd is not available in the Windows environment, we need to download the xxd program for Windows from the following link: https://sourceforge.net/projects/xxd-for-windows/files/latest/download.
Then, put the xxd.exe file in the Python 3 directory, which is usually this directory: C:\Users\User Name\AppData\Local\Programs\Python\Python311. Here, you need to replace User Name with your username.
The following command runs xxd on predict_humidity.tflite and outputs to predict_humidity.h:
$ xxd -i predict_humidity.tflite > predict_humidity.h
Now, we will look at deploying to the ESP32 device.
Deploying to ESP32 (the edge device)
We can now then wire up our ESP32 device and our DHT11 sensor, as in Figure 6.4. Wire the 5V pin to VCC, GND to GND, and DIO4 to DATA:
Figure 6.4 – Circuit diagram for wiring up DHT11 for exercise
We now must report the libraries that we need for running this deployment. As can be seen, we import the TensorFlowLite.h and EloquentTinyML.h libraries to run the model that we have already obtained, the temperature_predictor.h and humidity_predictor.h files as part of the predictor files we generated from the models we created as part of the C array we have generated, and use the DHT.h library to run the DHT11 sensor:
#include “EloquentTinyML.h”
#include <TensorFlowLite.h>
#include “temperature_predictor.h”
#include “humidity_predictor.h”
#include “DHT.h”
We will then use the EloquentTinyML.h library to create a TFLite instance, as can be seen here:
Eloquent::TinyML::TfLite<NUMBER_OF_INPUTS, NUMBER_OF_OUTPUTS, TENSOR_ARENA_SIZE> temp_estimator(temperature_predictor_tflite);
Eloquent::TinyML::TfLite<NUMBER_OF_INPUTS, NUMBER_OF_OUTPUTS, 3 * 1024> humid_estimator(humidity_predictor_tflite);
In the case that a sensor is not able to read the values properly, we will then predict it until it is able to read the values again. We pass the previously recorded temperature and humidity values and the spliced data time values as the input to the model. As part of this, we use the Real-Time Clock (RTC) module to get the real date and time, store it in an array, and use that as the input. An RTC module is a supplementary component that can be interfaced with the Arduino board to provide accurate timekeeping even when the Arduino is powered off or reset. We then print out these values accordingly, ensuring that there is a delay in the capturing of the data:
float humid_val = dht.readHumidity();
float temp_val = dht.readTemperature(true);
delay(1000);
We now need to check if the humidity or temperature readings are valid numbers. If either reading is not a number (isnan() returns true), the code will print a message to the Serial Monitor indicating a failure to read from the DHT sensor:
if (isnan(humid_val) || isnan(temp_val)) {
Serial.println(F(“Unable to read from DHT sensor; please check your configuration.”));
If the sensor readings are invalid, the code creates two input arrays, presumably representing a timestamp and the previously recorded temperature and humidity values. These input arrays are fed to ML models (humid_estimator and temp_estimator) to predict the current temperature and humidity based on the given input data. These estimated values are then stored for use in the next cycle:
float input_data[8] = {2020, 5, 26, 11, 30, 0, prev_temp_val, prev_humid_val};
float input_data2[8] = {2020, 2, 4, 6, 40, 0, prev_humid_val, prev_temp_val};
float humid_estimated = humid_estimator.predict(input_data2);
float temp_estimated = temp_estimator.predict(input_data);
prev_humid_val = humid_estimated;
prev_temp_val = temp_estimated;
Now, we want to print the estimated temperature and humidity values to the Serial Monitor for verification or debugging. The program then waits for 1 second before ending the function (via the return; statement) in case this code is part of a function:
Serial.print(“\t predicted humidity: “);
Serial.println(humid_estimated);
Serial.print(“\t predicted temp: “);
Serial.println(temp_estimated);
delay(1000);
return;}
else {
Serial.print(“\t humidity: “);
Serial.println(humid_val);
Serial.print(“\t temp: “);
Serial.println(temp_val);
prev_temp_val = temp_val;
prev_humid_val = humid_val;}
And that’s it! Now, open the output monitor to see the output that is being put through.
As can be seen, this creates an effective system that will continually read in the temperature and humidity based on the sensor but notify you if there is a failure to read from the sensor and uses the ML model we have created to predict the humidity and temperature based on the values that we have put into it. This ensures that we do not have any holes within the collection of data, given that we fill it in with well-informed guesses in the case that we do.
Now that we’ve looked at how an edge computing implementation within an IoT network can have such a powerful effect on how we establish and manage our system, we will now look at the requirements that we need to consider as part of the implementation of it.
Leave a Reply