alexis Cruz
Published

EcoHub V1.0 (MATRIX Creator Controlled Greenhouse)

The first version of an automated greenhouse controlled via a MATRIX Creator.

IntermediateWork in progress3 hours3,692

Things used in this project

Hardware components

Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×1
MATRIX Creator
MATRIX Labs MATRIX Creator
×1

Software apps and online services

Snips AIR
Snips AIR

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)

Story

Read more

Custom parts and enclosures

Matrix Creator Holster

the stl file is in the STL directory

Code

plantData.js

JavaScript
const regularly = 2;
const often = 1;
const not_that_much = 3;


var planta = {
    marigold: {
        name: "Marigold",
        water_cycle: regularly,
    },
    lily: {
        name: "Lily",
        water_cycle: often
    },
    snap_dragon: {
        name: "Snap dragon",
        water_cycle: regularly
    },
    Cactus: {
        name: "Cactus",
        water_cycle: not_that_much
    },
    Succulent: {
        name: "Succulent",
        water_cycle: regularly
    },
    Amaryllis: {
        name: 'Amaryllis',
        water_cycle: regularly
      },
      Beach_Spider_Lily: {
        name: 'Beach Spider Lily',
        water_cycle: regularly
      },
      Belladonna_Lily: {
        name: 'Belladonna Lily',
        water_cycle: not_that_much
      },
      Calla_Lily: {
        name: 'Calla Lily',
        water_cycle: often
      },
      Coral_Berry: {
        name: 'Coral Berry',
        water_cycle: sometimes
      },
      Eternal_Flame:{
        name: 'Eternal Flame',
        water_cycle: regularly
      },
      False_Shamrock:{
        name: 'False Shamrock',
        water_cycle: sometimes
      },
      Flamingo_Flower_Plant: {
        name: 'Flamingo Flower Plant',
        water_cycle: regularly
      },
      Kaffir_Lily_Plant: {
        name: 'Kaffir Lily Plant',
        water_cycle: regularly
      },
      Lycaste_Orchid: {
        name: 'Lycaste Orchid',
        water_cycle: regularly
      },
      Madagascar_Jasmine: {
        name: 'Madagascar Jasmine',
        water_cycle: regularly
      },
      Moth_Orchid: {
        name: 'Moth Orchid',
        water_cycle: regularly
      },
      Ornamental_Pepper_Plant: {
        name: 'Ornamental Pepper Plant',
        water_cycle: regularly
      },
      Peace_Lily: {
        name: 'Peace Lily',
        water_cycle: regularly
      },
      Rose_Of_China: {
        name: 'Rose Of China',
        water_cycle: regularly
      },
      Scarlet_Star: {
        name: 'Scarlet Star', 
        water_cycle: regularly
      },
      Winter_Cherry: {
        name: 'Winter Cherry',
        water_cycle: regularly
      }
};


module.exports = {
    planta: planta
}

servo.js

JavaScript
const matrix = require("@matrix-io/matrix-lite");

const plantData = require("./plantData");

const fs = require("fs");

var inuse = false;

var toggle = false;

const servopin1 = 0;

const servopin2 = 1;

var methods = {};

var averageHumidity = 0;

var averageTemperature = 0;

var currentHumidity = {};

var previousHumidity = [];

var previousTemperature = [];

var counter = 0;

var currentTime = 0;

var iswatered = false;

var greenHouse = {};



methods.findAverageWaterCycle = function (arr) {

    var result = 0;

    if (arr) {

        for (var i = 0; i < arr.length; i++) {

            try {

                result += (arr[i]).water_cycle;

            }

            catch (e) {

                console.log(e)

                console.log(arr[i]);

            }

        }

        result /= arr.length;

        switch (Math.round(result)) {

            case 1:

                return 18;

                break;

            case 2:

                return 36;

                break;

            case 3:

                return 72;

                break;

        }

    }

};



methods.clearData = function () {

    previousHumidity = [];
    previousTemperature = [];
}



methods.startWaiting = function () {

    toggle = true;

}
methods.stopWaiting = function () {

    toggle = false;
}



methods.tellHumidity = function (isAverage) {

    if (isAverage) {

        var res = 0;

        previousHumidity.forEach(element => {

            res += element;

        });

        return res / (previousHumidity.length);

    }

    else {

        return currentHumidity.humidity;

    }

}

methods.tellTemperature = function (isAverage) {
    var res = 0;
    if (isAverage) {
        previousTemperature.forEach(element => {
            res += element;
        });
        res /= previousTemperature.length;
    }
    else {
        res = currentHumidity.temperature;
    }
    return res;
}


methods.water = function () {
    iswatered = true;
    console.log("watering the plants");
}


methods.sleep = function (delay) {
    var start = new Date().getTime();
    while (new Date().getTime() < start + delay * 1000);
};
methods.timetohours = function (t) {
    return 1000 * t * 3600;
};
methods.reduceTime = function (t) {
    return t - 3600 * 1000;
};


methods.addPlant = function (plant) {
    greenHouse.plantsOnLevel1.push(plant)
}
methods.getPlants = function () {
    var res = '';
    greenHouse.plantsOnLevel1.forEach(element => {
        res += ' a ' + element + ' ,';
    })
    return res;
};
methods.removePlant = function (plant) {
    if (greenHouse.plantsOnLevel1.includes(plant)) {
        var index = greenHouse.plantsOnLevel1.indexOf(plant);
        greenHouse.plantsOnLevel1.splice(index, 1);
    }
}

methods.setupGreenHouse = function (lvl1, lvl2) {


    var lvl1Water = "";
    var lvl2Water = "";
    var plantsInlvl1 = lvl1;
    var plantsInlvl2 = lvl2;


    lvl1Water = methods.findAverageWaterCycle(plantsInlvl1);
    lvl2Water = methods.findAverageWaterCycle(plantsInlvl2);

    var timeleftlvl1 = methods.timetohours(lvl1Water);
    var timeleftlvl2 = methods.timetohours(lvl2Water);


    var greenhouse = {
        lvl1Water,
        plantsOnLevel1: lvl1,
        plantsOnLevel2: lvl2,
        lvl2Water,
        timeleftlvl1,
        timeleftlvl2
    }
    return greenhouse;
}


greenHouse = methods.setupGreenHouse([plantData.Succulent, plantData.Cactus, plantData.Amaryllis], [plantData.Marigold, plantData.Lily]);

matrix.gpio.setFunction(servopin1, "PWM");
matrix.gpio.setFunction(servopin2, "PWM");

matrix.gpio.setMode(servopin1, "output");
matrix.gpio.setMode(servopin2, "output");

matrix.gpio.setPWM({
    pin: servopin1,
    percentage: 25,
    frequency: 50
})
matrix.gpio.setPWM({
    pin: servopin2,
    percentage: 25,
    frequency: 50
})

setInterval(function () {

    inuse = true;

    if (greenHouse.timeleftlvl1 <= 0) {

        matrix.gpio.setServoAngle({

            pin: servopin1,

            angle: 0,
            min_pulse_ms: 0.1
        });

        matrix.gpio.setServoAngle({

            pin: servopin2,

            angle: 0,
            min_pulse_ms: 0.1

        });

        greenHouse.timeleftlvl1 = methods.timetohours(greenHouse.lvl1Water + 5 * Math.random() - 5 * Math.random());

        iswatered = false;

        methods.sleep(10);

    }
    else {

        matrix.gpio.setServoAngle({
            pin: servopin1,
            angle: 180,
            min_pulse_ms: 0.1
        });
        matrix.gpio.setServoAngle({
            pin: servopin2,
            angle: 180,
            min_pulse_ms: 0.1
        });
        greenHouse.timeleftlvl1 = methods.reduceTime(greenHouse.timeleftlvl1);
    }

    inuse = false;
}, methods.timetohours(1));



setInterval(function () {

    methods.clearData();

}, methods.timetohours(1 / 60));


setInterval(function () {

    var humidity = matrix.humidity.read();

    console.log(humidity);

    console.log(greenHouse.timeleftlvl1);

    console.log(greenHouse.timeleftlvl2);


    console.log(greenHouse.plantsOnLevel1);


    console.log(greenHouse.lvl1Water);

    console.log(greenHouse.lvl2Water);


    console.log(previousHumidity);


    console.log(previousTemperature);

    if (methods.findAverageWaterCycle(greenHouse.plantsOnLevel1) != greenHouse.lvl1Water) {

        greenHouse.lvl1Water = methods.findAverageWaterCycle(greenHouse.plantsOnLevel1);

    }
    currentHumidity = humidity;

    previousHumidity.push(currentHumidity.humidity);

    previousTemperature.push(currentHumidity.temperature);

    fs.appendFileSync('data.txt', "time is : " + String(currentTime++) + "\n");

    fs.appendFileSync('data.txt', "temperature is : " + String(humidity.temperature) + "\n");

    fs.appendFileSync('data.txt', "humidity is : " + String(humidity.humidity) + "\n")

    if (!inuse) {
        if (iswatered) {

            matrix.gpio.setServoAngle({
                pin: servopin1,
                angle: 0,
                min_pulse_ms: 0.1
            });

            matrix.gpio.setServoAngle({
                pin: servopin2,
                angle: 0,
                min_pulse_ms: 0.1
            });

            greenHouse.timeleftlvl1 = methods.timetohours(greenHouse.lvl1Water + 5 * Math.random() - 5 * Math.random());

            iswatered = false;

            methods.sleep(10);
        }
        else {

            matrix.gpio.setServoAngle({
                pin: servopin1,
                angle: 180,
                min_pulse_ms: 0.1
            });

            matrix.gpio.setServoAngle({
                pin: servopin2,
                angle: 180,
                min_pulse_ms: 0.1
            });

        }

    }

}, 1000);


setInterval(function () {

    if (toggle) matrix.led.set({ b: Math.sin(0.2 * counter) * 100 + 100 });

    else matrix.led.set({});


    counter++;
}, 50);

module.exports = methods;

assistant.js

JavaScript
/////////////
//VARIABLES//
/////////////
var mqtt = require('mqtt');
var client = mqtt.connect('mqtt://localhost', { port: 1883 });
var servo = require('./servo.js');
var snipsUsername = 'alexisCruz';
var wakeword = 'hermes/hotword/default/detected';
var sessionEnd = 'hermes/dialogueManager/sessionEnded';
var gardenControl = 'hermes/intent/' + snipsUsername + ':WaterTheGarden';

//snips method to respond
client.snipsRespond = function (payload) {
        client.publish(
                'hermes/dialogueManager/endSession',
                JSON.stringify({
                        sessionId: payload.sessionId,
                        text: payload.text
                })
        );

};

//////////////
//ON CONNECT//
//////////////
client.on('connect', function () {
        console.log('Connected to snips mqtt server\n');
        client.subscribe(wakeword);
        client.subscribe(sessionEnd);
        client.subscribe(gardenControl);
});

// when receiving a message
client.on('message', function (topic, message) {
        var message = JSON.parse(message);
        switch (topic) {
                // * On Wakeword
                case wakeword:
                        servo.startWaiting();
                        console.log('Wakeword Detected');
                        break;
                // * On gardenControl call
                case gardenControl:
                        try {
                                //tell the average of a certain data type
                                if (message.slots[0].value.value === 'get' && message.slots[1].value.value === 'average') {
                                        //get average temperature
                                        if (message.slots[2].value.value === 'temperature') {
                                                client.snipsRespond({
                                                        sessionId: message.sessionId,
                                                        text: String(Math.round(servo.tellTemperature(true) * 100) / 100) + " degrees celsius"
                                                });
                                        }
                                        //get average humidity 
                                        else if (message.slots[2].value.value === 'humidity') {
                                                client.snipsRespond({
                                                        sessionId: message.sessionId,
                                                        text: String(Math.round(servo.tellHumidity(true) * 100) / 100) + " grams of water per cubic meter"
                                                });
                                        }

                                        servo.clearData();
                                        servo.stopWaiting();
                                }
                                //get the current temperature
                                else if (message.slots[0].value.value === 'get' && message.slots[1].value.value === 'temperature') {
                                        client.snipsRespond({
                                                sessionId: message.sessionId,
                                                text: String(Math.round(servo.tellTemperature(false) * 100) / 100) + " degrees celsius"
                                        });
                                        servo.clearData();
                                        servo.stopWaiting();
                                }
                                //get the current humidity
                                else if (message.slots[0].value.value === 'get' && message.slots[1].value.value === 'humidity') {
                                        client.snipsRespond({
                                                sessionId: message.sessionId,
                                                text: String(Math.round(servo.tellHumidity(false) * 100) / 100) + " percent"
                                        });

                                        servo.clearData();
                                        servo.stopWaiting();
                                }
                                //water the plants
                                else if (message.slots[0].value.value === 'water') {
                                        servo.water();
                                } 
                                //name the current plants
                                else if (message.slots[0].slotName === 'currentPlants') {
                                        client.snipsRespond({
                                                sessionId: message.sessionId,
                                                text: String(servo.getPlants())
                                        });
                                } 
                                //add a new plant
                                else if (message.slots[0].value.value === 'add' && message.slots[1].slotName === 'plantTypes') {
                                        servo.addPlant(message.slots[1].value.value);
                                        client.snipsRespond({
                                                sessionId: message.sessionId,
                                                text: String(message.slots[1].value.value) + " was added to your collection"
                                        });

                                }
                                //remove a plant
                                else if (message.slots[0].value.value === 'remove' && message.slots[1].slotName === 'plantTypes') {
                                        servo.removePlant(message.slots[1].value.value);
                                        client.snipsRespond({
                                                sessionId: message.sessionId,
                                                text: String(message.slots[1].value.value) + " was removed from your collection"
                                        });
                                }
                                
                                else {
                                        servo.stopWaiting();
                                }
                        } catch (e) {
                                // Expect error if nothing is understood
                                console.log(e);
                        }
                        break;
                // * On Conversation End
                case sessionEnd:
                        servo.stopWaiting();
                        console.log('session ended\n');
                        break;
        }
});

Credits

alexis Cruz

alexis Cruz

8 projects • 12 followers

Comments