Line data Source code
1 : /* 2 : This program is free software: you can redistribute it and/or modify 3 : it under the terms of the GNU General Public License as published by 4 : the Free Software Foundation, either version 3 of the License, or 5 : (at your option) any later version. 6 : 7 : This program is distributed in the hope that it will be useful, 8 : but WITHOUT ANY WARRANTY; without even the implied warranty of 9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 : GNU General Public License for more details. 11 : 12 : You should have received a copy of the GNU General Public License 13 : along with this program. If not, see <http://www.gnu.org/licenses/>. 14 : */ 15 : 16 : #include "AP_TemperatureSensor_TMP119.h" 17 : 18 : #if AP_TEMPERATURE_SENSOR_TMP119_ENABLED 19 : 20 : #include <AP_HAL/AP_HAL.h> 21 : #include <AP_HAL/I2CDevice.h> 22 : #include <AP_Math/AP_Math.h> 23 : 24 : extern const AP_HAL::HAL &hal; 25 : 26 : // register addresses 27 : #define TMP119_REG_TEMP 0x00 // temperature result register 28 : #define TMP119_REG_CONFIG 0x01 // configuration register 29 : #define TMP119_REG_DEVICE_ID 0x0F // device ID register 30 : 31 : #define TMP119_DEVICE_ID 0x2117 // value reported in the device ID register 32 : 33 : // each LSB of the temperature register is 7.8125 m degrees C 34 : #define TMP119_TEMP_PER_LSB 0.0078125f 35 : 36 : // configuration register fields 37 : #define TMP119_CONFIG_MOD_CONTINUOUS (0x0 << 10) // continuous conversion mode 38 : #define TMP119_CONFIG_CONV_15MS (0x0 << 7) // 15.5ms conversion cycle 39 : #define TMP119_CONFIG_AVG_NONE (0x0 << 5) // no averaging 40 : 41 : // continuous conversion, no averaging, shortest (15.5ms / ~64Hz) conversion 42 : // cycle so that a fresh sample is available for every 20Hz poll 43 : #define TMP119_CONFIG_VALUE (TMP119_CONFIG_MOD_CONTINUOUS | \ 44 : TMP119_CONFIG_CONV_15MS | \ 45 : TMP119_CONFIG_AVG_NONE) 46 : 47 0 : void AP_TemperatureSensor_TMP119::init() 48 : { 49 0 : _params.bus_address.set_default(AP_TEMPERATURE_SENSOR_TMP119_DEFAULT_I2C_ADDR); 50 : 51 0 : _dev = hal.i2c_mgr->get_device_ptr(_params.bus, _params.bus_address); 52 0 : if (!_dev) { 53 0 : return; 54 : } 55 : 56 0 : WITH_SEMAPHORE(_dev->get_semaphore()); 57 : 58 0 : _dev->set_retries(10); 59 : 60 : // confirm we are talking to a TMP119 61 : uint16_t device_id; 62 0 : if (!read_registers(TMP119_REG_DEVICE_ID, device_id) || (device_id != TMP119_DEVICE_ID)) { 63 0 : return; 64 : } 65 : 66 : // configure for continuous conversion with no averaging and the shortest 67 : // conversion cycle so a new measurement is ready for each 20Hz poll. The 68 : // power-up default is a 1Hz cycle with 8x averaging, which is too slow. 69 0 : if (!write_register(TMP119_REG_CONFIG, TMP119_CONFIG_VALUE)) { 70 0 : return; 71 : } 72 : 73 : // lower retries for run 74 0 : _dev->set_retries(3); 75 : 76 : // poll the temperature register at 20Hz 77 0 : _dev->register_periodic_callback(50 * AP_USEC_PER_MSEC, 78 : FUNCTOR_BIND_MEMBER(&AP_TemperatureSensor_TMP119::_timer, void)); 79 0 : } 80 : 81 0 : void AP_TemperatureSensor_TMP119::_timer(void) 82 : { 83 : uint16_t raw; 84 0 : if (!read_registers(TMP119_REG_TEMP, raw)) { 85 0 : return; 86 : } 87 : 88 : // the temperature register holds a signed 16-bit value 89 0 : const float temp = (int16_t)raw * TMP119_TEMP_PER_LSB; 90 0 : set_temperature(temp); 91 : } 92 : 93 0 : bool AP_TemperatureSensor_TMP119::read_registers(uint8_t reg, uint16_t &value) const 94 : { 95 : uint8_t val[2]; 96 0 : if (!_dev->transfer(®, 1, val, sizeof(val))) { 97 0 : return false; 98 : } 99 0 : value = UINT16_VALUE(val[0], val[1]); 100 0 : return true; 101 : } 102 : 103 0 : bool AP_TemperatureSensor_TMP119::write_register(uint8_t reg, uint16_t value) const 104 : { 105 : // registers are 16-bit big-endian 106 0 : uint8_t buf[3] { reg, uint8_t(value >> 8), uint8_t(value & 0xFF) }; 107 0 : return _dev->transfer(buf, sizeof(buf), nullptr, 0); 108 : } 109 : 110 : #endif // AP_TEMPERATURE_SENSOR_TMP119_ENABLED