diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index d12ca22c..80012334 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -112,6 +112,7 @@ add_executable (tm1637-example tm1637.cxx) add_executable (zfm20-example zfm20.cxx) add_executable (zfm20-register-example zfm20-register.cxx) add_executable (uln200xa-example uln200xa.cxx) +add_executable (grovewfs-example grovewfs.cxx) include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l) include_directories (${PROJECT_SOURCE_DIR}/src/grove) @@ -202,6 +203,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/waterlevel) include_directories (${PROJECT_SOURCE_DIR}/src/tm1637) include_directories (${PROJECT_SOURCE_DIR}/src/zfm20) include_directories (${PROJECT_SOURCE_DIR}/src/uln200xa) +include_directories (${PROJECT_SOURCE_DIR}/src/grovewfs) target_link_libraries (hmc5883l-example hmc5883l ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (groveled-example grove ${CMAKE_THREAD_LIBS_INIT}) @@ -315,3 +317,4 @@ target_link_libraries (tm1637-example tm1637 ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (zfm20-example zfm20 ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (zfm20-register-example zfm20 ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (uln200xa-example uln200xa ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries (grovewfs-example grovewfs ${CMAKE_THREAD_LIBS_INIT}) diff --git a/examples/c++/grovewfs.cxx b/examples/c++/grovewfs.cxx new file mode 100644 index 00000000..ea819ae7 --- /dev/null +++ b/examples/c++/grovewfs.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 "grovewfs.h" + +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 Grove Water Flow Sensor on digital pin D2 + upm::GroveWFS* flow = new upm::GroveWFS(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/javascript/grovewfs.js b/examples/javascript/grovewfs.js new file mode 100644 index 00000000..daa232c6 --- /dev/null +++ b/examples/javascript/grovewfs.js @@ -0,0 +1,69 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ + +/* +* 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_grovewfs'); + +// Instantiate a Grove Water Flow Sensor on digital pin D2 +var myWaterFlow_obj = new waterFlow_lib.GroveWFS(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/grovewfs.py b/examples/python/grovewfs.py new file mode 100644 index 00000000..84c5a979 --- /dev/null +++ b/examples/python/grovewfs.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_grovewfs as upmGrovewfs + +# Instantiate a Grove Water Flow Sensor on digital pin D2 +myWaterFlow = upmGrovewfs.GroveWFS(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/grovewfs/CMakeLists.txt b/src/grovewfs/CMakeLists.txt new file mode 100644 index 00000000..826a32e5 --- /dev/null +++ b/src/grovewfs/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "grovewfs") +set (libdescription "upm grove water flow sensor module") +set (module_src ${libname}.cxx) +set (module_h ${libname}.h) +upm_module_init() diff --git a/src/grovewfs/grovewfs.cxx b/src/grovewfs/grovewfs.cxx new file mode 100644 index 00000000..69e63eb0 --- /dev/null +++ b/src/grovewfs/grovewfs.cxx @@ -0,0 +1,121 @@ +/* + * 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 "grovewfs.h" + +using namespace upm; +using namespace std; + +GroveWFS::GroveWFS(int pin) +{ + if ( !(m_gpio = mraa_gpio_init(pin)) ) + { + cerr << __FUNCTION__ << ": mraa_gpio_init() failed" << endl; + return; + } + + mraa_gpio_dir(m_gpio, MRAA_GPIO_IN); + + initClock(); + m_flowCounter = 0; + m_isrInstalled = false; +} + +GroveWFS::~GroveWFS() +{ + if (m_isrInstalled) + stopFlowCounter(); + + mraa_gpio_close(m_gpio); +} + +void GroveWFS::initClock() +{ + gettimeofday(&m_startTime, NULL); +} + +uint32_t GroveWFS::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 GroveWFS::startFlowCounter() +{ + initClock(); + // install our interrupt handler + mraa_gpio_isr(m_gpio, MRAA_GPIO_EDGE_RISING, + &flowISR, this); + + m_isrInstalled = true; +} + +void GroveWFS::stopFlowCounter() +{ + // remove the interrupt handler + mraa_gpio_isr_exit(m_gpio); + + m_isrInstalled = false; +} + +void GroveWFS::flowISR(void *ctx) +{ + upm::GroveWFS *This = (upm::GroveWFS *)ctx; + This->m_flowCounter++; +} + +float GroveWFS::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/grovewfs/grovewfs.h b/src/grovewfs/grovewfs.h new file mode 100644 index 00000000..95dd2f16 --- /dev/null +++ b/src/grovewfs/grovewfs.h @@ -0,0 +1,137 @@ +/* + * 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 UPM module for the Grove Water Flow sensor + * @defgroup grovewfs libupm-grovewfs + * @ingroup seeed gpio liquid + */ + + /** + * @sensor grovewfs + * @comname Grove Water Flow Sensor + * @type liquid + * @man seeed + * @con gpio + + * @brief C++ API for the Grove Water Flow Sensor + * + * This sensor is used to measure water flow, in LPM (Liters Per + * Minute). 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 pullup 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 in 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 may work + * with this connection, but probably not for very long. + * + * + * @snippet grovewfs.cxx Interesting + */ + class GroveWFS { + public: + /** + * GroveWFS constructor + * + * @param pin digital pin to use + */ + GroveWFS(int pin); + /** + * GroveWFS Destructor + */ + ~GroveWFS(); + /** + * Return the number of milliseconds elapsed since initClock() + * was last called. + * + * @return elapsed milliseconds + */ + uint32_t getMillis(); + + /** + * Reset the Clock + * + */ + void initClock(); + + /** + * Reset the flow counter to 0. The flow Counter should be + * stopped via stopFlowCounter() prior to calling this function. + * + */ + void clearFlowCounter() { m_flowCounter = 0; }; + + /** + * Start the flow counter + * + */ + void startFlowCounter(); + + /** + * Stop the flow counter + * + */ + void stopFlowCounter(); + + /** + * Get the flow Counter + * + * @return the flow counter + */ + uint32_t flowCounter() { return m_flowCounter; }; + + /** + * Flow Interrupt Service Routine + * + */ + static void flowISR(void *ctx); + + /** + * Compute the flow rate in liters per minute (LPM) + * + * @return the computed flow rate + */ + float flowRate(); + + private: + volatile uint32_t m_flowCounter; + struct timeval m_startTime; + mraa_gpio_context m_gpio; + bool m_isrInstalled; + }; +} + + diff --git a/src/grovewfs/jsupm_grovewfs.i b/src/grovewfs/jsupm_grovewfs.i new file mode 100644 index 00000000..d85d64de --- /dev/null +++ b/src/grovewfs/jsupm_grovewfs.i @@ -0,0 +1,8 @@ +%module jsupm_grovewfs +%include "../upm.i" + +%{ + #include "grovewfs.h" +%} + +%include "grovewfs.h" diff --git a/src/grovewfs/pyupm_grovewfs.i b/src/grovewfs/pyupm_grovewfs.i new file mode 100644 index 00000000..7e90d450 --- /dev/null +++ b/src/grovewfs/pyupm_grovewfs.i @@ -0,0 +1,9 @@ +%module pyupm_grovewfs +%include "../upm.i" + +%feature("autodoc", "3"); + +%include "grovewfs.h" +%{ + #include "grovewfs.h" +%}