px-fwlib 0.10.0
Cross-platform embedded library and documentation for 8/16/32-bit microcontrollers generated with Doxygen 1.9.2
px_veml6075.c
1/* =============================================================================
2 ____ ___ ____ ___ _ _ ___ __ __ ___ __ __ TM
3 | _ \ |_ _| / ___| / _ \ | \ | | / _ \ | \/ | |_ _| \ \/ /
4 | |_) | | | | | | | | | | \| | | | | | | |\/| | | | \ /
5 | __/ | | | |___ | |_| | | |\ | | |_| | | | | | | | / \
6 |_| |___| \____| \___/ |_| \_| \___/ |_| |_| |___| /_/\_\
7
8 Copyright (c) 2019 Pieter Conradie <https://piconomix.com>
9
10 License: MIT
11 https://github.com/piconomix/px-fwlib/blob/master/LICENSE.md
12
13 Title: px_veml6075.h : Vishay VEML6075 UV light sensor driver
14 Author(s): Pieter Conradie
15 Creation Date: 2019-09-05
16
17============================================================================= */
18
19/* _____STANDARD INCLUDES____________________________________________________ */
20
21/* _____PROJECT INCLUDES_____________________________________________________ */
22#include "px_veml6075.h"
23#include "px_i2c.h"
24
25#include "px_log.h"
26PX_LOG_NAME("px_veml6075")
27
28/* _____LOCAL DEFINITIONS____________________________________________________ */
29/// @name Command code and register map (table 1, p. 6)
30/// @{
31#define PX_VEML6075_REG_UV_CFG 0x00
32#define PX_VEML6075_REG_UVA_DATA 0x07
33#define PX_VEML6075_REG_UVB_DATA 0x09
34#define PX_VEML6075_REG_UVCOMP1_DATA 0x0A
35#define PX_VEML6075_REG_UVCOMP2_DATA 0x0B
36#define PX_VEML6075_REG_ID 0x0C
37/// @}
38
39/// @name Config register parameters (table 2, p. 7)
40/// @{
41#define PX_VEML6075_REG_CFG_UV_IT_50MS 0x00
42#define PX_VEML6075_REG_CFG_UV_IT_100MS 0x10
43#define PX_VEML6075_REG_CFG_UV_IT_200MS 0x20
44#define PX_VEML6075_REG_CFG_UV_IT_400MS 0x30
45#define PX_VEML6075_REG_CFG_UV_IT_800MS 0x40
46#define PX_VEML6075_REG_CFG_HD 0x08
47#define PX_VEML6075_REG_CFG_UV_TRIG_NO 0x00
48#define PX_VEML6075_REG_CFG_UV_TRIG_ONCE 0x04
49#define PX_VEML6075_REG_CFG_UV_AF_NORMAL 0x00
50#define PX_VEML6075_REG_CFG_UV_AF_FORCE 0x02
51#define PX_VEML6075_REG_CFG_SD 0x01
52/// @}
53
54/// Register 0x0C "ID" value
55#define PX_VEML6075_REG_ID_VAL 0x26
56
57/// Register data definition
58typedef struct
59{
60 uint8_t lsb; ///< Least Significant Byte
61 uint8_t msb; ///< Most Significant Byte
63
64/* _____MACROS_______________________________________________________________ */
65
66/* _____GLOBAL VARIABLES_____________________________________________________ */
67
68/* _____LOCAL VARIABLES______________________________________________________ */
69static px_i2c_handle_t * px_veml6075_i2c_handle;
70
71static const float px_veml6075_uva_a_coef = 2.22;
72static const float px_veml6075_uva_b_coef = 1.33;
73static const float px_veml6075_uva_c_coef = 2.95;
74static const float px_veml6075_uva_d_coef = 1.74;
75static const float px_veml6075_uva_resp = 0.001461;
76static const float px_veml6075_uvb_resp = 0.002591;
77
78/* _____LOCAL FUNCTION DECLARATIONS__________________________________________ */
79
80/* _____LOCAL FUNCTIONS______________________________________________________ */
81static bool px_veml6075_reg_wr(uint8_t cmd, const px_veml6075_reg_data * data)
82{
83 uint8_t buf[3];
84
85 buf[0] = cmd;
86 buf[1] = data->lsb;
87 buf[2] = data->msb;
88
89 if(!px_i2c_wr(px_veml6075_i2c_handle, buf, 3, PX_I2C_FLAG_START_AND_STOP))
90 {
91 PX_LOG_E("Write failed");
92 return false;
93 }
94
95 return true;
96}
97
98static bool px_veml6075_reg_rd(uint8_t cmd, px_veml6075_reg_data * data)
99{
100 uint8_t buf[2];
101
102 buf[0] = cmd;
103 if(!px_i2c_wr(px_veml6075_i2c_handle, buf, 1, PX_I2C_FLAG_START_AND_END))
104 {
105 PX_LOG_E("Write failed");
106 return false;
107 }
108 if(!px_i2c_rd(px_veml6075_i2c_handle, buf, 2, PX_I2C_FLAG_REP_START_AND_STOP))
109 {
110 PX_LOG_E("Read failed");
111 return false;
112 }
113 data->lsb = buf[0];
114 data->msb = buf[1];
115
116 return true;
117}
118
119/* _____GLOBAL FUNCTIONS_____________________________________________________ */
121{
122 px_veml6075_reg_data reg_data;
123
124 // Save I2C slave handle
125 px_veml6075_i2c_handle = handle;
126
127 // Verify Chip ID
128 if(!px_veml6075_reg_rd(PX_VEML6075_REG_ID, &reg_data))
129 {
130 // Error
131 PX_LOG_E("Unable to read Chip ID");
132 return false;
133 }
134 if(reg_data.lsb != PX_VEML6075_REG_ID_VAL)
135 {
136 // Error
137 PX_LOG_E("Chip ID does not match. Received %02X, but expected %02X",
138 reg_data.lsb, PX_VEML6075_REG_ID_VAL);
139 return false;
140 }
141 PX_LOG_D("UV sensor detected");
142 // Configure sensor
143 reg_data.lsb = PX_VEML6075_REG_CFG_UV_IT_100MS
144 | PX_VEML6075_REG_CFG_UV_TRIG_NO
145 | PX_VEML6075_REG_CFG_UV_AF_NORMAL;
146 reg_data.msb = 0;
147 if(!px_veml6075_reg_wr(PX_VEML6075_REG_UV_CFG, &reg_data))
148 {
149 // Error
150 PX_LOG_E("Unable to configure sensor");
151 return false;
152 }
153 if(!px_veml6075_reg_rd(PX_VEML6075_REG_UV_CFG, &reg_data))
154 {
155 // Error
156 PX_LOG_E("Unable to read config");
157 return false;
158 }
159 PX_LOG_D("Cfg = 0x%02X, 0x%02X", reg_data.lsb, reg_data.msb);
160
161 // Success
162 return true;
163}
164
166{
167 px_veml6075_reg_data reg_data;
168
169 // Read UVA register
170 if(!px_veml6075_reg_rd(PX_VEML6075_REG_UVA_DATA, &reg_data))
171 {
172 // Error
173 PX_LOG_E("Unable to read UVA");
174 return false;
175 }
176 data->uva = PX_U16_CONCAT_U8(reg_data.msb, reg_data.lsb);
177 // Read UVB register
178 if(!px_veml6075_reg_rd(PX_VEML6075_REG_UVB_DATA, &reg_data))
179 {
180 // Error
181 PX_LOG_E("Unable to read UVB");
182 return false;
183 }
184 data->uvb = PX_U16_CONCAT_U8(reg_data.msb, reg_data.lsb);
185 // Read UVCOMP1 register
186 if(!px_veml6075_reg_rd(PX_VEML6075_REG_UVCOMP1_DATA, &reg_data))
187 {
188 // Error
189 PX_LOG_E("Unable to read UVCOMP1");
190 return false;
191 }
192 data->uvcomp1 = PX_U16_CONCAT_U8(reg_data.msb, reg_data.lsb);
193 // Read UVCOMP2 register
194 if(!px_veml6075_reg_rd(PX_VEML6075_REG_UVCOMP2_DATA, &reg_data))
195 {
196 // Error
197 PX_LOG_E("Unable to read UVCOMP2");
198 return false;
199 }
200 data->uvcomp2 = PX_U16_CONCAT_U8(reg_data.msb, reg_data.lsb);
201 // Success
202 PX_LOG_D("UVA=0x%04X, UVB=%04X, UVCOMP1=0x%04X, UVCOMP2=0x%04X",
203 data->uva, data->uvb, data->uvcomp1, data->uvcomp2);
204 return true;
205}
206
208{
209 float uva;
210
211 uva = data->uva
212 - (px_veml6075_uva_a_coef * data->uvcomp1)
213 - (px_veml6075_uva_b_coef * data->uvcomp2);
214
215 return uva;
216}
217
219{
220 float uvb;
221
222 uvb = data->uvb
223 - (px_veml6075_uva_c_coef * data->uvcomp1)
224 - (px_veml6075_uva_d_coef * data->uvcomp2);
225
226 return uvb;
227}
228
230{
231 float uva;
232 float uvb;
233 float uvi;
234
235 uva = px_veml6075_uva(data);
236 uvb = px_veml6075_uvb(data);
237
238 uva = uva * px_veml6075_uva_resp;
239 uvb = uvb * px_veml6075_uvb_resp;
240 uvi = (uva + uvb) / 2.0;
241
242 return uvi;
243}
#define PX_U16_CONCAT_U8(hi8, lo8)
Concatenate 2 x 8 bits to form 16-bit value.
Definition: px_defs.h:268
#define PX_LOG_D(format,...)
Macro to display a formatted DEBUG message.
Definition: px_log.h:410
#define PX_LOG_NAME(name)
Macro to declare a log name string once for each file to reduce code size.
Definition: px_log.h:349
#define PX_LOG_E(format,...)
Macro to display a formatted ERROR message.
Definition: px_log.h:377
bool px_veml6075_init(px_i2c_handle_t *handle)
Initialise driver.
Definition: px_veml6075.c:120
float px_veml6075_uvi(const px_veml6075_data_t *data)
Calculate UVI from raw sensor data.
Definition: px_veml6075.c:229
float px_veml6075_uva(const px_veml6075_data_t *data)
Calculate UVA from raw sensor data.
Definition: px_veml6075.c:207
float px_veml6075_uvb(const px_veml6075_data_t *data)
Calculate UVB from raw sensor data.
Definition: px_veml6075.c:218
bool px_veml6075_meas(px_veml6075_data_t *data)
Take UVA & UVB measurement.
Definition: px_veml6075.c:165
Raw sensor data.
Definition: px_veml6075.h:52
#define PX_I2C_FLAG_START_AND_STOP
Begin and finish an I2C transaction with a START and STOP condition.
Definition: px_i2c.h:93
bool px_i2c_rd(px_i2c_handle_t *handle, void *data, size_t nr_of_bytes, uint8_t flags)
Perform an I2C read transaction with an I2C slave.
Definition: px_i2c.c:430
#define PX_I2C_FLAG_REP_START_AND_STOP
Begin and finish an I2C transaction with a REP START and STOP condition.
Definition: px_i2c.h:97
#define PX_I2C_FLAG_START_AND_END
Begin and finish an I2C transaction with a START and END condition.
Definition: px_i2c.h:95
bool px_i2c_wr(px_i2c_handle_t *handle, const void *data, size_t nr_of_bytes, uint8_t flags)
Perform an I2C write transaction with an I2C slave.
Definition: px_i2c.c:240
Define I2C handle for a slave.
Definition: px_i2c.h:104
Register data definition.
Definition: px_veml6075.c:59
uint8_t lsb
Least Significant Byte.
Definition: px_veml6075.c:60
uint8_t msb
Most Significant Byte.
Definition: px_veml6075.c:61