Driver for the Silicon Labs Si1133 Visible Light/UV sensor
Dependents: TBSense2_Sensor_Demo mbed-BLE-coragem-teste Pulga_BLE_GPS pulga-mbed-lorawan-gps ... more
Si1133.cpp
00001 /***************************************************************************//** 00002 * @file Si1133.cpp 00003 ******************************************************************************* 00004 * @section License 00005 * <b>(C) Copyright 2017 Silicon Labs, http://www.silabs.com</b> 00006 ******************************************************************************* 00007 * 00008 * SPDX-License-Identifier: Apache-2.0 00009 * 00010 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00011 * not use this file except in compliance with the License. 00012 * You may obtain a copy of the License at 00013 * 00014 * http://www.apache.org/licenses/LICENSE-2.0 00015 * 00016 * Unless required by applicable law or agreed to in writing, software 00017 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00018 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00019 * See the License for the specific language governing permissions and 00020 * limitations under the License. 00021 * 00022 ******************************************************************************/ 00023 00024 #include "Si1133.h " 00025 00026 #define SI1133_I2C_ADDRESS (0xAA) /** Hardcoded address for Si1133 sensor */ 00027 00028 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 00029 00030 #define X_ORDER_MASK 0x0070 00031 #define Y_ORDER_MASK 0x0007 00032 #define SIGN_MASK 0x0080 00033 #define GET_X_ORDER(m) ( ((m) & X_ORDER_MASK) >> 4) 00034 #define GET_Y_ORDER(m) ( ((m) & Y_ORDER_MASK) ) 00035 #define GET_SIGN(m) ( ((m) & SIGN_MASK) >> 7) 00036 00037 #define UV_INPUT_FRACTION 15 00038 #define UV_OUTPUT_FRACTION 12 00039 #define UV_NUMCOEFF 2 00040 00041 #define ADC_THRESHOLD 16000 00042 #define INPUT_FRACTION_HIGH 7 00043 #define INPUT_FRACTION_LOW 15 00044 #define LUX_OUTPUT_FRACTION 12 00045 #define NUMCOEFF_LOW 9 00046 #define NUMCOEFF_HIGH 4 00047 00048 /** @endcond */ 00049 00050 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 00051 /***************************************************************************//** 00052 * @brief 00053 * Coefficients for lux calculation 00054 ******************************************************************************/ 00055 const Si1133::LuxCoeff_t Si1133::lk = { 00056 { { 0, 209 }, /**< coeff_high[0] */ 00057 { 1665, 93 }, /**< coeff_high[1] */ 00058 { 2064, 65 }, /**< coeff_high[2] */ 00059 { -2671, 234 } }, /**< coeff_high[3] */ 00060 { { 0, 0 }, /**< coeff_low[0] */ 00061 { 1921, 29053 }, /**< coeff_low[1] */ 00062 { -1022, 36363 }, /**< coeff_low[2] */ 00063 { 2320, 20789 }, /**< coeff_low[3] */ 00064 { -367, 57909 }, /**< coeff_low[4] */ 00065 { -1774, 38240 }, /**< coeff_low[5] */ 00066 { -608, 46775 }, /**< coeff_low[6] */ 00067 { -1503, 51831 }, /**< coeff_low[7] */ 00068 { -1886, 58928 } } /**< coeff_low[8] */ 00069 }; 00070 00071 /***************************************************************************//** 00072 * @brief 00073 * Coefficients for UV index calculation 00074 ******************************************************************************/ 00075 const Si1133::Coeff_t Si1133::uk[2] = { 00076 { 1281, 30902 }, /**< coeff[0] */ 00077 { -638, 46301 } /**< coeff[1] */ 00078 }; 00079 00080 /**************************************************************************//** 00081 * @name Error Codes 00082 * @{ 00083 ******************************************************************************/ 00084 #define SI1133_OK 0x0000 /**< No errors */ 00085 #define SI1133_ERROR_I2C_TRANSACTION_FAILED 0x0001 /**< I2C transaction failed */ 00086 #define SI1133_ERROR_SLEEP_FAILED 0x0002 /**< Entering sleep mode failed */ 00087 /**@}*/ 00088 00089 /** @endcond */ 00090 00091 Si1133::Si1133(PinName sda, PinName scl, int hz) : m_I2C(sda, scl) 00092 { 00093 //Set the I2C bus frequency 00094 m_I2C.frequency(hz); 00095 } 00096 00097 Si1133::~Si1133(void) 00098 { 00099 deinit(); 00100 } 00101 00102 bool Si1133::open() 00103 { 00104 //Probe for the Si1133 using a Zero Length Transfer 00105 if (m_I2C.write(SI1133_I2C_ADDRESS, NULL, 0)) { 00106 //Return success 00107 return false; 00108 } 00109 00110 // initialize sensor 00111 if (SI1133_OK == init()) { 00112 return true; 00113 } 00114 return false; 00115 } 00116 00117 /** Measure the current light level (in lux) on the Si1133 00118 * 00119 * @returns The current temperature measurement in Lux. 00120 */ 00121 float Si1133::get_light_level() 00122 { 00123 float lux, uvi; 00124 measure_lux_uv(&lux, &uvi); 00125 return lux; 00126 } 00127 00128 /** Measure the current UV Index on the Si1133 00129 * 00130 * @returns The current UV index. 00131 */ 00132 float Si1133::get_uv_index() 00133 { 00134 float lux, uvi; 00135 measure_lux_uv(&lux, &uvi); 00136 return uvi; 00137 } 00138 00139 bool Si1133::get_light_and_uv(float *light_level, float *uv_index) 00140 { 00141 if(measure_lux_uv(light_level, uv_index)) { 00142 return false; 00143 } 00144 return true; 00145 } 00146 00147 /***************************************************************************//** 00148 * @brief 00149 * Reads register from the Si1133 sensor 00150 * 00151 * @param[in] reg 00152 * The register address to read from in the sensor. 00153 * 00154 * @param[out] data 00155 * The data read from the sensor 00156 * 00157 * @return 00158 * Returns zero on OK, non-zero otherwise 00159 ******************************************************************************/ 00160 uint32_t Si1133::read_register(enum Si1133::Register reg, uint8_t *data) 00161 { 00162 char buf[1]; 00163 buf[0] = (char) reg; 00164 00165 if (m_I2C.write(SI1133_I2C_ADDRESS, buf, 1, true)) { 00166 //Return failure 00167 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00168 } 00169 00170 if (m_I2C.read(SI1133_I2C_ADDRESS, buf, 1)) { 00171 //Return failure 00172 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00173 } 00174 00175 *data = buf[0]; 00176 00177 return SI1133_OK; 00178 } 00179 00180 /***************************************************************************//** 00181 * @brief 00182 * Writes register in the Si1133 sensor 00183 * 00184 * @param[in] reg 00185 * The register address to write to in the sensor 00186 * 00187 * @param[in] data 00188 * The data to write to the sensor 00189 * 00190 * @return 00191 * Returns zero on OK, non-zero otherwise 00192 ******************************************************************************/ 00193 uint32_t Si1133::write_register(enum Si1133::Register reg, uint8_t data) 00194 { 00195 char buf[2]; 00196 buf[0] = (char) reg; 00197 buf[1] = (char) data; 00198 00199 if (m_I2C.write(SI1133_I2C_ADDRESS, buf, 2)) { 00200 //Return failure 00201 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00202 } 00203 00204 return SI1133_OK; 00205 } 00206 00207 /***************************************************************************//** 00208 * @brief 00209 * Writes a block of data to the Si1133 sensor. 00210 * 00211 * @param[in] reg 00212 * The first register to begin writing to 00213 * 00214 * @param[in] length 00215 * The number of bytes to write to the sensor 00216 * 00217 * @param[in] data 00218 * The data to write to the sensor 00219 * 00220 * @return 00221 * Returns zero on OK, non-zero otherwise 00222 ******************************************************************************/ 00223 uint32_t Si1133::write_register_block(enum Si1133::Register reg, uint8_t length, uint8_t *data) 00224 { 00225 char buf[3]; 00226 buf[0] = (char)reg; 00227 00228 if (length > 2) { 00229 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00230 } 00231 00232 memcpy(&buf[1], data, length); 00233 00234 if (m_I2C.write(SI1133_I2C_ADDRESS, buf, length + 1)) { 00235 //Return failure 00236 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00237 } 00238 00239 return SI1133_OK; 00240 } 00241 00242 /***************************************************************************//** 00243 * @brief 00244 * Reads a block of data from the Si1133 sensor. 00245 * 00246 * @param[in] reg 00247 * The first register to begin reading from 00248 * 00249 * @param[in] length 00250 * The number of bytes to write to the sensor 00251 * 00252 * @param[out] data 00253 * The data read from the sensor 00254 * 00255 * @return 00256 * Returns zero on OK, non-zero otherwise 00257 ******************************************************************************/ 00258 uint32_t Si1133::read_register_block(enum Si1133::Register reg, uint8_t length, uint8_t *data) 00259 { 00260 char reg_c = (char)reg; 00261 if (m_I2C.write(SI1133_I2C_ADDRESS, ®_c, 1, true)) { 00262 //Return failure 00263 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00264 } 00265 00266 if (m_I2C.read(SI1133_I2C_ADDRESS, (char*) data, length)) { 00267 //Return failure 00268 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00269 } 00270 00271 return SI1133_OK; 00272 } 00273 00274 /***************************************************************************//** 00275 * @brief 00276 * Reads the interrupt status register of the device 00277 * 00278 * @param[out] irqStatus 00279 * The contentof the IRQ status register 00280 * 00281 * @return 00282 * Returns zero on OK, non-zero otherwise 00283 ******************************************************************************/ 00284 uint32_t Si1133::get_irq_status(uint8_t *irq_status) 00285 { 00286 return read_register(REG_IRQ_STATUS, irq_status); 00287 } 00288 00289 /***************************************************************************//** 00290 * @brief 00291 * Waits until the Si1133 is sleeping before proceeding 00292 * 00293 * @return 00294 * Returns zero on OK, non-zero otherwise 00295 ******************************************************************************/ 00296 uint32_t Si1133::wait_until_sleep(void) 00297 { 00298 uint32_t ret; 00299 uint8_t response; 00300 size_t count = 0; 00301 00302 /* This loops until the Si1133 is known to be in its sleep state */ 00303 /* or if an i2c error occurs */ 00304 while ( count < 5 ) { 00305 ret = read_register(REG_RESPONSE0, &response); 00306 if ( (response & (uint8_t)RSP0_CHIPSTAT_MASK) == (uint8_t)RSP0_SLEEP ) { 00307 return SI1133_OK; 00308 } 00309 00310 if ( ret != SI1133_OK ) { 00311 return SI1133_ERROR_SLEEP_FAILED; 00312 } 00313 00314 count++; 00315 } 00316 00317 return SI1133_ERROR_SLEEP_FAILED; 00318 } 00319 00320 /***************************************************************************//** 00321 * @brief 00322 * Resets the Si1133 00323 * 00324 * @return 00325 * Returns zero on OK, non-zero otherwise 00326 ******************************************************************************/ 00327 uint32_t Si1133::reset(void) 00328 { 00329 uint32_t retval; 00330 00331 /* Do not access the Si1133 earlier than 25 ms from power-up */ 00332 wait_ms(30); 00333 00334 /* Perform the Reset Command */ 00335 retval = write_register(REG_COMMAND, (uint8_t)CMD_RESET); 00336 00337 /* Delay for 10 ms. This delay is needed to allow the Si1133 */ 00338 /* to perform internal reset sequence. */ 00339 wait_ms(10); 00340 00341 return retval; 00342 } 00343 00344 /***************************************************************************//** 00345 * @brief 00346 * Helper function to send a command to the Si1133 00347 * 00348 * @param[in] command 00349 * The command to send to the sensor 00350 * 00351 * @return 00352 * Returns zero on OK, non-zero otherwise 00353 ******************************************************************************/ 00354 uint32_t Si1133::send_cmd(enum Si1133::Command command) 00355 { 00356 uint8_t response; 00357 uint8_t response_stored; 00358 uint8_t count = 0; 00359 uint32_t ret; 00360 00361 /* Get the response register contents */ 00362 ret = read_register(REG_RESPONSE0, &response_stored); 00363 if ( ret != SI1133_OK ) { 00364 return ret; 00365 } 00366 00367 response_stored = response_stored & (uint8_t)RSP0_COUNTER_MASK; 00368 00369 /* Double-check the response register is consistent */ 00370 while ( count < 5 ) { 00371 ret = wait_until_sleep(); 00372 if ( ret != SI1133_OK ) { 00373 return ret; 00374 } 00375 /* Skip if the command is RESET COMMAND COUNTER */ 00376 if ( command == (uint8_t)CMD_RESET_CMD_CTR ) { 00377 break; 00378 } 00379 00380 ret = read_register(REG_RESPONSE0, &response); 00381 00382 if ( (response & (uint8_t)RSP0_COUNTER_MASK) == response_stored ) { 00383 break; 00384 } else { 00385 if ( ret != SI1133_OK ) { 00386 return ret; 00387 } else { 00388 response_stored = response & (uint8_t)RSP0_COUNTER_MASK; 00389 } 00390 } 00391 00392 count++; 00393 } 00394 00395 /* Send the command */ 00396 ret = write_register(REG_COMMAND, command); 00397 if ( ret != SI1133_OK ) { 00398 return ret; 00399 } 00400 00401 count = 0; 00402 /* Expect a change in the response register */ 00403 while ( count < 5 ) { 00404 /* Skip if the command is RESET COMMAND COUNTER */ 00405 if ( command == (uint8_t)CMD_RESET_CMD_CTR ) { 00406 break; 00407 } 00408 00409 ret = read_register(REG_RESPONSE0, &response); 00410 if ( (response & (uint8_t)RSP0_COUNTER_MASK) != response_stored ) { 00411 break; 00412 } else { 00413 if ( ret != SI1133_OK ) { 00414 return ret; 00415 } 00416 } 00417 00418 count++; 00419 } 00420 00421 return SI1133_OK; 00422 } 00423 00424 /***************************************************************************//** 00425 * @brief 00426 * Sends a RESET COMMAND COUNTER command to the Si1133 00427 * 00428 * @return 00429 * Returns zero on OK, non-zero otherwise 00430 ******************************************************************************/ 00431 uint32_t Si1133::reset_cmd_counter(void) 00432 { 00433 return send_cmd(CMD_RESET_CMD_CTR); 00434 } 00435 00436 /***************************************************************************//** 00437 * @brief 00438 * Sends a FORCE command to the Si1133 00439 * 00440 * @return 00441 * Returns zero on OK, non-zero otherwise 00442 ******************************************************************************/ 00443 uint32_t Si1133::force_measurement(void) 00444 { 00445 return send_cmd(CMD_FORCE_CH); 00446 } 00447 00448 /***************************************************************************//** 00449 * @brief 00450 * Sends a START command to the Si1133 00451 * 00452 * @return 00453 * Returns zero on OK, non-zero otherwise 00454 ******************************************************************************/ 00455 uint32_t Si1133::start_measurement(void) 00456 { 00457 return send_cmd(CMD_START); 00458 } 00459 00460 /***************************************************************************//** 00461 * @brief 00462 * Sends a PAUSE command to the Si1133 00463 * 00464 * @return 00465 * Returns zero on OK, non-zero otherwise 00466 ******************************************************************************/ 00467 uint32_t Si1133::pause_measurement(void) 00468 { 00469 return send_cmd(CMD_PAUSE_CH); 00470 } 00471 00472 /***************************************************************************//** 00473 * @brief 00474 * Writes a byte to an Si1133 Parameter 00475 * 00476 * @param[in] address 00477 * The parameter address 00478 * 00479 * @param[in] value 00480 * The byte value to be written to the Si1133 parameter 00481 * 00482 * @return 00483 * Returns zero on OK, non-zero otherwise 00484 * 00485 * @note 00486 * This function ensures that the Si1133 is idle and ready to 00487 * receive a command before writing the parameter. Furthermore, 00488 * command completion is checked. If setting parameter is not done 00489 * properly, no measurements will occur. This is the most common 00490 * error. It is highly recommended that host code make use of this 00491 * function. 00492 ******************************************************************************/ 00493 uint32_t Si1133::set_parameter (enum Si1133::Parameter address, uint8_t value) 00494 { 00495 uint32_t retval; 00496 uint8_t buffer[2]; 00497 uint8_t response_stored; 00498 uint8_t response; 00499 size_t count; 00500 00501 retval = wait_until_sleep(); 00502 if ( retval != SI1133_OK ) { 00503 return retval; 00504 } 00505 00506 read_register(REG_RESPONSE0, &response_stored); 00507 response_stored &= (uint8_t)RSP0_COUNTER_MASK; 00508 00509 buffer[0] = value; 00510 buffer[1] = 0x80 + ((uint8_t)address & 0x3F); 00511 00512 retval = write_register_block(REG_HOSTIN0, 2, (uint8_t*) buffer); 00513 if ( retval != SI1133_OK ) { 00514 return retval; 00515 } 00516 00517 /* Wait for command to finish */ 00518 count = 0; 00519 /* Expect a change in the response register */ 00520 while ( count < 5 ) { 00521 retval = read_register(REG_RESPONSE0, &response); 00522 if ( (response & (uint8_t)RSP0_COUNTER_MASK) != response_stored ) { 00523 break; 00524 } else { 00525 if ( retval != SI1133_OK ) { 00526 return retval; 00527 } 00528 } 00529 00530 count++; 00531 } 00532 00533 if (count >= 5) { 00534 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00535 } 00536 00537 return SI1133_OK; 00538 } 00539 00540 /***************************************************************************//** 00541 * @brief 00542 * Reads a parameter from the Si1133 00543 * 00544 * @param[in] address 00545 * The address of the parameter. 00546 * 00547 * @return 00548 * Returns zero on OK, non-zero otherwise 00549 ******************************************************************************/ 00550 uint32_t Si1133::read_parameter (enum Si1133::Parameter address) 00551 { 00552 uint8_t retval; 00553 uint8_t cmd; 00554 00555 cmd = 0x40 + ((uint8_t)address & 0x3F); 00556 00557 retval = send_cmd((enum Si1133::Command)cmd); 00558 if ( retval != SI1133_OK ) { 00559 return retval; 00560 } 00561 00562 read_register(REG_RESPONSE1, &retval); 00563 00564 return retval; 00565 } 00566 00567 /**************************************************************************//** 00568 * @brief 00569 * Initializes the Si1133 chip 00570 * 00571 * @return 00572 * Returns zero on OK, non-zero otherwise 00573 *****************************************************************************/ 00574 uint32_t Si1133::init (void) 00575 { 00576 uint32_t retval; 00577 00578 /* Allow some time for the part to power up */ 00579 wait_ms(5); 00580 00581 retval = reset(); 00582 00583 wait_ms(10); 00584 00585 retval += set_parameter(PARAM_CH_LIST, 0x0f); 00586 retval += set_parameter(PARAM_ADCCONFIG0, 0x78); 00587 retval += set_parameter(PARAM_ADCSENS0, 0x71); 00588 retval += set_parameter(PARAM_ADCPOST0, 0x40); 00589 retval += set_parameter(PARAM_ADCCONFIG1, 0x4d); 00590 retval += set_parameter(PARAM_ADCSENS1, 0xe1); 00591 retval += set_parameter(PARAM_ADCPOST1, 0x40); 00592 retval += set_parameter(PARAM_ADCCONFIG2, 0x41); 00593 retval += set_parameter(PARAM_ADCSENS2, 0xe1); 00594 retval += set_parameter(PARAM_ADCPOST2, 0x50); 00595 retval += set_parameter(PARAM_ADCCONFIG3, 0x4d); 00596 retval += set_parameter(PARAM_ADCSENS3, 0x87); 00597 retval += set_parameter(PARAM_ADCPOST3, 0x40); 00598 00599 retval += write_register(REG_IRQ_ENABLE, 0x0f); 00600 00601 return retval; 00602 } 00603 00604 /***************************************************************************//** 00605 * @brief 00606 * Stops the measurements on all channel and waits until the chip 00607 * goes to sleep state. 00608 * 00609 * @return 00610 * Returns zero on OK, non-zero otherwise 00611 ******************************************************************************/ 00612 uint32_t Si1133::deinit (void) 00613 { 00614 uint32_t retval; 00615 00616 retval = set_parameter(PARAM_CH_LIST, 0x3f); 00617 retval += pause_measurement(); 00618 retval += wait_until_sleep(); 00619 00620 return retval; 00621 } 00622 00623 /***************************************************************************//** 00624 * @brief 00625 * Read samples from the Si1133 chip 00626 * 00627 * @param[out] samples 00628 * Retrieves interrupt status and measurement data for channel 0..3 and 00629 * converts the data to int32_t format 00630 * 00631 * @return 00632 * Returns zero on OK, non-zero otherwise 00633 ******************************************************************************/ 00634 uint32_t Si1133::measure (Si1133::Samples_t *samples) 00635 { 00636 uint8_t buffer[13]; 00637 uint32_t retval; 00638 00639 retval = read_register_block(REG_IRQ_STATUS, 13, buffer); 00640 00641 samples->irq_status = buffer[0]; 00642 00643 samples->ch0 = buffer[1] << 16; 00644 samples->ch0 |= buffer[2] << 8; 00645 samples->ch0 |= buffer[3]; 00646 if ( samples->ch0 & 0x800000 ) { 00647 samples->ch0 |= 0xFF000000; 00648 } 00649 00650 samples->ch1 = buffer[4] << 16; 00651 samples->ch1 |= buffer[5] << 8; 00652 samples->ch1 |= buffer[6]; 00653 if ( samples->ch1 & 0x800000 ) { 00654 samples->ch1 |= 0xFF000000; 00655 } 00656 00657 samples->ch2 = buffer[7] << 16; 00658 samples->ch2 |= buffer[8] << 8; 00659 samples->ch2 |= buffer[9]; 00660 if ( samples->ch2 & 0x800000 ) { 00661 samples->ch2 |= 0xFF000000; 00662 } 00663 00664 samples->ch3 = buffer[10] << 16; 00665 samples->ch3 |= buffer[11] << 8; 00666 samples->ch3 |= buffer[12]; 00667 if ( samples->ch3 & 0x800000 ) { 00668 samples->ch3 |= 0xFF000000; 00669 } 00670 00671 return retval; 00672 } 00673 00674 int32_t Si1133::calculate_polynomial_helper (int32_t input, int8_t fraction, uint16_t mag, int8_t shift) 00675 { 00676 int32_t value; 00677 00678 if ( shift < 0 ) { 00679 value = ( (input << fraction) / mag) >> -shift; 00680 } else { 00681 value = ( (input << fraction) / mag) << shift; 00682 } 00683 00684 return value; 00685 } 00686 00687 int32_t Si1133::calculate_polynomial (int32_t x, int32_t y, uint8_t input_fraction, uint8_t output_fraction, uint8_t num_coeff, const Si1133::Coeff_t *kp) 00688 { 00689 uint8_t info, x_order, y_order, counter; 00690 int8_t sign, shift; 00691 uint16_t mag; 00692 int32_t output = 0, x1, x2, y1, y2; 00693 00694 for ( counter = 0; counter < num_coeff; counter++ ) { 00695 info = kp->info; 00696 x_order = GET_X_ORDER(info); 00697 y_order = GET_Y_ORDER(info); 00698 00699 shift = ( (uint16_t) kp->info & 0xff00) >> 8; 00700 shift ^= 0x00ff; 00701 shift += 1; 00702 shift = -shift; 00703 00704 mag = kp->mag; 00705 00706 if ( GET_SIGN(info) ) { 00707 sign = -1; 00708 } else { 00709 sign = 1; 00710 } 00711 00712 if ( (x_order == 0) && (y_order == 0) ) { 00713 output += sign * mag << output_fraction; 00714 } else { 00715 if ( x_order > 0 ) { 00716 x1 = calculate_polynomial_helper(x, input_fraction, mag, shift); 00717 if ( x_order > 1 ) { 00718 x2 = calculate_polynomial_helper(x, input_fraction, mag, shift); 00719 } else { 00720 x2 = 1; 00721 } 00722 } else { 00723 x1 = 1; 00724 x2 = 1; 00725 } 00726 00727 if ( y_order > 0 ) { 00728 y1 = calculate_polynomial_helper(y, input_fraction, mag, shift); 00729 if ( y_order > 1 ) { 00730 y2 = calculate_polynomial_helper(y, input_fraction, mag, shift); 00731 } else { 00732 y2 = 1; 00733 } 00734 } else { 00735 y1 = 1; 00736 y2 = 1; 00737 } 00738 00739 output += sign * x1 * x2 * y1 * y2; 00740 } 00741 00742 kp++; 00743 } 00744 00745 if ( output < 0 ) { 00746 output = -output; 00747 } 00748 00749 return output; 00750 } 00751 00752 /***************************************************************************//** 00753 * @brief 00754 * Compute UV index 00755 * 00756 * @param[in] uv 00757 * UV sensor raw data 00758 * 00759 * @param[in] uk 00760 * UV calculation coefficients 00761 * 00762 * @return 00763 * UV index scaled by UV_OUPTUT_FRACTION 00764 ******************************************************************************/ 00765 int32_t Si1133::get_uv (int32_t uv) 00766 { 00767 int32_t uvi; 00768 00769 uvi = calculate_polynomial(0, uv, UV_INPUT_FRACTION, UV_OUTPUT_FRACTION, UV_NUMCOEFF, uk); 00770 00771 return uvi; 00772 } 00773 00774 /***************************************************************************//** 00775 * @brief 00776 * Compute lux value 00777 * 00778 * @param[in] vis_high 00779 * Visible light sensor raw data 00780 * 00781 * @param[in] vis_low 00782 * Visible light sensor raw data 00783 * 00784 * @param[in] ir 00785 * Infrared sensor raw data 00786 * 00787 * @param[in] lk 00788 * Lux calculation coefficients 00789 * 00790 * @return 00791 * Lux value scaled by LUX_OUPTUT_FRACTION 00792 ******************************************************************************/ 00793 int32_t Si1133::get_lux (int32_t vis_high, int32_t vis_low, int32_t ir) 00794 { 00795 int32_t lux; 00796 00797 if ( (vis_high > ADC_THRESHOLD) || (ir > ADC_THRESHOLD) ) { 00798 lux = calculate_polynomial(vis_high, 00799 ir, 00800 INPUT_FRACTION_HIGH, 00801 LUX_OUTPUT_FRACTION, 00802 NUMCOEFF_HIGH, 00803 &(lk.coeff_high[0]) ); 00804 } else { 00805 lux = calculate_polynomial(vis_low, 00806 ir, 00807 INPUT_FRACTION_LOW, 00808 LUX_OUTPUT_FRACTION, 00809 NUMCOEFF_LOW, 00810 &(lk.coeff_low[0]) ); 00811 } 00812 00813 return lux; 00814 } 00815 00816 /***************************************************************************//** 00817 * @brief 00818 * Measure lux and UV index using the Si1133 sensor 00819 * 00820 * @param[out] lux 00821 * The measured ambient light illuminace in lux 00822 * 00823 * @param[out] uvi 00824 * UV index 00825 * 00826 * @return 00827 * Returns zero on OK, non-zero otherwise 00828 ******************************************************************************/ 00829 uint32_t Si1133::measure_lux_uv (float *lux, float *uvi) 00830 { 00831 Si1133::Samples_t samples; 00832 uint32_t retval; 00833 uint8_t response; 00834 00835 /* Force measurement */ 00836 retval = force_measurement(); 00837 00838 /* Go to sleep while the sensor does the conversion */ 00839 wait_ms(200); 00840 00841 /* Check if the measurement finished, if not then wait */ 00842 retval += read_register(REG_IRQ_STATUS, &response); 00843 while ( response != 0x0F ) { 00844 wait_ms(5); 00845 retval += read_register(REG_IRQ_STATUS, &response); 00846 } 00847 00848 /* Get the results */ 00849 measure(&samples); 00850 00851 /* Convert the readings to lux */ 00852 *lux = (float) get_lux(samples.ch1, samples.ch3, samples.ch2); 00853 *lux = *lux / (1 << LUX_OUTPUT_FRACTION); 00854 00855 /* Convert the readings to UV index */ 00856 *uvi = (float) get_uv(samples.ch0); 00857 *uvi = *uvi / (1 << UV_OUTPUT_FRACTION); 00858 00859 return retval; 00860 } 00861 00862 /***************************************************************************//** 00863 * @brief 00864 * Reads Hardware ID from the SI1133 sensor 00865 * 00866 * @param[out] hardwareID 00867 * The Hardware ID of the chip (should be 0x33) 00868 * 00869 * @return 00870 * Returns zero on OK, non-zero otherwise 00871 ******************************************************************************/ 00872 uint32_t Si1133::get_hardware_id (uint8_t *hardware_id) 00873 { 00874 uint32_t retval; 00875 00876 retval = read_register(REG_PART_ID, hardware_id); 00877 00878 return retval; 00879 } 00880 00881 /***************************************************************************//** 00882 * @brief 00883 * Retrieve the sample values from the chip and convert them 00884 * to lux and UV index values 00885 * 00886 * @param[out] lux 00887 * The measured ambient light illuminace in lux 00888 * 00889 * @param[out] uvi 00890 * UV index 00891 * 00892 * @return 00893 * Returns zero on OK, non-zero otherwise 00894 ******************************************************************************/ 00895 uint32_t Si1133::get_measurement (float *lux, float *uvi) 00896 { 00897 Si1133::Samples_t samples; 00898 uint32_t retval; 00899 00900 /* Get the results */ 00901 retval = measure(&samples); 00902 00903 /* Convert the readings to lux */ 00904 *lux = (float) get_lux(samples.ch1, samples.ch3, samples.ch2); 00905 *lux = *lux / (1 << LUX_OUTPUT_FRACTION); 00906 00907 /* Convert the readings to UV index */ 00908 *uvi = (float) get_uv(samples.ch0); 00909 *uvi = *uvi / (1 << UV_OUTPUT_FRACTION); 00910 00911 return retval; 00912 }
Generated on Sat Jul 16 2022 18:44:29 by 1.7.2