Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 } 00913
Generated on Sun Jul 24 2022 19:56:57 by
1.7.2