From 971cb4ab511697ab277442a120b2f631a46d6837 Mon Sep 17 00:00:00 2001 From: Noel Eck Date: Thu, 17 Nov 2016 16:20:29 -0800 Subject: [PATCH] ims: Initial turnin of I2C Moisture Sensor * Added C library * Added CXX library * Added C/CXX/java/js/python examples Signed-off-by: Noel Eck --- docs/images/ims.png | Bin 0 -> 72329 bytes doxy/samples.mapping.txt | 1 + examples/c++/CMakeLists.txt | 1 + examples/c++/ims.cxx | 69 +++++++++++ examples/c/CMakeLists.txt | 3 +- examples/c/ims.c | 75 ++++++++++++ examples/java/IMS_Example.java | 53 +++++++++ examples/javascript/ims.js | 51 ++++++++ examples/python/ims.py | 44 +++++++ src/ims/CMakeLists.txt | 9 ++ src/ims/ims.c | 207 +++++++++++++++++++++++++++++++++ src/ims/ims.cxx | 110 ++++++++++++++++++ src/ims/ims.h | 178 ++++++++++++++++++++++++++++ src/ims/ims.hpp | 148 +++++++++++++++++++++++ src/ims/ims_fti.c | 118 +++++++++++++++++++ src/ims/javaupm_ims.i | 19 +++ src/ims/jsupm_ims.i | 8 ++ src/ims/pyupm_ims.i | 13 +++ 18 files changed, 1106 insertions(+), 1 deletion(-) create mode 100644 docs/images/ims.png create mode 100644 examples/c++/ims.cxx create mode 100644 examples/c/ims.c create mode 100644 examples/java/IMS_Example.java create mode 100644 examples/javascript/ims.js create mode 100755 examples/python/ims.py create mode 100644 src/ims/CMakeLists.txt create mode 100644 src/ims/ims.c create mode 100644 src/ims/ims.cxx create mode 100644 src/ims/ims.h create mode 100644 src/ims/ims.hpp create mode 100644 src/ims/ims_fti.c create mode 100644 src/ims/javaupm_ims.i create mode 100644 src/ims/jsupm_ims.i create mode 100644 src/ims/pyupm_ims.i diff --git a/docs/images/ims.png b/docs/images/ims.png new file mode 100644 index 0000000000000000000000000000000000000000..744cc06407bb45add03c25aeb9ce7bbc7afad216 GIT binary patch literal 72329 zcmV+5Kp($}P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 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
  • 2X417*i5~ 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 + * 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 "ims.hpp" + +using namespace upm; + +int shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + +int main(int argc, char **argv) +{ + signal(SIGINT, sig_handler); + //! [Interesting] + + // Instantiate a IMS instance using i2c bus 0 and default address + upm::IMS sensor(0); + + while (shouldRun) + { + std::cout << "Version: " + << sensor.get_version() + << " light: " + << sensor.get_light() + << " moisture: " + << sensor.get_moisture() + << " temp: " + << sensor.get_temperature() + << " C" + << std::endl; + + sleep(1); + } + //! [Interesting] + + std::cout << "Exiting..." << std::endl; + + return 0; +} diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index bfd4a2b7..ddbda942 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -23,7 +23,7 @@ macro(add_custom_example example_bin example_src example_module_list) set(found_all_modules FALSE) endif() if (MODULE_LIST) - list(FIND MODULE_LIST ${module}-c index) + list(FIND MODULE_LIST ${module} index) if (${index} EQUAL -1) set(found_all_modules FALSE) endif() @@ -139,6 +139,7 @@ add_example (button) add_example (button_intr) add_example (my9221) add_example (ms5803) +add_example (ims) # Custom examples add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps) diff --git a/examples/c/ims.c b/examples/c/ims.c new file mode 100644 index 00000000..23e4a716 --- /dev/null +++ b/examples/c/ims.c @@ -0,0 +1,75 @@ +/* + * Author: Noel Eck + * 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 "ims.h" +#include "upm_utilities.h" + +bool shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + +int main() +{ + signal(SIGINT, sig_handler); + + //! [Interesting] + ims_context* sensor = ims_init(0, IMS_ADDRESS_DEFAULT); + + if (!sensor) + { + printf("ims_init() failed\n"); + return 1; + } + + // Every second, sample the sensor outputs + while (shouldRun) + { + uint16_t version, light, moisture, temp; + + if (ims_get_version(sensor, &version) == UPM_SUCCESS && + ims_get_light(sensor, &light) == UPM_SUCCESS && + ims_get_moisture(sensor, &moisture) == UPM_SUCCESS && + ims_get_temperature(sensor, &temp) == UPM_SUCCESS) + printf("Version: %d light: 0x%04x moisture: 0x%04x temp: %3.2f C\n", + version, light, moisture, temp/10.0); + else + break; + + upm_delay(1); + } + + //! [Interesting] + printf("Exiting\n"); + ims_close(sensor); + + return 0; +} diff --git a/examples/java/IMS_Example.java b/examples/java/IMS_Example.java new file mode 100644 index 00000000..0db81b72 --- /dev/null +++ b/examples/java/IMS_Example.java @@ -0,0 +1,53 @@ +/* + * 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_ims.IMS; + +public class IMS_Example +{ + public static void main(String[] args) throws InterruptedException + { + // ! [Interesting] + + // Instantiate a IMS instance using bus 0 and default i2c address + IMS sensor = new IMS(0); + + while (true) + { + System.out.println("Version: " + + sensor.get_version() + + " light: " + + sensor.get_light() + + " moisture: " + + sensor.get_moisture() + + " temp: " + + sensor.get_temperature() + + " C"); + + Thread.sleep(1000); + } + + // ! [Interesting] + } +} diff --git a/examples/javascript/ims.js b/examples/javascript/ims.js new file mode 100644 index 00000000..e8d1bde6 --- /dev/null +++ b/examples/javascript/ims.js @@ -0,0 +1,51 @@ +/* + * Author: Noel Eck + * 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_ims'); + +// Instantiate a IMS instance using bus 0 and default i2c address +var sensor = new sensorObj.IMS(0); + +setInterval(function() +{ + console.log("Version: " + + sensor.get_version() + + " light: " + + sensor.get_light() + + " moisture: " + + sensor.get_moisture() + + " temp: " + + sensor.get_temperature().toFixed(2) + + " C"); +}, 1000); + +// exit on ^C +process.on('SIGINT', function() +{ + sensor = null; + sensorObj.cleanUp(); + sensorObj = null; + console.log("Exiting."); + process.exit(0); +}); diff --git a/examples/python/ims.py b/examples/python/ims.py new file mode 100755 index 00000000..1f4f6b29 --- /dev/null +++ b/examples/python/ims.py @@ -0,0 +1,44 @@ +#!/usr/bin/python +# Author: Noel Eck +# 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. + +from __future__ import print_function +import time, sys, signal, atexit +from upm import pyupm_ims + +def main(): + # Create an instance of the I2C Moisture Sensor + # I2C bus 0, default address = 0x20 + ims = pyupm_ims.IMS(0) + + print ('I2C moisture sensor example...') + while (1): + try: + print ('Version: %d light: 0x%04x moisture: 0x%04x temp: %3.2f C' \ + % (ims.get_version(), ims.get_light(), ims.get_moisture(), + ims.get_temperature())) + time.sleep(1) + except KeyboardInterrupt: + break + +if __name__ == '__main__': + main() diff --git a/src/ims/CMakeLists.txt b/src/ims/CMakeLists.txt new file mode 100644 index 00000000..f559602b --- /dev/null +++ b/src/ims/CMakeLists.txt @@ -0,0 +1,9 @@ +upm_mixed_module_init (NAME ims + DESCRIPTION "Catnip Electronics I2C moisture sensor" + C_HDR ims.h + C_SRC ims.c + CPP_HDR ims.hpp + CPP_SRC ims.cxx + FTI_SRC ims_fti.c + CPP_WRAPS_C + REQUIRES mraa) diff --git a/src/ims/ims.c b/src/ims/ims.c new file mode 100644 index 00000000..1eea5608 --- /dev/null +++ b/src/ims/ims.c @@ -0,0 +1,207 @@ +/* + * Author: Noel Eck + * 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 "ims.h" + +ims_context* ims_init(int16_t i2c_bus, int16_t i2c_address) +{ + /* Allocate space for the sensor structure */ + ims_context* dev = (ims_context*) malloc(sizeof(ims_context)); + if(dev == NULL) + { + syslog(LOG_CRIT, "%s: malloc() failed\n", __FUNCTION__); + goto ims_init_fail; + } + + /* Initilize mraa */ + mraa_result_t result = mraa_init(); + if (result != MRAA_SUCCESS) + { + syslog(LOG_ERR, "%s: mraa_init() failed (%d)\n", __FUNCTION__, result); + goto ims_init_fail; + } + + /* Init i2c */ + dev->_i2c_context = mraa_i2c_init(i2c_bus); + if(dev->_i2c_context == NULL) + { + syslog(LOG_ERR, "%s: mraa_i2c_init() failed\n", __FUNCTION__); + goto ims_init_fail; + } + + /* Set the i2c slave address for this device */ + if (mraa_i2c_address(dev->_i2c_context, i2c_address) != MRAA_SUCCESS) + { + syslog(LOG_ERR, "%s: mraa_i2c_address() failed\n", __FUNCTION__); + goto ims_init_fail; + } + + /* This device must run at 100kHz */ + if (mraa_i2c_frequency(dev->_i2c_context, MRAA_I2C_STD)) + { + syslog(LOG_ERR, "%s: mraa_i2c_frequency() failed\n", __FUNCTION__); + goto ims_init_fail; + } + + return dev; + +/* Handle all failing cases here */ +ims_init_fail: + /* Free structure memory if allocated */ + if (dev != NULL) + free(dev); + return NULL; +} + +void ims_close(ims_context* dev) +{ + if (dev == NULL) return; + + /* Cleanup the I2C context */ + mraa_i2c_stop(dev->_i2c_context); + free(dev); +} + +upm_result_t ims_read(const ims_context* dev, IMS_RD_COMMAND cmd, uint16_t* rd_data) +{ + int32_t val = 0; + uint8_t readbuf[2] = {0, 0}; + switch (cmd) + { + /* One byte reads */ + case IMS_GET_ADDRESS: + case IMS_GET_VERSION: + case IMS_GET_BUSY: + val = mraa_i2c_read_bytes_data(dev->_i2c_context, cmd, readbuf, 1); + *rd_data = readbuf[0]; + break; + /* Two byte reads */ + case IMS_GET_CAPACITANCE: + case IMS_GET_LIGHT: + case IMS_GET_TEMPERATURE: + val = mraa_i2c_read_bytes_data(dev->_i2c_context, cmd, readbuf, 2); + *rd_data = readbuf[1]; + *rd_data += ((uint16_t)readbuf[0] << 8) & 0xFF00; + break; + default: + syslog(LOG_ERR, "%s: Invalid read command: 0x%02x\n", __FUNCTION__, cmd); + return UPM_ERROR_INVALID_PARAMETER; + } + + /* val will be < 0 on failing case */ + if (val < 0) + { + syslog(LOG_ERR, "%s: mraa_i2c_read_byte/word_data() failed\n", __FUNCTION__); + return UPM_ERROR_NO_DATA; + } + + return UPM_SUCCESS; +} + +upm_result_t ims_write(const ims_context* dev, IMS_WR_COMMAND cmd, uint8_t wr_data) +{ + mraa_result_t mr; + switch (cmd) + { + /* One byte write */ + case IMS_SET_ADDRESS: + mr = mraa_i2c_write_byte_data(dev->_i2c_context, wr_data, cmd); + break; + /* Zero byte write */ + case IMS_MEASURE_LIGHT: + case IMS_RESET: + case IMS_SLEEP: + mr = mraa_i2c_write(dev->_i2c_context, (const uint8_t *)&cmd, 1); + break; + default: + syslog(LOG_ERR, "%s: Invalid read command: 0x%02x\n", __FUNCTION__, cmd); + return UPM_ERROR_INVALID_PARAMETER; + } + + if (mr != MRAA_SUCCESS) return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t ims_get_version(const ims_context* dev, uint16_t* rd_data) +{ + return ims_read(dev, IMS_GET_VERSION, rd_data); +} + +upm_result_t ims_get_moisture(const ims_context* dev, uint16_t* rd_data) +{ + return ims_read(dev, IMS_GET_CAPACITANCE, rd_data); +} + +upm_result_t ims_get_light(const ims_context* dev, uint16_t* rd_data) +{ + /* Initiate a light measurement */ + upm_result_t res = ims_write(dev, IMS_MEASURE_LIGHT, 0); + if (res != UPM_SUCCESS) return res; + + /* Technical data for the ISM specifies a 3 second wait. Check the BUSY + * command every 100 ms for 3 seconds. The sensor will return quickly in + * bright light and much slower in less light. */ + int retry = 30; + *rd_data = 1; + while ((retry-- > 0) && (*rd_data != 0)) + { + // Always delay at least 100 ms + upm_delay_ms(100); + res = ims_read(dev, IMS_GET_BUSY, rd_data); + if (res != UPM_SUCCESS) return res; + } + + /* If the sensor is STILL not ready, go ahead and perform the read. + * From testing, this appears to happen only in complete darkness, + * at which point the sensor get light read returns 0xffff anyway.*/ + + return ims_read(dev, IMS_GET_LIGHT, rd_data); +} + +upm_result_t ims_get_temperature(const ims_context* dev, uint16_t* rd_data) +{ + return ims_read(dev, IMS_GET_TEMPERATURE, rd_data); +} + +upm_result_t ims_reset(const ims_context* dev) +{ + return ims_write(dev, IMS_RESET, 0); +} + +upm_result_t ims_reset_i2c_address(const ims_context* dev, uint8_t address_new) +{ + upm_result_t res = ims_write(dev, IMS_SET_ADDRESS, address_new); + if (res != UPM_SUCCESS) return res; + + return ims_reset(dev); +} + +upm_result_t ims_sleep(const ims_context* dev) +{ + return ims_write(dev, IMS_SLEEP, 0); +} diff --git a/src/ims/ims.cxx b/src/ims/ims.cxx new file mode 100644 index 00000000..1831f88f --- /dev/null +++ b/src/ims/ims.cxx @@ -0,0 +1,110 @@ +/* + * Author: Noel Eck + * 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 "ims.hpp" + +using namespace upm; + +IMS::IMS(int16_t i2c_bus, int16_t i2c_address) : + _dev(ims_init(i2c_bus, i2c_address)) +{ + if (_dev == NULL) + throw std::runtime_error(std::string(__FUNCTION__) + + ": failed to initialize sensor, check syslog"); +} + +uint16_t IMS::get_version() +{ + uint16_t retval; + if (ims_get_version(_dev, &retval) != UPM_SUCCESS) + throw std::runtime_error(std::string(__FUNCTION__) + + ": ims_get_version command failed"); + return retval; +} + +uint16_t IMS::get_moisture() +{ + uint16_t retval; + if (ims_get_moisture(_dev, &retval) != UPM_SUCCESS) + throw std::runtime_error(std::string(__FUNCTION__) + + ": ims_get_moisture command failed"); + return retval; +} + +uint16_t IMS::get_light() +{ + uint16_t retval; + if (ims_get_light(_dev, &retval) != UPM_SUCCESS) + throw std::runtime_error(std::string(__FUNCTION__) + + ": ims_get_light command failed"); + return retval; +} + +float IMS::get_temperature() +{ + uint16_t retval; + if (ims_get_temperature(_dev, &retval) != UPM_SUCCESS) + throw std::runtime_error(std::string(__FUNCTION__) + + ": ims_get_temperature command failed"); + return static_cast(retval)/10.0; +} + +void IMS::reset_i2c_address(uint8_t address_new) +{ + if (ims_reset_i2c_address(_dev, address_new) != UPM_SUCCESS) + throw std::runtime_error(std::string(__FUNCTION__) + + ": reset_i2c_address command failed"); +} + +void IMS::reset() +{ + if ( ims_write(_dev, IMS_RESET, 1) != UPM_SUCCESS ) + throw std::runtime_error(std::string(__FUNCTION__) + + ": ims_write command failed"); +} + +uint16_t IMS::read(IMS_RD_COMMAND cmd) +{ + uint16_t retval; + if (ims_read(_dev, cmd, &retval) != UPM_SUCCESS) + throw std::runtime_error(std::string(__FUNCTION__) + + ": ims_read command failed"); + return retval; +} + +void IMS::write(IMS_WR_COMMAND cmd, uint8_t value) +{ + if ( ims_write(_dev, cmd, value) != UPM_SUCCESS ) + throw std::runtime_error(std::string(__FUNCTION__) + + ": ims_write command failed"); +} + +void IMS::sleep() +{ + if ( ims_sleep(_dev) != UPM_SUCCESS ) + throw std::runtime_error(std::string(__FUNCTION__) + + ": ims_sleep command failed"); +} diff --git a/src/ims/ims.h b/src/ims/ims.h new file mode 100644 index 00000000..07af1302 --- /dev/null +++ b/src/ims/ims.h @@ -0,0 +1,178 @@ +/* + * Author: Noel Eck + * 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 "mraa/i2c.h" +#include "upm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IMS_ADDRESS_DEFAULT 0x20 + + /* @brief Moisture sensor I2C READ commands */ +typedef enum _IMS_RD_COMMAND { + /* Read capacitance (moisture) register */ + IMS_GET_CAPACITANCE = 0x00, /* (r) 2 */ + /* Read I2C address register */ + IMS_GET_ADDRESS = 0x02, /* (r) 1 */ + /* Read light register (requires write to IMS_MEASURE_LIGHT) */ + IMS_GET_LIGHT = 0x04, /* (r) 2 */ + /* Read temperature register */ + IMS_GET_TEMPERATURE = 0x05, /* (r) 2 */ + /* Read version register */ + IMS_GET_VERSION = 0x07, /* (r) 1 */ + /* Read busy register (0 = ready, 1 = sampling) */ + IMS_GET_BUSY = 0x09, /* (r) 1 */ +} IMS_RD_COMMAND; + + /* @brief Moisture sensor I2C WRITE commands */ +typedef enum { + /* Write I2C address register (latched w/IMS_RESET) */ + IMS_SET_ADDRESS = 0x01, /* (w) 1 */ + /* Initiate light measurement */ + IMS_MEASURE_LIGHT = 0x03, /* (w) 0 */ + /* Reset device */ + IMS_RESET = 0x06, /* (w) 0 */ + /* Sleep microcontroller, wake on any I2C request */ + IMS_SLEEP = 0x08, /* (w) 0 */ +} IMS_WR_COMMAND; + +/** + * @file ims.h + * @library ims + * @brief C API for the Catnip Electronics I2C moisture sensor. This sensor + * must run at 100 kHz. + * + * @include ims.c + */ + +/** + * device context + */ +typedef struct { + /* mraa i2c context */ + mraa_i2c_context _i2c_context; +} ims_context; + +/** + * Initialize sensor + * @param i2c_bus Target I2C bus + * @param i2c_address Target I2C address (default is 0x20) + * @return sensor context pointer + */ +ims_context* ims_init(int16_t i2c_bus, int16_t i2c_address); + +/** + * Sensor close method. + * Cleans up any memory held by this device + * @param sensor context pointer + */ +void ims_close(ims_context* dev); + +/** + * Read I2C Moisture Sensor registers + * @param dev Sensor context pointer + * @param cmd Read command + * @param rd_data Data returned from sensor (1 or 2 bytes depending on cmd) + * @return Function result code + */ +upm_result_t ims_read(const ims_context* dev, IMS_RD_COMMAND cmd, uint16_t* rd_data); + +/** + * Write I2C Moisture Sensor registers + * @param dev Sensor context pointer + * @param cmd Write command + * @param wr_data Target data to write (only used for IMS_SET_ADDRESS) + * @return Function result code + */ +upm_result_t ims_write(const ims_context* dev, IMS_WR_COMMAND cmd, uint8_t wr_data); + +/** + * Get sensor version + * @param dev Sensor context pointer + * @param rd_data Sensor version + * @return Function result code + */ +upm_result_t ims_get_version(const ims_context* dev, uint16_t* rd_data); + +/** + * Get moisture reading from sensor + * @param dev Sensor context pointer + * @param rd_data Unitless, relative capacitance value (used to determine moisture) + * @return Function result code + */ +upm_result_t ims_get_moisture(const ims_context* dev, uint16_t* rd_data); + +/** + * Get light reading from LED on device. The technical data for the I2C + * moisture sensor specifies a 3 second wait. Loop for 3 seconds checking + * the GET_BUSY register. IF the sensor is NOT ready after 3 seconds, + * assume there is NO light and return a max uint16_t (dark) value. + * @param dev Sensor context pointer + * @param rd_data Unitless, relative value for brightness + * dark (0xFFFF) ---> light (0x0000) + * @return Function result code + */ +upm_result_t ims_get_light(const ims_context* dev, uint16_t* rd_data); + +/** + * Get temperature reading from device + * @param dev Sensor context pointer + * @param rd_data Temperature in degrees Celsius * 10 + * ie, 256 = 25.6 C + * @return Function result code + */ +upm_result_t ims_get_temperature(const ims_context* dev, uint16_t* rd_data); + +/** + * Reset sensor + * @param dev Sensor context pointer + * @return Function result code + */ +upm_result_t ims_reset(const ims_context* dev); + +/** + * Set I2C address AND reset sensor + * @param dev Sensor context pointer + * @param address_new New I2C for device + * @return Function result code + */ +upm_result_t ims_reset_i2c_address(const ims_context* dev, uint8_t address_new); + +/** + * Put device into low-power mode. Device wakes on any I2C command. + * @param dev Sensor context pointer + * @return Function result code + */ +upm_result_t ims_sleep(const ims_context* dev); + +#ifdef __cplusplus +} +#endif diff --git a/src/ims/ims.hpp b/src/ims/ims.hpp new file mode 100644 index 00000000..a9c1b299 --- /dev/null +++ b/src/ims/ims.hpp @@ -0,0 +1,148 @@ +/* + * Author: Noel Eck + * 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 "mraa/i2c.h" +#include "ims.h" + +namespace upm { +/** + * @brief Catnip Electronics I2C moisture sensor + * @defgroup ims libupm-ims + * @ingroup catnip i2c liquid light temp + */ + +/** + * @library ims + * @sensor ims + * @comname Catnip Electronics I2C moisture sensor + * @type liquid light temp + * @man catnip + * @web https://www.tindie.com/products/miceuz/i2c-soil-moisture-sensor/ + * @con i2c + * + * @brief API for the Catnip Electronics I2C moisture sensor + * + * I2C sensor which can be used to read: + * moisture + * light + * temperature + * + * This sensor must run at 100 kHz + * + * @image html ims.png + * @snippet ims.cxx Interesting + */ + +class IMS { + public: + /** + * I2C Moisture Sensor constructor + * + * Initialize I2C Moisture Sensor + * @param i2c_bus Target I2C bus + * @param i2c_address Target I2C address (default is 0x20) + * @return sensor context pointer + * @throws std::runtime_error if sensor initializate fails + */ + IMS(int16_t i2c_bus, int16_t i2c_address = IMS_ADDRESS_DEFAULT); + + /** + * IMS destructor + */ + virtual ~IMS() {}; + + /** + * Write I2C Moisture Sensor registers + * @param cmd Write command + * @param wr_data Target data to write (only used for IMS_SET_ADDRESS) + * @throws std::runtime_error if I2C write command fails + */ + void write(IMS_WR_COMMAND cmd, uint8_t wr_data); + + /** + * Read I2C Moisture Sensor registers + * @param cmd Read command + * @return Data returned from sensor (1 or 2 bytes depending on CMD) + * @throws std::runtime_error if I2C read command fails + */ + uint16_t read(IMS_RD_COMMAND cmd); + + /** + * Get sensor version + * @return Sensor version + * @throws std::runtime_error if I2C read command fails + */ + uint16_t get_version(); + + /** + * Get moisture reading from sensor + * @return Unitless, relative capacitance value (moisture) + * @throws std::runtime_error if I2C read command fails + */ + uint16_t get_moisture(); + + /** + * Get light reading from LED on device. The technical data for the I2C + * moisture sensor specifies a 3 second wait. Loop for 3 seconds + * checking the GET_BUSY register. IF the sensor is NOT ready after 3 + * seconds, assume there is NO light and return a max uint16_t (dark) + * value. + * @return rd_data Unitless, relative value for brightness + * dark (0xFFFF) ---> light (0x0000) + * @throws std::runtime_error if I2C write/read command fails + */ + uint16_t get_light(); + + /** + * Get temperature reading from device + * @return rd_data Temperature in degrees Celsius + * @throws std::runtime_error if I2C read command fails + */ + float get_temperature(); + + /** + * Reset sensor + * @throws std::runtime_error if I2C write command fails + */ + void reset(); + + /** + * Set I2C address AND reset sensor + * @param address_new New I2C for device + * @throws std::runtime_error if I2C write command fails + */ + void reset_i2c_address(uint8_t address_new); + + /** + * Put device into low-power mode. Device wakes on any I2C command. + * @throws std::runtime_error if I2C write command fails + */ + void sleep(); + private: + /* device context struct */ + ims_context* _dev; +}; +} diff --git a/src/ims/ims_fti.c b/src/ims/ims_fti.c new file mode 100644 index 00000000..5d761928 --- /dev/null +++ b/src/ims/ims_fti.c @@ -0,0 +1,118 @@ +/* + * Author: Noel Eck + * 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 "ims.h" +#include "upm_fti.h" +#include "fti/upm_sensor.h" + +/** + * This file implements the Function Table Interface (FTI) for this sensor + */ + +const char upm_ims_name[] = "IMS"; +const char upm_ims_description[] = "Analog pH Meter Pro"; +const upm_protocol_t upm_ims_protocol[] = {UPM_ANALOG}; +const upm_sensor_t upm_ims_category[] = {UPM_PH}; + +// forward declarations +const void* upm_ims_get_ft(upm_sensor_t sensor_type); +void* upm_ims_init_str(const char* protocol, const char* params); +void upm_ims_close(void* dev); +const upm_sensor_descriptor_t upm_ims_get_descriptor(); +upm_result_t upm_ims_set_offset(const void* dev, float offset); +upm_result_t upm_ims_set_scale(const void* dev, float scale); +upm_result_t upm_ims_get_value(const void* dev, float *value); + +/* This sensor implementes 2 function tables */ +/* 1. Generic base function table */ +static const upm_sensor_ft ft_gen = +{ + .upm_sensor_init_name = &upm_ims_init_str, + .upm_sensor_close = &upm_ims_close, + .upm_sensor_get_descriptor = &upm_ims_get_descriptor +}; + +/* 2. PH function table */ +static const upm_ph_ft ft_ph = +{ + .upm_ph_set_offset = &upm_ims_set_offset, + .upm_ph_set_scale = &upm_ims_set_scale, + .upm_ph_get_value = &upm_ims_get_value +}; + +const void* upm_ims_get_ft(upm_sensor_t sensor_type) +{ + switch(sensor_type) + { + case UPM_SENSOR: + return &ft_gen; + case UPM_PH: + return &ft_ph; + default: + return NULL; + } +} + +void* upm_ims_init_str(const char* protocol, const char* params) +{ + fprintf(stderr, "String initialization - not implemented, using ain0: %s\n", __FILENAME__); + return ims_init(0); +} + +void upm_ims_close(void* dev) +{ + ims_close(dev); +} + +const upm_sensor_descriptor_t upm_ims_get_descriptor() +{ + /* Fill in the descriptor */ + upm_sensor_descriptor_t usd; + usd.name = upm_ims_name; + usd.description = upm_ims_description; + usd.protocol_size = 1; + usd.protocol = upm_ims_protocol; + usd.category_size = 1; + usd.category = upm_ims_category; + + return usd; +} + +upm_result_t upm_ims_set_offset(const void* dev, float offset) +{ + return ims_set_offset((ims_context)dev, offset); +} + +upm_result_t upm_ims_set_scale(const void* dev, float scale) +{ + return ims_set_scale((ims_context)dev, scale); +} + +upm_result_t upm_ims_get_value(const void* dev, float *value) +{ + return ims_get_ph((ims_context)dev, value); +} diff --git a/src/ims/javaupm_ims.i b/src/ims/javaupm_ims.i new file mode 100644 index 00000000..c48a1142 --- /dev/null +++ b/src/ims/javaupm_ims.i @@ -0,0 +1,19 @@ +%module javaupm_ims +%include "../upm.i" + +%{ + #include "ims.hpp" +%} + +%include "ims.hpp" + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_ims"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. \n" + e); + System.exit(1); + } + } +%} diff --git a/src/ims/jsupm_ims.i b/src/ims/jsupm_ims.i new file mode 100644 index 00000000..5c06329a --- /dev/null +++ b/src/ims/jsupm_ims.i @@ -0,0 +1,8 @@ +%module jsupm_ims +%include "../upm.i" + +%{ + #include "ims.hpp" +%} + +%include "ims.hpp" diff --git a/src/ims/pyupm_ims.i b/src/ims/pyupm_ims.i new file mode 100644 index 00000000..c1c32535 --- /dev/null +++ b/src/ims/pyupm_ims.i @@ -0,0 +1,13 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_ims +%include "../upm.i" + +%feature("autodoc", "3"); + +%{ + #include "ims.hpp" +%} + +%include "ims.h" +%include "ims.hpp"