/ Adafruit_SI1145.cpp
Adafruit_SI1145.cpp
  1  /***************************************************
  2    This is a library for the Si1145 UV/IR/Visible Light Sensor
  3  
  4    Designed specifically to work with the Si1145 sensor in the
  5    adafruit shop
  6    ----> https://www.adafruit.com/products/1777
  7  
  8    These sensors use I2C to communicate, 2 pins are required to
  9    interface
 10    Adafruit invests time and resources providing this open source code,
 11    please support Adafruit and open-source hardware by purchasing
 12    products from Adafruit!
 13  
 14    Written by Limor Fried/Ladyada for Adafruit Industries.
 15    BSD license, all text above must be included in any redistribution
 16   ****************************************************/
 17  
 18  #include "Adafruit_SI1145.h"
 19  
 20  /**
 21   * @brief Destructor
 22   *
 23   */
 24  Adafruit_SI1145::~Adafruit_SI1145() {
 25    if (i2c_dev)
 26      delete i2c_dev;
 27  }
 28  /**
 29   * @brief Construct a new Adafruit_SI1145::Adafruit_SI1145 object
 30   *
 31   */
 32  Adafruit_SI1145::Adafruit_SI1145() {}
 33  /**
 34   * @brief Initize the driver, specifying the `TwoWire` bus to use
 35   *
 36   * @param pBus Pointer to the `TwoWire` I2C bus to use
 37   * @return boolean true: success false: failure to initialize the sensor
 38   */
 39  boolean Adafruit_SI1145::begin(TwoWire *pBus) {
 40    return begin(SI1145_ADDR, pBus);
 41  }
 42  /**
 43   * @brief Initize the driver, supplying both a `TwoWire` bus and I2C address
 44   *
 45   * @param addr The I2C address of the Sensor
 46   * @param pBus Pointer to the `TwoWire` instance to use
 47   * @return boolean true: success false: failure to initize the sensor
 48   */
 49  boolean Adafruit_SI1145::begin(uint8_t addr, TwoWire *pBus) {
 50    if (i2c_dev)
 51      delete i2c_dev;
 52    i2c_dev = new Adafruit_I2CDevice(addr, pBus);
 53    if (!i2c_dev->begin()) {
 54      return false;
 55    }
 56  
 57    uint8_t id = read8(SI1145_REG_PARTID);
 58    if (id != 0x45)
 59      return false; // look for SI1145
 60  
 61    reset();
 62  
 63    /***********************************/
 64    // enable UVindex measurement coefficients!
 65    write8(SI1145_REG_UCOEFF0, 0x29);
 66    write8(SI1145_REG_UCOEFF1, 0x89);
 67    write8(SI1145_REG_UCOEFF2, 0x02);
 68    write8(SI1145_REG_UCOEFF3, 0x00);
 69  
 70    // enable UV sensor
 71    writeParam(SI1145_PARAM_CHLIST,
 72               SI1145_PARAM_CHLIST_ENUV | SI1145_PARAM_CHLIST_ENALSIR |
 73                   SI1145_PARAM_CHLIST_ENALSVIS | SI1145_PARAM_CHLIST_ENPS1);
 74    // enable interrupt on every sample
 75    write8(SI1145_REG_INTCFG, SI1145_REG_INTCFG_INTOE);
 76    write8(SI1145_REG_IRQEN, SI1145_REG_IRQEN_ALSEVERYSAMPLE);
 77  
 78    /****************************** Prox Sense 1 */
 79  
 80    // program LED current
 81    write8(SI1145_REG_PSLED21, 0x03); // 20mA for LED 1 only
 82    writeParam(SI1145_PARAM_PS1ADCMUX, SI1145_PARAM_ADCMUX_LARGEIR);
 83    // prox sensor #1 uses LED #1
 84    writeParam(SI1145_PARAM_PSLED12SEL, SI1145_PARAM_PSLED12SEL_PS1LED1);
 85    // fastest clocks, clock div 1
 86    writeParam(SI1145_PARAM_PSADCGAIN, 0);
 87    // take 511 clocks to measure
 88    writeParam(SI1145_PARAM_PSADCOUNTER, SI1145_PARAM_ADCCOUNTER_511CLK);
 89    // in prox mode, high range
 90    writeParam(SI1145_PARAM_PSADCMISC,
 91               SI1145_PARAM_PSADCMISC_RANGE | SI1145_PARAM_PSADCMISC_PSMODE);
 92  
 93    writeParam(SI1145_PARAM_ALSIRADCMUX, SI1145_PARAM_ADCMUX_SMALLIR);
 94    // fastest clocks, clock div 1
 95    writeParam(SI1145_PARAM_ALSIRADCGAIN, 0);
 96    // take 511 clocks to measure
 97    writeParam(SI1145_PARAM_ALSIRADCOUNTER, SI1145_PARAM_ADCCOUNTER_511CLK);
 98    // in high range mode
 99    writeParam(SI1145_PARAM_ALSIRADCMISC, SI1145_PARAM_ALSIRADCMISC_RANGE);
100  
101    // fastest clocks, clock div 1
102    writeParam(SI1145_PARAM_ALSVISADCGAIN, 0);
103    // take 511 clocks to measure
104    writeParam(SI1145_PARAM_ALSVISADCOUNTER, SI1145_PARAM_ADCCOUNTER_511CLK);
105    // in high range mode (not normal signal)
106    writeParam(SI1145_PARAM_ALSVISADCMISC, SI1145_PARAM_ALSVISADCMISC_VISRANGE);
107  
108    /************************/
109  
110    // measurement rate for auto
111    write8(SI1145_REG_MEASRATE0, 0xFF); // 255 * 31.25uS = 8ms
112  
113    // auto run
114    write8(SI1145_REG_COMMAND, SI1145_PSALS_AUTO);
115  
116    return true;
117  }
118  /**
119   * @brief Reset the sensor's registers to an initial state
120   *
121   */
122  void Adafruit_SI1145::reset() {
123    write8(SI1145_REG_MEASRATE0, 0);
124    write8(SI1145_REG_MEASRATE1, 0);
125    write8(SI1145_REG_IRQEN, 0);
126    write8(SI1145_REG_IRQMODE1, 0);
127    write8(SI1145_REG_IRQMODE2, 0);
128    write8(SI1145_REG_INTCFG, 0);
129    write8(SI1145_REG_IRQSTAT, 0xFF);
130  
131    write8(SI1145_REG_COMMAND, SI1145_RESET);
132    delay(10);
133    write8(SI1145_REG_HWKEY, 0x17);
134  
135    delay(10);
136  }
137  
138  //////////////////////////////////////////////////////
139  
140  /**
141   * @brief Get the current UV reading
142   *
143   * @return uint16_t The the UV index * 100 (divide by 100 to get the index)
144   */
145  uint16_t Adafruit_SI1145::readUV(void) { return read16(0x2C); }
146  
147  /**
148   * @brief Get the Visible & IR light levels
149   *
150   * @return uint16_t The Visible & IR light levels
151   */
152  uint16_t Adafruit_SI1145::readVisible(void) { return read16(0x22); }
153  
154  // returns IR light levels
155  /**
156   * @brief Get the Infrared light level
157   *
158   * @return uint16_t The Infrared light level
159   */
160  uint16_t Adafruit_SI1145::readIR(void) { return read16(0x24); }
161  
162  // returns "Proximity" - assumes an IR LED is attached to LED
163  /**
164   * @brief Gets the Proximity measurement - **Requires an attached IR LED**
165   *
166   * @return uint16_t The proximity measurement
167   */
168  uint16_t Adafruit_SI1145::readProx(void) { return read16(0x26); }
169  
170  /*********************************************************************/
171  
172  uint8_t Adafruit_SI1145::writeParam(uint8_t p, uint8_t v) {
173    // Serial.print("Param 0x"); Serial.print(p, HEX);
174    // Serial.print(" = 0x"); Serial.println(v, HEX);
175  
176    write8(SI1145_REG_PARAMWR, v);
177    write8(SI1145_REG_COMMAND, p | SI1145_PARAM_SET);
178    return read8(SI1145_REG_PARAMRD);
179  }
180  
181  uint8_t Adafruit_SI1145::readParam(uint8_t p) {
182    write8(SI1145_REG_COMMAND, p | SI1145_PARAM_QUERY);
183    return read8(SI1145_REG_PARAMRD);
184  }
185  
186  /*********************************************************************/
187  
188  uint8_t Adafruit_SI1145::read8(uint8_t reg) {
189    uint8_t buffer[1] = {reg};
190    i2c_dev->write_then_read(buffer, 1, buffer, 1);
191    return buffer[0];
192  }
193  
194  uint16_t Adafruit_SI1145::read16(uint8_t a) {
195    uint8_t buffer[2] = {a, 0};
196    i2c_dev->write_then_read(buffer, 1, buffer, 2);
197    return ((uint16_t)buffer[0]) | ((uint16_t)buffer[1] << 8);
198  }
199  
200  void Adafruit_SI1145::write8(uint8_t reg, uint8_t val) {
201    uint8_t buffer[2] = {reg, val};
202    i2c_dev->write(buffer, 2);
203  }