From 46d9b14ba0d2e23ee6f76fddad8a45240585d74e Mon Sep 17 00:00:00 2001 From: Phil-Engljaehringer Date: Mon, 12 Jan 2026 18:42:51 +0100 Subject: [PATCH] Feat: Add driver for TMP102 temperature sensor for Skynode-N (#26241) * feat: added driver for tmp102 temperature sensor * style: removed new line * style: adjusted date in header * style: removed duplicated logging * fix: moved start-up command from rc.board_sensors to rc.sensors * style: used consexpr for expected config reg value * feat: added retry logic to probe function * style: added _ as prefix to global variable * style: used make format * fix: corrected temperature calculation * fix: mask AL-bit in probe function * style: removed header files from CMakeLists * style: used correct english in comments * refactor: return error right after failure * style: moved init call to correct place * fix: corrected temperature calculation (again) * refactor: removed _curr_pr variable => always have to set PR to desired register on read * fix: add multi logged topic --- ROMFS/px4fmu_common/init.d/rc.sensors | 6 + src/drivers/drv_sensor.h | 1 + .../temperature_sensor/tmp102/CMakeLists.txt | 45 ++++++ src/drivers/temperature_sensor/tmp102/Kconfig | 5 + .../temperature_sensor/tmp102/module.yaml | 15 ++ .../temperature_sensor/tmp102/tmp102.cpp | 129 ++++++++++++++++++ .../temperature_sensor/tmp102/tmp102.h | 73 ++++++++++ .../temperature_sensor/tmp102/tmp102_main.cpp | 90 ++++++++++++ src/modules/logger/logged_topics.cpp | 2 +- 9 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 src/drivers/temperature_sensor/tmp102/CMakeLists.txt create mode 100644 src/drivers/temperature_sensor/tmp102/Kconfig create mode 100644 src/drivers/temperature_sensor/tmp102/module.yaml create mode 100644 src/drivers/temperature_sensor/tmp102/tmp102.cpp create mode 100644 src/drivers/temperature_sensor/tmp102/tmp102.h create mode 100644 src/drivers/temperature_sensor/tmp102/tmp102_main.cpp diff --git a/ROMFS/px4fmu_common/init.d/rc.sensors b/ROMFS/px4fmu_common/init.d/rc.sensors index b67384483b..ea6b8d4f1e 100644 --- a/ROMFS/px4fmu_common/init.d/rc.sensors +++ b/ROMFS/px4fmu_common/init.d/rc.sensors @@ -237,6 +237,12 @@ then tla2528 start -X fi +# Start TMP102 temperature sensor +if param compare SENS_EN_TMP102 1 +then + tmp102 start -X +fi + # probe for optional external I2C devices if param compare SENS_EXT_I2C_PRB 1 then diff --git a/src/drivers/drv_sensor.h b/src/drivers/drv_sensor.h index 32ec379ac9..bcd663dd05 100644 --- a/src/drivers/drv_sensor.h +++ b/src/drivers/drv_sensor.h @@ -267,6 +267,7 @@ #define DRV_TEMP_DEVTYPE_MCP9808 0xEE +#define DRV_TEMP_DEVTYPE_TMP102 0xF0 #define DRV_DEVTYPE_UNUSED 0xff diff --git a/src/drivers/temperature_sensor/tmp102/CMakeLists.txt b/src/drivers/temperature_sensor/tmp102/CMakeLists.txt new file mode 100644 index 0000000000..39e23322ba --- /dev/null +++ b/src/drivers/temperature_sensor/tmp102/CMakeLists.txt @@ -0,0 +1,45 @@ +############################################################################ +# +# Copyright (c) 2026 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +px4_add_module( + MODULE drivers__temperature_sensor__tmp102 + MAIN tmp102 + COMPILE_FLAGS + SRCS + tmp102_main.cpp + tmp102.cpp + MODULE_CONFIG + module.yaml + DEPENDS + px4_work_queue + ) diff --git a/src/drivers/temperature_sensor/tmp102/Kconfig b/src/drivers/temperature_sensor/tmp102/Kconfig new file mode 100644 index 0000000000..977a82929b --- /dev/null +++ b/src/drivers/temperature_sensor/tmp102/Kconfig @@ -0,0 +1,5 @@ +menuconfig DRIVERS_TEMPERATURE_SENSOR_TMP102 + bool "TMP102 temperature sensor" + default n + ---help--- + Enable support for the TMP102 temperature sensor diff --git a/src/drivers/temperature_sensor/tmp102/module.yaml b/src/drivers/temperature_sensor/tmp102/module.yaml new file mode 100644 index 0000000000..1d159deaa7 --- /dev/null +++ b/src/drivers/temperature_sensor/tmp102/module.yaml @@ -0,0 +1,15 @@ +__max_num_config_instances: &max_num_config_instances 1 + +module_name: TMP102 + +parameters: + - group: Sensors + definitions: + SENS_EN_TMP102: + description: + short: Enable TMP102 + long: | + Enable the driver for the TMP102 temperature sensor + type: boolean + reboot_required: true + default: 0 diff --git a/src/drivers/temperature_sensor/tmp102/tmp102.cpp b/src/drivers/temperature_sensor/tmp102/tmp102.cpp new file mode 100644 index 0000000000..5dc9df27e3 --- /dev/null +++ b/src/drivers/temperature_sensor/tmp102/tmp102.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include "tmp102.h" + +TMP102::TMP102(const I2CSPIDriverConfig &config) : + I2C(config), + I2CSPIDriver(config), + _cycle_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": single-sample")), + _comms_errors(perf_alloc(PC_COUNT, MODULE_NAME": comms errors")) +{ +} + +TMP102::~TMP102() +{ + ScheduleClear(); + perf_free(_cycle_perf); + perf_free(_comms_errors); +} + +void TMP102::RunImpl() +{ + if (should_exit()) { + exit_and_cleanup(); + return; + } + + perf_begin(_cycle_perf); + + float temperature = read_temperature(); + + if (std::isnan(temperature)) { + perf_count(_comms_errors); + + } else { + sensor_temp_s _sensor_temp{}; + _sensor_temp.timestamp = hrt_absolute_time(); + _sensor_temp.temperature = temperature; + _sensor_temp.device_id = get_device_id(); + _sensor_temp_pub.publish(_sensor_temp); + } + + perf_end(_cycle_perf); +} + +int TMP102::probe() +{ + uint16_t conf_reg; + + for (int i = 0; i < 3; i++) { + if (read_reg(TMP102_CONFIG_REG, conf_reg) == PX4_OK && (conf_reg | 0x0020) == DEFAULT_CONFIG_REG) { // Mask the AL bit + return PX4_OK; + } + + px4_sleep(1); + } + + return PX4_ERROR; +} + +int TMP102::init() +{ + int ret = I2C::init(); + + if (ret != PX4_OK) { + PX4_ERR("TMP102, I2C init failed"); + return ret; + } + + _sensor_temp_pub.advertise(); + ScheduleOnInterval(250_ms); // DEFAULT SAMPLE RATE IS 4HZ => 250ms INTERVAL + return PX4_OK; +} + +float TMP102::read_temperature() +{ + uint16_t tmp_data; + + if (read_reg(TMP102_TEMP_REG, tmp_data) != PX4_OK) { + return NAN; + } + + float temperature = ((int16_t)(tmp_data) >> 4) * 0.0625f; + return temperature; +} + +int TMP102::read_reg(uint8_t reg, uint16_t &data) +{ + uint8_t tmp_data[2]; + tmp_data[0] = reg; + + if (transfer(tmp_data, 1, nullptr, 0) != PX4_OK) { // Set the PR to the desired register + return PX4_ERROR; + } + + int ret = transfer(nullptr, 0, tmp_data, 2); // Read the data from the desired register + data = (tmp_data[0] << 8) | tmp_data[1]; + return ret; +} diff --git a/src/drivers/temperature_sensor/tmp102/tmp102.h b/src/drivers/temperature_sensor/tmp102/tmp102.h new file mode 100644 index 0000000000..e0265867a6 --- /dev/null +++ b/src/drivers/temperature_sensor/tmp102/tmp102.h @@ -0,0 +1,73 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +using namespace time_literals; + +#define TMP102_TEMP_REG 0x00 +#define TMP102_CONFIG_REG 0x01 +#define TMP102_TLOW_REG 0x02 +#define TMP102_THIGH_REG 0x03 + +constexpr uint16_t DEFAULT_CONFIG_REG = 0x60A0; // 12-bit resolution, comparator mode, active low, 4Hz + +class TMP102 : public device::I2C, public I2CSPIDriver +{ +public: + TMP102(const I2CSPIDriverConfig &config); + ~TMP102() override; + + int init() override; + int probe() override; + void RunImpl(); + static void print_usage(); + +protected: + void print_status(); + +private: + uORB::PublicationMulti _sensor_temp_pub{ORB_ID(sensor_temp)}; + perf_counter_t _cycle_perf; + perf_counter_t _comms_errors; + + float read_temperature(); + int read_reg(uint8_t address, uint16_t &data); +}; diff --git a/src/drivers/temperature_sensor/tmp102/tmp102_main.cpp b/src/drivers/temperature_sensor/tmp102/tmp102_main.cpp new file mode 100644 index 0000000000..22ea03bcbf --- /dev/null +++ b/src/drivers/temperature_sensor/tmp102/tmp102_main.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** + * + * Copyright (c) 2026 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file tmp102_main.cpp + * @author Philipp Engljaehringer + * + * Driver for the TMP102 Temperature Sensor connected via I2C. + */ + +#include "tmp102.h" +#include + +void TMP102::print_usage() +{ + PRINT_MODULE_USAGE_NAME("tmp102", "driver"); + PRINT_MODULE_USAGE_COMMAND("start"); + PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false); + PRINT_MODULE_USAGE_PARAMS_I2C_ADDRESS(0x48); + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); +} + +void TMP102::print_status() +{ + I2CSPIDriverBase::print_status(); + perf_print_counter(_cycle_perf); + perf_print_counter(_comms_errors); +} + +extern "C" int tmp102_main(int argc, char *argv[]) +{ + using ThisDriver = TMP102; + BusCLIArguments cli{true, false}; + cli.default_i2c_frequency = 400000; + cli.i2c_address = 0x48; + + const char *verb = cli.parseDefaultArguments(argc, argv); + + if (!verb) { + ThisDriver::print_usage(); + return -1; + } + + BusInstanceIterator iterator(MODULE_NAME, cli, DRV_TEMP_DEVTYPE_TMP102); + + if (!strcmp(verb, "start")) { + return ThisDriver::module_start(cli, iterator); + } + + if (!strcmp(verb, "stop")) { + return ThisDriver::module_stop(iterator); + } + + if (!strcmp(verb, "status")) { + return ThisDriver::module_status(iterator); + } + + ThisDriver::print_usage(); + return -1; +} diff --git a/src/modules/logger/logged_topics.cpp b/src/modules/logger/logged_topics.cpp index 43a4c40fb5..9f585500eb 100644 --- a/src/modules/logger/logged_topics.cpp +++ b/src/modules/logger/logged_topics.cpp @@ -125,7 +125,6 @@ void LoggedTopics::add_default_topics() add_optional_topic("sensor_gyro_fft", 50); add_topic("sensor_selection"); add_topic("sensors_status_imu", 200); - add_optional_topic("sensor_temp", 100); add_optional_topic("spoilers_setpoint", 1000); add_topic("system_power", 500); add_optional_topic("takeoff_status", 1000); @@ -167,6 +166,7 @@ void LoggedTopics::add_default_topics() add_optional_topic_multi("control_allocator_status", 200, 2); add_optional_topic_multi("rate_ctrl_status", 200, 2); add_optional_topic_multi("sensor_hygrometer", 500, 4); + add_optional_topic_multi("sensor_temp", 100, 4); add_optional_topic_multi("rpm", 200); add_topic_multi("timesync_status", 1000, 3); add_optional_topic_multi("telemetry_status", 1000, 4);