diff --git a/docs/images/wfs.jpg b/docs/images/wfs.jpg new file mode 100755 index 00000000..557830ba Binary files /dev/null and b/docs/images/wfs.jpg differ diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index 93441dbe..85b40b85 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -212,6 +212,7 @@ add_example (zfm20) add_example (zfm20-register) add_example (uln200xa) add_example (grovewfs) +add_example (wfs) add_example (isd1820) add_example (sx6119) add_example (si114x) diff --git a/examples/c++/wfs.cxx b/examples/c++/wfs.cxx new file mode 100644 index 00000000..24bb97f5 --- /dev/null +++ b/examples/c++/wfs.cxx @@ -0,0 +1,78 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2014 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "wfs.hpp" + +using namespace std; + +int shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + + +int main() +{ + signal(SIGINT, sig_handler); + +//! [Interesting] + // Instantiate a Water Flow Sensor on digital pin D2 + upm::WFS* flow = new upm::WFS(2); + + // set the flow counter to 0 and start counting + flow->clearFlowCounter(); + flow->startFlowCounter(); + + while (shouldRun) + { + // we grab these (,illis and flowCount) just for display + // purposes in this example + uint32_t millis = flow->getMillis(); + uint32_t flowCount = flow->flowCounter(); + + float fr = flow->flowRate(); + + // output milliseconds passed, flow count, and computed flow rate + cout << "Millis: " << millis << " Flow Count: " << flowCount; + cout << " Flow Rate: " << fr << " LPM" << endl; + + // best to gather data for at least one second for reasonable + // results. + sleep(2); + } + + flow->stopFlowCounter(); +//! [Interesting] + + cout << "Exiting..." << endl; + + delete flow; + return 0; +} diff --git a/examples/java/CMakeLists.txt b/examples/java/CMakeLists.txt index 5dbf2905..ddcf73af 100644 --- a/examples/java/CMakeLists.txt +++ b/examples/java/CMakeLists.txt @@ -72,6 +72,7 @@ add_example(GroveVDivSample grovevdiv) add_example(WaterSample water) add_example(GroveWaterSample grovewater) add_example(GroveWFSSample grovewfs) +add_example(WFSSample wfs) add_example(GUVAS12DSample guvas12d) add_example(H3LIS331DLSample h3lis331dl) add_example(HCSR04Sample hcsr04) diff --git a/examples/java/WFSSample.java b/examples/java/WFSSample.java new file mode 100644 index 00000000..c0c0a14a --- /dev/null +++ b/examples/java/WFSSample.java @@ -0,0 +1,44 @@ +/* + * Author: Stefan Andritoiu + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +//NOT TESTED!!! +public class WFSSample { + + public static void main(String[] args) throws InterruptedException { + // ! [Interesting] + // Instantiate a Water Flow Sensor on digital pin D2 + upm_wfs.WFS flow = new upm_wfs.WFS(2); + + flow.clearFlowCounter(); + flow.startFlowCounter(); + + while (true) { + System.out.print("Millis: " + flow.getMillis() + " FlowCount: " + flow.flowCounter()); + System.out.println(" Flow Rate: " + flow.flowRate() + " LPM"); + + Thread.sleep(2000); + } + // ! [Interesting] + } +} diff --git a/examples/javascript/wfs.js b/examples/javascript/wfs.js new file mode 100644 index 00000000..f24481d9 --- /dev/null +++ b/examples/javascript/wfs.js @@ -0,0 +1,66 @@ +/* +* Author: Zion Orent +* Copyright (c) 2015 Intel Corporation. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +var waterFlow_lib = require('jsupm_wfs'); + +// Instantiate a Grove Water Flow Sensor on digital pin D2 +var myWaterFlow_obj = new waterFlow_lib.WFS(2); + +// set the flow counter to 0 and start counting +myWaterFlow_obj.clearFlowCounter(); +myWaterFlow_obj.startFlowCounter(); + + +var millis, flowCount, fr; +var myInterval = setInterval(function() +{ + // we grab these (millis and flowCount) just for display + // purposes in this example + millis = myWaterFlow_obj.getMillis(); + flowCount = myWaterFlow_obj.flowCounter(); + + fr = myWaterFlow_obj.flowRate(); + + // output milliseconds passed, flow count, and computed flow rate + outputStr = "Millis: " + millis + " Flow Count: " + flowCount + + " Flow Rate: " + fr + " LPM"; + console.log(outputStr); + + // best to gather data for at least one second for reasonable + // results. +}, 2000); + + +// When exiting: clear interval and print message +process.on('SIGINT', function() +{ + clearInterval(myInterval); + myWaterFlow_obj.stopFlowCounter(); + myWaterFlow_obj = null + waterFlow_lib.cleanUp(); + waterFlow_lib = null; + + console.log("Exiting"); + process.exit(0); +}); diff --git a/examples/python/wfs.py b/examples/python/wfs.py new file mode 100644 index 00000000..ce7f70af --- /dev/null +++ b/examples/python/wfs.py @@ -0,0 +1,64 @@ +#!/usr/bin/python +# Author: Zion Orent +# Copyright (c) 2015 Intel Corporation. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import time, sys, signal, atexit +import pyupm_wfs as upmwfs + +# Instantiate a Water Flow Sensor on digital pin D2 +myWaterFlow = upmwfs.WFS(2) + + +## Exit handlers ## +# This stops python from printing a stacktrace when you hit control-C +def SIGINTHandler(signum, frame): + raise SystemExit + +# This function lets you run code on exit, +# including functions from myWaterFlow +def exitHandler(): + myWaterFlow.stopFlowCounter() + print "Exiting" + sys.exit(0) + +# Register exit handlers +atexit.register(exitHandler) +signal.signal(signal.SIGINT, SIGINTHandler) + + +# set the flow counter to 0 and start counting +myWaterFlow.clearFlowCounter() +myWaterFlow.startFlowCounter() + +while (1): + # we grab these (millis and flowCount) just for display + # purposes in this example + millis = myWaterFlow.getMillis() + flowCount = myWaterFlow.flowCounter() + + fr = myWaterFlow.flowRate() + + # output milliseconds passed, flow count, and computed flow rate + outputStr = "Millis: {0} Flow Count: {1} Flow Rate: {2} LPM".format( + millis, flowCount, fr) + print outputStr + time.sleep(2) diff --git a/src/wfs/CMakeLists.txt b/src/wfs/CMakeLists.txt new file mode 100644 index 00000000..ce50d56a --- /dev/null +++ b/src/wfs/CMakeLists.txt @@ -0,0 +1,5 @@ +upm_mixed_module_init (NAME wfs + DESCRIPTION "UPM WFS Module" + CPP_HDR wfs.hpp + CPP_SRC wfs.cxx + REQUIRES mraa) diff --git a/src/wfs/javaupm_wfs.i b/src/wfs/javaupm_wfs.i new file mode 100644 index 00000000..35f7ee08 --- /dev/null +++ b/src/wfs/javaupm_wfs.i @@ -0,0 +1,21 @@ +%module javaupm_wfs +%include "../upm.i" + +%ignore flowISR; + +%{ + #include "wfs.hpp" +%} + +%include "wfs.hpp" + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_wfs"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. \n" + e); + System.exit(1); + } + } +%} diff --git a/src/wfs/jsupm_wfs.i b/src/wfs/jsupm_wfs.i new file mode 100644 index 00000000..52cbaf23 --- /dev/null +++ b/src/wfs/jsupm_wfs.i @@ -0,0 +1,8 @@ +%module jsupm_wfs +%include "../upm.i" + +%{ + #include "wfs.hpp" +%} + +%include "wfs.hpp" diff --git a/src/wfs/pyupm_wfs.i b/src/wfs/pyupm_wfs.i new file mode 100644 index 00000000..b722c47c --- /dev/null +++ b/src/wfs/pyupm_wfs.i @@ -0,0 +1,11 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_wfs +%include "../upm.i" + +%feature("autodoc", "3"); + +%include "wfs.hpp" +%{ + #include "wfs.hpp" +%} diff --git a/src/wfs/wfs.cxx b/src/wfs/wfs.cxx new file mode 100644 index 00000000..98ea4a6d --- /dev/null +++ b/src/wfs/wfs.cxx @@ -0,0 +1,124 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include "wfs.hpp" + +using namespace upm; +using namespace std; + +WFS::WFS(int pin) +{ + if ( !(m_gpio = mraa_gpio_init(pin)) ) + { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_gpio_init() failed, invalid pin?"); + return; + } + + mraa_gpio_dir(m_gpio, MRAA_GPIO_IN); + + initClock(); + m_flowCounter = 0; + m_isrInstalled = false; +} + +WFS::~WFS() +{ + if (m_isrInstalled) + stopFlowCounter(); + + mraa_gpio_close(m_gpio); +} + +void WFS::initClock() +{ + gettimeofday(&m_startTime, NULL); +} + +uint32_t WFS::getMillis() +{ + struct timeval elapsed, now; + uint32_t elapse; + + // get current time + gettimeofday(&now, NULL); + + // compute the delta since m_startTime + if( (elapsed.tv_usec = now.tv_usec - m_startTime.tv_usec) < 0 ) + { + elapsed.tv_usec += 1000000; + elapsed.tv_sec = now.tv_sec - m_startTime.tv_sec - 1; + } + else + { + elapsed.tv_sec = now.tv_sec - m_startTime.tv_sec; + } + + elapse = (uint32_t)((elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000)); + + // never return 0 + if (elapse == 0) + elapse = 1; + + return elapse; +} + +void WFS::startFlowCounter() +{ + initClock(); + // install our interrupt handler + mraa_gpio_isr(m_gpio, MRAA_GPIO_EDGE_RISING, + &flowISR, this); + + m_isrInstalled = true; +} + +void WFS::stopFlowCounter() +{ + // remove the interrupt handler + mraa_gpio_isr_exit(m_gpio); + + m_isrInstalled = false; +} + +void WFS::flowISR(void *ctx) +{ + upm::WFS *This = (upm::WFS *)ctx; + This->m_flowCounter++; +} + +float WFS::flowRate() +{ + uint32_t millis = getMillis(); + uint32_t flow = flowCounter(); + + // 7.5 comes from the seeedstudio page, see the confusing datasheet :) + float flowRate = (float(flow) * 7.5) / ((float(millis) / 1000.0) * 60.0); + + return flowRate; +} diff --git a/src/wfs/wfs.hpp b/src/wfs/wfs.hpp new file mode 100644 index 00000000..2cd20795 --- /dev/null +++ b/src/wfs/wfs.hpp @@ -0,0 +1,140 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#include +#include +#include +#include + +namespace upm { + + /** + * @brief Grove Water Flow Sensor library + * @defgroup wfs libupm-wfs + * @ingroup seeed gpio liquid eak + */ + + /** + * @library wfs + * @sensor wfs + * @comname Grove Water Flow Sensor + * @type liquid + * @man seeed + * @web http://www.seeedstudio.com/wiki/index.php?title=G1/2_Water_Flow_sensor + * @con gpio + * @kit eak + + * @brief API for the Grove Water Flow Sensor + * + * This sensor is used to measure water flow in liters per + * minute (LPM). It incorporates a Hall Effect sensor. The UPM module + * defines an interrupt routine to be triggered on each low pulse, + * keeping count. This device requires a 10K pull-up resistor for + * the signal line (yellow wire). There is a schematic diagram on + * the SeeedStudio site (3/2015): + * http://www.seeedstudio.com/wiki/index.php?title=G1/2_Water_Flow_sensor + * + * However, be careful when wiring this up - the schematic appears to + * have a bug in it: the lower left connection of the signal line + * (yellow) to Vcc (red) should not be there. The sensor can work + * with this connection, but probably not for very long. + * + * @image html wfs.jpg + * @snippet wfs.cxx Interesting + */ + class WFS { + public: + /** + * Grove Water Flow sensor constructor + * + * @param pin Digital pin to use + */ + WFS(int pin); + /** + * WFS destructor + */ + ~WFS(); + /** + * Returns the number of milliseconds elapsed since initClock() + * was last called. + * + * @return Elapsed milliseconds + */ + uint32_t getMillis(); + + /** + * Resets the clock + * + */ + void initClock(); + + /** + * Resets the flow counter to 0. The flow counter should be + * stopped via stopFlowCounter() prior to calling this function. + * + */ + void clearFlowCounter() { m_flowCounter = 0; }; + + /** + * Starts the flow counter + * + */ + void startFlowCounter(); + + /** + * Stops the flow counter + * + */ + void stopFlowCounter(); + + /** + * Gets the flow counter + * + * @return Flow counter + */ + uint32_t flowCounter() { return m_flowCounter; }; + + /** + * Computes the flow rate in liters per minute (LPM) + * + * @return Computed flow rate + */ + float flowRate(); + + private: + /** + * Flow interrupt service routine (ISR) + * + */ + static void flowISR(void *ctx); + + volatile uint32_t m_flowCounter; + struct timeval m_startTime; + mraa_gpio_context m_gpio; + bool m_isrInstalled; + }; +} + +