LM75 no-OS Driver
Supported Devices
Overview
The LM75 is a digital temperature sensor and thermal watchdog with 2-wire interface. It is available in 8-pin SOP and uSOP packages - incorporating a 9-bit Delta Sigma ADC that allows for temperature readings with precision of 0.5°C. It is compatible with ADT75 and AD7416 register formats, functioning over a voltage range of 3.3V to 5V, with a typical power consumption of 5mA.The device features a low-power shutdown mode with a typical consumption of 4µA, and it operates within a temperature range of −55°C to +125°C. Address configuration is carried out via pins A0, A1, and A2, while the OS/ALERT pin, which is open-drain, activates if the temperature exceeds user-defined limits. This pin can be set to comparator or interrupt modes, making the LM75 well-suited for diverse temperature monitoring applications.
Applications
Isolated sensors
Environmental control systems
Computer thermal monitoring
Thermal protection
Industrial process control
Power-system monitors
Hand-held applications
Device Configuration
Setup and Teardown
The lm75_init function manages the setup of the LM75 device
structure. It allocates memory for the device descriptor and initializes
the I2C communication interface using specified parameters. The function
includes mechanisms to gracefully handle errors in memory allocation or
I2C setup by releasing any allocated resources, thus preserving system
integrity.
The lm75_remove function handles the deinitialization and release of memory
structures that the lm75 driver allocated.
Configuration
A set of APIs are available for the configuration of the LM75 temperature sensor. The range of configuration includes functions to bring the LM75 into shutdown or low power mode, set the overtemperature and hysteresis values, change the fault tolerance values as well as change to polarity of the overtemperature signal.
The lm75_write_temperature function can target both the hysteresis and
overtemperature setting of LM75. This function provides the user with an
interface to change the raw temperature values of LM75.
The lm75_shutdown function is used to bring the LM75 in or out of low-power
mode.
The lm75_write_os_polarity function is used to update the polarity of the
OS signal of LM75 to either active high or active low.
The lm75_read_fault_queue function is used to update the fault tolerance
of LM75 which can help to prevent tripping in noisy environments.
Data Management
Data management with the LM75 involves functions such as
lm75_read_temperature, lm75_read_mode. lm75_read_os_polarity,
and lm75_read_fault_queue. The most useful of which is the
lm75_read_temperature function which will be used for temperature monitoring.
Temperature reads are raw LM75 values which need further processing to extract
the actual milliCelsius temperature reading. We use the function
lm75_raw_to_millicelsius to convert the raw temperature value to
milliCelsius. Conversely, if we have a milliCelsius and want to have a raw
temperature for writing to the over-temperature and hysteresis, we can use the
lm75_millicelsius_to_raw function.
Driver Initialization Example
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "no_os_i2c.h"
#include "lm75.h"
#include "no_os_delay.h"
#include "no_os_error.h"
#include "no_os_util.h"
#include "no_os_units.h"
#include "no_os_alloc.h"
int main()
{
struct lm75_init_param lm75_ip = {
.fault_count = 0, /* POR state */
.os_polarity = lm75_os_active_low,
.i2c_ip = &lm75_i2c_ip,
};
struct lm75_dev *lm75;
int ret;
uint16_t raw_temp;
int mc;
ret = lm75_init(&lm75, &lm75_ip);
if (ret != 0) {
printf("LM75 initialization failed: %d\n", ret);
goto init_error;
}
printf("LM75 initialization successful\n");
/* Read raw temperature value */
ret = lm75_read_temperature(lm75, lm75_die_temperature, &raw_temp);
if (ret != 0) {
printf("Failed to read temperature: %d\n", ret);
goto init_error;
}
/* and convert it to MilliCelsius to make it more meaningful */
mc = lm75_raw_to_millicelsius(raw_temp);
printf("Temperature: %d MilliCelsius\n", mc);
/* Clean up and exit */
lm75_remove(lm75);
return 0;
init_error:
if (lm75)
lm75_remove(lm75);
return ret;
}
IIO Support
The LM75 driver is designed to support the Industrial I/O (IIO) framework, which is a subsystem in the Linux kernel for interfacing with industrial sensors and actuators. The IIO framework provides a unified API for accessing various sensors, enabling applications to read sensor data, configure sensors, and manage their lifecycle in a consistent manner. The LM75 driver integrates with this framework, allowing users to leverage the IIO application for temperature monitoring tasks.
The LM75 IIO design mimics the way Linux hwmon presents the LM75 driver to userspace via IIO. That is, it exposes attributes like input, max and max_hyst.
IIO Initialization Functions
The initialization of the IIO example code for the LM75 temperature
sensor involves several key functions: iio_lm75_init prepares the
LM75 IIO descriptor using specified just a plain lm75 device descriptor
which has been created and initialized prior. The iio_app_init function
configures the IIO environment by setting up devices like the LM75 sensor.
It also orchestrates the process of integrating the sensor into the IIO
framework and configuring the application to acquire and process temperature
data continuously with iio_app_run. This initialization process ensures
proper operation and data handling from the sensor within the IIO
infrastructure.
IIO Device Configuration
Post-initialization, the LM75 IIO driver exposes a single temperature type
channel temp with 3 attributes, aligning closely with the Linux kernel way
of exposing sensors of this type to the user via hwmon and IIO.
The key attributes are input which is the raw die temperature, max
which is the threshold temperature which the chip uses to trigger an over
temperature event/alarm and lastly, the max_hyst which provides the
temperature value where the alarm condition is not valid.
IIO Initialization Example
int iio_example_main()
{
int ret;
struct lm75_init_param lm75_ip = {
.fault_count = 0,
.os_polarity = lm75_os_active_low,
.i2c_ip = &lm75_i2c_ip,
};
struct lm75_dev *lm75;
struct iio_lm75 *iio_lm75;
struct iio_app_desc *app;
struct iio_app_init_param app_init_param = { 0 };
/* initialize the lm75 device separately */
ret = lm75_init(&lm75, &lm75_ip);
if (ret)
return ret;
ret = iio_lm75_init(&iio_lm75, lm75);
if (ret)
goto err_cleanup_lm75;
struct iio_app_device iio_devices[] = {
{
.name = "lm75",
.dev = iio_lm75,
.dev_descriptor = &iio_lm75->iio_dev,
}
};
app_init_param.devices = iio_devices;
app_init_param.nb_devices = NO_OS_ARRAY_SIZE(iio_devices);
app_init_param.uart_init_params = lm75_uart_ip;
ret = iio_app_init(&app, app_init_param);
if (ret)
goto err_cleanup_lm75_iio;
ret = iio_app_run(app);
err_cleanup_lm75_iio:
iio_lm75_remove(iio_lm75);
err_cleanup_lm75:
lm75_remove(lm75);
return ret;
}