#include <Arduino.h>
#include <stdint.h>
#include <string.h>
// Compile-time constants (zero runtime CPU cycles wasted)
constexpr uint8_t SENSOR_ID = 42;
constexpr size_t MAX_PAYLOAD_SIZE = 32;
// Packed structure for our telemetry data
struct TelemetryPacket {
uint8_t id;
float soil_moisture;
float battery_voltage;
};
class AgriSensorNode {
private:
// Static allocation using a fixed C-style array (Zero Heap, 100% Safe)
uint8_t tx_buffer_[MAX_PAYLOAD_SIZE];
size_t payload_len_;
public:
// Constructor initializes state statically
AgriSensorNode() : payload_len_(0) {
memset(tx_buffer_, 0, MAX_PAYLOAD_SIZE);
}
bool preparePayload(float moisture, float voltage) {
TelemetryPacket packet{SENSOR_ID, moisture, voltage};
if (sizeof(TelemetryPacket) > MAX_PAYLOAD_SIZE) {
return false;
}
// Copy struct bytes directly into our static buffer
memcpy(tx_buffer_, &packet, sizeof(TelemetryPacket));
payload_len_ = sizeof(TelemetryPacket);
return true;
}
const uint8_t* getData() const { return tx_buffer_; }
size_t getLength() const { return payload_len_; }
};
// Global instance allocated statically at boot—zero runtime reallocation
static AgriSensorNode node;
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("=== Zero-Heap Static Allocation Test ===");
float current_moisture = 34.5f; // Simulated soil reading
float current_voltage = 3.85f; // Simulated LiFePO4 voltage
if (node.preparePayload(current_moisture, current_voltage)) {
Serial.printf("Payload packed successfully. Size: %u bytes\n", node.getLength());
Serial.print("Raw byte dump in static buffer: ");
const uint8_t* data = node.getData();
for(size_t i = 0; i < node.getLength(); i++) {
Serial.printf("0x%02X ", data[i]);
}
Serial.println("\n----------------------------------------");
}
}
void loop() {
delay(10000);
Serial.println("Node idle: Memory footprint is 100% static (No heap fragmentation).");
}Loading
esp32-devkit-c-v4
esp32-devkit-c-v4