sensor_mlx90614: add library to read from MLX90614 IR-thermometer
This commit is contained in:
parent
95b63a06f5
commit
ac255816a1
86
lib/sensor_mlx90614.c
Normal file
86
lib/sensor_mlx90614.c
Normal file
@ -0,0 +1,86 @@
|
||||
/** library to communicate with MLX90614 infra-red thermometer
|
||||
* @file
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @copyright SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* @date 2020
|
||||
* @note peripherals used: GPIO @ref sensor_mlx90614_gpio, I2C @ref i2c_master_i2c
|
||||
* @note this library only uses the I²C interface, not the PWM output
|
||||
*/
|
||||
/* standard libraries */
|
||||
#include <stdint.h> // standard integer types
|
||||
#include <stdbool.h> // boolean type
|
||||
#include <stdlib.h> // general utilities
|
||||
#include <math.h> // NaN definition
|
||||
|
||||
/* STM32 (including CM3) libraries */
|
||||
#include <libopencm3/stm32/rcc.h> // real-time control clock library
|
||||
#include <libopencm3/stm32/gpio.h> // general purpose input output library
|
||||
#include <libopencm3/stm32/i2c.h> // I²C library
|
||||
|
||||
/* own libraries */
|
||||
#include "global.h" // global utilities
|
||||
#include "sensor_mlx90614.h" // own definitions
|
||||
#include "smbus_master.h" // SMBus utilities
|
||||
|
||||
/** @defgroup sensor_mlx90614_gpio GPIO pin used to control the MLX90614
|
||||
* @{
|
||||
*/
|
||||
#define SENSOR_MLX90614_SCL PA8 /**< GPIO pin for SMBus SCL, use to send request condition to switch mode from PWM to SMBus (must be the same as used for SMBus communication) */
|
||||
/** @} */
|
||||
|
||||
/** MLX90614 I²C slave address */
|
||||
static uint8_t sensor_mlx90614_slave_addr = 0x5a;
|
||||
|
||||
bool sensor_mlx90614_setup(uint8_t slave_addr)
|
||||
{
|
||||
if (!smbus_master_check_signals()) { // check if there are pull-ups to operate I²C
|
||||
return false;
|
||||
}
|
||||
|
||||
// send request condition to switch to I²C mode
|
||||
rcc_periph_clock_enable(GPIO_RCC(SENSOR_MLX90614_SCL)); // enable clock for GPIO port domain
|
||||
gpio_mode_setup(GPIO_PORT(SENSOR_MLX90614_SCL), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN(SENSOR_MLX90614_SCL)); // set pin as output
|
||||
gpio_set_output_options(GPIO_PORT(SENSOR_MLX90614_SCL), GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ, GPIO_PIN(SENSOR_MLX90614_SCL)); // set pin output as open-drain (should be pulled up by external resistors required for I²C communication
|
||||
gpio_clear(GPIO_PORT(SENSOR_MLX90614_SCL), GPIO_PIN(SENSOR_MLX90614_SCL)); // set low to send request condition
|
||||
sleep_us(1024 + 500); // SMBus Request is min. 1.024 ms
|
||||
gpio_set(GPIO_PORT(SENSOR_MLX90614_SCL), GPIO_PIN(SENSOR_MLX90614_SCL)); // set back high to end request condition
|
||||
|
||||
if (slave_addr < 0x80) { // only the least 7-bit are valid (use default address else)
|
||||
sensor_mlx90614_slave_addr = slave_addr; // save I²C slave address of MLX90614
|
||||
}
|
||||
smbus_master_setup(100, true); // setup SMBus with PEC
|
||||
uint8_t response[2]; // response is always 2 bytes
|
||||
// test if the device is present
|
||||
smbus_master_command_read(sensor_mlx90614_slave_addr, 0x20 | 0x0e, response, LENGTH(response)); // I don't know whey, but the PEC for the first transfer is erroneous, maybe because it has some old bits in the calculation buffer
|
||||
const enum smbus_master_rc rc = smbus_master_command_read(sensor_mlx90614_slave_addr, 0x20 | 0x0e, response, LENGTH(response)); // read its own slave address
|
||||
if (SMBUS_MASTER_RC_NONE != rc) { // read failed
|
||||
return false; // could not read from SMBus device
|
||||
}
|
||||
|
||||
if (sensor_mlx90614_slave_addr != response[0]) { // the used slave address does not match the one in the ROM
|
||||
return false; // this is probably not a MLX90614
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
float sensor_mlx90614_temperature_ambient(void)
|
||||
{
|
||||
uint8_t response[2]; // response is always 2 bytes
|
||||
const enum smbus_master_rc rc = smbus_master_command_read(sensor_mlx90614_slave_addr, 0x00 | 0x06, response, LENGTH(response)); // read Ta from RAM
|
||||
if (SMBUS_MASTER_RC_NONE != rc) { // read failed
|
||||
return NAN;
|
||||
}
|
||||
const uint16_t temp = response[0] + (response[1] << 8); // low byte is transferred first
|
||||
return temp * 0.02 - 273.15; // calculated temperature according to specification 7.7.1
|
||||
}
|
||||
|
||||
float sensor_mlx90614_temperature_object(void)
|
||||
{
|
||||
uint8_t response[2]; // response is always 2 bytes
|
||||
const enum smbus_master_rc rc = smbus_master_command_read(sensor_mlx90614_slave_addr, 0x00 | 0x07, response, LENGTH(response)); // read Tobj1 from RAM
|
||||
if (SMBUS_MASTER_RC_NONE != rc) { // read failed
|
||||
return NAN;
|
||||
}
|
||||
const uint16_t temp = response[0] + (response[1] << 8); // low byte is transferred first
|
||||
return temp * 0.02 - 273.15; // calculated temperature according to specification 7.7.1
|
||||
}
|
27
lib/sensor_mlx90614.h
Normal file
27
lib/sensor_mlx90614.h
Normal file
@ -0,0 +1,27 @@
|
||||
/** library to communicate with MLX90614 infra-red thermometer
|
||||
* @file
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @copyright SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* @date 2020
|
||||
* @note peripherals used: GPIO @ref sensor_mlx90614_gpio, I2C @ref i2c_master_i2c
|
||||
* @note this library only uses the I²C interface, not the PWM output
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/** setup I²C bus to communicated with MLX90614 Infra-Red thermometer
|
||||
* @param[in] slave_addr I²C slave address of MLX90614 device (least significant 7-bit, 0xff for default)
|
||||
* @return if the display setup is successful, else the display is probably not on the I²C bus
|
||||
* @warning only one display on the I²C bus is currently supported
|
||||
* @note I²C frequency is 100 kHz
|
||||
*/
|
||||
bool sensor_mlx90614_setup(uint8_t slave_addr);
|
||||
/** get ambient temperature of sensor
|
||||
* @return ambient temperature in °C
|
||||
* @note uses internal thermistor
|
||||
*/
|
||||
float sensor_mlx90614_temperature_ambient(void);
|
||||
/** get measured object temperature
|
||||
* @return object temperature in °C
|
||||
* @note uses IR sensor
|
||||
*/
|
||||
float sensor_mlx90614_temperature_object(void);
|
Loading…
Reference in New Issue
Block a user