sensors/mcp9600: Converted MCP9600 legacy driver to UORB driver as per suggestions on PR #15525.

This commit is contained in:
Matteo Golin
2025-01-16 23:21:20 -05:00
committed by Xiang Xiao
parent e5a7f55d9f
commit 1d205e9ae2
8 changed files with 520 additions and 386 deletions
@@ -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
==================================
@@ -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 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.
The MCP9600 measures three types of temperature:
* Hot junction temperature
* Cold junction temperature
* Temperature delta
The `write()` operation is not implemented for this sensor.
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:
Specific operations the sensor offers can be performed via the POSIX `ioctl`
operation. The supported commands are:
.. 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
*/
int err;
err = mcp9600_register(i2c_master, 0x60, 1, 2, 3);
if (err < 0) {
syslog(LOG_ERR, "Could not register MCP9600: %d\n", err);
}
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``
------------------
@@ -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);
@@ -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``
--------------------------
@@ -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``
-------------------
@@ -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``
-------------------
@@ -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);
@@ -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);
+15
View File
@@ -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
+1 -1
View File
@@ -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)
File diff suppressed because it is too large Load Diff
+28 -1
View File
@@ -454,7 +454,7 @@
#endif
/* Command: SNIOC_FLUSH
* Description: Flush sensor harware fifo buffer.
* Description: Flush sensor hardware fifo buffer.
*/
#define SNIOC_FLUSH _SNIOC(0x009D)
@@ -466,4 +466,31 @@
#define SNIOC_GET_EVENTS _SNIOC(0x009E)
/* Command: SNIOC_SET_THERMO
* Description: Set the thermocouple type.
* Argument: An option from `enum sensor_thermo_type_e`
*/
#define SNIOC_SET_THERMO _SNIOC(0x009F)
/****************************************************************************
* Public types
****************************************************************************/
/* Possible thermocouple types. Implementations should not rely on the enum's
* underlying value.
*/
enum sensor_thermo_type_e
{
SENSOR_THERMO_TYPE_K,
SENSOR_THERMO_TYPE_J,
SENSOR_THERMO_TYPE_T,
SENSOR_THERMO_TYPE_N,
SENSOR_THERMO_TYPE_S,
SENSOR_THERMO_TYPE_E,
SENSOR_THERMO_TYPE_B,
SENSOR_THERMO_TYPE_R,
};
#endif /* __INCLUDE_NUTTX_SENSORS_IOCTL_H */
+9 -28
View File
@@ -56,20 +56,6 @@ enum mcp9600_alert_e
MCP9600_ALERT4 = 3, /* Alert 4 */
};
/* Thermocouple types */
enum mcp9600_thermocouple_e
{
MCP9600_THERMO_TYPE_K = 0x0,
MCP9600_THERMO_TYPE_J = 0x1,
MCP9600_THERMO_TYPE_T = 0x2,
MCP9600_THERMO_TYPE_N = 0x3,
MCP9600_THERMO_TYPE_S = 0x4,
MCP9600_THERMO_TYPE_E = 0x5,
MCP9600_THERMO_TYPE_B = 0x6,
MCP9600_THERMO_TYPE_R = 0x7,
};
/* ADC resolution */
enum mcp9600_resolution_e
@@ -134,7 +120,7 @@ struct mcp9600_alert_conf_s
struct mcp9600_devconf_s
{
enum mcp9600_thermocouple_e thermo_type; /* Thermocouple type */
enum sensor_thermo_type_e thermo_type; /* Thermocouple type */
uint8_t filter_coeff; /* Filter coefficient */
enum mcp9600_resolution_e resolution; /* ADC resolution */
enum mcp9600_samples_e num_samples; /* Number of samples */
@@ -161,15 +147,6 @@ struct mcp9600_status_s
bool alerts[4]; /* Alert statuses for alerts 1-4 (0-3) */
};
/* Temperature readings */
struct mcp9600_temp_s
{
int16_t temp_delta; /* Temperature delta in degrees Celsius */
int16_t hot_junc; /* Hot junction temperature in degrees Celsius */
int16_t cold_junc; /* Cold junction temperature in degrees Celsius */
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
@@ -178,20 +155,24 @@ struct mcp9600_temp_s
* Name: mcp9600_register
*
* Description:
* Register the MCP9600 character device as 'devpath'
* Register the MCP9600 UORB sensor. This registers 3 temperature UORB
* topics.
*
* Input Parameters:
* devpath - The full path to the driver to register. E.g., "/dev/temp0"
* i2c - An instance of the I2C interface to use to communicate with
* the MCP9600
* addr - The I2C address of the MCP9600, between 0x60 and 0x67
*
* h_devno - The device number for the hot junction topic
* c_devno - The device number for the cold junction topic
* d_devno - The device number for the delta topic
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int mcp9600_register(FAR const char *devpath, FAR struct i2c_master_s *i2c,
uint8_t addr);
int mcp9600_register(FAR struct i2c_master_s *i2c, uint8_t addr,
uint8_t h_devno, uint8_t c_devno, uint8_t d_devno);
#endif /* __INCLUDE_NUTTX_SENSORS_MCP9600_H */
+2 -2
View File
@@ -112,7 +112,7 @@
* Celsius.
*/
#define SENSOR_TYPE_TEMPERAUTRE 7
#define SENSOR_TYPE_TEMPERATURE 7
/* Proximity
* The values correspond to the distance to the nearest
@@ -162,7 +162,7 @@
#define SENSOR_TYPE_AMBIENT_TEMPERATURE 13
/* Magneric Field Uncalibrated
/* Magnetic Field Uncalibrated
* Similar to MAGNETIC_FIELD, all values are in micro-Tesla (uT)
* and measure the geomagnetic field in X, Y and Z axis.
*/