Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[driver] TMP12x temperature sensor #757

Merged
merged 3 commits into from
Oct 21, 2021
Merged
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -667,11 +667,12 @@ you specific needs.
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tlc594x">TLC594X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp102">TMP102</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp12x">TMP12X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp175">TMP175</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-touch2046">TOUCH2046</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl53l0">VL53L0</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl6180">VL6180</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl6180">VL6180</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ws2812">WS2812</a></td>
</tr>
</table>
Expand Down
50 changes: 50 additions & 0 deletions examples/nucleo_f042k6/tmp12x/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2021, Christopher Durand
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include <modm/board.hpp>
#include <modm/driver/temperature/tmp12x.hpp>
#include <modm/processing/timer.hpp>

using namespace Board;
using namespace std::chrono_literals;

/*
* Example for the TMP12x driver
* It assumes a TMP121 or TM123 is connected to the following pins:
* A4 CS
* A5 SCK
* A6 MISO
*/

using SpiCs = GpioA4;
using SpiSck = GpioA5;
using SpiMiso = GpioA6;

int
main()
{
Board::initialize();

MODM_LOG_INFO << "TMP12x test" << modm::endl;

SpiMaster1::connect<SpiSck::Sck, SpiMiso::Miso>();
SpiMaster1::initialize<SystemClock, 1'500'000_Hz>();

modm::Tmp123<SpiMaster1, SpiCs> sensor;
sensor.initialize();

modm::PeriodicTimer timer{500ms};
while(true) {
if (timer.execute()) {
const modm::Tmp123Temperature temperature = RF_CALL_BLOCKING(sensor.read());
MODM_LOG_INFO.printf("Temperature %2.2f\n", temperature.getTemperatureFloat());
}
}
}
12 changes: 12 additions & 0 deletions examples/nucleo_f042k6/tmp12x/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<library>
<extends>modm:nucleo-f042k6</extends>
<options>
<option name="modm:build:build.path">../../../build/nucleo_f042k6/tmp12x</option>
</options>
<modules>
<module>modm:build:scons</module>
<module>modm:driver:tmp12x</module>
<module>modm:platform:spi:1</module>
<module>modm:processing:timer</module>
</modules>
</library>
171 changes: 171 additions & 0 deletions src/modm/driver/temperature/tmp12x.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* Copyright (c) 2020, Christopher Durand
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#ifndef MODM_TMP12x_HPP
#define MODM_TMP12x_HPP

#include <modm/architecture/interface/spi_device.hpp>
#include <modm/processing/resumable/nested_resumable.hpp>
#include <array>
#include <ratio>

namespace modm
{

/**
* TMP12x temperature data
* Use aliases Tmp121Temperature, Tmp123Temperature, Tmp125Temperature
* for the respective sensor.
*
* @ingroup modm_driver_tmp12x
* @author Christopher Durand
*
* @tparam numBits Number of bits of measured temperature
* @tparam offsetBits Invalid LSB of raw sensor value
* @tparam numerator
* @tparam denominator
*/
template<
uint8_t NumBits,
uint8_t OffsetBits,
uint8_t Numerator,
uint8_t Denominator
>
class Tmp12xTemperature
{
public:
using Fraction = std::ratio<Numerator, Denominator>;

constexpr Tmp12xTemperature() = default;

constexpr explicit Tmp12xTemperature(uint16_t sensorData)
{
static_assert((NumBits + OffsetBits) <= 16);

// mask out invalid bits
constexpr uint16_t mask = ((1U << NumBits) - 1u) << OffsetBits;
const uint16_t rawTemp = sensorData & mask;
// convert to int16_t 2's complement representation
temperature = int16_t(rawTemp << (16 - OffsetBits - NumBits)) >> (16 - NumBits);
}

constexpr float
getTemperatureFloat() const
{
return temperature * (Fraction::num / float(Fraction::den));
}

constexpr int16_t
getTemperatureInteger() const
{
return temperature * Fraction::num / Fraction::den;
}

constexpr int16_t
getTemperatureFractional() const
{
return temperature;
}

private:
int16_t temperature = 0;
};

/// @ingroup modm_driver_tmp12x
using Tmp121Temperature = Tmp12xTemperature<13, 3, 1, 16>; // 12+1 bit, 1/16th °C resolution

/// @ingroup modm_driver_tmp12x
using Tmp123Temperature = Tmp121Temperature;

/// @ingroup modm_driver_tmp12x
using Tmp125Temperature = Tmp12xTemperature<10, 5, 1, 4>; // 10 bit, 1/4 °C resolution

/**
* TMP12x temperature sensor driver
* Use aliases Tmp121, Tmp123, Tmp125 for convenience.
*
* @ingroup modm_driver_tmp12x
* @author Christopher Durand
*
* @tparam SpiMaster SPI master interface
* @tparam Cs Chip select output
* @tparam TemperatureT Sensor temperature type
*/
template<typename SpiMaster, typename Cs, typename TemperatureT>
class Tmp12x : public modm::SpiDevice<SpiMaster>, protected modm::NestedResumable<1>
{
public:
using Temperature = TemperatureT;

Tmp12x()
{
this->attachConfigurationHandler([]() {
SpiMaster::setDataMode(SpiMaster::DataMode::Mode0);
SpiMaster::setDataOrder(SpiMaster::DataOrder::MsbFirst);
SpiMaster::setDataSize(SpiMaster::DataSize::Bit8);
});
}

void
initialize()
{
Cs::setOutput(true);
}

modm::ResumableResult<Temperature>
read()
{
RF_BEGIN();

RF_WAIT_UNTIL(this->acquireMaster());
Cs::reset();
RF_CALL(SpiMaster::transfer(nullptr, buffer_.data(), 2));

if (this->releaseMaster()) {
Cs::set();
}

RF_END_RETURN(Temperature(buffer_[1] | (buffer_[0] << 8)));
}
private:
std::array<uint8_t, 2> buffer_{};
};

/**
* TMP121 temperature sensor driver
*
* @tparam SpiMaster SPI master interface
* @tparam Cs Chip select output
*/
template<typename SpiMaster, typename Cs>
using Tmp121 = Tmp12x<SpiMaster, Cs, Tmp121Temperature>;

/**
* TMP123 temperature sensor driver
*
* @tparam SpiMaster SPI master interface
* @tparam Cs Chip select output
*/
template<typename SpiMaster, typename Cs>
using Tmp123 = Tmp12x<SpiMaster, Cs, Tmp123Temperature>;

/**
* TMP125 temperature sensor driver
*
* @tparam SpiMaster SPI master interface
* @tparam Cs Chip select output
*/
template<typename SpiMaster, typename Cs>
using Tmp125 = Tmp12x<SpiMaster, Cs, Tmp125Temperature>;

} // namespace modm

#endif // MODM_TMP12x_HPP
34 changes: 34 additions & 0 deletions src/modm/driver/temperature/tmp12x.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2020, Christopher Durand
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------


def init(module):
module.name = ":driver:tmp12x"
module.description = """\
# TMP121/123/125 Thermometer

TMP121/123/125 temperature sensor driver

This driver supports the TMP125 device but not its optional shutdown function.
"""

def prepare(module, options):
module.depends(
":architecture:gpio",
":architecture:register",
":architecture:spi.device",
":processing:resumable")
return True

def build(env):
env.outbasepath = "modm/src/modm/driver/temperature"
env.copy("tmp12x.hpp")
1 change: 1 addition & 0 deletions test/modm/driver/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def prepare(module, options):
"modm:driver:drv832x_spi",
"modm:driver:mcp2515",
"modm:driver:block.allocator",
"modm:driver:tmp12x",
"modm:platform:gpio",
":mock:spi.device",
":mock:spi.master")
Expand Down
75 changes: 75 additions & 0 deletions test/modm/driver/temperature/tmp12x_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2020, Christopher Durand
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include "tmp12x_test.hpp"

void Tmp12xTest::testTmp123TemperatureData()
{
// Test TMP121, TMP123 temperature conversion (12+1 bit, 1/16 °C resolution)
// Testcases are example values from the TMP123 datasheet

// 0xE480, -55 °C
const modm::Tmp123Temperature temp0{0xE480};
TEST_ASSERT_EQUALS(temp0.getTemperatureInteger(), -55);
TEST_ASSERT_EQUALS(temp0.getTemperatureFractional(), -55 * 16);
TEST_ASSERT_EQUALS_FLOAT(temp0.getTemperatureFloat(), -55.f);
// 0x4B00, 150 °C
const modm::Tmp123Temperature temp1{0x4B00};
TEST_ASSERT_EQUALS(temp1.getTemperatureInteger(), 150);
TEST_ASSERT_EQUALS(temp1.getTemperatureFractional(), 150 * 16);
TEST_ASSERT_EQUALS_FLOAT(temp1.getTemperatureFloat(), 150.f);
// 0x0000, 0 °C
const modm::Tmp123Temperature temp2{0x0000};
TEST_ASSERT_EQUALS(temp2.getTemperatureInteger(), 0);
TEST_ASSERT_EQUALS(temp2.getTemperatureFractional(), 0);
TEST_ASSERT_EQUALS_FLOAT(temp2.getTemperatureFloat(), 0.f);
// 0x0000, 0 °C, test 3 invalid lsb are ignored
const modm::Tmp123Temperature temp3{0x0007};
TEST_ASSERT_EQUALS(temp3.getTemperatureInteger(), 0);
TEST_ASSERT_EQUALS(temp3.getTemperatureFractional(), 0);
TEST_ASSERT_EQUALS_FLOAT(temp3.getTemperatureFloat(), 0.f);
// 0xFFF8, -0.0625 °C
const modm::Tmp123Temperature temp4{0xFFF8};
TEST_ASSERT_EQUALS(temp4.getTemperatureInteger(), 0);
TEST_ASSERT_EQUALS(temp4.getTemperatureFractional(), -1);
TEST_ASSERT_EQUALS_FLOAT(temp4.getTemperatureFloat(), -0.0625f);
}

void Tmp12xTest::testTmp125TemperatureData()
{
// Test TMP125 temperature conversion (10 bit, 1/4 °C resolution)
// Testcases are example values from the TMP125 datasheet

// 0x6480, -55 °C
const modm::Tmp125Temperature temp5{0x6480};
TEST_ASSERT_EQUALS(temp5.getTemperatureInteger(), -55);
TEST_ASSERT_EQUALS(temp5.getTemperatureFractional(), -55 * 4);
TEST_ASSERT_EQUALS_FLOAT(temp5.getTemperatureFloat(), -55.f);
// 0x3F80, 127 °C
const modm::Tmp125Temperature temp6{0x3F80};
TEST_ASSERT_EQUALS(temp6.getTemperatureInteger(), 127);
TEST_ASSERT_EQUALS(temp6.getTemperatureFractional(), 127 * 4);
TEST_ASSERT_EQUALS_FLOAT(temp6.getTemperatureFloat(), 127.f);
// 0x0000, 0 °C
const modm::Tmp125Temperature temp7{0x0000};
TEST_ASSERT_EQUALS(temp7.getTemperatureInteger(), 0);
TEST_ASSERT_EQUALS(temp7.getTemperatureFractional(), 0);
TEST_ASSERT_EQUALS_FLOAT(temp7.getTemperatureFloat(), 0.f);
// 0x0000, 0 °C, test bits 15,4-0 are ignored
const modm::Tmp125Temperature temp8{uint16_t((1 << 15) | 0b11111)};
TEST_ASSERT_EQUALS(temp8.getTemperatureInteger(), 0);
TEST_ASSERT_EQUALS(temp8.getTemperatureFractional(), 0);
TEST_ASSERT_EQUALS_FLOAT(temp8.getTemperatureFloat(), 0.f);
// 0xFFF8, -0.0625 °C
const modm::Tmp125Temperature temp9{0x7FE0};
TEST_ASSERT_EQUALS(temp9.getTemperatureInteger(), 0);
TEST_ASSERT_EQUALS(temp9.getTemperatureFractional(), -1);
TEST_ASSERT_EQUALS_FLOAT(temp9.getTemperatureFloat(), -0.25f);
}
23 changes: 23 additions & 0 deletions test/modm/driver/temperature/tmp12x_test.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2020, Christopher Durand
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include <unittest/testsuite.hpp>
#include <modm/driver/temperature/tmp12x.hpp>

/// @ingroup modm_test_test_driver
class Tmp12xTest : public unittest::TestSuite
{
public:
void
testTmp123TemperatureData();

void
testTmp125TemperatureData();
};