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_TSYS03.h" 17 : 18 : #if AP_TEMPERATURE_SENSOR_TSYS03_ENABLED 19 : #include <utility> 20 : #include <stdio.h> 21 : #include <AP_HAL/I2CDevice.h> 22 : #include <AP_Math/AP_Math.h> 23 : 24 : #include <GCS_MAVLink/GCS.h> 25 : 26 : #ifndef AP_TEMPERATURE_SENSOR_TSYS03_ENFORCE_KNOWN_VALID_I2C_ADDRESS 27 : #define AP_TEMPERATURE_SENSOR_TSYS03_ENFORCE_KNOWN_VALID_I2C_ADDRESS 1 28 : #endif 29 : 30 : extern const AP_HAL::HAL &hal; 31 : 32 : static const uint8_t TSYS03_CMD_RESET = 0x1E; 33 : static const uint8_t TSYS03_CMD_CONVERT = 0x46; 34 : static const uint8_t TSYS03_CMD_READ_ADC = 0x00; 35 : 36 0 : void AP_TemperatureSensor_TSYS03::init() 37 : { 38 0 : constexpr char name[] = "TSYS03"; 39 : (void)name; // sometimes this is unused (e.g. HAL_GCS_ENABLED false) 40 : 41 : #if AP_TEMPERATURE_SENSOR_TSYS03_ENFORCE_KNOWN_VALID_I2C_ADDRESS 42 : // I2C Address: Default to using TSYS03_ADDR_CSB0 & Check I2C Address is Correct 43 0 : if ((_params.bus_address != TSYS03_ADDR_CSB0) ) { 44 0 : GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "%s wrong I2C addr of 0x%2X, setting to 0x%2X", name, (unsigned)_params.bus_address.get(), (unsigned)TSYS03_ADDR_CSB0); 45 0 : _params.bus_address.set(TSYS03_ADDR_CSB0); 46 : } 47 : #endif 48 : 49 0 : _dev = hal.i2c_mgr->get_device_ptr(_params.bus, _params.bus_address); 50 0 : if (!_dev) { 51 0 : GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "%s device is null!", name); 52 0 : return; 53 : } 54 : 55 0 : WITH_SEMAPHORE(_dev->get_semaphore()); 56 : 57 0 : _dev->set_retries(10); 58 : 59 : // reset 60 0 : if (!_dev->transfer(&TSYS03_CMD_RESET, 1, nullptr, 0)) { 61 0 : GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "%s reset failed", name); 62 0 : return; 63 : } 64 : 65 0 : hal.scheduler->delay(4); 66 : 67 0 : start_next_sample(); 68 : 69 : // lower retries for run 70 0 : _dev->set_retries(3); 71 : 72 : /* Request 20Hz update */ 73 : // Max conversion time is 9.04 ms 74 0 : _dev->register_periodic_callback(50 * AP_USEC_PER_MSEC, 75 : FUNCTOR_BIND_MEMBER(&AP_TemperatureSensor_TSYS03::_timer, void)); 76 0 : } 77 : 78 0 : uint16_t AP_TemperatureSensor_TSYS03::read_adc() const 79 : { 80 : uint8_t val[3]; 81 0 : if (!_dev->transfer(&TSYS03_CMD_READ_ADC, 1, val, 3)) { 82 0 : return 0; 83 : } 84 : 85 : // ensure crc is correct: 86 0 : uint8_t expected_crc = 0; 87 0 : for (uint8_t i=0; i<2; i++) { 88 0 : expected_crc = crc8_dvb(expected_crc, val[i], 0x31); 89 : } 90 0 : if (expected_crc != val[2]) { 91 0 : return 0; 92 : } 93 : 94 0 : return UINT16_VALUE(val[0],val[1]); 95 : } 96 : 97 0 : void AP_TemperatureSensor_TSYS03::_timer(void) 98 : { 99 0 : const uint16_t adc = read_adc(); 100 : 101 0 : if (adc != 0) { 102 0 : const float temp = calculate(adc); 103 0 : set_temperature(temp); 104 : } 105 : 106 0 : start_next_sample(); 107 0 : } 108 : 109 0 : void AP_TemperatureSensor_TSYS03::start_next_sample() 110 : { 111 0 : _dev->transfer(&TSYS03_CMD_CONVERT, 1, nullptr, 0); 112 0 : } 113 : 114 0 : float AP_TemperatureSensor_TSYS03::calculate(const uint16_t adc) const 115 : { 116 0 : const float temperature = -40.0 + adc * 165 / (powf(2, 16) - 1.0); 117 : 118 0 : return temperature; 119 : } 120 : 121 : #endif // AP_TEMPERATURE_SENSOR_TSYS03_ENABLED