| title | Firmware Dev - The Core Logic | |||||
|---|---|---|---|---|---|---|
| project | Solar-Doctor | |||||
| phase | 08 - Firmware Development | |||||
| status | CODING | |||||
| tags |
|
|||||
| aliases |
|
|||||
| date | 2025-11-22 | |||||
| owner | mr.princetheprogrammerbtw |
Breathing Life into Silicon: The C++ Firmware.
To ensure responsive and non-blocking operation, the firmware will leverage the ESP32's dual-core architecture using FreeRTOS tasks.
- Task 1 (Core 1): High-speed sensor sampling (e.g., reads sensors every 50ms).
- Task 2 (Core 0): Handles network communication (Wi-Fi, ESP-NOW) and cloud reporting (runs every 5 seconds).
- Task 3 (Core 1): Executes the fault detection and decision logic.
Define hardware-specific values and pin assignments at the beginning of the code for easy tuning.
#define VOLT_PIN 35
#define CURR_PIN 34
#define RELAY_PIN 26
// Resistor values for the voltage divider
const float R1 = 150000.0; // 150kΩ
const float R2 = 10000.0; // 10kΩ
// Reference voltage for ADC calculations
const float V_REF = 3.3;
// Sensitivity for the ACS712-20A current sensor
const float ACS712_SENSITIVITY = 0.100; // 100mV per AmpThis C++ code for the Arduino IDE provides a basic, single-threaded framework for initial testing.
#include <Arduino.h>
// Pin definitions
const int voltagePin = 35;
const int currentPin = 34;
const int relayPin = 26;
// Global state variables
float voltage = 0.0;
float current = 0.0;
bool isFaulty = false;
// Forward function declarations
float readVoltage();
float readCurrent();
void triggerBypass();
void disableBypass();
void setup() {
Serial.begin(115200);
pinMode(relayPin, OUTPUT);
// Default to Normal Operation (Bypass OFF). Note the inverted logic from Phase 7.
digitalWrite(relayPin, LOW);
Serial.println("Solar-Doctor System Initialized...");
}
void loop() {
// 1. Read sensor values
voltage = readVoltage();
current = readCurrent();
// 2. Print data for debugging
Serial.print("V: "); Serial.print(voltage);
Serial.print(" V | I: "); Serial.print(current);
Serial.println(" A");
// 3. Simple threshold logic (pre-AI)
// If voltage drops below 20V but is above 2V (to avoid night triggers)
if (voltage < 20.0 && voltage > 2.0) {
triggerBypass();
} else {
disableBypass();
}
delay(500); // Main loop delay for testing
}
/**
* @brief Reads and averages voltage from the sensor.
* @return The calculated real voltage.
*/
float readVoltage() {
float adc_value = 0.0;
for(int i = 0; i < 10; i++) { // Average 10 samples to reduce noise
adc_value += analogRead(voltagePin);
delay(5);
}
adc_value /= 10.0;
// Convert ADC value to voltage at the pin
float pinVoltage = (adc_value / 4095.0) * V_REF;
// Scale pin voltage to the actual panel voltage
float realVoltage = pinVoltage * ((R1 + R2) / R2);
return realVoltage;
}
/**
* @brief Reads and calculates current, correcting for zero-offset.
* @return The absolute current value.
*/
float readCurrent() {
float adc_value = analogRead(currentPin);
float pinVoltage = (adc_value / 4095.0) * V_REF;
// ACS712 zero-current offset is typically VCC/2 (3.3V/2 = 1.65V)
float current = (pinVoltage - 1.65) / ACS712_SENSITIVITY;
return abs(current); // Use absolute value to ignore current direction
}
/**
* @brief Activates the bypass mechanism if not already active.
*/
void triggerBypass() {
if (!isFaulty) {
digitalWrite(relayPin, HIGH); // Activate bypass
isFaulty = true;
Serial.println(">>> FAULT DETECTED! BYPASS ACTIVE <<<");
}
}
/**
* @brief Deactivates the bypass mechanism if it is currently active.
*/
void disableBypass() {
if (isFaulty) {
digitalWrite(relayPin, LOW); // Deactivate bypass
isFaulty = false;
Serial.println(">>> SYSTEM NORMAL <<<");
}
}- Upload the code to the ESP32.
- Open the Arduino IDE's Serial Monitor at 115200 baud.
- Test Normal Operation: Apply 30V. The serial output should show
V: 30.1 Vand the bypass should be OFF. - Test Fault Condition: Lower the input voltage to 15V. The serial output should show
FAULT DETECTED!and the bypass mechanism should activate. - Test Night Condition: Turn off the power supply (0V). The bypass should remain OFF due to the
> 2.0check.
- Problem: If the voltage flickers around the 20V threshold (e.g., 20.1V → 19.9V → 20.1V), the relay will rapidly switch on and off ("chatter"), causing wear.
- Fix: A debounce mechanism is required. A simple fix is to only trigger the bypass if the voltage remains below the threshold for a set duration (e.g., 5 seconds). This logic will be implemented in the next phase with the TinyML model.
- Wrote basic sensor reading functions for voltage and current.
- Implemented signal averaging (10 samples) to reduce noise.
- Implemented a basic threshold-based fault detection logic.
- Added a check to prevent false triggers during nighttime.
- Verified the core logic and output on the Serial Monitor.
The core firmware is alive. It can perceive its environment and react.
[[09_Edge_AI]]