Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions Tools/autotest/ardusub.py
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,34 @@ def SHT3X(self):
if m is None:
raise NotAchievedException("Did not get good TEMP message")

def MCP9808(self):
'''test for the MCP9808 temperature driver'''

self.set_parameters({
'TEMP1_TYPE': 11, # Replace with your MCP9808 enum
'TEMP1_ADDR': 0x18, # MCP9808 default I2C address
'TEMP1_BUS': 0, # Bus used by your SITL simulator
'TEMP_LOG': 1,
})
self.reboot_sitl()
self.context_push()
self.set_parameter('LOG_DISARMED', 1)
self.delay_sim_time(10, reason="temperature data to be logged")
self.context_pop()

dfreader = self.dfreader_for_current_onboard_log()

while True:
m = dfreader.recv_match(type='TEMP')
if m is None:
break
self.progress(m)
# Check for a reasonable temperature
if 30 < m.Temp < 90:
return

raise NotAchievedException("Did not get valid MCP9808 TEMP message")

def MAV_mgs(self):
'''test individual GCS backends timestamps'''
self.reboot_sitl()
Expand Down Expand Up @@ -1644,6 +1672,7 @@ def tests(self):
self.INA3221,
self.PosHoldBounceBack,
self.SHT3X,
self.MCP9808,
self.SurfaceSensorless,
self.GPSForYaw,
self.WaterDepth,
Expand Down
1 change: 1 addition & 0 deletions Tools/scripts/build_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ def config_option(self):
Feature('Sensors', 'TEMP_MLX90614', 'AP_TEMPERATURE_SENSOR_MLX90614_ENABLED', 'Enable Temp Sensor - MLX90614', 0, "TEMP"),
Feature('Sensors', 'TEMP_SHT3X', 'AP_TEMPERATURE_SENSOR_SHT3X_ENABLED', 'Enable Temp Sensor - SHT3x', 0, "TEMP"),
Feature('Sensors', 'TEMP_TMP119', 'AP_TEMPERATURE_SENSOR_TMP119_ENABLED', 'Enable Temp Sensor - TMP119', 0, "TEMP"),
Feature('Sensors', 'TEMP_MCP9808', 'AP_TEMPERATURE_SENSOR_MCP9808_ENABLED', 'Enable Temp Sensor - MCP9808', 0, "TEMP"),

Feature('Sensors', 'AIRSPEED', 'AP_AIRSPEED_ENABLED', 'Enable Airspeed Sensors', 1, None), # Default to enabled to not annoy Plane users # NOQA: E501
Feature('Sensors', 'BEACON', 'AP_BEACON_ENABLED', 'Enable Beacon', 0, None),
Expand Down
6 changes: 6 additions & 0 deletions libraries/AP_TemperatureSensor/AP_TemperatureSensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "AP_TemperatureSensor_MLX90614.h"
#include "AP_TemperatureSensor_SHT3x.h"
#include "AP_TemperatureSensor_TMP119.h"
#include "AP_TemperatureSensor_MCP9808.h"

#include <AP_Logger/AP_Logger.h>
#include <AP_Vehicle/AP_Vehicle_Type.h>
Expand Down Expand Up @@ -344,6 +345,11 @@ void AP_TemperatureSensor::init()
case AP_TemperatureSensor_Params::Type::TMP119:
drivers[instance] = NEW_NOTHROW AP_TemperatureSensor_TMP119(*this, _state[instance], _params[instance]);
break;
#endif
#if AP_TEMPERATURE_SENSOR_MCP9808_ENABLED
case AP_TemperatureSensor_Params::Type::MCP9808:
drivers[instance] = NEW_NOTHROW AP_TemperatureSensor_MCP9808(*this, _state[instance], _params[instance]);
break;
#endif
case AP_TemperatureSensor_Params::Type::NONE:
default:
Expand Down
2 changes: 2 additions & 0 deletions libraries/AP_TemperatureSensor/AP_TemperatureSensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class AP_TemperatureSensor_TSYS03;
class AP_TemperatureSensor_Analog;
class AP_TemperatureSensor_MLX90614;
class AP_TemperatureSensor_TMP119;
class AP_TemperatureSensor_MCP9808;

class AP_TemperatureSensor
{
Expand All @@ -41,6 +42,7 @@ class AP_TemperatureSensor
friend class AP_TemperatureSensor_DroneCAN;
friend class AP_TemperatureSensor_MLX90614;
friend class AP_TemperatureSensor_TMP119;
friend class AP_TemperatureSensor_MCP9808;

public:

Expand Down
100 changes: 100 additions & 0 deletions libraries/AP_TemperatureSensor/AP_TemperatureSensor_MCP9808.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "AP_TemperatureSensor_config.h"

#if AP_TEMPERATURE_SENSOR_MCP9808_ENABLED

#include "AP_TemperatureSensor_MCP9808.h"
#include <AP_HAL/AP_HAL.h>
#include <AP_HAL/I2CDevice.h>
#include <AP_Math/AP_Math.h>

extern const AP_HAL::HAL &hal;

// MCP9808 register addresses
#define MCP9808_REG_AMBIENT_TEMP 0x05 // ambient temperature register
#define MCP9808_REG_RESOLUTION 0x08 // resolution register
// Resolution register - 0.25°C resolution (65ms conversion time)
#define MCP9808_RESOLUTION_VALUE 0x01

void AP_TemperatureSensor_MCP9808::init()
{
_params.bus_address.set_default(AP_TEMPERATURE_SENSOR_MCP9808_DEFAULT_I2C_ADDR);
_dev = hal.i2c_mgr->get_device_ptr( _params.bus, _params.bus_address);
if (_dev == nullptr) {
return;
}
WITH_SEMAPHORE(_dev->get_semaphore());
// Increase retries during startup
_dev->set_retries(10);
// Configure sensor resolution
if (!write_register8(MCP9808_REG_RESOLUTION, MCP9808_RESOLUTION_VALUE)) {
return;
Comment thread
lavleshpoyrekar marked this conversation as resolved.
}
// Reduce retries during normal operation
_dev->set_retries(3);
// Poll temperature at 10Hz (100ms)
_dev->register_periodic_callback(100 * AP_USEC_PER_MSEC, FUNCTOR_BIND_MEMBER(&AP_TemperatureSensor_MCP9808::_timer, void));
}

void AP_TemperatureSensor_MCP9808::_timer(void)
{
uint16_t raw;
if (!read_registers(MCP9808_REG_AMBIENT_TEMP, raw)) {
return;
}
// MCP9808 temperature register format:
// bit15 : Alert flag
// bit14-13 : Temperature alert status
// bit12 : Sign bit
// bit11-0 : Temperature data
//
// Temperature register LSB is always 0.0625°C
int16_t temp_raw = raw & 0x1FFF;
// Sign extend negative temperature values
if (temp_raw & 0x1000) {
temp_raw |= 0xE000;
}
float temp = temp_raw * 0.0625f;
set_temperature(temp);
}

bool AP_TemperatureSensor_MCP9808::read_registers(uint8_t reg, uint16_t &value) const
{
uint8_t val[2];
if (!_dev->transfer(&reg, 1, val, sizeof(val))) {
return false;
}
// MCP9808 registers are 16-bit big endian
value = UINT16_VALUE(val[0], val[1]);
return true;
}

bool AP_TemperatureSensor_MCP9808::write_register8(uint8_t reg, uint8_t value) const
{
// Registers are 8-bit big endian
uint8_t buf[2] = {reg, value};
return _dev->transfer(buf, sizeof(buf), nullptr, 0);
}

bool AP_TemperatureSensor_MCP9808::write_register(uint8_t reg, uint16_t value) const
{
// Registers are 16-bit big endian
uint8_t buf[3] {reg, uint8_t(value >> 8), uint8_t(value & 0xFF)};
return _dev->transfer(buf, sizeof(buf), nullptr, 0);
}

#endif // AP_TEMPERATURE_SENSOR_MCP9808_ENABLED
55 changes: 55 additions & 0 deletions libraries/AP_TemperatureSensor/AP_TemperatureSensor_MCP9808.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/*
* I2C driver for Microchip MCP9808 high-accuracy digital temperature sensor.
*
* The MCP9808 is a digital temperature sensor with 0.0625°C resolution.
* It communicates over I2C and provides a 16-bit ambient temperature register.
*/

#pragma once
#include "AP_TemperatureSensor_Backend.h"

#if AP_TEMPERATURE_SENSOR_MCP9808_ENABLED

#ifndef AP_TEMPERATURE_SENSOR_MCP9808_DEFAULT_I2C_ADDR
#define AP_TEMPERATURE_SENSOR_MCP9808_DEFAULT_I2C_ADDR 0x18
#endif


class AP_TemperatureSensor_MCP9808 : public AP_TemperatureSensor_Backend {
using AP_TemperatureSensor_Backend::AP_TemperatureSensor_Backend;
public:

__INITFUNC__ void init(void) override;

void update() override {};

private:
// update the temperature, called at 20Hz
void _timer(void);

// read a 16-bit big-endian register
bool read_registers(uint8_t reg, uint16_t &value) const;

// write a 16-bit big-endian register
bool write_register(uint8_t reg, uint16_t value) const;

// write a 8-bit big-endian register
bool write_register8(uint8_t reg, uint8_t value) const;
};

#endif // AP_TEMPERATURE_SENSOR_MCP9808_ENABLED
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const AP_Param::GroupInfo AP_TemperatureSensor_Params::var_info[] = {
// @Param: TYPE
// @DisplayName: Temperature Sensor Type
// @Description: Enables temperature sensors
// @Values: 0:Disabled, 1:TSYS01, 2:MCP9600, 3:MAX31865 2 or 4 wire, 4:TSYS03, 5:Analog, 6:DroneCAN, 7:MLX90614, 8:SHT3x, 9:MAX31865 3 wire, 10:TMP119
// @Values: 0:Disabled, 1:TSYS01, 2:MCP9600, 3:MAX31865 2 or 4 wire, 4:TSYS03, 5:Analog, 6:DroneCAN, 7:MLX90614, 8:SHT3x, 9:MAX31865 3 wire, 10:TMP119 ,11:MCP9808
// @User: Standard
// @RebootRequired: True
AP_GROUPINFO_FLAGS("TYPE", 1, AP_TemperatureSensor_Params, type, (float)Type::NONE, AP_PARAM_FLAG_ENABLE),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class AP_TemperatureSensor_Params {
SHT3x = 8,
MAX31865_3_wire = 9,
TMP119 = 10,
MCP9808 = 11,
};

// option to map to another system component
Expand Down
5 changes: 5 additions & 0 deletions libraries/AP_TemperatureSensor/AP_TemperatureSensor_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
#define AP_TEMPERATURE_SENSOR_TMP119_ENABLED AP_TEMPERATURE_SENSOR_BACKEND_DEFAULT_ENABLED
#endif // AP_TEMPERATURE_SENSOR_TMP119_ENABLED


#ifndef AP_TEMPERATURE_SENSOR_MCP9808_ENABLED
#define AP_TEMPERATURE_SENSOR_MCP9808_ENABLED AP_TEMPERATURE_SENSOR_BACKEND_DEFAULT_ENABLED
#endif // AP_TEMPERATURE_SENSOR_MCP9808_ENABLED

// maximum number of Temperature Sensors
#ifndef AP_TEMPERATURE_SENSOR_MAX_INSTANCES
#define AP_TEMPERATURE_SENSOR_MAX_INSTANCES 3
Expand Down
7 changes: 7 additions & 0 deletions libraries/SITL/SIM_I2C.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "SIM_Temperature_SHT3x.h"
#include "SIM_Temperature_TSYS01.h"
#include "SIM_Temperature_TSYS03.h"
#include "SIM_Temperature_MCP9808.h"
#include "SIM_TeraRangerI2C.h"
#include "SIM_TFS20L.h"
#include "SIM_ToshibaLED.h"
Expand Down Expand Up @@ -98,6 +99,9 @@ static TSYS03 tsys03;
#if AP_SIM_TEMPERATURE_MCP9600_ENABLED
static MCP9600 mcp9600;
#endif
#if AP_SIM_TEMPERATURE_MCP9808_ENABLED
static MCP9808 mcp9808;
#endif
#if AP_SIM_ICM40609_ENABLED
static ICM40609 icm40609;
#endif
Expand Down Expand Up @@ -162,6 +166,9 @@ struct i2c_device_at_address {
#if AP_SIM_TEMPERATURE_MCP9600_ENABLED
{ 0, 0x60, mcp9600 }, // 0x60 is low address
#endif
#if AP_SIM_TEMPERATURE_MCP9808_ENABLED
{ 0, 0x18, mcp9808 }, // MCP9808 default address
#endif
#if AP_SIM_MAXSONAR_I2C_XL_ENABLED
{ 0, 0x71, maxsonari2cxl_2 }, // RNGFNDx_TYPE = 2, RNGFNDx_ADDR = 113
#endif
Expand Down
84 changes: 84 additions & 0 deletions libraries/SITL/SIM_Temperature_MCP9808.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* SITL simulation for MCP9808 temperature sensor
*/

#include "SIM_config.h"

#if AP_SIM_TEMPERATURE_MCP9808_ENABLED

#include "SIM_Temperature_MCP9808.h"
#include <AP_HAL/AP_HAL.h>
#include <AP_Math/AP_Math.h>
using namespace SITL;

void MCP9808::init()
{
set_debug(true);
// Configuration register
add_register("CONFIG", MCP9808DevReg::CONFIG, 2, I2CRegisters::RegMode::RDWR);
set_register(MCP9808DevReg::CONFIG, uint16_t(htobe16(0x0000)));
// Ambient temperature register
add_register("AMBIENT_TEMP", MCP9808DevReg::AMBIENT_TEMP, 2, I2CRegisters::RegMode::RDONLY);
// Resolution register
add_register("RESOLUTION", MCP9808DevReg::RESOLUTION, 1, I2CRegisters::RegMode::RDWR);
// Default power-up resolution
// 0x03 = 0.0625°C, 250 ms
set_register(MCP9808DevReg::RESOLUTION, uint8_t(0x03));
}

void MCP9808::update(const Aircraft &aircraft)
{
const uint32_t now_ms = AP_HAL::millis();
// Read current resolution selected by ArduPilot
uint8_t resolution;
get_reg_value(MCP9808DevReg::RESOLUTION, resolution);

uint32_t conversion_time_ms = 250;

switch (resolution)
{
case 0x00:
conversion_time_ms = 30;
break;

case 0x01:
conversion_time_ms = 65;
break;

case 0x02:
conversion_time_ms = 130;
break;

case 0x03:
default:
conversion_time_ms = 250;
break;
}

if ((now_ms - last_temperature_update_ms) < conversion_time_ms) {
return;
}

last_temperature_update_ms = now_ms;

const float period_s = 10.0f; // One complete cycle every 10 sec
const float phase = (2.0f * M_PI * (now_ms * 0.001f)) / period_s;
const float temperature = 60.0f + 35.0f * sinf(phase);

// MCP9808 resolution = 0.0625°C
int16_t raw_temperature = int16_t(temperature / 0.0625f);
uint16_t value = uint16_t(raw_temperature & 0x0FFF);

if (temperature < 0) {
value |= (1 << 12);
}
set_register(
MCP9808DevReg::AMBIENT_TEMP, uint16_t(htobe16(value)));
}

int MCP9808::rdwr(I2C::i2c_rdwr_ioctl_data *&data)
{
return I2CRegisters_ConfigurableLength::rdwr(data);
}

#endif // AP_SIM_TEMPERATURE_MCP9808_ENABLED
Loading
Loading