// Space - Memory Management & Efficient Coding Practices Demo for Wokwi
// Pin Definitions (referencing your diagram.json)
const int RED_LED_PIN = 7;
const int GREEN_LED_PIN = 6;
const int YELLOW_LED_PIN = 5;
const int PUSH_BUTTON_PIN = 8;
const int SERVO_PIN = 4; // Not used in this specific demo, but defined as per your connections
// Global variables (allocated in static/data memory segment)
// Try to minimize global variables, especially large arrays/objects, if their scope is limited.
int globalCounter = 0;
char globalStatusMessage[50] = "System Initialized."; // Fixed-size buffer
void setup() {
Serial.begin(115200); // Initialize serial communication for output
Serial.println("--- Space - Memory Management & Efficient Coding Practices Demo ---");
// Print initial memory usage (approximate free heap after setup)
Serial.print("1. Free Heap Memory after setup (bytes): ");
Serial.println(ESP.getFreeHeap());
Serial.println("--------------------------------------------------");
// Pin setup for LEDs (though not actively blinked, they are initialized)
pinMode(RED_LED_PIN, OUTPUT);
pinMode(GREEN_LED_PIN, OUTPUT);
pinMode(YELLOW_LED_PIN, OUTPUT);
pinMode(PUSH_BUTTON_PIN, INPUT_PULLUP); // Button needs pull-up for proper reading
// Example of a local variable (allocated on stack, deallocated on function exit)
int localVariable = 100;
Serial.print("2. Value of a local variable in setup(): ");
Serial.println(localVariable);
Serial.println("--------------------------------------------------");
// Efficient string formatting using snprintf (avoids String class and heap fragmentation)
snprintf(globalStatusMessage, sizeof(globalStatusMessage), "3. Status: Setup complete, counter starts at %d", globalCounter);
Serial.println(globalStatusMessage);
Serial.print(" Free Heap after initial string operations: ");
Serial.println(ESP.getFreeHeap());
Serial.println("--------------------------------------------------");
} // 'localVariable' is deallocated here as setup() exits
void loop() {
// --- Efficient Coding Practice: String Handling ---
// AVOID this pattern in long-running embedded systems, especially in loops:
// String tempString = "Counter: " + String(globalCounter);
// Serial.println(tempString);
// Using 'String' concatenation (the '+' operator on String objects) inside a loop
// can cause memory fragmentation and eventually lead to memory exhaustion because
// it constantly allocates and deallocates memory on the heap.
// GOOD PRACTICE: Use fixed-size character arrays and snprintf()
char buffer[80]; // Allocate a fixed-size buffer on the stack (efficient)
// Use snprintf to safely format strings into the buffer, preventing overflow
snprintf(buffer, sizeof(buffer), "Loop %lu | Counter: %d | Free Heap: %lu bytes", millis(), globalCounter, ESP.getFreeHeap());
Serial.println(buffer);
globalCounter++; // Increment global counter
// A small delay to slow down the serial output for readability
delay(1000);
// --- Conceptual Example of Potential Memory Pitfalls (Commented Out) ---
// This function demonstrates potential memory issues if not careful
// with very large local arrays or deep recursion.
// Uncommenting this line might lead to a stack overflow on repeated calls
// if 'veryLargeLocalArray' within it was truly massive.
// dontCallThisOften();
}
/*
// Example of a function that could consume a lot of stack memory if called frequently
// or if it declares very large local arrays.
// In this case, we're not using it to prevent actual issues in this demo.
void dontCallThisOften() {
// char veryLargeLocalArray[10000]; // This is a conceptual example. A real large array
// could cause a stack overflow if stack space is limited
// or if the function is called recursively many times.
// veryLargeLocalArray[0] = 'a'; // Dummy operation
// Serial.println("Very large local array conceptually 'used'.");
}
*/