Brian Chamberlain
Published © MIT

Home Environment Monitor

A simple build-your-own environment monitor for your home. This project uses Particle Photon, sensors from Adafruit, and a 3D-printed case.

AdvancedShowcase (no instructions)6,040
Home Environment Monitor

Things used in this project

Hardware components

Photon
Particle Photon
×1
Perma-proto Breadboard
×1
SparkFun Sensor Kit
SparkFun Sensor Kit
×1

Software apps and online services

Fusion 360
Autodesk Fusion 360
Used this tool to design the enclosure for the sensor circuit board
Librato
I used Librato to graph the data collected from each of the sensors in each sensor device.

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

3D printable holder for the sensor circuit board

Print this to hold the sensor project circuit board

Environment Shell for sensor board

3D print this to hold the circuit board

Code

Prototype code for the Photon

C/C++
// This #include statement was automatically added by the Spark IDE.
#include "SFE_TSL2561.h"

// This #include statement was automatically added by the Spark IDE.
#include "AudioGetAverageLib/AudioGetAverageLib.h"

// TEMP/HUMIDITY SENSOR
// This #include statement was automatically added by the Spark IDE.
#include "Adafruit_DHT/Adafruit_DHT.h"
#define DHTPIN 2    
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
#define TEMPSAMPLE 2000
int counter;

// Light sesnsor
#define HASLIGHT 1 // BC Sense 1 has light sensor 2561 from sparkfun, BC Sense 3 does NOT, BC Sense 2 has a 2561 light sensor fram adafruit

// Create an SFE_TSL2561 object, here called "light"
SFE_TSL2561 light;

// Global variables:
boolean gain;     // Gain setting, 0 = X1, 1 = X16;
unsigned int ms;  // Integration ("shutter") time in milliseconds


// AUDIO SENSOR
#define AUDIO_INPUTCHANNEL A0
//set the audio input board reference voltage
#define AUDIO_VOLTREF 0.0022
//set the audio input board reference dB value
#define AUDIO_DBREF 10
// The number of samples, eg 32
#define SAMPLE_COUNT 32
// Smoothing 0:more 64:less
#define SMOOTHFILTERVAL 48
#define DYNAMICBIAS 0

//set the reference ADC voltage
#define ANALOGVOLTAGEREF 3.3
double analogVoltageRef = ANALOGVOLTAGEREF; //ADC reference voltage

//initialize audioGet library
AudioGetAverageLib audioGet(
    AUDIO_INPUTCHANNEL,
    DYNAMICBIAS,
    AUDIOGETAVERAGE_DEFAULTBIASZERORAW,
    SMOOTHFILTERVAL,
    SAMPLE_COUNT,
    AUDIOGETAVERAGE_DEFAULTSAMPLESINTERVALMICROSEC,
    AUDIOGETAVERAGE_DEFAULTRMSCORRECTION);

// Spark variables used to store data values
double temperature;
double humidity;
double soundDbl;
double luxVal;
boolean lightGood;

// Sound generation
int speakerPin = A5;

// notes in the melody:
//int melody[] = {1908,2551,2551,2273,2551,0,2024,1908}; //C4,G3,G3,A3,G3,0,B3,C4
int melody[] = {2637,2637,0,2637,0,2093,2637,0,3136,0,1568,0};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
//int noteDurations[] = {4,8,8,4,4,4,4,4 };
int noteDurations[] = {8,8,8,8,8,8,8,8,4,4,4,4};

void song() {
    // iterate over the notes of the melody:
  for (int thisNote = 0; thisNote < arraySize(noteDurations); thisNote++) {

    // to calculate the note duration, take one second 
    // divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int noteDuration = 1000/noteDurations[thisNote];
    tone(speakerPin, melody[thisNote],noteDuration);

    // to distinguish the notes, set a minimum time between them.
    // the note's duration + 30% seems to work well:
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    // stop the tone playing:
    noTone(speakerPin);
  }
}

// Takes a command attribute to match method signature, we don't use it.
int playSong(String command)
{
    song();
    return 1;
}

void setup() {
    
    Spark.publish("BC2 Booted!");
    song();
    
    Spark.variable("temperature", &temperature, DOUBLE);
    Spark.variable("humidity", &humidity, DOUBLE);
    Spark.variable("sound_dbl", &soundDbl, DOUBLE);
    Spark.variable("lux", &luxVal, DOUBLE);
    Spark.variable("light_good", &lightGood, BOOLEAN);
    
    Spark.function("play_song", playSong);
    
	dht.begin();
    
    if (HASLIGHT){
        light.begin();
        // If gain = false (0), device is set to low gain (1X)
        // If gain = high (1), device is set to high gain (16X)
        gain = 0;
        // If time = 0, integration will be 13.7ms
        // If time = 1, integration will be 101ms
        // If time = 2, integration will be 402ms
        // If time = 3, use manual start / stop to perform your own integration
        unsigned char time = 2;
        
        // setTiming() will set the third parameter (ms) to the
        // requested integration time in ms (this will be useful later):
        light.setTiming(gain,time,ms);
        // To start taking measurements, power up the sensor:
        light.setPowerUp();
    }

}

void loop() {
    

    // do readings
    humidity = dht.getHumidity();
    temperature = dht.getTempFarenheit() - 8;
    Spark.publish("librato_bc2_humidity", String(humidity));
    delay(2000);
    Spark.publish("librato_bc2_temperature", String(temperature));
    delay(2000);

    // LIGHT
    if (HASLIGHT){
        unsigned int data0, data1;
        if (light.getData(data0,data1)){
            // Perform lux calculation:
            lightGood = light.getLux(gain,ms,data0,data1,luxVal);
            Spark.publish("librato_bc2_lux", String((int)luxVal));
            delay(2000);
        }else{
            lightGood = false;
            luxVal = 0.0;
        }
    }
	
	// AUDIO
	int audioRms = 0; //audio RMS value
    int audioAdc = 0; //audio raw ADC
    
    //get raw ADC
    audioAdc = analogRead(AUDIO_INPUTCHANNEL);
    //get RMS value
    audioRms = audioGet.getRms();
    double voltageRms = AUDIO_VOLTREF;
    if(audioRms > 0) {
          voltageRms = (audioRms * analogVoltageRef) / 4095;
          if(voltageRms < AUDIO_VOLTREF) { //prevent values less than AUDIO_DBREF
              voltageRms = AUDIO_VOLTREF;
          }
     }
    //get Spl value
    soundDbl = (double)audioGet.getSpl(voltageRms, AUDIO_VOLTREF, AUDIO_DBREF);
    Spark.publish("librato_bc2_dbl", String((int)soundDbl));
    delay(10000);
}

SFE_TSL2561.cpp

C/C++
Code file for the SparkFun TSL2561 light sensor
/*
	SFE_TSL2561 illumination sensor library for Arduino
	Mike Grusin, SparkFun Electronics
	
	This library provides functions to access the TAOS TSL2561
	Illumination Sensor.
	
	Our example code uses the "beerware" license. You can do anything
	you like with this code. No really, anything. If you find it useful,
	buy me a beer someday.

	version 1.0 2013/09/20 MDG initial version
*/

#include "SFE_TSL2561.h"
#include "application.h"
#include "math.h"

// Macros
#define highByte(x) ( (x) >> (8) ) // keep upper 8 bits
#define lowByte(x) ( (x) & (0xff) ) // keep lower 8 bits


SFE_TSL2561::SFE_TSL2561(void)
	// SFE_TSL2561 object
{}


boolean SFE_TSL2561::begin(void)
	// Initialize TSL2561 library with default address (0x39)
	// Always returns true
{
	return(begin(TSL2561_ADDR));
}


boolean SFE_TSL2561::begin(char i2c_address)
	// Initialize TSL2561 library to arbitrary address or:
	// TSL2561_ADDR_0 (0x29 address with '0' shorted on board)
	// TSL2561_ADDR   (0x39 default address)
	// TSL2561_ADDR_1 (0x49 address with '1' shorted on board)
	// Always returns true
{
	_i2c_address = i2c_address;
	Wire.begin();
	return(true);
}


boolean SFE_TSL2561::setPowerUp(void)
	// Turn on TSL2561, begin integrations
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() below)
{
	// Write 0x03 to command byte (power on)
	return(writeByte(TSL2561_REG_CONTROL,0x03));
}


boolean SFE_TSL2561::setPowerDown(void)
	// Turn off TSL2561
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() below)
{
	// Clear command byte (power off)
	return(writeByte(TSL2561_REG_CONTROL,0x00));
}


boolean SFE_TSL2561::setTiming(boolean gain, unsigned char time)
	// If gain = false (0), device is set to low gain (1X)
	// If gain = high (1), device is set to high gain (16X)
	// If time = 0, integration will be 13.7ms
	// If time = 1, integration will be 101ms
	// If time = 2, integration will be 402ms
	// If time = 3, use manual start / stop
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() below)
{
	unsigned char timing;

	// Get timing byte
	if (readByte(TSL2561_REG_TIMING,timing))
	{
		// Set gain (0 or 1)
		if (gain)
			timing |= 0x10;
		else
			timing &= ~0x10;

		// Set integration time (0 to 3)
		timing &= ~0x03;
		timing |= (time & 0x03);

		// Write modified timing byte back to device
		if (writeByte(TSL2561_REG_TIMING,timing))
			return(true);
	}
	return(false);
}


boolean SFE_TSL2561::setTiming(boolean gain, unsigned char time, unsigned int &ms)
	// If gain = false (0), device is set to low gain (1X)
	// If gain = high (1), device is set to high gain (16X)
	// If time = 0, integration will be 13.7ms
	// If time = 1, integration will be 101ms
	// If time = 2, integration will be 402ms
	// If time = 3, use manual start / stop (ms = 0)
	// ms will be set to integration time
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() below)
{
	// Calculate ms for user
	switch (time)
	{
		case 0: ms = 14; break;
		case 1: ms = 101; break;
		case 2: ms = 402; break;
		default: ms = 0;
	}
	// Set integration using base function
	return(setTiming(gain,time));
}


boolean SFE_TSL2561::manualStart(void)
	// Starts a manual integration period
	// After running this command, you must manually stop integration with manualStop()
	// Internally sets integration time to 3 for manual integration (gain is unchanged)
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() below)
{
	unsigned char timing;
	
	// Get timing byte
	if (readByte(TSL2561_REG_TIMING,timing))
	{
		// Set integration time to 3 (manual integration)
		timing |= 0x03;

		if (writeByte(TSL2561_REG_TIMING,timing))
		{
			// Begin manual integration
			timing |= 0x08;

			// Write modified timing byte back to device
			if (writeByte(TSL2561_REG_TIMING,timing))
				return(true);
		}
	}
	return(false);
}


boolean SFE_TSL2561::manualStop(void)
	// Stops a manual integration period
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() below)
{
	unsigned char timing;
	
	// Get timing byte
	if (readByte(TSL2561_REG_TIMING,timing))
	{
		// Stop manual integration
		timing &= ~0x08;

		// Write modified timing byte back to device
		if (writeByte(TSL2561_REG_TIMING,timing))
			return(true);
	}
	return(false);
}


boolean SFE_TSL2561::getData(unsigned int &data0, unsigned int &data1)
	// Retrieve raw integration results
	// data0 and data1 will be set to integration results
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() below)
{
	// Get data0 and data1 out of result registers
	if (readUInt(TSL2561_REG_DATA_0,data0) && readUInt(TSL2561_REG_DATA_1,data1)) 
		return(true);

	return(false);
}


boolean SFE_TSL2561::getLux(unsigned char gain, unsigned int ms, unsigned int CH0, unsigned int CH1, double &lux)
	// Convert raw data to lux
	// gain: 0 (1X) or 1 (16X), see setTiming()
	// ms: integration time in ms, from setTiming() or from manual integration
	// CH0, CH1: results from getData()
	// lux will be set to resulting lux calculation
	// returns true (1) if calculation was successful
	// RETURNS false (0) AND lux = 0.0 IF EITHER SENSOR WAS SATURATED (0XFFFF)
{
	double ratio, d0, d1;

	// Determine if either sensor saturated (0xFFFF)
	// If so, abandon ship (calculation will not be accurate)
	if ((CH0 == 0xFFFF) || (CH1 == 0xFFFF))
	{
		lux = 0.0;
		return(false);
	}

	// Convert from unsigned integer to floating point
	d0 = CH0; d1 = CH1;

	// We will need the ratio for subsequent calculations
	ratio = d1 / d0;

	// Normalize for integration time
	d0 *= (402.0/ms);
	d1 *= (402.0/ms);

	// Normalize for gain
	if (!gain)
	{
		d0 *= 16;
		d1 *= 16;
	}

	// Determine lux per datasheet equations:
	
	if (ratio < 0.5)
	{
		lux = 0.0304 * d0 - 0.062 * d0 * pow(ratio,1.4);
		return(true);
	}

	if (ratio < 0.61)
	{
		lux = 0.0224 * d0 - 0.031 * d1;
		return(true);
	}

	if (ratio < 0.80)
	{
		lux = 0.0128 * d0 - 0.0153 * d1;
		return(true);
	}

	if (ratio < 1.30)
	{
		lux = 0.00146 * d0 - 0.00112 * d1;
		return(true);
	}

	// if (ratio > 1.30)
	lux = 0.0;
	return(true);
}


boolean SFE_TSL2561::setInterruptControl(unsigned char control, unsigned char persist)
	// Sets up interrupt operations
	// If control = 0, interrupt output disabled
	// If control = 1, use level interrupt, see setInterruptThreshold()
	// If persist = 0, every integration cycle generates an interrupt
	// If persist = 1, any value outside of threshold generates an interrupt
	// If persist = 2 to 15, value must be outside of threshold for 2 to 15 integration cycles
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() below)
{
	// Place control and persist bits into proper location in interrupt control register
	if (writeByte(TSL2561_REG_INTCTL,((control | 0B00000011) << 4) & (persist | 0B00001111)))
		return(true);
		
	return(false);
}


boolean SFE_TSL2561::setInterruptThreshold(unsigned int low, unsigned int high)
	// Set interrupt thresholds (channel 0 only)
	// low, high: 16-bit threshold values
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() below)
{
	// Write low and high threshold values
	if (writeUInt(TSL2561_REG_THRESH_L,low) && writeUInt(TSL2561_REG_THRESH_H,high))
		return(true);
		
	return(false);
}


boolean SFE_TSL2561::clearInterrupt(void)
	// Clears an active interrupt
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() below)
{
	// Set up command byte for interrupt clear
	Wire.beginTransmission(_i2c_address);
	Wire.write(TSL2561_CMD_CLEAR);
	_error = Wire.endTransmission();
	if (_error == 0)
		return(true);

	return(false);
}


boolean SFE_TSL2561::getID(unsigned char &ID)
	// Retrieves part and revision code from TSL2561
	// Sets ID to part ID (see datasheet)
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() below)
{
	// Get ID byte from ID register
	if (readByte(TSL2561_REG_ID,ID))
		return(true);

	return(false);
}


byte SFE_TSL2561::getError(void)
	// If any library command fails, you can retrieve an extended
	// error code using this command. Errors are from the wire library: 
	// 0 = Success
	// 1 = Data too long to fit in transmit buffer
	// 2 = Received NACK on transmit of address
	// 3 = Received NACK on transmit of data
	// 4 = Other error
{
	return(_error);
}

// Private functions:

boolean SFE_TSL2561::readByte(unsigned char address, unsigned char &value)
	// Reads a byte from a TSL2561 address
	// Address: TSL2561 address (0 to 15)
	// Value will be set to stored byte
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() above)
{
	// Set up command byte for read
	Wire.beginTransmission(_i2c_address);
	Wire.write((address & 0x0F) | TSL2561_CMD);
	_error = Wire.endTransmission();

	// Read requested byte
	if (_error == 0)
	{
		Wire.requestFrom(_i2c_address,1);
		if (Wire.available() == 1)
		{
			value = Wire.read();
			return(true);
		}
	}
	return(false);
}


boolean SFE_TSL2561::writeByte(unsigned char address, unsigned char value)
	// Write a byte to a TSL2561 address
	// Address: TSL2561 address (0 to 15)
	// Value: byte to write to address
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() above)
{
	// Set up command byte for write
	Wire.beginTransmission(_i2c_address);
	Wire.write((address & 0x0F) | TSL2561_CMD);
	// Write byte
	Wire.write(value);
	_error = Wire.endTransmission();
	if (_error == 0)
		return(true);

	return(false);
}


boolean SFE_TSL2561::readUInt(unsigned char address, unsigned int &value)
	// Reads an unsigned integer (16 bits) from a TSL2561 address (low byte first)
	// Address: TSL2561 address (0 to 15), low byte first
	// Value will be set to stored unsigned integer
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() above)
{
	char high, low;
	
	// Set up command byte for read
	Wire.beginTransmission(_i2c_address);
	Wire.write((address & 0x0F) | TSL2561_CMD);
	_error = Wire.endTransmission();

	// Read two bytes (low and high)
	if (_error == 0)
	{
		Wire.requestFrom(_i2c_address,2);
		if (Wire.available() == 2)
		{
			low = Wire.read();
			high = Wire.read();
			// Combine bytes into unsigned int
			value = ((unsigned int)high << 8) + low;
			return(true);
		}
	}	
	return(false);
}


boolean SFE_TSL2561::writeUInt(unsigned char address, unsigned int value)
	// Write an unsigned integer (16 bits) to a TSL2561 address (low byte first)
	// Address: TSL2561 address (0 to 15), low byte first
	// Value: unsigned int to write to address
	// Returns true (1) if successful, false (0) if there was an I2C error
	// (Also see getError() above)
{
	// Split int into lower and upper bytes, write each byte
	if (writeByte(address,lowByte(value)) 
		&& writeByte(address + 1,highByte(value)))
		return(true);

	return(false);
}

SFE_TSL2561.h

C/C++
Header file for SparkFun TSL2561 code
/*
	SFE_TSL2561 illumination sensor library for Arduino
	Mike Grusin, SparkFun Electronics
	
	This library provides functions to access the TAOS TSL2561
	Illumination Sensor.
	
	Our example code uses the "beerware" license. You can do anything
	you like with this code. No really, anything. If you find it useful,
	buy me a beer someday.

	version 1.0 2013/09/20 MDG initial version
*/

#ifndef SFE_TSL2561_h
#define SFE_TSL2561_h

#include "application.h"

class SFE_TSL2561
{
	public:
		SFE_TSL2561(void);
			// SFE_TSL2561 object
			
		boolean begin(void);
			// Initialize TSL2561 library with default address (0x39)
			// Always returns true

		boolean begin(char i2c_address);
			// Initialize TSL2561 library to arbitrary address or:
			// TSL2561_ADDR_0 (0x29 address with '0' shorted on board)
			// TSL2561_ADDR   (0x39 default address)
			// TSL2561_ADDR_1 (0x49 address with '1' shorted on board)
			// Always returns true
		
		boolean setPowerUp(void);
			// Turn on TSL2561, begin integration
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() below)

		boolean setPowerDown(void);
			// Turn off TSL2561
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() below)

		boolean setTiming(boolean gain, unsigned char time);
			// If gain = false (0), device is set to low gain (1X)
			// If gain = high (1), device is set to high gain (16X)
			// If time = 0, integration will be 13.7ms
			// If time = 1, integration will be 101ms
			// If time = 2, integration will be 402ms
			// If time = 3, use manual start / stop
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() below)

		boolean setTiming(boolean gain, unsigned char time, unsigned int &ms);
			// Identical to above command, except ms is set to selected integration time
			// If gain = false (0), device is set to low gain (1X)
			// If gain = high (1), device is set to high gain (16X)
			// If time = 0, integration will be 13.7ms
			// If time = 1, integration will be 101ms
			// If time = 2, integration will be 402ms
			// If time = 3, use manual start / stop (ms = 0)
			// ms will be set to requested integration time
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() below)

		boolean manualStart(void);
			// Starts a manual integration period
			// After running this command, you must manually stop integration with manualStop()
			// Internally sets integration time to 3 for manual integration (gain is unchanged)
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() below)

		boolean manualStop(void);
			// Stops a manual integration period
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() below)

		boolean getData(unsigned int &CH0, unsigned int &CH1);
			// Retrieve raw integration results
			// data0 and data1 will be set to integration results
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() below)
			
		boolean getLux(unsigned char gain, unsigned int ms, unsigned int CH0, unsigned int CH1, double &lux);
			// Convert raw data to lux
			// gain: 0 (1X) or 1 (16X), see setTiming()
			// ms: integration time in ms, from setTiming() or from manual integration
			// CH0, CH1: results from getData()
			// lux will be set to resulting lux calculation
			// returns true (1) if calculation was successful
			// RETURNS false (0) AND lux = 0.0 IF EITHER SENSOR WAS SATURATED (0XFFFF)

		boolean setInterruptControl(unsigned char control, unsigned char persist);
			// Sets up interrupt operations
			// If control = 0, interrupt output disabled
			// If control = 1, use level interrupt, see setInterruptThreshold()
			// If persist = 0, every integration cycle generates an interrupt
			// If persist = 1, any value outside of threshold generates an interrupt
			// If persist = 2 to 15, value must be outside of threshold for 2 to 15 integration cycles
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() below)

		boolean setInterruptThreshold(unsigned int low, unsigned int high);
			// Set interrupt thresholds (channel 0 only)
			// low, high: 16-bit threshold values
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() below)

		boolean clearInterrupt(void);
			// Clears an active interrupt
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() below)

		boolean getID(unsigned char &ID);
			// Retrieves part and revision code from TSL2561
			// Sets ID to part ID (see datasheet)
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() below)
			
		byte getError(void);
			// If any library command fails, you can retrieve an extended
			// error code using this command. Errors are from the wire library: 
			// 0 = Success
			// 1 = Data too long to fit in transmit buffer
			// 2 = Received NACK on transmit of address
			// 3 = Received NACK on transmit of data
			// 4 = Other error

//	private:

		boolean readByte(unsigned char address, unsigned char &value);
			// Reads a byte from a TSL2561 address
			// Address: TSL2561 address (0 to 15)
			// Value will be set to stored byte
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() above)
	
		boolean writeByte(unsigned char address, unsigned char value);
			// Write a byte to a TSL2561 address
			// Address: TSL2561 address (0 to 15)
			// Value: byte to write to address
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() above)

		boolean readUInt(unsigned char address, unsigned int &value);
			// Reads an unsigned integer (16 bits) from a TSL2561 address (low byte first)
			// Address: TSL2561 address (0 to 15), low byte first
			// Value will be set to stored unsigned integer
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() above)

		boolean writeUInt(unsigned char address, unsigned int value);
			// Write an unsigned integer (16 bits) to a TSL2561 address (low byte first)
			// Address: TSL2561 address (0 to 15), low byte first
			// Value: unsigned int to write to address
			// Returns true (1) if successful, false (0) if there was an I2C error
			// (Also see getError() above)
			
		char _i2c_address;
		byte _error;
};

#define TSL2561_ADDR_0 0x29 // address with '0' shorted on board
#define TSL2561_ADDR   0x39 // default address
#define TSL2561_ADDR_1 0x49 // address with '1' shorted on board

// TSL2561 registers

#define TSL2561_CMD           0x80
#define TSL2561_CMD_CLEAR     0xC0
#define	TSL2561_REG_CONTROL   0x00
#define	TSL2561_REG_TIMING    0x01
#define	TSL2561_REG_THRESH_L  0x02
#define	TSL2561_REG_THRESH_H  0x04
#define	TSL2561_REG_INTCTL    0x06
#define	TSL2561_REG_ID        0x0A
#define	TSL2561_REG_DATA_0    0x0C
#define	TSL2561_REG_DATA_1    0x0E

#endif

Credits

Brian Chamberlain

Brian Chamberlain

11 projects • 19 followers
Hi! I am a software engineer who enjoys hacking on hardware on the side. My interests are in DIY projects for the home, IOT, and 3D printing

Comments