diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..5f63eff --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,30 @@ +name: Test + +on: ["pull_request", "push"] + +jobs: + Test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Cache pip + uses: actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + - name: Cache PlatformIO + uses: actions/cache@v4 + with: + path: ~/.platformio + key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }} + - name: Set up Python + uses: actions/setup-python@v5 + - name: Install PlatformIO + run: | + python -m pip install --upgrade pip + pip install --upgrade platformio + - name: Run PlatformIO + run: platformio ci --lib="." --board=uno --board=megaatmega2560 examples/TMP119_Example/*.ino diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b8bd026 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..adbd1dd --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2026 Blue Robotics + +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. diff --git a/README.md b/README.md index a1f3bd1..1843a4b 100644 --- a/README.md +++ b/README.md @@ -1 +1,77 @@ # BlueRobotics TMP119 Temperature Sensor Library + +Arduino library for the TMP119 temperature sensor. The TMP119 is an ultra-high-accuracy, low-power digital temperature sensor from Texas Instruments with an I2C-compatible interface. + +# Documentation + +Please see the examples for normal operation. Below are the available functions used in the library. + +``` cpp +/** Construct an instance of the sensor manager. The TMP119 supports up to four + * I2C addresses (0x48 - 0x4B), selected by the ADD0 pin; the default address + * (ADD0 to GND) is 0x48. Uses the default Wire bus if left unspecified. + * (e.g. "TMP119 mySensor;" is equivilent to "TMP119 mySensor(0x48, &Wire);") + */ +TMP119(uint8_t address = 0x48, TwoWire *wire = &Wire); + +/** Initialize the sensor connection - return false if not detected. + * Configures the sensor for the fastest update rate (no averaging, shortest + * standby delay); call setAveraging()/setReadDelay() afterwards to override. + */ +bool init(); + +/** Reads the latest temperature conversion from the sensor. + */ +void read(); + +/** Temperature returned in deg C. + */ +float temperature(); + +/** Sets the conversion averaging mode (TMP119_AVERAGE_1X, _8X, _32X, _64X). + * More averaging reduces noise but takes longer per result (1X=15.5ms, + * 8X=125ms, 32X=500ms, 64X=1s). Returns false if the I2C write fails. + */ +bool setAveraging(tmp119_average_count_t avg); + +/** Sets the minimum standby delay between conversions in continuous-conversion + * mode (TMP119_DELAY_NONE, TMP119_DELAY_125_MS, _250_MS, _500_MS, _1000_MS, + * _4000_MS, _8000_MS, _16000_MS). Returns false if the I2C write fails. + */ +bool setReadDelay(tmp119_delay_t delay); + +/** Reads / writes the raw 16-bit configuration register (address 0x01) + * for advanced use. + */ +uint16_t getConfig(); +bool setConfig(uint16_t config); + +``` + +The TMP119 runs in continuous-conversion mode, so `read()` always returns the +latest result. `init()` configures the sensor for the fastest update rate (no +averaging, no added standby delay, ~15.5 ms cycle). To trade speed for lower +noise, call `setAveraging()` and `setReadDelay()` after `init()`. + +`setReadDelay()` sets only the *minimum* standby delay. The actual time between +readings is the greater of the averaging time and that standby delay (datasheet +Table 8-6). For example, `TMP119_AVERAGE_64X` always yields at least a ~1 s +cycle because the averaging alone takes 1 s, regardless of the delay setting. + +``` cpp +TMP119 sensor; +sensor.init(); // fastest rate by default +sensor.setAveraging(TMP119_AVERAGE_64X); // 64-sample averaging +sensor.setReadDelay(TMP119_DELAY_1000_MS); // ~1 s standby between reads +``` + +See `examples/TMP119_Example` for a complete sketch that reads the sensor +and configures averaging and the read delay (with all options listed). + +# Versions + +- `1.0.0` - initial release + +# Reference + +You can find the [TMP119 datasheet here](https://www.ti.com/lit/ds/symlink/tmp119.pdf). diff --git a/TMP119.cpp b/TMP119.cpp new file mode 100644 index 0000000..9186372 --- /dev/null +++ b/TMP119.cpp @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2026 Blue Robotics Inc. + +#include "TMP119.h" + +#define TMP119_TEMP_REG 0x00 +#define TMP119_CONFIG_REG 0x01 +#define TMP119_DEVICE_ID_REG 0x0F +#define TMP119_DEVICE_ID 0x2117 + +#define TMP119_CONV_SHIFT 7 +#define TMP119_CONV_MASK 0x0380 // CONV[2:0], bits 9:7 +#define TMP119_AVG_SHIFT 5 +#define TMP119_AVG_MASK 0x0060 // AVG[1:0], bits 6:5 + +TMP119::TMP119(uint8_t address, TwoWire *wire) { + _address = address; + _wire = wire; +} + +bool TMP119::init() { + // Verify the device by reading its ID register + _wire->beginTransmission(_address); + _wire->write(TMP119_DEVICE_ID_REG); + _wire->endTransmission(); + + if ( _wire->requestFrom(_address, (uint8_t)2) != 2 ) { + return false; + } + + uint16_t id = (_wire->read() << 8) | _wire->read(); + if ( id != TMP119_DEVICE_ID ) { + return false; + } + + // Configure for the fastest update rate: no averaging and no added standby + // delay, giving a ~15.5 ms conversion cycle (datasheet Table 8-6) + uint16_t config = getConfig(); + // Cute trick to set all the values to zero to acheive AVG = 1X, delay = none + config &= ~(TMP119_AVG_MASK | TMP119_CONV_MASK); + return setConfig(config); +} + +void TMP119::read() { + // The TMP119 powers up in continuous-conversion mode, so the + // temperature register always holds the most recent conversion. + _wire->beginTransmission(_address); + _wire->write(TMP119_TEMP_REG); + _wire->endTransmission(); + + _wire->requestFrom(_address, (uint8_t)2); + int16_t raw = (_wire->read() << 8) | _wire->read(); + + // Each LSB represents 0.0078125 deg C, data is in 2's complement format + TEMP = raw * 0.0078125f; +} + +float TMP119::temperature() { + return TEMP; +} + +uint16_t TMP119::getConfig() { + _wire->beginTransmission(_address); + _wire->write(TMP119_CONFIG_REG); + _wire->endTransmission(); + + _wire->requestFrom(_address, (uint8_t)2); + return (_wire->read() << 8) | _wire->read(); +} + +bool TMP119::setConfig(uint16_t config) { + _wire->beginTransmission(_address); + _wire->write(TMP119_CONFIG_REG); + _wire->write(config >> 8); // MSB first + _wire->write(config & 0xFF); // LSB + return _wire->endTransmission() == 0; +} + +bool TMP119::setAveraging(tmp119_average_count_t avg) { + uint16_t config = getConfig(); + config = (config & ~TMP119_AVG_MASK) | ((uint16_t)avg << TMP119_AVG_SHIFT); + return setConfig(config); +} + +bool TMP119::setReadDelay(tmp119_delay_t delay) { + uint16_t config = getConfig(); + config = (config & ~TMP119_CONV_MASK) | ((uint16_t)delay << TMP119_CONV_SHIFT); + return setConfig(config); +} diff --git a/TMP119.h b/TMP119.h new file mode 100644 index 0000000..a3bb715 --- /dev/null +++ b/TMP119.h @@ -0,0 +1,104 @@ +/* Blue Robotics Arduino TMP119 Temperature Sensor Library + * + * This library provides utilities to communicate with and read data from the + * Texas Instruments TMP119 high-accuracy temperature sensor. + * + * Author: Zachariah Mears, Blue Robotics Inc. + * + * SPDX-License-Identifier: MIT + * Copyright (c) 2026 Blue Robotics Inc. + */ + +#ifndef TMP119_H_BLUEROBOTICS +#define TMP119_H_BLUEROBOTICS + +#include "Arduino.h" +#include + +/** Conversion averaging mode (AVG[1:0], configuration register bits 6:5). + * Determines how many conversions are accumulated and averaged before the + * temperature register updates. More averaging reduces noise but takes longer + * to produce each result. The time to compute one averaged result is the + * per-mode minimum conversion time shown below (datasheet Table 8-6). + * Power-on default: TMP119_AVERAGE_8X. + */ +typedef enum { + TMP119_AVERAGE_1X, // No averaging (min conversion time 15.5 ms) + TMP119_AVERAGE_8X, // 8 conversions (min conversion time 125 ms, default) + TMP119_AVERAGE_32X, // 32 conversions (min conversion time 500 ms) + TMP119_AVERAGE_64X, // 64 conversions (min conversion time 1 s) +} tmp119_average_count_t; + +/** Minimum standby delay inserted between conversions in continuous-conversion + * mode (CONV[2:0], configuration register bits 9:7). + * + * This is not the actual time between readings on its own. The actual + * conversion cycle time is the greater of this standby delay and the time + * needed by the selected averaging mode (see tmp119_average_count_t). For + * example, TMP119_DELAY_NONE with TMP119_AVERAGE_64X still produces a ~1 s + * cycle because the 64x average alone takes 1 s. See datasheet Table 8-6. + * + * Power-on default: TMP119_DELAY_1000_MS. + */ +typedef enum { + TMP119_DELAY_NONE, // no added standby delay + TMP119_DELAY_125_MS, + TMP119_DELAY_250_MS, + TMP119_DELAY_500_MS, + TMP119_DELAY_1000_MS, // power-on default + TMP119_DELAY_4000_MS, + TMP119_DELAY_8000_MS, + TMP119_DELAY_16000_MS, +} tmp119_delay_t; + +class TMP119 { +public: + + /** The TMP119 supports up to four I2C addresses (0x48 - 0x4B), selected + * by the ADD0 pin. The default address (ADD0 to GND) is 0x48. + */ + TMP119(uint8_t address = 0x48, TwoWire *wire = &Wire); + + /** Initialize the sensor connection - returns false if not detected. + * Configures the sensor for the fastest update rate (no averaging and + * the shortest standby delay). Call setAveraging() / setReadDelay() + * afterwards to override. + */ + bool init(); + + /** Reads the latest temperature conversion from the sensor. + */ + void read(); + + /** Temperature returned in deg C. + */ + float temperature(); + + /** Sets the conversion averaging mode. Returns false if the I2C write + * fails. Other configuration bits are preserved. + */ + bool setAveraging(tmp119_average_count_t avg); + + /** Sets the minimum standby delay between conversions in + * continuous-conversion mode. Returns false if the I2C write fails. + * Other configuration bits are preserved. + */ + bool setReadDelay(tmp119_delay_t delay); + + /** Reads the raw 16-bit configuration register (address 0x01). + */ + uint16_t getConfig(); + + /** Writes the raw 16-bit configuration register (address 0x01). Returns + * false if the I2C write fails. Read-only bits are ignored by the device. + */ + bool setConfig(uint16_t config); + +private: + TwoWire* _wire; + uint8_t _address; + float TEMP; + +}; + +#endif diff --git a/examples/TMP119_Example/TMP119_Example.ino b/examples/TMP119_Example/TMP119_Example.ino new file mode 100644 index 0000000..cad015e --- /dev/null +++ b/examples/TMP119_Example/TMP119_Example.ino @@ -0,0 +1,65 @@ +/* Blue Robotics TMP119 Library Example + * + * This example demonstrates the TMP119 Library with a connected sensor. It + * reads the sensor and prints the values to the serial terminal, and shows how + * to configure the conversion averaging and the standby delay between + * conversions. After init(), the sensor is set to its fastest update rate; + * here we override that with heavy averaging and a 1 second cycle for low-noise + * readings. + * + * Designed for the Arduino Uno; compile and upload via the Arduino 1.0+ IDE. + * + * SPDX-License-Identifier: MIT + * Copyright (c) 2026 Blue Robotics Inc. + */ + +#include +#include "TMP119.h" + +// Optional constructor parameters: TMP119(address, wire) +// address - I2C address set by the ADD0 pin (default 0x48): +// 0x48 (GND), 0x49 (V+), 0x4A (SDA), 0x4B (SCL) +// wire - I2C bus to use (default &Wire) +// e.g. "TMP119 sensor;" is equivalent to "TMP119 sensor(0x48, &Wire);" +TMP119 sensor; + +void setup() { + Serial.begin(9600); + Serial.println("Starting"); + + Wire.begin(); + + while (!sensor.init()) { + Serial.println("TMP119 device failed to initialize!"); + delay(2000); + } + + // Override the fast defaults set by init() with low-noise settings: + // average 64 conversions and update roughly once per second. + // + // Averaging options (setAveraging) and the time each takes per result: + // TMP119_AVERAGE_1X -> 15.5 ms + // TMP119_AVERAGE_8X -> 125 ms + // TMP119_AVERAGE_32X -> 500 ms + // TMP119_AVERAGE_64X -> 1 s + // + // Minimum standby delay options (setReadDelay): + // TMP119_DELAY_NONE, TMP119_DELAY_125_MS, TMP119_DELAY_250_MS, + // TMP119_DELAY_500_MS, TMP119_DELAY_1000_MS, TMP119_DELAY_4000_MS, + // TMP119_DELAY_8000_MS, TMP119_DELAY_16000_MS + // + // The actual time between readings is the greater of the averaging time + // above and the standby delay (datasheet Table 8-6). So 64x averaging with + // TMP119_DELAY_1000_MS gives ~1 s, but 64x with TMP119_DELAY_NONE is also + // ~1 s since the averaging itself takes 1 s. + sensor.setAveraging(TMP119_AVERAGE_64X); + sensor.setReadDelay(TMP119_DELAY_1000_MS); +} + +void loop() { + sensor.read(); + Serial.print("Temperature: "); + Serial.print(sensor.temperature()); + Serial.println(" deg C"); + delay(1000); +} diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..cbf779d --- /dev/null +++ b/library.properties @@ -0,0 +1,9 @@ +name=BlueRobotics TMP119 Library +version=1.0.0 +author=BlueRobotics +maintainer=BlueRobotics +sentence=A simple and easy library for the TMP119 temperature sensor +paragraph=A simple and easy library for the TMP119 temperature sensor +category=Sensors +url=https://github.com/bluerobotics/BlueRobotics_TMP119_Library +architectures=*