From a94ee4382bb3f50b41f7a1b70374b25a48862cb6 Mon Sep 17 00:00:00 2001 From: TedObrien Date: Tue, 4 Feb 2025 11:43:01 +0000 Subject: [PATCH] MCP9808: Create driver for MCP9808 temperature sensor --- ROMFS/px4fmu_common/init.d/rc.sensors | 6 + boards/px4/fmu-v6x/default.px4board | 1 + msg/CMakeLists.txt | 1 + msg/SensorTemp.msg | 6 + src/drivers/drv_sensor.h | 2 + src/drivers/temperature_sensor/Kconfig | 3 + .../temperature_sensor/mcp9808/CMakeLists.txt | 44 ++++++ .../temperature_sensor/mcp9808/Kconfig | 5 + .../temperature_sensor/mcp9808/mcp9808.cpp | 124 +++++++++++++++++ .../temperature_sensor/mcp9808/mcp9808.h | 83 +++++++++++ .../mcp9808/mcp9808_main.cpp | 130 ++++++++++++++++++ .../mcp9808/mcp9808_params.c | 41 ++++++ src/modules/logger/logged_topics.cpp | 1 + 13 files changed, 447 insertions(+) create mode 100644 msg/SensorTemp.msg create mode 100644 src/drivers/temperature_sensor/Kconfig create mode 100644 src/drivers/temperature_sensor/mcp9808/CMakeLists.txt create mode 100644 src/drivers/temperature_sensor/mcp9808/Kconfig create mode 100644 src/drivers/temperature_sensor/mcp9808/mcp9808.cpp create mode 100644 src/drivers/temperature_sensor/mcp9808/mcp9808.h create mode 100644 src/drivers/temperature_sensor/mcp9808/mcp9808_main.cpp create mode 100644 src/drivers/temperature_sensor/mcp9808/mcp9808_params.c diff --git a/ROMFS/px4fmu_common/init.d/rc.sensors b/ROMFS/px4fmu_common/init.d/rc.sensors index d558d381b1..e01fd03c50 100644 --- a/ROMFS/px4fmu_common/init.d/rc.sensors +++ b/ROMFS/px4fmu_common/init.d/rc.sensors @@ -154,6 +154,12 @@ then fi fi +# Microchip MCP9808 temperature sensor external I2C +if param compare -s SENS_EN_MCP9808 1 +then + mcp9808 start -X +fi + # TE MS4515 differential pressure sensor external I2C if param compare -s SENS_EN_MS4515 1 then diff --git a/boards/px4/fmu-v6x/default.px4board b/boards/px4/fmu-v6x/default.px4board index 4a20430f10..2a3f0c9efb 100644 --- a/boards/px4/fmu-v6x/default.px4board +++ b/boards/px4/fmu-v6x/default.px4board @@ -43,6 +43,7 @@ CONFIG_DRIVERS_PWM_OUT=y CONFIG_DRIVERS_PX4IO=y CONFIG_COMMON_RC=y CONFIG_DRIVERS_SAFETY_BUTTON=y +CONFIG_DRIVERS_TEMPERATURE_SENSOR_MCP9808=y CONFIG_DRIVERS_TONE_ALARM=y CONFIG_DRIVERS_UAVCAN=y CONFIG_BOARD_UAVCAN_TIMER_OVERRIDE=2 diff --git a/msg/CMakeLists.txt b/msg/CMakeLists.txt index 7eda1cc316..5aae7118df 100644 --- a/msg/CMakeLists.txt +++ b/msg/CMakeLists.txt @@ -207,6 +207,7 @@ set(msg_files SensorSelection.msg SensorsStatus.msg SensorsStatusImu.msg + SensorTemp.msg SensorUwb.msg SensorAirflow.msg SystemPower.msg diff --git a/msg/SensorTemp.msg b/msg/SensorTemp.msg new file mode 100644 index 0000000000..303fb5ba42 --- /dev/null +++ b/msg/SensorTemp.msg @@ -0,0 +1,6 @@ +uint64 timestamp # time since system start (microseconds) +uint64 timestamp_sample # Time at which measurement was taken + +uint32 device_id # unique device ID for the sensor that does not change between power cycles + +float32 temperature # Temperature provided by sensor (Celsius) diff --git a/src/drivers/drv_sensor.h b/src/drivers/drv_sensor.h index eeafc722cf..82969aac2c 100644 --- a/src/drivers/drv_sensor.h +++ b/src/drivers/drv_sensor.h @@ -262,6 +262,8 @@ #define DRV_ADC_DEVTYPE_ADS7953 0xED +#define DRV_TEMP_DEVTYPE_MCP9808 0xEE + #define DRV_DEVTYPE_UNUSED 0xff #endif /* _DRV_SENSOR_H */ diff --git a/src/drivers/temperature_sensor/Kconfig b/src/drivers/temperature_sensor/Kconfig new file mode 100644 index 0000000000..af8c27e657 --- /dev/null +++ b/src/drivers/temperature_sensor/Kconfig @@ -0,0 +1,3 @@ +menu "TEMPERATURE_SENSOR" +rsource "*/Kconfig" +endmenu #TEMPERATURE_SENSOR diff --git a/src/drivers/temperature_sensor/mcp9808/CMakeLists.txt b/src/drivers/temperature_sensor/mcp9808/CMakeLists.txt new file mode 100644 index 0000000000..dd8325b7c4 --- /dev/null +++ b/src/drivers/temperature_sensor/mcp9808/CMakeLists.txt @@ -0,0 +1,44 @@ +############################################################################ +# +# Copyright (c) 2024 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__mcp9808 + MAIN mcp9808 + COMPILE_FLAGS + SRCS + mcp9808_main.cpp + mcp9808.cpp + mcp9808.h + DEPENDS + px4_work_queue + ) diff --git a/src/drivers/temperature_sensor/mcp9808/Kconfig b/src/drivers/temperature_sensor/mcp9808/Kconfig new file mode 100644 index 0000000000..f0f9f04145 --- /dev/null +++ b/src/drivers/temperature_sensor/mcp9808/Kconfig @@ -0,0 +1,5 @@ +menuconfig DRIVERS_TEMPERATURE_SENSOR_MCP9808 + bool "MCP9808 temperature sensor" + default n + ---help--- + Enable support MCP9808 temperature sensor diff --git a/src/drivers/temperature_sensor/mcp9808/mcp9808.cpp b/src/drivers/temperature_sensor/mcp9808/mcp9808.cpp new file mode 100644 index 0000000000..2cfebda67d --- /dev/null +++ b/src/drivers/temperature_sensor/mcp9808/mcp9808.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** + * + * Copyright (c) 2024 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 "mcp9808.h" + +int MCP9808::probe() +{ + uint16_t manuf_id, device_id; + int ret = read_reg(Register::MANUF_ID, manuf_id); + + if (ret != PX4_OK) { + return ret; + } + + ret = read_reg(Register::DEVICE_ID, device_id); + + if (ret != PX4_OK) { + return ret; + } + + // Verify manufacturer and device ID + if (manuf_id != 0x0054 || device_id != 0x0400) { + PX4_ERR("MCP9808 not found (manuf_id: 0x%04X, device_id: 0x%04X)", manuf_id, device_id); + return PX4_ERROR; + } + + PX4_INFO("MCP9808 found (manuf_id: 0x%04X, device_id: 0x%04X)", manuf_id, device_id); + return PX4_OK; +} + +int MCP9808::init() +{ + int ret = I2C::init(); + + if (ret != PX4_OK) { + PX4_ERR("I2C init failed"); + return ret; + } + + PX4_INFO("I2C initialized successfully"); + + ret = write_reg(Register::CONFIG, 0x0000); // Ensure default configuration + + if (ret != PX4_OK) { + PX4_ERR("Configuration failed"); + return ret; + } + + _to_sensor_temp.advertise(); + + ScheduleOnInterval(100_ms); // Sample at 10 Hz + return PX4_OK; +} + +float MCP9808::read_temperature() +{ + uint16_t temp_raw; + + if (read_reg(Register::AMBIENT_TEMP, temp_raw) != PX4_OK) { + return NAN; + } + + float temp = (temp_raw & 0x0FFF) / 16.0f; + + if (temp_raw & 0x1000) { + temp -= 256.0f; + } + + return temp; +} + +int MCP9808::read_reg(Register address, uint16_t &data) +{ + uint8_t addr = static_cast(address); + uint8_t buffer[2]; // Buffer to hold the raw data + + // Read 2 bytes from the register + int ret = transfer(&addr, 1, buffer, 2); + + if (ret != PX4_OK) { + return ret; + } + + // Combine bytes (big-endian) + data = (buffer[0] << 8) | buffer[1]; + + return PX4_OK; +} + +int MCP9808::write_reg(Register address, uint16_t value) +{ + uint8_t buf[3] = {static_cast(address), static_cast(value >> 8), static_cast(value & 0xFF)}; + return transfer(buf, sizeof(buf), nullptr, 0); +} diff --git a/src/drivers/temperature_sensor/mcp9808/mcp9808.h b/src/drivers/temperature_sensor/mcp9808/mcp9808.h new file mode 100644 index 0000000000..c26320b589 --- /dev/null +++ b/src/drivers/temperature_sensor/mcp9808/mcp9808.h @@ -0,0 +1,83 @@ +/**************************************************************************** + * + * Copyright (c) 2024 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; + +class MCP9808 : public device::I2C, public I2CSPIDriver +{ +public: + MCP9808(const I2CSPIDriverConfig &config); + ~MCP9808() override; + + int init() override; + int probe() override; + void RunImpl(); + static void print_usage(); + +protected: + void print_status() override; + void exit_and_cleanup() override; + +private: + enum class Register : uint8_t { + CONFIG = 0x01, + AMBIENT_TEMP = 0x05, + MANUF_ID = 0x06, + DEVICE_ID = 0x07, + RESOLUTION = 0x08 + }; + + uORB::PublicationMulti _to_sensor_temp{ORB_ID(sensor_temp)}; + perf_counter_t _cycle_perf; + + sensor_temp_s _sensor_temp{}; + + + int read_reg(Register address, uint16_t &data); + int write_reg(Register address, uint16_t value); + float read_temperature(); + + uint32_t measurement_time = 0; + +}; diff --git a/src/drivers/temperature_sensor/mcp9808/mcp9808_main.cpp b/src/drivers/temperature_sensor/mcp9808/mcp9808_main.cpp new file mode 100644 index 0000000000..1a0c619876 --- /dev/null +++ b/src/drivers/temperature_sensor/mcp9808/mcp9808_main.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** + * + * Copyright (c) 2024 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 mcp9808_main.cpp + * @author TedObrien + * + * Driver for the Microchip MCP9080 Temperature Sensor connected via I2C. + */ + +#include "mcp9808.h" +#include + +MCP9808::MCP9808(const I2CSPIDriverConfig &config) : + I2C(config), + I2CSPIDriver(config), + _cycle_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": single-sample")) +{ + _sensor_temp.device_id = this->get_device_id(); + +} + +MCP9808::~MCP9808() +{ + ScheduleClear(); + perf_free(_cycle_perf); +} + +void MCP9808::exit_and_cleanup() +{ + I2CSPIDriverBase::exit_and_cleanup(); // nothing to do +} + +void MCP9808::RunImpl() +{ + perf_begin(_cycle_perf); + + // publish at around 5HZ + if ((hrt_absolute_time() - measurement_time) > 200_ms) { + + measurement_time = hrt_absolute_time(); // get the time the measurement was taken + float temperature = read_temperature(); + + _sensor_temp.timestamp = hrt_absolute_time(); + _sensor_temp.timestamp_sample = measurement_time; + _sensor_temp.temperature = temperature; + + _to_sensor_temp.publish(_sensor_temp); + } + + perf_end(_cycle_perf); +} + +void MCP9808::print_usage() +{ + PRINT_MODULE_USAGE_NAME("mcp9808", "driver"); + PRINT_MODULE_USAGE_COMMAND("start"); + PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false); + PRINT_MODULE_USAGE_PARAMS_I2C_ADDRESS(0x18); + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); +} + + +void MCP9808::print_status() +{ + I2CSPIDriverBase::print_status(); + perf_print_counter(_cycle_perf); +} + +extern "C" int mcp9808_main(int argc, char *argv[]) +{ + using ThisDriver = MCP9808; + BusCLIArguments cli{true, false}; + cli.default_i2c_frequency = 400000; + cli.i2c_address = 0x18; + + const char *verb = cli.parseDefaultArguments(argc, argv); + + if (!verb) { + ThisDriver::print_usage(); + return -1; + } + + BusInstanceIterator iterator(MODULE_NAME, cli, DRV_TEMP_DEVTYPE_MCP9808); + + 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/drivers/temperature_sensor/mcp9808/mcp9808_params.c b/src/drivers/temperature_sensor/mcp9808/mcp9808_params.c new file mode 100644 index 0000000000..285e284da7 --- /dev/null +++ b/src/drivers/temperature_sensor/mcp9808/mcp9808_params.c @@ -0,0 +1,41 @@ +/**************************************************************************** + * + * Copyright (c) 2024 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. + * + ****************************************************************************/ + +/** + * Enable MCP9808 temperature sensor (external I2C) + * + * @reboot_required true + * @group Sensors + * @boolean + */ +PARAM_DEFINE_INT32(SENS_EN_MCP9808, 0); diff --git a/src/modules/logger/logged_topics.cpp b/src/modules/logger/logged_topics.cpp index bdca16eae3..033209150a 100644 --- a/src/modules/logger/logged_topics.cpp +++ b/src/modules/logger/logged_topics.cpp @@ -123,6 +123,7 @@ 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", 10); add_optional_topic("spoilers_setpoint", 1000); add_topic("system_power", 500); add_optional_topic("takeoff_status", 1000);