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

MCP9600 UORB implementation #15605

Merged
merged 1 commit into from
Jan 21, 2025
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
107 changes: 57 additions & 50 deletions Documentation/components/drivers/special/sensors/mcp9600.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
=======
MCP9600
=======

Contributed by Matteo Golin.

The MCP9600 is a thermocouple EMF to temperature converter made by Microchip. It is also sold as a `breakout board module
by Adafruit <https://learn.adafruit.com/adafruit-mcp9600-i2c-thermocouple-amplifier>`_.
The MCP9600 is a thermocouple EMF to temperature converter made by Microchip. It
is also sold as a `breakout board module by Adafruit
<https://learn.adafruit.com/adafruit-mcp9600-i2c-thermocouple-amplifier>`_.

Application Programming Interface
==================================
Expand All @@ -15,26 +17,63 @@ The header file for the MCP9600 driver interface can be included using:

#include <nuttx/sensors/mcp9600.h>

The MCP9600 registration function allows the driver to be registered as a POSIX
character driver.
The MCP9600 registration function allows the driver to be registered as a
:doc:`UORB </components/drivers/special/sensors/sensors_uorb>` sensor.

The MCP9600 measures three types of temperature:
* Hot junction temperature
* Cold junction temperature
* Temperature delta

Registering this sensor will create three UORB temperature topics, each with
their own unique device number. You must specify the unique device numbers for
each topic in the registration function:

.. code-block:: c

/* Registers sensor_temp1, sensor_temp2 and sensor_temp 3, where 1 is the
* hot junction topic, 2 is the cold junction topic and 3 is the delta
*/

The standard POSIX `read()` operation will return the device information in
plain-text, which is useful when debugging/testing the driver using `cat` from
the shell.
int err;
err = mcp9600_register(i2c_master, 0x60, 1, 2, 3);
if (err < 0) {
syslog(LOG_ERR, "Could not register MCP9600: %d\n", err);
}

The `write()` operation is not implemented for this sensor.

Specific operations the sensor offers can be performed via the POSIX `ioctl`
operation. The supported commands are:
This sensor offers some additional control commands for features that are not
accessible with the standard UORB interface.

* :c:macro:`SNIOC_SET_THERMO`
* :c:macro:`SNIOC_WHO_AM_I`
* :c:macro:`SNIOC_READ_RAW_DATA`
* :c:macro:`SNIOC_CHECK_STATUS_REG`
* :c:macro:`SNIOC_CONFIGURE`
* :c:macro:`SNIOC_WRITECONF`
* :c:macro:`SNIOC_READTEMP`
* :c:macro:`SNIOC_SHUTDOWN`
* :c:macro:`SNIOC_START`

``SNIOC_SET_THERMO``
--------------------

This command configures the thermocouple type of the MCP9600. The device
supports the following thermocouple types:

* K
* J
* T
* N
* E
* S
* B
* R

.. code-block:: c

int err;
err = orb_ioctl(sensor, SNIOC_SET_THERMO, SENSOR_THERMO_TYPE_J);
if (err < 0) {
syslog(LOG_ERR, "Failed to set thermocouple type: %d\n", err);
}

``SNIOC_WHO_AM_I``
------------------
Expand All @@ -46,7 +85,7 @@ type ``struct mcp9600_devinfo_s *``.
.. code-block:: c

struct mcp9600_devinfo_s devinfo;
err = ioctl(sensor, SNIOC_WHO_AM_I, &devinfo);
err = orb_ioctl(sensor, SNIOC_WHO_AM_I, &devinfo);

uint8_t revision_minor = MCP9600_REV_MINOR(devinfo.revision);
uint8_t revision_major = MCP9600_REV_MAJOR(devinfo.revision);
Expand All @@ -64,7 +103,7 @@ configured resolution; consult the data sheet.
.. code-block:: c

int32_t raw;
err = ioctl(sensor, SNIOC_READ_RAW_DATA, &raw);
err = orb_ioctl(sensor, SNIOC_READ_RAW_DATA, &raw);

``SNIOC_CHECK_STATUS_REG``
--------------------------
Expand All @@ -75,7 +114,7 @@ this command must be a pointer to type ``struct mcp9600_status_s``.
.. code-block:: c

struct mcp9600_status_s status;
err = ioctl(sensor, SNIOC_CHECK_STATUS_REG, &status);
err = orb_ioctl(sensor, SNIOC_CHECK_STATUS_REG, &status);

``SNIOC_CONFIGURE``
-------------------
Expand All @@ -93,7 +132,7 @@ mcp9600_devconf_s``.
.resolution = MCP9600_ADC_RES_18,
/* More fields ... */
};
err = ioctl(sensor, SNIOC_CONFIGURE, &conf);
err = orb_ioctl(sensor, SNIOC_CONFIGURE, &conf);

``SNIOC_WRITECONF``
-------------------
Expand All @@ -111,36 +150,4 @@ mcp9600_alertconf_s``.
.limit = 40 / 0.25,
/* More fields ... */
};
err = ioctl(sensor, SNIOC_WRITECONF, &conf);

``SNIOC_READTEMP``
------------------

This command lets you read the three different types of temperature that the
MCP9600 can measure. The argument to this command must be a pointer to type
``struct mcp9600_temp_s``.

.. code-block:: c

struct mcp9600_temp_s temps;
err = ioctl(sensor, SNIOC_READTEMP, &temps);

printf("Temperature: %d C\n", temps.hot_junc);

``SNIOC_SHUTDOWN``
------------------

This command shuts down the sensor. It takes no arguments.

.. code-block:: c

err = ioctl(sensor, SNIOC_SHUTDOWN, NULL);

``SNIOC_START``
---------------

This command starts the sensor in normal mode. It takes no arguments.

.. code-block:: c

err = ioctl(sensor, SNIOC_START, NULL);
err = orb_ioctl(sensor, SNIOC_WRITECONF, &conf);
4 changes: 2 additions & 2 deletions boards/arm/rp2040/common/src/rp2040_common_bringup.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,9 +549,9 @@ int rp2040_common_bringup(void)
#endif

#ifdef CONFIG_SENSORS_MCP9600
/* Try to register MCP9600 device as /dev/thermo0 at I2C0. */
/* Try to register MCP9600 device as /dev/therm0 at I2C0. */

ret = mcp9600_register("/dev/thermo0", rp2040_i2cbus_initialize(0), 0x60);
ret = mcp9600_register(rp2040_i2cbus_initialize(0), 0x60, 1, 2, 3);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: couldn't initialize MCP9600: %d\n", ret);
Expand Down
15 changes: 15 additions & 0 deletions drivers/sensors/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,21 @@ config MCP9600_I2C_FREQUENCY
range 10000 100000
depends on SENSORS_MCP9600

config SENSORS_MCP9600_POLL
bool "MCP9600 polling"
default y
depends on SENSORS_MCP9600
---help---
Enable the worker thread for polling the MCP9600 and collecting
measurements

config MCP9600_THREAD_STACKSIZE
int "MCP9600 stack size"
default 1024
depends on SENSORS_MCP9600
---help---
Stack size of the worker thread polling the MCP9600 for measurements

endif # SENSORS_MCP9600

config SENSORS_MCP9844
Expand Down
2 changes: 1 addition & 1 deletion drivers/sensors/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ ifeq ($(CONFIG_SENSORS_MB7040),y)
endif

ifeq ($(CONFIG_SENSORS_MCP9600),y)
CSRCS += mcp9600.c
CSRCS += mcp9600_uorb.c
endif

ifeq ($(CONFIG_SENSORS_MCP9844),y)
Expand Down
Loading
Loading