diff --git a/examples/tsl4531/Makefile b/examples/tsl4531/Makefile new file mode 100644 index 0000000..f52d04f --- /dev/null +++ b/examples/tsl4531/Makefile @@ -0,0 +1,3 @@ +PROGRAM=tsl4531_example +EXTRA_COMPONENTS = extras/i2c extras/tsl4531 +include ../../common.mk diff --git a/examples/tsl4531/tsl4531_example.c b/examples/tsl4531/tsl4531_example.c new file mode 100644 index 0000000..9b69b29 --- /dev/null +++ b/examples/tsl4531/tsl4531_example.c @@ -0,0 +1,55 @@ +/* + * This sample code is in the public domain. + */ + +#include +#include +#include "esp/uart.h" +#include "FreeRTOS.h" +#include "i2c/i2c.h" +#include "task.h" +#include "tsl4531/tsl4531.h" + +/* An example using the TSL4531 light sensor + * to read and print lux values from a sensor + * attached to GPIO pin 2 (SCL) and GPIO pin 0 (SDA) + * Connect 3.3v from the ESP to Vin and GND to GND + */ + +#define SCL_PIN (2) +#define SDA_PIN (0) + +void tsl4531MeasurementTask(void *pvParameters) +{ + tsl4531_t lightSensor; + lightSensor.i2c_addr = TSL4531_I2C_ADDR; + tsl4531_init(&lightSensor); + + tsl4531_set_integration_time(&lightSensor, TSL4531_INTEGRATION_400MS); + tsl4531_set_power_save_skip(&lightSensor, true); + + uint16_t lux = 0; + + while (1) + { + if (tsl4531_read_lux(&lightSensor, &lux)) + { + printf("Lux: %u\n", lux); + } + else + { + printf("Could not read data from TSL4531\n"); + } + + // 0.05 second delay + vTaskDelay(50 / portTICK_PERIOD_MS); + } +} + +void user_init(void) +{ + uart_set_baud(0, 115200); + i2c_init(SCL_PIN, SDA_PIN); + + xTaskCreate(tsl4531MeasurementTask, "tsl4531MeasurementTask", 256, NULL, 2, NULL); +} diff --git a/extras/tsl2561/tsl2561.c b/extras/tsl2561/tsl2561.c index 991d803..f60825a 100644 --- a/extras/tsl2561/tsl2561.c +++ b/extras/tsl2561/tsl2561.c @@ -107,9 +107,9 @@ static uint8_t read_register(uint8_t i2c_addr, uint8_t reg) uint8_t data[1]; reg = TSL2561_REG_COMMAND | reg; - if (i2c_slave_read(i2c_addr, ® , data, 1)) + if (i2c_slave_read(i2c_addr, ®, data, 1)) { - printf("Error in tsl261 read_register\n"); + printf("Error in tsl2561 read_register\n"); } return data[0]; diff --git a/extras/tsl4531/component.mk b/extras/tsl4531/component.mk new file mode 100644 index 0000000..8752823 --- /dev/null +++ b/extras/tsl4531/component.mk @@ -0,0 +1,9 @@ +# Component makefile for extras/tsl4531 + +# Include the TSL4531 driver as "tsl4531/tsl4531.h" +INC_DIRS += $(tsl4531_ROOT).. + +# args for passing into compile rule generation +tsl4531_SRC_DIR = $(tsl4531_ROOT) + +$(eval $(call component_compile_rules,tsl4531)) diff --git a/extras/tsl4531/tsl4531.c b/extras/tsl4531/tsl4531.c new file mode 100644 index 0000000..54963e9 --- /dev/null +++ b/extras/tsl4531/tsl4531.c @@ -0,0 +1,166 @@ +/* + * Part of esp-open-rtos + * Copyright (C) 2017 Brian Schwind (https://github.com/bschwind) + * BSD Licensed as described in the file LICENSE + */ + +#include +#include "FreeRTOS.h" +#include "i2c/i2c.h" +#include "task.h" +#include "tsl4531.h" + +// Registers +#define TSL4531_REG_COMMAND 0x80 +#define TSL4531_REG_CONTROL 0x00 +#define TSL4531_REG_CONFIG 0x01 +#define TSL4531_REG_DATA_LOW 0x04 +#define TSL4531_REG_DATA_HIGH 0x05 +#define TSL4531_REG_DEVICE_ID 0x0A + +// TSL4531 Misc Values +#define TSL4531_ON 0x03 +#define TSL4531_OFF 0x00 + +// Integration times in milliseconds +#define TSL4531_INTEGRATION_TIME_100MS 120 +#define TSL4531_INTEGRATION_TIME_200MS 240 +#define TSL4531_INTEGRATION_TIME_400MS 480 // Default + +static int write_register(uint8_t i2c_addr, uint8_t reg, uint8_t value) +{ + reg = TSL4531_REG_COMMAND | reg; + return i2c_slave_write(i2c_addr, ®, &value, 1); +} + +static uint8_t read_register(uint8_t i2c_addr, uint8_t reg) +{ + uint8_t data[1]; + reg = TSL4531_REG_COMMAND | reg; + + if (i2c_slave_read(i2c_addr, ®, data, 1)) + { + printf("Error in tsl4531 read_register\n"); + } + + return data[0]; +} + +static uint16_t read_register_16(uint8_t i2c_addr, uint8_t low_register_addr) +{ + uint16_t value = 0; + uint8_t data[2]; + low_register_addr = TSL4531_REG_COMMAND | low_register_addr; + + if (i2c_slave_read(i2c_addr, &low_register_addr, data, 2)) + { + printf("Error with i2c_slave_read in read_register_16\n"); + } + + value = ((uint16_t)data[1] << 8) | (data[0]); + + return value; +} + +static int enable(tsl4531_t *device) +{ + return write_register(device->i2c_addr, TSL4531_REG_CONTROL, TSL4531_ON); +} + +static int disable(tsl4531_t *device) +{ + return write_register(device->i2c_addr, TSL4531_REG_CONTROL, TSL4531_OFF); +} + +void tsl4531_init(tsl4531_t *device) +{ + if (enable(device)) + { + printf("Error initializing tsl4531, the enable write failed\n"); + } + + uint8_t control_reg = read_register(device->i2c_addr, TSL4531_REG_CONTROL); + + if (control_reg != TSL4531_ON) { + printf("Error initializing tsl4531, control register wasn't set to ON\n"); + } + + uint8_t idRegister = read_register(device->i2c_addr, TSL4531_REG_DEVICE_ID); + uint8_t id = (idRegister & 0xF0) >> 4; + + if (id == TSL4531_PART_TSL45317) { + device->part_id = TSL4531_PART_TSL45317; + } else if (id == TSL4531_PART_TSL45313) { + device->part_id = TSL4531_PART_TSL45313; + } else if (id == TSL4531_PART_TSL45315) { + device->part_id = TSL4531_PART_TSL45315; + } else if (id == TSL4531_PART_TSL45311) { + device->part_id = TSL4531_PART_TSL45311; + } else { + printf("Unknown part id for TSL4531 sensor: %u\n", id); + } + + disable(device); +} + +void tsl4531_set_integration_time(tsl4531_t *device, tsl4531_integration_time_t integration_time_id) +{ + uint8_t power_save_bit = device->skip_power_save ? 0x08 : 0x00; + uint8_t integration_time_bits = 0x03 & integration_time_id; + uint8_t new_config_reg = power_save_bit | integration_time_bits; + + enable(device); + write_register(device->i2c_addr, TSL4531_REG_CONFIG, new_config_reg); + disable(device); + + device->integration_time_id = integration_time_id; +} + +void tsl4531_set_power_save_skip(tsl4531_t *device, bool skip_power_save) +{ + uint8_t power_save_bit = skip_power_save ? 0x08 : 0x00; + uint8_t integration_time_bits = 0x03 & device->integration_time_id; + uint8_t new_config_reg = power_save_bit | integration_time_bits; + + enable(device); + write_register(device->i2c_addr, TSL4531_REG_CONFIG, new_config_reg); + disable(device); + + device->skip_power_save = skip_power_save; +} + +bool tsl4531_read_lux(tsl4531_t *device, uint16_t *lux) +{ + bool success = true; + uint16_t multiplier = 1; + + enable(device); + + switch (device->integration_time_id) + { + case TSL4531_INTEGRATION_100MS: + multiplier = 4; + vTaskDelay(TSL4531_INTEGRATION_TIME_100MS / portTICK_PERIOD_MS); + break; + case TSL4531_INTEGRATION_200MS: + multiplier = 2; + vTaskDelay(TSL4531_INTEGRATION_TIME_200MS / portTICK_PERIOD_MS); + break; + case TSL4531_INTEGRATION_400MS: + multiplier = 1; + vTaskDelay(TSL4531_INTEGRATION_TIME_400MS / portTICK_PERIOD_MS); + break; + default: + multiplier = 1; + vTaskDelay(TSL4531_INTEGRATION_TIME_400MS / portTICK_PERIOD_MS); + break; + } + + uint16_t lux_data = read_register_16(device->i2c_addr, TSL4531_REG_DATA_LOW); + + disable(device); + + *lux = multiplier * lux_data; + + return success; +} diff --git a/extras/tsl4531/tsl4531.h b/extras/tsl4531/tsl4531.h new file mode 100644 index 0000000..3b57664 --- /dev/null +++ b/extras/tsl4531/tsl4531.h @@ -0,0 +1,56 @@ +/* + * Part of esp-open-rtos + * Copyright (C) 2017 Brian Schwind (https://github.com/bschwind) + * BSD Licensed as described in the file LICENSE + */ + +#ifndef __TSL4531_H__ +#define __TSL4531_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// I2C Addresses +typedef enum +{ + TSL4531_I2C_ADDR = 0x29 +} tsl4531_i2c_addr_t; + +// Integration time IDs +typedef enum +{ + TSL4531_INTEGRATION_100MS = 0x02, + TSL4531_INTEGRATION_200MS = 0x01, + TSL4531_INTEGRATION_400MS = 0x00 // Default +} tsl4531_integration_time_t; + +// Part IDs +typedef enum +{ + TSL4531_PART_TSL45317 = 0x08, + TSL4531_PART_TSL45313 = 0x09, + TSL4531_PART_TSL45315 = 0x0A, + TSL4531_PART_TSL45311 = 0x0B +} tsl4531_part_id_t; + +typedef struct { + tsl4531_i2c_addr_t i2c_addr; + uint8_t integration_time_id; + bool skip_power_save; + tsl4531_part_id_t part_id; +} tsl4531_t; + +void tsl4531_init(tsl4531_t *device); +void tsl4531_set_integration_time(tsl4531_t *device, tsl4531_integration_time_t integration_time_id); +void tsl4531_set_power_save_skip(tsl4531_t *device, bool skip_power_save); +bool tsl4531_read_lux(tsl4531_t *device, uint16_t *lux); + +#ifdef __cplusplus +} +#endif + +#endif // __TSL4531_H__