Creating a IoT enabled Hydroponics Controller using the Intel Edison during the Boston
Our Goal:
Within a 36 hour
What's Inside the Grove Starter Kit Plus - Intel®
Additional Sensors/Parts
We wanted to implement the base functionality to add automation to our previous instructable (Vertical Hydroponic Farm) which would include;
We utilized Intel's XDK
The software can be found
function setSecondsTimer(waitTime)<br>{<br> var endTime;<br> var d = new Date();<br><br> endTime = d.getTime() + (waitTime * 1000); // convert back to milliseconds from seconds<br> return endTime;<br> <br>} // setSecondsTimer<br><br>function setMinutesTimer(waitTime)<br>{<br> var endTime = 0;<br> var d = new Date();<br><br> endTime = d.getTime() + (waitTime * 60000); // convert back to milliseconds from minutes<br> return endTime;<br> <br>} // setMinutesTimer<br><br>function checkTimer(timer) {<br> var d = new Date();<br>// console.log('current time ' + d.getTime() + ' timer =' + timer);<br> if (d.getTime() > timer) {return true;} <br> else {return false;}<br><br>} // checkTimer<br><br><br>// Main Routine<br>function periodicActivity()<br>{<br> if (checkTimer(weatherTimer)) {getWeather(); weatherTimer = setMinutesTimer(240);} // every 4 hours<br> growLights();<br> tempControl();<br> checkECDoser();<br> waterEC();<br> if (checkTimer(waterLeverTimer)) {waterCirculation(); waterLeverTimer = setSecondsTimer(1);}<br> if (checkTimer(lcdDisplayTimer)) {lcdDisplay(); lcdDisplayTimer = setSecondsTimer(1);}<br> if (checkTimer(logTimer)) {sendToCloud(); logTimer = setMinutesTimer(1);}<br> setTimeout(periodicActivity,500); //call the indicated function after 1 second (1000 milliseconds)<br>}<br><br><br>
// #EC Sensor <br><br>var ecSensor = new mraa.Aio(1);<br>var EC_reading = 0;<br>var ecDoser = new mraa.Gpio(6); <br>ecDoser.dir(mraa.DIR_OUT); //set the gpio direction to output<br>var ecDoserState = 0;<br>var ecDoserTimer = 0;<br>var ecDoserActivate = false;<br>var ecSampleTimer = 0;<br>var EC_DOSER_INTERVAL = 2; // seconds to run doser<br>var EC_SAMPLE_INTERVAL = 1; // minutes to wait before using EC reading to determine to dose<br>var EC_LIMIT = 1500; // dose when below this value minus EC_Band until it reaches this level<br>var EC_BAND = 200;<br>var EC_MS = 0; // EC micro/S<br><br><br>function waterEC() //Read Water ED<br>{<br> EC_reading = ecSensor.read(); // read the analog input voltage<br> // 0 to 1024 = 0 to 5v<br> // 204 micro/S per volt<br> EC_MS = (EC_reading * 4.88).toFixed(); // 5000 micro/S / 1024 = 4.88<br> if (EC_MS < (EC_LIMIT - EC_BAND)) { // outside of acceptible range<br> if (checkTimer(ecSampleTimer)) { // time to re-dose<br> ecSampleTimer = 0;<br> // console.log('--ecDoserState ' + ecDoserState);<br> if (ecDoserState != 1) { // if doser not ON then turn it ON<br> ecDoserActivate = true; <br> ecSampleTimer = setMinutesTimer(EC_SAMPLE_INTERVAL); // reset time until next sample - dose<br> console.log('dose for EC');<br> }<br> }<br>// console.log('lower than ' + (EC_LIMIT - EC_BAND));<br> }<br>// console.log('ecSampleTimer ' + ecSampleTimer);<br>// console.log('EC = ' + EC_MS);<br><br>} // waterEC()<br><br>function checkECDoser()<br>{ <br> if (ecDoserState == 0 && ecDoserActivate == true) // if not already on and needs to be on<br> {<br> ecDoserTimer = setSecondsTimer(EC_DOSER_INTERVAL); <br> ecDoserState = 1;<br> ecDoser.write(ecDoserState); <br> console.log('EC Doser is ' + ecDoserState + ' for ' + EC_DOSER_INTERVAL + ' seconds');<br> }<br> if (checkTimer(ecDoserTimer)) { // timer went off<br> ecDoserActivate = false;<br> ecDoserState = 0; // turn doser off <br> ecDoser.write(ecDoserState); <br>// console.log('EC Doser Timer Fired');<br> }<br>// console.log('ecDoserTimer ' + ecDoserTimer);<br>} // checkECDoser<br>
// Temperature<br>var tempSensor = new groveSensor.GroveTemp(3);<br>var tempBase = 23; // goal temperature<br>var tempTheshold = 25; // try to cool down<br>var tempAlarm = 27; // too hot sound alarm<br>var louverOpened = 160;<br>var louverClosed = 0;<br>var tempValue = 0;<br><br>function tempControl()<br>{<br> // when temp to high; turn on fans, open louvers<br> // if temp above theshold, stay on until lowered to base temp<br> // turn on buzzer at alarm temp<br> tempValue = tempSensor.value();<br>// console.log('temp is=' + tempValue);<br> if (tempValue > tempTheshold) {<br> fanCoolingState = 1;<br> servo.setAngle(louverOpened);<br> // console.log('temp hot');<br> } else if (tempValue <= tempBase) {<br> fanCoolingState = 0;<br> servo.setAngle(louverClosed);<br> // console.log('temp normal');<br> }<br> fanCooling.write(fanCoolingState);<br> <br> <br> if (tempValue >= tempAlarm) {<br> alarmState = alarmState ? 0:1;<br> alarm.write(alarmState);<br> } else {<br> alarm.write(0);<br> alarmState = 0;<br> }<br> // console.log('alarm is=' + alarmState);<br><br>} // tempControl()<br>
var waterSensor = require('jsupm_grovewater');<br>var waterLevel = new waterSensor.GroveWater(2);<br>var waterLeverTimer = 0;<br>var waterLevelValue = 0;<br>
var digitalLightSensor = require("jsupm_tsl2561");<br>var lightSensor = new digitalLightSensor.TSL2561();<br>var lightLevel = 0;<br>var lightLowCnt = 0;<br>var lightTimeRemaining = 960; // minutes in 16 hours<br>var lightDay = 1440; // minutes in 24 hour day<br>var lightsState = 0;<br>
var circulationPump = new mraa.Gpio(4); <br>circulationPump.dir(mraa.DIR_OUT); //set the gpio direction to output<br>var circulationPumpState = 0;<br>var circulationPumpTimer = 0;<br>var CIRCULATION_PUMP_TIME_ON = 1; // pump time on<br>var CIRCULATION_PUMP_TIME_OFF = 1; // pump time off<br><br><br>function waterCirculation()<br>{<br> waterLevelValue = waterLevel.isWet();<br> if (waterLevelValue == true)<br> {<br> if (checkTimer(circulationPumpTimer)) {<br> if (circulationPumpState == 1) {<br> circulationPumpState = 0;<br> circulationPumpTimer = setMinutesTimer(CIRCULATION_PUMP_TIME_OFF);<br> } else {<br> circulationPumpState = 1;<br> circulationPumpTimer = setMinutesTimer(CIRCULATION_PUMP_TIME_ON);<br> }<br> circulationPump.write(circulationPumpState);<br> }<br> } else {<br> console.log('low water');<br> circulationPumpTimer = 0;<br> circulationPumpState = 0;<br> circulationPump.write(circulationPumpState);<br> }<br>// console.log('pump = ' + circulationPumpState);<br><br>} // waterCirculation<br>
//Instantiate Servo module on digital port 5<br>var servo = new servoModule.Servo(5);<br>servo.setMinPulseWidth(600);<br>servo.setMaxPulseWidth(2200);<br>
var fanCooling = new mraa.Gpio(7); <br>fanCooling.dir(mraa.DIR_OUT); //set the gpio direction to output<br>var fanCoolingState = 0;<br>
function tempControl()<br>{<br> // when temp to high; turn on fans, open louvers<br> // if temp above theshold, stay on until lowered to base temp<br> // turn on buzzer at alarm temp<br> tempValue = tempSensor.value();<br>// console.log('temp is=' + tempValue);<br> if (tempValue > tempTheshold) {<br> fanCoolingState = 1;<br> servo.setAngle(louverOpened);<br> // console.log('temp hot');<br> } else if (tempValue <= tempBase) {<br> fanCoolingState = 0;<br> servo.setAngle(louverClosed);<br> // console.log('temp normal');<br> }<br> fanCooling.write(fanCoolingState);<br> <br> <br> if (tempValue >= tempAlarm) {<br> alarmState = alarmState ? 0:1;<br> alarm.write(alarmState);<br> } else {<br> alarm.write(0);<br> alarmState = 0;<br> }<br> // console.log('alarm is=' + alarmState);<br><br>} // tempControl()<br><br>
function growLights() // called every minute<br>{ <br> lightLevel = lightSensor.getLux();<br> if (lightLevel < 100 && lightTimeRemaining > 0) {<br> if (lightLowCnt < 2) {lightLowCnt++;} else {lightsState = 1; lightLowCnt = 0;}<br> } else {<br> lightsState = 0;<br> lightLowCnt = 0;<br> }<br> lights.write(lightsState);<br> lightTimeRemaining--; <br> lightDay--;<br> if (lightDay < 1) {lightDay = 1440; lightRemaining = 640;} // new day 24 hr day with 16 hours of light<br> if (lightLowCnt > 0) console.log('lightLow: ' + lightLowCnt); <br> console.log('LightLevel: ' + lightLevel);<br>} // end growLights<br>
function lcdDisplay()<br>{<br> var lums = 0;<br> myLcd.clear();<br> myLcd.setCursor(0,0);<br> myLcd.write('Cond: ' + localWeather);<br> <br> myLcd.setCursor(1,0);<br> myLcd.write('EC:' + EC_MS);<br> <br> myLcd.setCursor(1,8);<br> if (lightLevel < 100) {lums = 'L';} else if (lightLevel < 130) {lums = 'M';} else {lums = 'H';}<br> myLcd.write('L:' + lums);<br> <br> myLcd.setCursor(1,12); <br> myLcd.write('T:' + tempSensor.value());<br>} // lcdDisplay<br><br>
// Define your sensors for cloud publish<br>var data = [{<br> sensorName :"light",<br> sensorType:"light.v1.0"<br>},{<br> sensorName :"temperature", // air temp<br> sensorType:"temperature.v1.0"<br>}];<br><br>//Run Once to Init/Register sensors<br>data.forEach(function(item) {<br> registerNewSensor(item.sensorName, item.sensorType, function () { <br> });<br>});<br><br><br><br>function registerNewSensor(name, type, callback){<br> var msg = JSON.stringify({<br> n: name,<br> t: type<br> });<br><br> var sentMsg = new Buffer(msg);<br> console.log("Registering sensor:"+ sentMsg);<br> client.send(sentMsg, 0, sentMsg.length, options.port, options.host, callback);<br>};<br><br><br>function sendObservation(name, value, on){<br> var msg = JSON.stringify({<br> n: name,<br> v: value,<br> on: on<br> });<br><br> var sentMsg = new Buffer(msg);<br> console.log("Sending observation:"+ sentMsg);<br> client.send(sentMsg, 0, sentMsg.length, options.port, options.host);<br> <br>};<br><br><br>function sendToCloud(){<br> sendObservation("light", lightLevel, new Date().getTime());<br> sendObservation("temperature", tempValue, new Date().getTime());<br>} //sendToCloud<br><br>
var localWeather = 'Waiting';<br>var url = 'http://api.wunderground.com/api/df5bd75178df2c09/conditions/q/MA/Boston.json';<br>var weatherTimer = 1; // wait 1 minute before first call<br><br>function getWeather()<br>{<br> request({<br> url: url,<br> json: false<br> }, function (error, response, body) {<br> if (!error && response.statusCode === 200) {<br>var weatherReport = response.body;<br>localWeather = weatherReport.substr(weatherReport.indexOf('"weather":"') + 11,10);<br> }<br> });<br>} // getWeather<br><br>
There are some great tutorials on getting set up on the dashboard here on
Once you get your account set up as described in the
Building Rules in Intel's IoT Analytics Dashboard
We are happy to announce we won 3rd place in the Intel IoT Hackathon - Boston!!!
A fun event and it was amazing to see all the great projects that came out of the event.