# Monitoring Perishable Commodities Using Cellular IoT:
## 2 Materials and Methods
### Software Architecture  
#### 2.3.1 Firmware Description  
The microcontroller firmware programming was developed using C++ language (version C++20). A flowchart detailing the general operation of the datalogger is shown in Figure 4. Measurement data were logged every 15 min in the microcontroller's flash memory and sent wirelessly with less frequency, depending on the state of the battery, the number of vibrations and the difference with respect to the previous measurement, as detailed in Section 2.3.2. Sampling and sending frequencies were determined by a trade-off between energy consumption and the dynamics of perishable food behavior. That is, a higher sampling frequency would not be useful because it would not provide relevant information on food spoilage. The ESP32 entered Deep Sleep mode while it had no activity to save as much power as possible. The data in flash memory were backed up for data recovery via USB in case of communications failure or any other incident. While the device stays in Deep Sleep mode, as vibrations can occur at any time, an interruption is programmed when a predefined threshold of 2 g is exceeded to record the vibration, returning to Deep Sleep mode immediately afterwards. After the initializations, it is checked whether the USB is connected because the data stored on the flash memory are to be retrieved. If this is the case, the programmed system shell comes into operation, which reads and executes commands through UART to dump the data to the computer and to erase the flash memory. If the reset command is sent to it or it is manually restarted, the program starts again. If the USB is not connected, it enters the normal mode of operation of sensor measurement and Deep Sleep. First, the accelerometer is initialized and measured. Then, it is checked if the microcontroller has been awakened before 15 min by the external interrupt of the accelerometer itself, in which case it records the measurement, determines the time asleep and goes back to sleep the remaining time until 15 min in order to obtain the maximum and average accelerations and the number of vibrations recorded during those 15 min. When the 15 min elapse, which is checked thanks to an internal timer of the microcontroller, the rest of the sensors are activated with the MOSFET and initialized, measured and switched off again. Then, the measured data from the sensors are stored in the flash in CSV format together with a packet counter, including the battery voltage to monitor its state of charge and the codes of the cell towers it has connected to. When the time is right, depending on the previously mentioned autonomy improvement strategies, the data  
Figure 4: Flowchart of the general operation of the datalogger. are sent over NB-IoT wirelessly in CayenneLPP format [66] to optimize the payload size through the SIM7000G, synchronizing the timestamp and disconnecting the SIM7000G afterwards. After all this, the microcontroller goes into Deep Sleep mode and repeats the cycle again when it wakes up, either by the accelerometer or after 15 min by the timer. In the flash memory, there is a file containing the current data and another file to store a history of the data, in case the data obtained in previous dates should be kept, while the other file is only to have the most recent data. Both files can be cleared from the flash memory. When connecting the SIM7000G and synchronizing the timestamp, the possibility of obtaining the GPS location through an external antenna and sending this data also through NB-IoT has been left open; although, by default, the system obtains the geolocation through the operator or cell towers in order to extend the battery life, as will be shown later. When the datalogger is turned on for the first time, the First Scan mode is executed, which allows for synchronization through the SIM7000G, the timestamp, and takes care of calibrating the CO\({}_{2}\) sensor with a concentration of 400 ppm, with the system exposed to fresh air for this first calibration.