diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index e2606b30..6bd292d8 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -278,6 +278,7 @@ add_example (mma7361) add_example (bh1750) add_example (hka5) add_example (dfrorp) +add_example (dfrec) # These are special cases where you specify example binary, source file and module(s) include_directories (${PROJECT_SOURCE_DIR}/src) diff --git a/examples/c++/dfrec.cxx b/examples/c++/dfrec.cxx new file mode 100644 index 00000000..90b51c3f --- /dev/null +++ b/examples/c++/dfrec.cxx @@ -0,0 +1,81 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 "dfrec.hpp" + +using namespace std; + +bool shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + +int main() +{ + signal(SIGINT, sig_handler); + +//! [Interesting] + + // Instantiate a DFRobot EC sensor on analog pin A0, with a ds18b20 + // temperature sensor connected to UART 0, and a device index (for + // the ds1820b uart bus) of 0, and an analog reference voltage of + // 5.0. + upm::DFREC *sensor = new upm::DFREC(0, 0, 0, 5.0); + + // Every 2 seconds, update and print values + while (shouldRun) + { + sensor->update(); + + cout << "EC = " + << sensor->getEC() + << " ms/cm" + << endl; + + cout << "Volts = " + << sensor->getVolts() + << ", Temperature = " + << sensor->getTemperature() + << " C" + << endl; + + cout << endl; + + sleep(2); + } + +//! [Interesting] + + cout << "Exiting" << endl; + + delete sensor; + return 0; +} diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index 925a364a..13b6cfba 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -117,6 +117,7 @@ add_example (collision) add_example (moisture) add_example (led) add_example (ds18b20) +add_example (dfrec) # Custom examples add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps) diff --git a/examples/c/dfrec.c b/examples/c/dfrec.c new file mode 100644 index 00000000..7177fb63 --- /dev/null +++ b/examples/c/dfrec.c @@ -0,0 +1,76 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 "dfrec.h" + +bool shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + +int main() +{ + signal(SIGINT, sig_handler); + +//! [Interesting] + + // Instantiate a DFRobot EC sensor on analog pin A0, with a ds18b20 + // temperature sensor connected to UART 0, and a device index (for + // the ds1820b uart bus) of 0, and an analog reference voltage of + // 5.0. + dfrec_context sensor = dfrec_init(0, 0, 0, 5.0); + + if (!sensor) + { + printf("dfrec_init() failed.\n"); + return(1); + } + + // Every 2 seconds, update and print values + while (shouldRun) + { + dfrec_update(sensor); + + printf("EC = %f ms/cm\n", dfrec_get_ec(sensor)); + printf("Volts = %f, Temperature = %f C\n", + dfrec_get_volts(sensor), dfrec_get_temperature(sensor)); + printf("\n"); + + sleep(2); + } + +//! [Interesting] + + printf("Exiting...\n"); + + dfrec_close(sensor); + + return 0; +} diff --git a/examples/java/CMakeLists.txt b/examples/java/CMakeLists.txt index fafc6c6f..b54d471d 100644 --- a/examples/java/CMakeLists.txt +++ b/examples/java/CMakeLists.txt @@ -135,6 +135,7 @@ add_example(MMA7361_Example mma7361) add_example(BH1750_Example bh1750) add_example(HKA5_Example hka5) add_example(DFRORP_Example dfrorp) +add_example(DFREC_Example dfrec) add_example_with_path(Jhd1313m1_lcdSample lcd i2clcd) add_example_with_path(Jhd1313m1Sample lcd i2clcd) diff --git a/examples/java/DFREC_Example.java b/examples/java/DFREC_Example.java new file mode 100644 index 00000000..62092605 --- /dev/null +++ b/examples/java/DFREC_Example.java @@ -0,0 +1,59 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 upm_dfrec.DFREC; + +public class DFREC_Example +{ + public static void main(String[] args) throws InterruptedException + { +// ! [Interesting] + + // Instantiate a DFRobot EC sensor on analog pin A0, with a ds18b20 + // temperature sensor connected to UART 0, and a device index (for + // the ds1820b uart bus) of 0, and an analog reference voltage of + // 5.0. + DFREC sensor = new DFREC(0, 0, 0, 5.0f); + + // Every 2 seconds, update and print values + while (true) + { + sensor.update(); + + System.out.println("EC = " + + sensor.getEC() + + " ms/cm"); + System.out.println("Volts = " + + sensor.getVolts() + + ", Temperature = " + + sensor.getTemperature() + + " C"); + + System.out.println(); + Thread.sleep(2000); + } + +// ! [Interesting] + } +} diff --git a/examples/javascript/dfrec.js b/examples/javascript/dfrec.js new file mode 100644 index 00000000..cb2993fe --- /dev/null +++ b/examples/javascript/dfrec.js @@ -0,0 +1,59 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 sensorObj = require('jsupm_dfrec'); + +// Instantiate a DFRobot EC sensor on analog pin A0, with a ds18b20 +// temperature sensor connected to UART 0, and a device index (for +// the ds1820b uart bus) of 0, and an analog reference voltage of +// 5.0. +var sensor = new sensorObj.DFREC(0, 0, 0, 5.0); + +// Every 2 seconds, update and print values +setInterval(function() +{ + sensor.update(); + + console.log("EC = " + + sensor.getEC() + + " ms/cm"); + console.log("Volts = " + + sensor.getVolts() + + ", Temperature = " + + sensor.getTemperature() + + " C"); + + console.log(); + +}, 2000); + +// exit on ^C +process.on('SIGINT', function() +{ + sensor = null; + sensorObj.cleanUp(); + sensorObj = null; + console.log("Exiting."); + process.exit(0); +}); diff --git a/examples/python/dfrec.py b/examples/python/dfrec.py new file mode 100644 index 00000000..6b2d48d9 --- /dev/null +++ b/examples/python/dfrec.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +# Author: Jon Trulson +# Copyright (c) 2016 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_dfrec as sensorObj + +# Instantiate a DFRobot EC sensor on analog pin A0, with a ds18b20 +# temperature sensor connected to UART 0, and a device index (for +# the ds1820b uart bus) of 0, and an analog reference voltage of +# 5.0. +sensor = sensorObj.DFREC(0, 0, 0, 5.0) + +## Exit handlers ## +# This function 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 +def exitHandler(): + print "Exiting" + sys.exit(0) + +# Register exit handlers +atexit.register(exitHandler) +signal.signal(signal.SIGINT, SIGINTHandler) + +# Every 2 seconds, update and print values +while (True): + sensor.update() + + print "EC =", sensor.getEC(), "ms/cm" + print "Volts =", sensor.getVolts(), + print ", Temperature = ", sensor.getTemperature(), "C" + print + + time.sleep(2) diff --git a/include/fti/upm_ec.h b/include/fti/upm_ec.h new file mode 100644 index 00000000..1e0ae332 --- /dev/null +++ b/include/fti/upm_ec.h @@ -0,0 +1,48 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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. + */ +#ifndef UPM_EC_H_ +#define UPM_EC_H_ + +#include "upm_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* EC (Electrical Conductivity) function table */ +typedef struct _upm_ec_ft +{ + /* Set sensor offset */ + upm_result_t (*upm_ec_set_offset) (const void* dev, float offset); + /* Set sensor scale */ + upm_result_t (*upm_ec_set_scale) (const void* dev, float scale); + /* Read sensor value */ + upm_result_t (*upm_ec_get_value) (const void* dev, float *value); +} upm_ec_ft; + +#ifdef __cplusplus +} +#endif + +#endif /* UPM_EC_H_ */ diff --git a/include/upm_fti.h b/include/upm_fti.h index 25a74891..7ad42355 100644 --- a/include/upm_fti.h +++ b/include/upm_fti.h @@ -116,6 +116,7 @@ typedef struct _upm_sensor_ft* (*func_get_upm_sensor_ft)(upm_sensor_t sensor_typ #include #include #include +#include #ifdef __cplusplus } diff --git a/src/dfrec/CMakeLists.txt b/src/dfrec/CMakeLists.txt new file mode 100644 index 00000000..f7d8d11e --- /dev/null +++ b/src/dfrec/CMakeLists.txt @@ -0,0 +1,17 @@ +# we need includes from ds18b20 +include_directories("../ds18b20") + +upm_mixed_module_init (NAME dfrec + DESCRIPTION "upm dfrobot analog EC sensor" + C_HDR dfrec.h + C_SRC dfrec.c + CPP_HDR dfrec.hpp + CPP_SRC dfrec.cxx + FTI_SRC dfrec_fti.c + CPP_WRAPS_C + REQUIRES upmc-ds18b20 mraa) + +# make sure the C library has the appropriate dependency on the UPM +# DS18B20 C library +add_dependencies(${libnamec} ds18b20-c) +target_link_libraries(${libnamec} ds18b20-c) diff --git a/src/dfrec/dfrec.c b/src/dfrec/dfrec.c new file mode 100644 index 00000000..ff487614 --- /dev/null +++ b/src/dfrec/dfrec.c @@ -0,0 +1,278 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 "dfrec.h" + +#include "upm_utilities.h" + +#define DFREC_NUM_SAMPLES 10 + +// taken from the DFRobot example code +#define TEMPERATURE_COEFF (1.0 + 0.0185) + +static float average(const dfrec_context dev, int samples) +{ + int sum = 0; + + if (samples < 1) + samples = 1; + + int i; + for (i=0; i< samples; i++) + { + int j = mraa_aio_read(dev->aio); + if (j < 0) + { + printf("%s: mraa_aio_read() failed.\n", __FUNCTION__); + return -1.0; + } + sum += j; + upm_delay_ms(20); + } + + return (float)(sum / samples); +} + +dfrec_context dfrec_init(unsigned int apin, unsigned int uart_ow, + unsigned int device_idx, float a_ref) +{ + dfrec_context dev = + (dfrec_context)malloc(sizeof(struct _dfrec_context)); + + if (!dev) + return NULL; + + // zero out context + memset((void *)dev, 0, sizeof(struct _dfrec_context)); + + dev->aio = NULL; + dev->ds18b20 = NULL; + dev->device_idx = device_idx; + + dev->a_ref = a_ref; + + dev->offset = 0.0; + dev->scale = 1.0; + + // init the defaults based on the DFRobot code example + dev->thres_min = 150; + dev->thres_max = 3300; + + dev->thres_1 = 448; + dev->scale_1 = 6.84; + dev->offset_1 = -64.32; + + dev->thres_2 = 1457; + dev->scale_2 = 6.98; + dev->offset_2 = -127; + + dev->scale_3 = 5.3; + dev->offset_3 = 2278; + + // initialize the AIO context + + if (!(dev->aio = mraa_aio_init(apin))) + { + printf("%s: mraa_aio_init() failed.\n", __FUNCTION__); + dfrec_close(dev); + return NULL; + } + + // set our analog resolution + dev->a_res = (float)(1 << mraa_aio_get_bit(dev->aio)) - 1; + + // inistialize our ds18b20 context + if (!(dev->ds18b20 = ds18b20_init(uart_ow))) + { + printf("%s: ds18b20_init() failed.\n", __FUNCTION__); + dfrec_close(dev); + return NULL; + } + + // make sure the device index exists... + if (dev->device_idx >= ds18b20_devices_found(dev->ds18b20)) + { + printf("%s: ds18b20 device index %d does not exist. Max index is %d\n", + __FUNCTION__, dev->device_idx, + ds18b20_devices_found(dev->ds18b20) - 1); + dfrec_close(dev); + return NULL; + } + + return dev; +} + +void dfrec_close(dfrec_context dev) +{ + assert(dev != NULL); + + if (dev->aio) + mraa_aio_close(dev->aio); + + if (dev->ds18b20) + ds18b20_close(dev->ds18b20); + + free(dev); +} + +void dfrec_set_offset(const dfrec_context dev, float offset) +{ + assert(dev != NULL); + + dev->offset = offset; +} + +void dfrec_set_scale(const dfrec_context dev, float scale) +{ + assert(dev != NULL); + + dev->scale = scale; +} + +upm_result_t dfrec_update(const dfrec_context dev) +{ + assert(dev != NULL); + + // update temperature + ds18b20_update(dev->ds18b20, dev->device_idx); + dev->temperature = ds18b20_get_temperature(dev->ds18b20, dev->device_idx); + + float sample = average(dev, DFREC_NUM_SAMPLES); + + if (sample == -1.0) + return UPM_ERROR_OPERATION_FAILED; + + dev->normalized = sample / dev->a_res; + dev->volts = dev->normalized * dev->a_ref; + + float mVolts = dev->volts * 1000.0; + float tempCoefficient = TEMPERATURE_COEFF * (dev->temperature - 25.0); + float voltageCoefficient = mVolts / tempCoefficient; + + if (voltageCoefficient < dev->thres_min) + { + printf("%s: Not in solution (voltageCoefficient %f < %f).\n", + __FUNCTION__, voltageCoefficient, dev->thres_min); + dev->ec = 0.0; + return UPM_ERROR_OUT_OF_RANGE; + } + else if (voltageCoefficient > dev->thres_max) + { + printf("%s: Out of range (voltageCoefficient %f > %f).\n", + __FUNCTION__, voltageCoefficient, dev->thres_max); + dev->ec = 0.0; + return UPM_ERROR_OUT_OF_RANGE; + } + else + { + if (voltageCoefficient <= dev->thres_1) + { + // 1ms/cmec = dev->scale_1 * voltageCoefficient + dev->offset_1; + } + else if (voltageCoefficient <= dev->thres_2) + { + // 3ms/cmec = dev->scale_2 * voltageCoefficient + dev->offset_2; + } + else + { + // 10ms/cmec = dev->scale_3 * voltageCoefficient + dev->offset_3; + } + + // convert us/cm to ms/cm + dev->ec /= 1000.0; + } + + return UPM_SUCCESS; +} + +float dfrec_get_ec(const dfrec_context dev) +{ + assert(dev != NULL); + + return dev->ec * dev->scale + (dev->offset * dev->scale); +} + +float dfrec_get_temperature(const dfrec_context dev) +{ + assert(dev != NULL); + + return dev->temperature; +} + +float dfrec_get_volts(const dfrec_context dev) +{ + assert(dev != NULL); + + return dev->volts; +} + +float dfrec_get_normalized(const dfrec_context dev) +{ + assert(dev != NULL); + + return dev->normalized; +} + +void dfrec_set_threshold_min_max(const dfrec_context dev, float min, + float max) +{ + assert(dev != NULL); + + dev->thres_min = min; + dev->thres_max = max; +} + +void dfrec_set_threshold_1(const dfrec_context dev, float thres, + float scale, float offset) +{ + assert(dev != NULL); + + dev->thres_1 = thres; + dev->scale_1 = scale; + dev->offset_1 = scale; +} + +void dfrec_set_threshold_2(const dfrec_context dev, float thres, + float scale, float offset) +{ + assert(dev != NULL); + + dev->thres_2 = thres; + dev->scale_2 = scale; + dev->offset_2 = scale; +} + +void dfrec_set_threshold_3(const dfrec_context dev, float scale, float offset) +{ + assert(dev != NULL); + + dev->scale_3 = scale; + dev->offset_3 = scale; +} diff --git a/src/dfrec/dfrec.cxx b/src/dfrec/dfrec.cxx new file mode 100644 index 00000000..fd729c2a --- /dev/null +++ b/src/dfrec/dfrec.cxx @@ -0,0 +1,108 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 "dfrec.hpp" + +using namespace upm; +using namespace std; + +DFREC::DFREC(unsigned int apin, unsigned int uart_ow, + unsigned int device_idx, + float a_ref) : + m_dfrec(dfrec_init(apin, uart_ow, device_idx, a_ref)) +{ + if (!m_dfrec) + throw std::runtime_error(string(__FUNCTION__) + + ": dfrec_init() failed"); +} + +DFREC::~DFREC() +{ + dfrec_close(m_dfrec); +} +void DFREC::update() +{ + upm_result_t rv = dfrec_update(m_dfrec); + + // we only want to throw on "real" fatal errors + if (!(rv == UPM_ERROR_OUT_OF_RANGE || rv == UPM_SUCCESS)) + { + throw std::runtime_error(string(__FUNCTION__) + + ": dfrec_update() failed with UPM error " + + std::to_string(int(rv)) ); + } +} + +void DFREC::setOffset(float offset) +{ + dfrec_set_offset(m_dfrec, offset); +} + +void DFREC::setScale(float scale) +{ + dfrec_set_scale(m_dfrec, scale); +} + +float DFREC::getEC() +{ + return dfrec_get_ec(m_dfrec); +} + +float DFREC::getVolts() +{ + return dfrec_get_volts(m_dfrec); +} + +float DFREC::getNormalized() +{ + return dfrec_get_normalized(m_dfrec); +} + +float DFREC::getTemperature() +{ + return dfrec_get_temperature(m_dfrec); +} + +void DFREC::setThresholdMinMax(float min, float max) +{ + dfrec_set_threshold_min_max(m_dfrec, min, max); +} + +void DFREC::setThreshold1(float thres, float scale, float offset) +{ + dfrec_set_threshold_1(m_dfrec, thres, scale, offset); +} + +void DFREC::setThreshold2(float thres, float scale, float offset) +{ + dfrec_set_threshold_2(m_dfrec, thres, scale, offset); +} + +void DFREC::setThreshold3(float scale, float offset) +{ + dfrec_set_threshold_3(m_dfrec, scale, offset); +} diff --git a/src/dfrec/dfrec.h b/src/dfrec/dfrec.h new file mode 100644 index 00000000..b2dbeca9 --- /dev/null +++ b/src/dfrec/dfrec.h @@ -0,0 +1,236 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 "upm.h" +#include "mraa/aio.h" + +#include "ds18b20.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * @brief DFRobot EC Meter + * + * The driver was tested with the DFRobot EC Analog Sensor. + * + * This device measure the electrical conductivity of an aqueous + * solution. The included probe is a K=1 model. + * + * Calibration is somewhat complicated - see the DFRobot wiki for + * instructions on calibration. Functions are provided to supply + * the appropriate values. By default, the values used in the + * DFRobot arduino example are used. + * + * wiki: https://www.dfrobot.com/wiki/index.php/Analog_EC_Meter_SKU:DFR0300 + * + * @snippet dfrec.c Interesting + */ + + /** + * Device context + */ + typedef struct _dfrec_context { + mraa_aio_context aio; + + // ds18b20 context (for temperature measurement + ds18b20_context ds18b20; + unsigned int device_idx; + + // analog ADC resolution + float a_res; + + // analog reference voltage + float a_ref; + + // for external offset and scaling of the results + float offset; + float scale; + + // volts + float volts; + + // normalized ADC + float normalized; + + // the EC value + float ec; + + // EC threshold min/max (mV) + float thres_min; // 150 + float thres_max; // 3300 + + // the temperature read from the ds18b29 + float temperature; + + // thresholds, scales, and offsets taken from the DFRobot code + float thres_1; // 448 + float scale_1; // 6.84 + float offset_1; // -64.32 + + float thres_2; // 1457 + float scale_2; // 6.98 + float offset_2; // -127.0 + + float scale_3; // 5.3 + float offset_3; // +2278.0 + } *dfrec_context; + + /** + * DFREC Initializer + * + * @param apin Analog pin to use. + * @param uart_ow The UART that the ds10b20 temperature sensor is + * connected to. + * @param device_idx The device index of the ds18b20 sensor to use. + * If you only have 1 ds18b20 sensor on your DS one wire bus, you + * would pass 0 here. + * @param a_ref The analog reference voltage in use + * @return dfrec context + */ + dfrec_context dfrec_init(unsigned int apin, unsigned int uart_ow, + unsigned int device_idx, + float a_ref); + + /** + * DFREC sensor close function + */ + void dfrec_close(dfrec_context dev); + + /** + * Read the sensor status and update internal state. dfrec_update() + * must have been called before calling any of the other + * dfrec_get*() functions + * + * @param dev sensor context + * @return UPM result + */ + upm_result_t dfrec_update(const dfrec_context dev); + + /** + * Set sensor offset. This offset is applied to the EC value + * before scaling. Default is 0.0. + * + * @param dev sensor context pointer + * @param offset Offset to apply to the computed EC value + */ + void dfrec_set_offset(const dfrec_context dev, float offset); + + /** + * Set sensor scale. The EC return value is scaled by this value + * before the offset is applied. Default is 1.0. + * + * @param dev sensor context pointer + * @param scale The scale to apply to the computed EC value + */ + void dfrec_set_scale(const dfrec_context dev, float scale); + + /** + * Get computed EC (in ms/cm) value from the sensor. dfrec_update() + * must have been called prior to calling this function. + * + * @param dev sensor context pointer + * @return EC value in millivolts + */ + float dfrec_get_ec(const dfrec_context dev); + + /** + * Get the raw measured volts from the sensor. dfrec_update() must + * have been called prior to calling this function. + * + * @param dev sensor context pointer + * @return Voltage read from the sensor + */ + float dfrec_get_volts(const dfrec_context dev); + + /** + * Get the measured temperature from the temperature sensor. The + * return value will be in Celsius. + * + * @param dev sensor context pointer + * @return Temperature read from the sensor in Celsius. + */ + float dfrec_get_temperature(const dfrec_context dev); + + /** + * Get the raw normalized ADC values from the sensor. + * dfrec_update() must have been called prior to calling this + * function. + * + * @param dev sensor context pointer + * @return Normalized ADC value read from the sensor + */ + float dfrec_get_normalized(const dfrec_context dev); + + /** + * Set the global threshold min and max values. See the DFRobot + * wiki for details. + * + * @param dev sensor context pointer + * @param min Minimum threshold to be valid. Default 150. + * @param max Maximum threshold to be valid. Default 3300. + */ + void dfrec_set_threshold_min_max(const dfrec_context dev, float min, + float max); + + /** + * Set the threshold 1 values. See the DFRobot wiki for details. + * + * @param dev sensor context pointer + * @param thres Threshold maximum for value section 1. Default 448. + * @param scale Scale for value section 1. Default 6.64. + * @param offset Offset for value section 1. Default -64.32. + */ + void dfrec_set_threshold_1(const dfrec_context dev, float thres, + float scale, float offset); + + /** + * Set the threshold 2 values. See the DFRobot wiki for details. + * + * @param dev sensor context pointer + * @param thres Threshold maximum for value section 2. Default 1457. + * @param scale Scale for value section 2. Default 6.98. + * @param offset Offset for value section 2. Default -127.0. + */ + void dfrec_set_threshold_2(const dfrec_context dev, float thres, + float scale, float offset); + + /** + * Set the threshold 3 values. See the DFRobot wiki for details. + * + * @param dev sensor context pointer + * @param scale Scale for value section 3. Default 5.3. + * @param offset Offset for value section 3. Default 2278. + */ + void dfrec_set_threshold_3(const dfrec_context dev, float scale, + float offset); + + +#ifdef __cplusplus +} +#endif diff --git a/src/dfrec/dfrec.hpp b/src/dfrec/dfrec.hpp new file mode 100644 index 00000000..a8879b7c --- /dev/null +++ b/src/dfrec/dfrec.hpp @@ -0,0 +1,188 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 +#include + +#include "dfrec.h" + +namespace upm { + /** + * @brief DFRobot EC Meter + * @defgroup dfrec libupm-dfrec + * @ingroup dfrobot ainput uart liquid + */ + + /** + * @library dfrec + * @sensor dfrec + * @comname DFRobot EC Meter + * @type liquid + * @man dfrobot + * @con ainput uart + * @web https://www.dfrobot.com/index.php?route=product/product&product_id=1123&search=DFR0300&description=true#.Vx49p-_n-M8 + * + * @brief DFRobot EC Meter + * + * The driver was tested with the DFRobot EC Analog Sensor. + * + * This device measure the electrical conductivity of an aqueous + * solution. The included probe is a K=1 model. + * + * Calibration is somewhat complicated - see the DFRobot wiki for + * instructions on calibration. Functions are provided to supply + * the appropriate values. By default, the values used in the + * DFRobot arduino example are used. + * + * wiki: https://www.dfrobot.com/wiki/index.php/Analog_EC_Meter_SKU:DFR0300 + * + * @snippet dfrec.cxx Interesting + */ + + class DFREC { + public: + + /** + * DFREC object constructor + * + * @param apin Analog pin to use. + * @param uart_ow The UART that the ds10b20 temperature sensor is + * connected to. + * @param device_idx The device index of the ds18b20 sensor to use. + * If you only have 1 ds18b20 sensor on your DS one wire bus, you + * would pass 0 here. + * @param a_ref The analog reference voltage in use + * @return dfrec context + */ + DFREC(unsigned int apin, unsigned int uart_ow, + unsigned int device_idx, + float a_ref); + + /** + * DFREC object destructor + */ + ~DFREC(); + + /** + * Read the sensor status and update internal state. + * dfrec_update() must have been called before calling any of the + * other get*() functions. + */ + void update(); + + /** + * Set sensor offset. This offset is applied to the return EC + * value before scaling. Default is 0.0. + * + * @param offset The offset to apply. + */ + void setOffset(float offset); + + /** + * Set sensor scale. The return EC value is scaled by this value + * before the offset is applied. Default is 1.0. + * + * @param scale The scale to apply. + */ + void setScale(float scale); + + /** + * Get computed EC (ms/cm) value from the sensor. update() must + * have been called prior to calling this function. + * + * @return EC value in ms/cm. + */ + float getEC(); + + /** + * Get the measured volts from the sensor. update() must have been + * called prior to calling this function. + * + * @return The voltage measurement. + */ + float getVolts(); + + /** + * Get the normalized ADC value from the sensor. update() must have + * been called prior to calling this function. + * + * @return The normalized ADC value. + */ + float getNormalized(); + + /** + * Get the measured temperature from the temperature sensor. The + * return value will be in Celsius. + * + * @return temperature read from the sensor in Celsius. + */ + float getTemperature(); + + /** + * Set the global threshold min and max values. See the DFRobot + * wiki for details. + * + * @param min Minimum threshold to be valid. Default 150. + * @param max Maximum threshold to be valid. Default 3300. + */ + void setThresholdMinMax(float min, float max); + + /** + * Set the threshold 1 values. See the DFRobot wiki for details. + * + * @param thres Threshold maximum for value section 1. Default 448. + * @param scale Scale for value section 1. Default 6.64. + * @param offset Offset for value section 1. Default -64.32. + */ + void setThreshold1(float thres, float scale, float offset); + + /** + * Set the threshold 2 values. See the DFRobot wiki for details. + * + * @param thres Threshold maximum for value section 2. Default 1457. + * @param scale Scale for value section 2. Default 6.98. + * @param offset Offset for value section 2. Default -127.0. + */ + void setThreshold2(float thres, float scale, float offset); + + /** + * Set the threshold 3 values. See the DFRobot wiki for details. + * + * @param scale Scale for value section 3. Default 5.3. + * @param offset Offset for value section 3. Default 2278. + */ + void setThreshold3(float scale, float offset); + + protected: + // dfrec device context + dfrec_context m_dfrec; + + private: + }; +} diff --git a/src/dfrec/dfrec_fti.c b/src/dfrec/dfrec_fti.c new file mode 100644 index 00000000..c1bc9d76 --- /dev/null +++ b/src/dfrec/dfrec_fti.c @@ -0,0 +1,105 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 "dfrec.h" +#include "upm_fti.h" + +/** + * This file implements the Function Table Interface (FTI) for this sensor + */ + +const char upm_dfrec_name[] = "DFREC"; +const char upm_dfrec_description[] = "DFRobot Analog EC Sensor"; +const upm_protocol_t upm_dfrec_protocol[] = {UPM_ANALOG}; +const upm_sensor_t upm_dfrec_category[] = {UPM_EC}; + +// forward declarations +const void* upm_dfrec_get_ft(upm_sensor_t sensor_type); +void* upm_dfrec_init_name(); +void upm_dfrec_close(void *dev); +upm_result_t upm_dfrec_get_value(const void *dev, float *value); +upm_result_t upm_dfrec_set_scale(const void *dev, float scale); +upm_result_t upm_dfrec_set_offset(const void *dev, float offset); + +static const upm_sensor_ft ft = +{ + .upm_sensor_init_name = &upm_dfrec_init_name, + .upm_sensor_close = &upm_dfrec_close, +}; + +static const upm_ec_ft ecft = +{ + .upm_ec_set_offset = upm_dfrec_set_offset, + .upm_ec_set_scale = upm_dfrec_set_scale, + .upm_ec_get_value = upm_dfrec_get_value +}; + +const void* upm_dfrec_get_ft(upm_sensor_t sensor_type) +{ + switch(sensor_type) + { + case UPM_SENSOR: + return &ft; + + case UPM_EC: + return &ecft; + + default: + return NULL; + } +} + +void* upm_dfrec_init_name() +{ + return NULL; +} + +void upm_dfrec_close(void *dev) +{ + dfrec_close((dfrec_context)dev); +} + +upm_result_t upm_dfrec_set_scale(const void *dev, float scale) +{ + dfrec_set_scale((dfrec_context)dev, scale); + return UPM_SUCCESS; +} + +upm_result_t upm_dfrec_set_offset(const void *dev, float offset) +{ + dfrec_set_offset((dfrec_context)dev, offset); + return UPM_SUCCESS; +} + +upm_result_t upm_dfrec_get_value(const void *dev, float *value) +{ + upm_result_t rv; + + if ((rv = dfrec_update((dfrec_context)dev))) + return rv; + + *value = dfrec_get_ec((dfrec_context)dev); + + return UPM_SUCCESS; +} diff --git a/src/dfrec/javaupm_dfrec.i b/src/dfrec/javaupm_dfrec.i new file mode 100644 index 00000000..6efab860 --- /dev/null +++ b/src/dfrec/javaupm_dfrec.i @@ -0,0 +1,21 @@ +%module javaupm_dfrec +%include "../upm.i" +%include "std_string.i" +%include "cpointer.i" +%include "typemaps.i" + +%include "dfrec.hpp" +%{ + #include "dfrec.hpp" +%} + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_dfrec"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. \n" + e); + System.exit(1); + } + } +%} diff --git a/src/dfrec/jsupm_dfrec.i b/src/dfrec/jsupm_dfrec.i new file mode 100644 index 00000000..4d4b27be --- /dev/null +++ b/src/dfrec/jsupm_dfrec.i @@ -0,0 +1,13 @@ +%module jsupm_dfrec +%include "../upm.i" +%include "std_string.i" +%include "cpointer.i" + +/* Send "int *" and "float *" to JavaScript as intp and floatp */ +%pointer_functions(int, intp); +%pointer_functions(float, floatp); + +%include "dfrec.hpp" +%{ + #include "dfrec.hpp" +%} diff --git a/src/dfrec/pyupm_dfrec.i b/src/dfrec/pyupm_dfrec.i new file mode 100644 index 00000000..0fdc0c90 --- /dev/null +++ b/src/dfrec/pyupm_dfrec.i @@ -0,0 +1,17 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_dfrec +%include "../upm.i" +%include "std_string.i" +%include "cpointer.i" + +/* Send "int *" and "float *" to python as intp and floatp */ +%pointer_functions(int, intp); +%pointer_functions(float, floatp); + +%feature("autodoc", "3"); + +%include "dfrec.hpp" +%{ + #include "dfrec.hpp" +%}