int TSL2561_OPEN(TSL2561 *sensor) { char filename[20]; if(sensor->adapter_fd != -1) { // already opened // TODO: choose a valid errno error sensor->lasterr = -1; return -1; } snprintf(filename, 20, "/dev/i2c-%d", sensor->adapter_nr); if ((sensor->adapter_fd = open(filename, O_RDWR)) < 0) { // open the device file (requests i2c-dev kernel module loaded) sensor->lasterr = errno; return -1; } if (ioctl(sensor->adapter_fd, I2C_SLAVE, sensor->sensor_addr) < 0) { // talk to the requested device sensor->lasterr = errno; close(sensor->adapter_fd); sensor->adapter_fd = -1; return -1; } TSL2561_SETINTEGRATIONTIME(sensor, TSL2561_INTEGRATIONTIME_402MS); TSL2561_SETGAIN(sensor, TSL2561_GAIN_16X); /* TSL2561_ON(sensor); tsl2561_write8(sensor, 0x81, 0x11); TSL2561_OFF(sensor); */ return 0; }
int main() { int rc; uint16_t broadband, ir; uint32_t lux=0; // prepare the sensor // (the first parameter is the raspberry pi i2c master controller attached to the TSL2561, the second is the i2c selection jumper) // The i2c selection address can be one of: TSL2561_ADDR_LOW, TSL2561_ADDR_FLOAT or TSL2561_ADDR_HIGH TSL2561 light1 = TSL2561_INIT(1, TSL2561_ADDR_FLOAT); // initialize the sensor rc = TSL2561_OPEN(&light1); if(rc != 0) { fprintf(stderr, "Error initializing TSL2561 sensor (%s). Check your i2c bus (es. i2cdetect)\n", strerror(light1.lasterr)); // you don't need to TSL2561_CLOSE() if TSL2561_OPEN() failed, but it's safe doing it. TSL2561_CLOSE(&light1); return 1; } // set the gain to 1X (it can be TSL2561_GAIN_1X or TSL2561_GAIN_16X) // use 16X gain to get more precision in dark ambients, or enable auto gain below rc = TSL2561_SETGAIN(&light1, TSL2561_GAIN_1X); // set the integration time // (TSL2561_INTEGRATIONTIME_402MS or TSL2561_INTEGRATIONTIME_101MS or TSL2561_INTEGRATIONTIME_13MS) // TSL2561_INTEGRATIONTIME_402MS is slower but more precise, TSL2561_INTEGRATIONTIME_13MS is very fast but not so precise rc = TSL2561_SETINTEGRATIONTIME(&light1, TSL2561_INTEGRATIONTIME_101MS); // sense the luminosity from the sensor (lux is the luminosity taken in "lux" measure units) // the last parameter can be 1 to enable library auto gain, or 0 to disable it rc = TSL2561_SENSELIGHT(&light1, &broadband, &ir, &lux, 1); printf("Test. RC: %i(%s), broadband: %i, ir: %i, lux: %i\n", rc, strerror(light1.lasterr), broadband, ir, lux); TSL2561_CLOSE(&light1); return 0; }
/** * sense the ambient light. Returns 0 on success, -1 on errors. * the parameter pointer fullspectrum is the quantity og light at full spectrum (including infrared) * the parameter pointer infrared is the quantity of infrared light * if autogain is 0 a single sensor reading is done with the gain and integration time previously selected by invoking * the TSL2561_SETINTEGRATIONTIME() and TSL2561_SETGAIN() functions. It autogain is 1 and automatic gain adjustment alghoritm is used */ int TSL2561_SENSELIGHT(TSL2561 *sensor, uint16_t *full_spectrum, uint16_t *infrared, uint32_t *lux, int autogain) { int rc=1; uint16_t fs, ir, hi, lo; //tsl2561Gain_t old_gain; if(sensor->adapter_fd == -1) { // TODO: choose a valid errno error sensor->lasterr = -1; return -1; } if (autogain == 0) { // autogain not requested. Executing a single sensor read rc = tsl2561_getdata(sensor, full_spectrum, infrared); *lux = TSL2561_CALCULATE_LUX(sensor, *full_spectrum, *infrared); return rc; } // autogain requested switch(sensor->integration_time) { case TSL2561_INTEGRATIONTIME_13MS: hi = TSL2561_AGC_THI_13MS; lo = TSL2561_AGC_TLO_13MS; break; case TSL2561_INTEGRATIONTIME_101MS: hi = TSL2561_AGC_THI_101MS; lo = TSL2561_AGC_TLO_101MS; break; case TSL2561_INTEGRATIONTIME_402MS: hi = TSL2561_AGC_THI_402MS; lo = TSL2561_AGC_TLO_402MS; break; default: hi = TSL2561_AGC_THI_402MS; lo = TSL2561_AGC_TLO_402MS; break; } // save the old gain //old_gain = sensor->gain; // try to adjust the gain rc = tsl2561_getdata(sensor, &fs, &ir); if(rc != 0) { return -1; // invalid read or sensor error } if ((fs < lo) && (sensor->gain == TSL2561_GAIN_1X)) { // light too low with this gain // raise the gain and redo the reading TSL2561_SETGAIN(sensor, TSL2561_GAIN_16X); //printf("gain raised\n"); rc = tsl2561_getdata(sensor, &fs, &ir); // restore the previous gain //TSL2561_SETGAIN(sensor, old_gain); if(rc != 0) { // invalid read or sensor error return -1; } else { // now consider the reading valid after being adjusted *full_spectrum = fs; *infrared = ir; *lux = TSL2561_CALCULATE_LUX(sensor, *full_spectrum, *infrared); return 0; } } if ((fs > hi) && (sensor->gain == TSL2561_GAIN_16X)) { // light too high with this gain // lower the gain and redo the reading TSL2561_SETGAIN(sensor, TSL2561_GAIN_1X); //printf("gain lowered\n"); rc = tsl2561_getdata(sensor, &fs, &ir); // restore the previous gain //TSL2561_SETGAIN(sensor, old_gain); if(rc != 0) { // invalid read or sensor error return -1; } else { // now consider the reading valid after being adjusted *full_spectrum = fs; *infrared = ir; *lux = TSL2561_CALCULATE_LUX(sensor, *full_spectrum, *infrared); return 0; } } // the reading was valid without gain adjustment (or chip limits encountered!) *full_spectrum = fs; *infrared = ir; *lux = TSL2561_CALCULATE_LUX(sensor, *full_spectrum, *infrared); return 0; }