diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index ce6e0fbb..483695c6 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -249,6 +249,7 @@ add_example (si1132) add_example (si7005) add_example (t6713) add_example (cwlsxxa) +add_example (teams) # 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++/teams.cxx b/examples/c++/teams.cxx new file mode 100644 index 00000000..8d8b54c0 --- /dev/null +++ b/examples/c++/teams.cxx @@ -0,0 +1,84 @@ +/* + * 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 "teams.h" + +using namespace std; + +bool shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + +int main(int argc, char **argv) +{ + signal(SIGINT, sig_handler); + +//! [Interesting] + + cout << "Initializing..." << endl; + + // Instantiate an TEAMS instance, using A0 for temperature, and + // 165.0 ohms for the rResistor value (for the libelium 4-20ma + // interface) + upm::TEAMS *sensor = new upm::TEAMS(0, 165.0); + + // update and print available values every second + while (shouldRun) + { + // update our values from the sensor + sensor->update(); + + // is the sensor connected? (current >= 4ma) + cout << "Is Connected: " << sensor->isConnected() << endl; + + // print computed current on the loop. This includes the offset, + // if one was set by setOffsetMilliamps(). + cout << "Milliamps: " << sensor->getRawMilliamps() << endl; + + // we show both C and F for temperature + cout << "Temperature: " << sensor->getTemperature() + << " C / " << sensor->getTemperature(true) << " F" + << endl; + + cout << endl; + + sleep(1); + } + + cout << "Exiting..." << endl; + + delete sensor; + +//! [Interesting] + + return 0; +} diff --git a/examples/java/CMakeLists.txt b/examples/java/CMakeLists.txt index 60f436ad..6e8d0537 100644 --- a/examples/java/CMakeLists.txt +++ b/examples/java/CMakeLists.txt @@ -106,6 +106,7 @@ add_example(Gp2y0aExample gp2y0a) add_example(Th02Example th02) add_example(FlexSensorExample flex) add_example(CWLSXXA_Example cwlsxxa) +add_example(TEAMS_Example teams) add_example_with_path(Jhd1313m1_lcdSample lcd/upm_i2clcd.jar) diff --git a/examples/java/TEAMS_Example.java b/examples/java/TEAMS_Example.java new file mode 100644 index 00000000..caeda6fa --- /dev/null +++ b/examples/java/TEAMS_Example.java @@ -0,0 +1,64 @@ +/* + * 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_teams.TEAMS; + +public class TEAMS_Example +{ + public static void main(String[] args) throws InterruptedException + { +// ! [Interesting] + System.out.println("Initializing..."); + + // Instantiate an TEAMS instance, using A0 for temperature, and + // 165.0 ohms for the rResistor value (for the libelium 4-20ma + // interface) + TEAMS sensor = new TEAMS(0, 165.0f); + + while (true) + { + // update our values from the sensor + sensor.update(); + + // is the sensor connected? (current >= 4ma) + System.out.println("Is Connected: " + sensor.isConnected()); + + // print computed current on the loop. This includes + // the offset, if one was set by setOffsetMilliamps(). + System.out.println("Milliamps: " + sensor.getRawMilliamps()); + + // we show both C and F for temperature + System.out.println("Temperature: " + + sensor.getTemperature() + + " C / " + + sensor.getTemperature(true) + + " F"); + + System.out.println(); + Thread.sleep(1000); + } + +// ! [Interesting] + } +} diff --git a/examples/javascript/teams.js b/examples/javascript/teams.js new file mode 100644 index 00000000..5c5b8839 --- /dev/null +++ b/examples/javascript/teams.js @@ -0,0 +1,70 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ + +/* + * 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_teams'); + + +/************** Main code **************/ + +console.log("Initializing..."); + +// Instantiate an TEAMS instance, using A0 for temperature, and +// 165.0 ohms for the rResistor value (for the libelium 4-20ma +// interface) +var sensor = new sensorObj.TEAMS(0, 165.0); + +// update and print available values every second +setInterval(function() +{ + // update our values from the sensor + sensor.update(); + + // is the sensor connected? (current >= 4ma) + console.log("Is Connected:", sensor.isConnected()); + + // print computed current on the loop. This includes the offset, + // if one was set by setOffsetMilliamps(). + console.log("Milliamps:", sensor.getRawMilliamps()); + + // we show both C and F for temperature + console.log("Temperature:", sensor.getTemperature(), + "C /", sensor.getTemperature(true), "F"); + + console.log(""); + +}, 1000); + + +process.on('SIGINT', function() +{ + sensor = null; + sensorObj.cleanUp(); + sensorObj = null; + console.log("Exiting..."); + process.exit(0); +}); diff --git a/examples/python/teams.py b/examples/python/teams.py new file mode 100644 index 00000000..8acfa092 --- /dev/null +++ b/examples/python/teams.py @@ -0,0 +1,65 @@ +#!/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_teams as sensorObj + +## 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) + +print "Initializing..." + +# Instantiate an TEAMS instance, using A0 for temperature, and +# 165.0 ohms for the rResistor value (for the libelium 4-20ma +# interface) +sensor = sensorObj.TEAMS(0, 165.0) + +# update and print available values every second +while (1): + # update our values from the sensor + sensor.update() + + # is the sensor connected? (current >= 4ma) + print "Is Connected:", sensor.isConnected() + + # print computed current on the loop. This includes the offset, + # if one was set by setOffsetMilliamps(). + print "Milliamps:", sensor.getRawMilliamps() + + # we show both C and F for temperature + print "Temperature:", sensor.getTemperature(), "C /", + print sensor.getTemperature(True), "F" + + print + time.sleep(1) diff --git a/src/teams/CMakeLists.txt b/src/teams/CMakeLists.txt new file mode 100644 index 00000000..8122e265 --- /dev/null +++ b/src/teams/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "teams") +set (libdescription "upm Veris TEAMS Temperature transmitter") +set (module_src ${libname}.cxx) +set (module_h ${libname}.h) +upm_module_init() diff --git a/src/teams/javaupm_teams.i b/src/teams/javaupm_teams.i new file mode 100644 index 00000000..ddf62b30 --- /dev/null +++ b/src/teams/javaupm_teams.i @@ -0,0 +1,19 @@ +%module javaupm_teams +%include "../upm.i" +%include "std_string.i" + +%include "teams.h" +%{ + #include "teams.h" +%} + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_teams"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. \n" + e); + System.exit(1); + } + } +%} diff --git a/src/teams/jsupm_teams.i b/src/teams/jsupm_teams.i new file mode 100644 index 00000000..73a8115e --- /dev/null +++ b/src/teams/jsupm_teams.i @@ -0,0 +1,10 @@ +%module jsupm_teams +%include "../upm.i" +%include "std_string.i" + +%{ + #include "teams.h" +%} + +%include "teams.h" + diff --git a/src/teams/pyupm_teams.i b/src/teams/pyupm_teams.i new file mode 100644 index 00000000..94d0d0b1 --- /dev/null +++ b/src/teams/pyupm_teams.i @@ -0,0 +1,13 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_teams +%include "../upm.i" +%include "std_string.i" + +%feature("autodoc", "3"); + +%{ + #include "teams.h" +%} +%include "teams.h" + diff --git a/src/teams/teams.cxx b/src/teams/teams.cxx new file mode 100644 index 00000000..794100a8 --- /dev/null +++ b/src/teams/teams.cxx @@ -0,0 +1,125 @@ +/* + * 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 "teams.h" + +using namespace upm; +using namespace std; + +// for current loop reads that seems a little noisy, we average over +// several aio reads. +static const int maxSamples = 50; + +// conversion from celcius to fahrenheit + +static float c2f(float c) +{ + return (c * (9.0 / 5.0) + 32.0); +} + + +TEAMS::TEAMS(int tPin, float rResistor, float aref) : + m_aioTemp(tPin) +{ + if (rResistor < 0.0) + { + throw std::out_of_range(std::string(__FUNCTION__) + + ": rResistor must be >= 0.0"); + } + + m_aResTemp = (1 << m_aioTemp.getBit()); + + m_temperature = 0.0; + + m_aref = aref; + m_rResistor = rResistor; + m_connected = false; + + // this will only be non-zero when using a direct 4-20ma interface + // like libelium + m_rawMilliamps = 0.0; + + m_offset = 0.0; +} + +TEAMS::~TEAMS() +{ +} + +void TEAMS::update() +{ + float milliamps = 0.0; + + int val = average(maxSamples); + float volts = (float(val) * (m_aref / m_aResTemp)); + + // valid temp range is 25.0 (35C - 10C), current loop range is 16ma + // (20ma - 4ma) + if (m_rResistor) + { + // direct 4-20 current loop interface + milliamps = (volts / m_rResistor * 1000.0) + m_offset; + m_rawMilliamps = milliamps; + + // subtract 0 (4ma) value + milliamps -= 4.0; + if (milliamps < 0.0) // not connected + { + milliamps = 0.0; + m_connected = false; + } + else + m_connected = true; + + m_temperature = (milliamps * (25.0 / 16.0)) + 10.0; + } + else + { + // normal analog read, already scaled to 0-5v, always connected + m_temperature = ((volts / m_aref) * 25.0) + 10.0; + m_connected = true; + } +} + +float TEAMS::getTemperature(bool fahrenheit) +{ + if (fahrenheit) + return c2f(m_temperature); + else + return m_temperature; +} + +int TEAMS::average(int samples) +{ + if (samples <= 0) + samples = 1; + + int avg = 0; + for (int i=0; i + * 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 + +// Unlikey to be changable +#define TEAMS_DEFAULT_AREF 5.0 + +namespace upm { + /** + * @brief Veris TEAMS Temperature Transmitter + * @defgroup teams libupm-teams + * @ingroup veris ainput temp + */ + + /** + * @library teams + * @sensor teams + * @comname Veris TEAMS Temperature Transmitter + * @type temp + * @man veris + * @con ainput + * @web http://www.veris.com/Item/TEAMS.aspx + * + * @brief API for the Veris TEAMS Temperature Transmitter + * + * The Veris TEAMS temperature sensor provides it's output via a + * 4-20ma current loop. The supported temperature range is 10C to + * 35C. + * + * This sensor was developed with a Cooking Hacks (Libelium) + * 4-channel 4-20ma Arduino interface shield. For this interface, + * the receiver resistance (rResistor) was specified as 165.0 + * ohms. + * + * When using a 4-20ma current loop interface which scales the + * sensors' values to a 0-5vdc range, you can supply 0.0 as the + * rResistor value in the constructor (default), and it will act + * just like a normal analog input. + * + * @snippet teams.cxx Interesting + */ + + class TEAMS { + public: + + /** + * TEAMS object constructor + * + * @param tPin Analog pin to use for temperature. + * @param rResistor The receiver resistance in ohms, when using a + * 4-20ma current loop interface. When specified, this value will + * be used in computing the current based on the voltage read when + * scaling the return values. Default is 0.0, for standard + * scaling based on voltage output rather than current (4-20ma + * mode). + * @param aref The analog reference voltage, default 5.0 + */ + TEAMS(int tPin, float rResistor=0.0, float aref=TEAMS_DEFAULT_AREF); + + /** + * TEAMS object destructor + */ + ~TEAMS(); + + /** + * Read current values from the sensor and update internal stored + * values. This method must be called prior to querying any + * values, such as temperature. + */ + void update(); + + /** + * Get the current temperature. update() must have been called + * prior to calling this method. + * + * @param fahrenheit true to return the temperature in degrees + * fahrenheit, false to return the temperature in degrees celcius. + * The default is false (degrees Celcius). + * @return The last temperature reading in Celcius or Fahrenheit + */ + float getTemperature(bool fahrenheit=false); + + /** + * When using a direct 4-20ma interface (rResistor supplied in the + * constructor is >0.0), this function will return false when the + * computed milliamps falls below 4ma, indicating that the sensor + * is not connected. If rResistor was specified as 0.0 in the + * constructor, this function will always return true. + * + * @return true if the sensor is connected, false otherwise. + */ + bool isConnected() + { + return m_connected; + }; + + /** + * When using a direct 4-20ma interface (rResistor supplied in the + * constructor is >0.0), this function will return the computed + * milliamps (after the offset has been applied). If rResistor was + * specified as 0.0 in the constructor, this function will always + * return 0.0. + * + * @return The last measured current in milliamps after any offset + * has been applied. + */ + float getRawMilliamps() + { + return m_rawMilliamps; + }; + + /** + * Specify an offset in milliamps to be applied to the computed + * current prior to scaling and conversion. This can be used to + * 'adjust' the computed value. If rResistor was specified as 0.0 + * in the constructor, this function will have no effect. + * + * @param offset a positive or negative value that will be applied + * to the computed current measured. + */ + void setOffsetMilliamps(float offset) + { + m_offset = offset; + }; + + protected: + mraa::Aio m_aioTemp; + + private: + float m_aref; + float m_rResistor; + int m_aResTemp; + + // for a 4-20 ma loop + bool m_connected; + float m_rawMilliamps; + + // in Celcius + float m_temperature; + + // in case an offset should be applied to the cumputed current + float m_offset; + + int average(int samples); + }; +} + +