1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #6292 from bergzand/jc42

drivers/jc42: Add JEDEC JC42.4 temperature sensors
This commit is contained in:
Peter Kietzmann 2017-01-15 15:18:31 +01:00 committed by GitHub
commit 937e3a28c2
13 changed files with 594 additions and 0 deletions

View File

@ -82,6 +82,10 @@ ifneq (,$(filter io1_xplained,$(USEMODULE)))
USEMODULE += at30tse75x
endif
ifneq (,$(filter jc42,$(USEMODULE)))
FEATURES_REQUIRED += periph_i2c
endif
ifneq (,$(filter kw2xrf,$(USEMODULE)))
USEMODULE += ieee802154
USEMODULE += netif

View File

@ -64,6 +64,9 @@ endif
ifneq (,$(filter bmp180,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/bmp180/include
endif
ifneq (,$(filter jc42,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/jc42/include
endif
ifneq (,$(filter cc2420,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc2420/include
endif

125
drivers/include/jc42.h Normal file
View File

@ -0,0 +1,125 @@
/*
* Copyright (C) 2017 Koen Zandberg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup drivers_jc42 JC42 compliant temperature sensor driver
* @ingroup drivers_sensors
*
* @brief JC42 compliant temperature sensor driver
*
* ## Description
*
* The connection between the MCU and jc42 compliant temperature sensors is
* based on a I2C-interface. There are multiple jc42 compliant temperature
* sensors available such as the mcp9804 and the MAX6604. This driver reads the
* temperature from these sensors. The sensors support a alarm wire, but this
* is not supported by this driver.
*
* @{
*
* @file
* @brief Driver for jc42 compliant temperature sensors
*
* @author Koen Zandberg <koen@bergzand.net>
*/
#ifndef JC42_TEMP_H_
#define JC42_TEMP_H_
#include "periph/i2c.h"
#include "saul.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name jc42 status return codes
* @{
*/
#define JC42_OK (0)
#define JC42_NOI2C (-1)
#define JC42_NODEV (-2)
/** @} */
/**
* @brief Device descriptor for a jc42 device
*/
typedef struct {
i2c_t i2c; /**< I2C device that sensor is connected to */
uint8_t addr; /**< I2C address of this particular sensor */
} jc42_t;
/**
* @brief Device initialization parameters
*/
typedef struct {
i2c_t i2c; /**< I2C device that sensor is connected to */
i2c_speed_t speed; /**< I2C device speed */
uint8_t addr; /**< Configured address of the sensor */
} jc42_params_t;
/**
* @brief export SAUL endpoint
*/
extern const saul_driver_t jc42_temperature_saul_driver;
/**
* @brief Initialize a jc42 device
*
* @param[out] dev device descriptor
* @param[in] params jc42 initialization struct
*
*
* @return 0 on success
* @return -1 on error
*/
int jc42_init(jc42_t* dev, jc42_params_t* params);
/**
* @brief Get content of configuration register
*
* @param[in] dev device descriptor
* @param[out] data buffer where config register will be written to
*
* @return 0 on success
* @return -1 on error
*/
int jc42_get_config(jc42_t* dev, uint16_t* data);
/**
* @brief Set content of configuration register
*
* @param[in] dev device descriptor
* @param[in] data new value for configuration register
*
* @return 0 on success
* @return -1 on error
*/
int jc42_set_config(jc42_t* dev, uint16_t data);
/**
* @brief Get measured temperature
*
* @param[in] dev device descriptor
* @param[out] temperature uint16_t buffer where temperature will be written to in centi-degree
*
* @return 0 on success
* @return -1 on error
*/
int jc42_get_temperature(jc42_t* dev, int16_t* temperature);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* JC42_TEMP_H_ */

2
drivers/jc42/Makefile Normal file
View File

@ -0,0 +1,2 @@
MODULE = jc42
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2017 Koen Zandberg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_sensors
* @{
*
* @file
* @brief Internal addresses, registers, constants for jc42 sensors.
*
* @author Koen Zandberg <koen@bergzand.net>
*/
#ifndef JC42_INTERNAL_H_
#define JC42_INTERNAL_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name JC42 register addresses
* @{
*/
#define JC42_REG_CAP (0x00)
#define JC42_REG_CONFIG (0x01)
#define JC42_REG_TEMP_UPPER (0x02)
#define JC42_REG_TEMP_LOWER (0x03)
#define JC42_REG_TEMP_CRITICAL (0x04)
#define JC42_REG_TEMP (0x05)
#define JC42_REG_MANID (0x06)
#define JC42_REG_DEVICEID (0x07)
#define jc42_BUS_FREE_TIME_US (1)
/** @} */
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* JC42_INTERNAL_H_ */

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2017 Koen Zandberg <koen@bergzand.net>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_jc42
*
* @{
* @file
* @brief Default configuration for jc42
*
* @author Koen Zandberg <koen@bergzand.net>
*/
#ifndef JC42_PARAMS_H
#define JC42_PARAMS_H
#include "jc42.h"
#include "periph/i2c.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set default configuration parameters for the JC42
* @{
*/
#ifndef JC42_PARAM_I2C_DEV
#define JC42_PARAM_I2C_DEV (0)
#endif
#ifndef JC42_PARAM_ADDR
#define JC42_PARAM_ADDR (0x18)
#endif
#ifndef JC42_PARAM_SPEED
#define JC42_PARAM_SPEED I2C_SPEED_FAST
#endif
#define JC42_PARAMS_DEFAULT {.i2c = JC42_PARAM_I2C_DEV, \
.speed = JC42_PARAM_SPEED, \
.addr = JC42_PARAM_ADDR }
/**@}*/
/**
* @brief Configure JC42
*/
static const jc42_params_t jc42_params[] =
{
#ifdef JC42_PARAMS_BOARD
JC42_PARAMS_BOARD,
#else
JC42_PARAMS_DEFAULT,
#endif
};
#ifdef __cplusplus
}
#endif
#endif /* JC42_PARAMS_H */
/** @} */

102
drivers/jc42/jc42.c Normal file
View File

@ -0,0 +1,102 @@
/*
* Copyright (C) 2017 Koen Zandberg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_jc42
* @{
*
* @file
* @brief Device driver implementation for the JEDEC jc42.4 compliant temperature sensors
*
* @author Koen Zandberg <koen@bergzand.net>
*
* @}
*/
#include "periph/i2c.h"
#include "byteorder.h"
#include "jc42.h"
#include "jc42_internal.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
static int jc42_get_register(jc42_t* dev, uint8_t reg, uint16_t* data)
{
i2c_acquire(dev->i2c);
if (i2c_read_regs(dev->i2c, dev->addr, reg, data, 2) <= 0) {
DEBUG("[jc42] Problem reading register 0x%x\n", reg);
i2c_release(dev->i2c);
return JC42_NODEV;
}
i2c_release(dev->i2c);
return JC42_OK;
}
static int jc42_set_register(jc42_t* dev, uint8_t reg, uint16_t* data)
{
i2c_acquire(dev->i2c);
if (i2c_write_regs(dev->i2c, dev->addr, reg, data, 2) <= 0) {
DEBUG("[jc42] Problem writing to register 0x%x\n", reg);
i2c_release(dev->i2c);
return JC42_NODEV;
}
i2c_release(dev->i2c);
return JC42_OK;
}
int jc42_get_config(jc42_t* dev, uint16_t* data)
{
return jc42_get_register(dev, JC42_REG_CONFIG, data);
}
int jc42_set_config(jc42_t* dev, uint16_t data)
{
return jc42_set_register(dev, JC42_REG_CONFIG, &data);
}
int jc42_get_temperature(jc42_t* dev, int16_t* temperature)
{
struct { signed int x:12;} s;
uint16_t tmp;
/* Read temperature */
if (jc42_get_register(dev, JC42_REG_TEMP, &tmp) != 0) {
return JC42_NODEV;
}
tmp = NTOHS(tmp);
/* Convert fixed point to uint16_t */
*temperature = ((s.x = tmp)*100)>>4;
return JC42_OK;
}
int jc42_init(jc42_t* dev, jc42_params_t* params)
{
uint16_t config;
dev->i2c = params->i2c;
dev->addr = params->addr;
i2c_acquire(dev->i2c);
if (i2c_init_master(dev->i2c, params->speed) != 0) {
DEBUG("[jc42] Problem initializing I2C master\n");
i2c_release(dev->i2c);
return JC42_NOI2C;
}
i2c_release(dev->i2c);
/* Poll the device, fail if unavailable */
if (jc42_get_config(dev, &config) != 0) {
return JC42_NODEV;
}
DEBUG("[jc42] Config: 0x%x\n", config);
return JC42_OK;
}

44
drivers/jc42/jc42_saul.c Normal file
View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2017 Koen Zandberg <koen@bergzand.net>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_jc42
* @{
*
* @file
* @brief SAUL adaption for jc42 compatible device
*
* @author Koen Zandberg <koen@bergzand.net>
*
* @}
*/
#include <string.h>
#include "saul.h"
#include "jc42.h"
static int read_temperature(void *dev, phydat_t *res)
{
int16_t temperature;
jc42_t *d = (jc42_t *)dev;
jc42_get_temperature(d, &temperature);
res->val[0] = temperature;
res->unit = UNIT_TEMP_C;
res->scale = -2;
return 1;
}
const saul_driver_t jc42_temperature_saul_driver = {
.read = read_temperature,
.write = saul_notsup,
.type = SAUL_SENSE_TEMP
};

View File

@ -294,6 +294,10 @@ void auto_init(void)
extern void auto_init_bmp180(void);
auto_init_bmp180();
#endif
#ifdef MODULE_JC42
extern void auto_init_jc42(void);
auto_init_jc42();
#endif
#endif /* MODULE_AUTO_INIT_SAUL */

View File

@ -0,0 +1,82 @@
/*
* Copyright (C) 2017 Koen Zandberg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup auto_init_saul
* @{
*
* @file
* @brief Auto initialization of jc42 compatible driver.
*
* @author Koen Zandberg <koen@bergzand.net>
*
* @}
*/
#ifdef MODULE_JC42
#include "log.h"
#include "saul_reg.h"
#include "jc42.h"
#include "jc42_params.h"
/**
* @brief Define the number of configured sensors
*/
#define JC42_NUMOF (sizeof(jc42_params) / sizeof(jc42_params[0]))
/**
* @brief Allocation of memory for device descriptors
*/
static jc42_t jc42_devs[JC42_NUMOF];
/**
* @brief Memory for the SAUL registry entries
*/
static saul_reg_t saul_entries[JC42_NUMOF];
/**
* @brief Reference the driver structs.
* @{
*/
extern const saul_driver_t jc42_temperature_saul_driver;
/** @} */
/**
* @brief Allocate and configure entries to the SAUL registry
*/
saul_reg_t jc42_saul_reg_info[]=
{
{
.name= "jc42",
.driver = &jc42_temperature_saul_driver
}
};
void auto_init_jc42(void)
{
for (unsigned i = 0; i < JC42_NUMOF; i++) {
const jc42_params_t *p = &jc42_params[i];
if (jc42_init(&jc42_devs[i], (jc42_params_t*) p) < 0) {
LOG_ERROR("Unable to initialize jc42 sensor #%i\n", i);
return;
}
/* temperature */
saul_entries[i].dev = &(jc42_devs[i]);
saul_entries[i].name = jc42_saul_reg_info[i].name;
saul_entries[i].driver = &jc42_temperature_saul_driver;
/* register to saul */
saul_reg_add(&(saul_entries[i]));
}
}
#else
typedef int dont_be_pedantic;
#endif /* MODULE_JC42 */

View File

@ -0,0 +1,17 @@
APPLICATION = driver_jc42
include ../Makefile.tests_common
USEMODULE += jc42
USEMODULE += xtimer
# set default device parameters in case they are undefined
TEST_I2C ?= 0
TEST_I2C_ADDR ?= 0x18
TEST_I2C_SPEED ?= I2C_SPEED_NORMAL
# export parameters
CFLAGS += -DTEST_I2C=$(TEST_I2C)
CFLAGS += -DTEST_I2C_ADDR=$(TEST_I2C_ADDR)
CFLAGS += -DTEST_I2C_SPEED=$(TEST_I2C_SPEED)
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,14 @@
# JC42 Driver Test
## Introduction
This test will test if the jc42 compatible temperature sensor is working.
## Configuration
There are three parameters to configure:
* `TEST_I2C` &mdash; I2C device to use.
* `TEST_I2C_ADDR` &mdash; The sensor address (usually 0x18).
* `TEST_I2C_SPEED` &mdash; The sensor address (usually I2C_SPEED_NORMAL).
## Expected result
The sensor should continuously (every 1 sec) output the temperature. The precision should be two digits.

82
tests/driver_jc42/main.c Normal file
View File

@ -0,0 +1,82 @@
/*
* Copyright (C) 2017 Koen Zandberg <koen@bergzand.net>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup tests
* @{
*
* @file
* @brief Test application for the jc42 sensor driver
*
* @author Koen Zandberg <koen@bergzand.net>
*
* @}
*/
#ifndef TEST_I2C
#error "TEST_I2C not defined"
#endif
#ifndef TEST_I2C_ADDR
#error "TEST_I2C_ADDR not defined"
#endif
#ifndef TEST_I2C_SPEED
#error "TEST_I2C_SPEED not defined"
#endif
#include <stdio.h>
#include "xtimer.h"
#include "periph/i2c.h"
#include "jc42.h"
int main(void)
{
jc42_t dev;
jc42_params_t params = {
.i2c = TEST_I2C,
.addr = TEST_I2C_ADDR,
.speed = TEST_I2C_SPEED,
};
puts("JC42 temperature sensor test application\n");
/* initialize the sensor */
printf("Initializing sensor...");
if (jc42_init(&dev, &params) == 0) {
puts("[OK]");
}
else {
puts("[Failed]");
return 1;
}
/* read temperature every 1 seconds */
int16_t temperature;
while (1) {
printf("Testing sensor communication...");
if (jc42_get_temperature(&dev, &temperature) == 0) {
puts("[OK]");
}
else {
puts("[Failed]");
return 1;
}
/* display results */
printf("temperature: %d.%02d C\n", temperature / 100, temperature % 100);
/* sleep between measurements */
xtimer_usleep(1000 * MS_IN_USEC);
}
return 0;
}