Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/python
{
"name": "Python 3",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/python:1-3.12-bullseye",
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/git-lfs:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/powershell:1": {},
"ghcr.io/devcontainers/features/python:1": {},
"ghcr.io/devcontainers-extra/features/actions-runner:1": {},
"ghcr.io/devcontainers-extra/features/gh-cli:1": {},
"ghcr.io/devcontainers-extra/features/gh-release:1": {},
"ghcr.io/devcontainers-extra/features/gitomatic:1": {},
"ghcr.io/devcontainers-extra/features/jmc-sdkman:2": {},
"ghcr.io/devcontainers-extra/features/pipenv:2": {},
"ghcr.io/dotnet/aspire-devcontainer-feature/dotnetaspire:1": {}
},
"customizations": {
"vscode": {
"extensions": [
"BazelBuild.vscode-bazel",
"Oracle.oracle-java"
]
}
}

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "pip3 install --user -r requirements.txt",

// Configure tool-specific properties.
// "customizations": {},

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for more information:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
# https://containers.dev/guide/dependabot

version: 2
updates:
- package-ecosystem: "devcontainers"
directory: "/"
schedule:
interval: weekly
1 change: 1 addition & 0 deletions .vscode/Untitled-1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
C:\Users\Thoma\AppData\Roaming\Python\Python314\Scripts\platformio.exe device monitor
9 changes: 9 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"cSpell.words": [
"tflite"
],
"makefile.makefilePath": "\"C:\\Users\\Thoma\\arduino-uno-aws-irrigation-system\"",
"java.project.sourcePaths": [
".venv"
]
}
23 changes: 23 additions & 0 deletions @echo off.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@echo off
REM Batch script to copy TensorFlow Lite Micro source into PlatformIO project

REM Set the source path to the downloaded tflite-micro repo
set SRC=C:\Users\Thoma\Downloads\tflite-micro-main\tensorflow
REM Set the destination path in your PlatformIO project
set DST=lib\tflite-micro\tensorflow

REM Remove any existing tensorflow folder in the destination
if exist "%DST%" (
rmdir /s /q "%DST%"
)

REM Create the destination directory if it doesn't exist
if not exist "lib\tflite-micro" (
mkdir "lib\tflite-micro"
)

REM Copy the tensorflow folder
xcopy /E /I /Y "%SRC%" "%DST%"

echo TensorFlow Lite Micro source copied to %DST%
pause
416 changes: 416 additions & 0 deletions compile_commands.json

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions edge-ai/esp32-ml/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ lib_deps =
WiFi
DNSServer
ArduinoOTA
; TensorFlow Lite Micro for ESP32
https://github.com/tensorflow/tflite-micro-arduino-examples
Arduino_TensorFlowLite

; Build flags
build_flags =
Expand Down
44 changes: 44 additions & 0 deletions launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// AUTOMATICALLY GENERATED FILE. PLEASE DO NOT MODIFY IT MANUALLY
//
// PlatformIO Debugging Solution
//
// Documentation: https://docs.platformio.org/en/latest/plus/debugging.html
// Configuration: https://docs.platformio.org/en/latest/projectconf/sections/env/options/debug/index.html

{
"version": "0.2.0",
"configurations": [
{
"type": "platformio-debug",
"request": "launch",
"name": "PIO Debug",
"executable": "C:/Users/Thoma/arduino-uno-aws-irrigation-system/.pio/build/esp32/firmware.elf",
"projectEnvName": "esp32",
"toolchainBinDir": "C:/Users/Thoma/.platformio/packages/toolchain-xtensa-esp32/bin",
"internalConsoleOptions": "openOnSessionStart",
"preLaunchTask": {
"type": "PlatformIO",
"task": "Pre-Debug (esp32)"
}
},
{
"type": "platformio-debug",
"request": "launch",
"name": "PIO Debug (skip Pre-Debug)",
"executable": "C:/Users/Thoma/arduino-uno-aws-irrigation-system/.pio/build/esp32/firmware.elf",
"projectEnvName": "esp32",
"toolchainBinDir": "C:/Users/Thoma/.platformio/packages/toolchain-xtensa-esp32/bin",
"internalConsoleOptions": "openOnSessionStart"
},
{
"type": "platformio-debug",
"request": "launch",
"name": "PIO Debug (without uploading)",
"executable": "C:/Users/Thoma/arduino-uno-aws-irrigation-system/.pio/build/esp32/firmware.elf",
"projectEnvName": "esp32",
"toolchainBinDir": "C:/Users/Thoma/.platformio/packages/toolchain-xtensa-esp32/bin",
"internalConsoleOptions": "openOnSessionStart",
"loadMode": "manual"
}
]
}
12 changes: 6 additions & 6 deletions lib/LocalMLEngine/LocalMLEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void LocalMLEngine::setGrowthStage(int sensorIndex, GrowthStage stage)
}
}

float LocalMLEngine::predictWaterNeed(const SensorData &data)
float LocalMLEngine::predictWaterNeed(const LocalSensorData &data)
{
unsigned long startTime = millis();

Expand Down Expand Up @@ -112,7 +112,7 @@ float LocalMLEngine::predictWaterNeed(const SensorData &data)
return adjustedPrediction;
}

bool LocalMLEngine::detectAnomaly(const SensorData &data)
bool LocalMLEngine::detectAnomaly(const LocalSensorData &data)
{
// Use anomaly detector for sensor fault detection
float anomalyScore = sensorMonitor->calculateAnomalyScore(data);
Expand All @@ -130,9 +130,9 @@ bool LocalMLEngine::detectAnomaly(const SensorData &data)
return isAnomaly;
}

Action LocalMLEngine::getImmediateAction(int sensorIndex, const SensorData &data)
LocalAction LocalMLEngine::getImmediateAction(int sensorIndex, const LocalSensorData &data)
{
Action action;
LocalAction action;

// Validate sensor index
if (sensorIndex < 0 || sensorIndex >= 4)
Expand All @@ -141,7 +141,7 @@ Action LocalMLEngine::getImmediateAction(int sensorIndex, const SensorData &data
}

// Create modified sensor data with plant-specific info
SensorData modifiedData = data;
LocalSensorData modifiedData = data;
modifiedData.plantType = plantTypes[sensorIndex];
modifiedData.growthStage = growthStages[sensorIndex];
modifiedData.lastWatered = (millis() - lastWateringTime[sensorIndex]) / 3600000; // Convert to hours
Expand Down Expand Up @@ -196,7 +196,7 @@ Action LocalMLEngine::getImmediateAction(int sensorIndex, const SensorData &data
return action;
}

float LocalMLEngine::calculateFeatureScore(const SensorData &data)
float LocalMLEngine::calculateFeatureScore(const LocalSensorData &data)
{
// Normalize features to 0-1 scale and calculate weighted score
float moistureScore = constrain(data.moisture / 1023.0, 0.0, 1.0);
Expand Down
74 changes: 26 additions & 48 deletions lib/LocalMLEngine/LocalMLEngine.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
#ifndef LOCAL_ML_ENGINE_H
#define LOCAL_ML_ENGINE_H
// Only use one set of include guards
#ifndef LOCALMLENGINE_H
#define LOCALMLENGINE_H

#include <Arduino.h>
#include "PlantTypes.h"

// Debug mode - comment out to disable
// #define DEBUG_ML 1

// Action structure for pump control
struct LocalAction {
bool shouldWater;
unsigned int waterDuration; // milliseconds
float waterAmount; // ml (calculated)
bool isFailsafe; // emergency watering

// Constructor with defaults
LocalAction() : shouldWater(false), waterDuration(0),
waterAmount(0), isFailsafe(false) {}
};

// Sensor data structure
struct SensorData
{
struct LocalSensorData {
float moisture; // 0-1023 analog reading
float temperature; // Celsius
float humidity; // Percentage
Expand All @@ -19,77 +31,43 @@ struct SensorData
GrowthStage growthStage;

// Constructor with defaults
SensorData() : moisture(0), temperature(25), humidity(50),
LocalSensorData() : moisture(0), temperature(25), humidity(50),
lightLevel(500), lastWatered(0),
plantType(TOMATO), growthStage(VEGETATIVE) {}
};

// Action structure for pump control
struct Action
{
bool shouldWater;
unsigned int waterDuration; // milliseconds
float waterAmount; // ml (calculated)
bool isFailsafe; // emergency watering

// Constructor with defaults
Action() : shouldWater(false), waterDuration(0),
waterAmount(0), isFailsafe(false) {}
};

// Forward declarations
class DecisionTree;
class LookupTable;
class AnomalyDetector;

class LocalMLEngine
{
class LocalMLEngine {
private:
DecisionTree* irrigationTree;
LookupTable* plantThresholds;
AnomalyDetector* sensorMonitor;

// Plant configurations per sensor
PlantType plantTypes[4];
GrowthStage growthStages[4];
unsigned long lastWateringTime[4];

// Internal calculation methods
float calculateFeatureScore(const SensorData &data);
WaterAmount mapToWaterAmount(float prediction);
unsigned int calculateWaterDuration(WaterAmount amount);

#ifdef DEBUG_ML
void debugPrint(const char *message, float value = 0);
#endif

public:
LocalMLEngine();

// Initialization
bool begin();
void setPlantType(int sensorIndex, PlantType type);
void setGrowthStage(int sensorIndex, GrowthStage stage);

// Main inference methods
float predictWaterNeed(const SensorData &data);
bool detectAnomaly(const SensorData &data);
Action getImmediateAction(int sensorIndex, const SensorData &data);

// Configuration methods
void updatePlantThresholds(PlantType type, float moistureThreshold,
float tempOptimal, float humidityOptimal);
float predictWaterNeed(const LocalSensorData &data);
bool detectAnomaly(const LocalSensorData &data);
LocalAction getImmediateAction(int sensorIndex, const LocalSensorData &data);
float calculateFeatureScore(const LocalSensorData &data);
WaterAmount mapToWaterAmount(float prediction);
unsigned int calculateWaterDuration(WaterAmount amount);
void updatePlantThresholds(PlantType type, float moistureThreshold, float tempOptimal, float humidityOptimal);
void setFailsafeMode(bool enabled);

// Utility methods
bool isTimeToWater(int sensorIndex, unsigned long currentTime);
float getMoistureThreshold(PlantType type, GrowthStage stage);
void recordWatering(int sensorIndex, unsigned long timestamp);

// Statistics
unsigned long getInferenceCount();
float getAverageInferenceTime();
void resetStats();
};

#endif // LOCAL_ML_ENGINE_H
#endif // LOCALMLENGINE_H
Loading