Last active
August 29, 2015 13:57
-
-
Save smittytone/9524970 to your computer and use it in GitHub Desktop.
Sample code showing the use of I2C with the Electric Imp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Print light reading trigger URL | |
server.log("Sensor Agent URL: " + http.agenturl()); | |
// Define funtions | |
function requestHandler(request, response) | |
{ | |
// Handle an incoming web request for a reading | |
try | |
{ | |
device.send("sense", true); | |
response.send(200, "OK"); | |
} | |
catch (ex) | |
{ | |
response.send(500, "Internal Server Error: " + ex); | |
} | |
} | |
// Register the HTTP handler | |
http.onrequest(requestHandler); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Configure the Adafruit/TAOS TSL2561 light sensor | |
// Note: Imp I2C command values are strings with | |
// the \x escape character to indicate a hex value | |
const TSL2561_COMMAND_BIT = "\x80"; // Command register. Bit 7 must be 1 | |
const TSL2561_CONTROL_POWERON = "\x03"; // Power on setting | |
const TSL2561_CONTROL_POWEROFF = "\x00"; // Power off setting | |
const TSL2561_REGISTER_TIMING = "\x81"; // Access timing register | |
const TSL2561_REGISTER_ADC0_LSB = "\xAC"; // LSB of sensor's two-byte ADC value | |
const TSL2561_REGISTER_ADC1_LSB = "\xAE"; // MSB of sensor's two-byte ADC value | |
const TSL2561_GAIN_HIGH = "\x01"; // Gain to high | |
const TSL2561_GAIN_LOW = "\x00"; // Gain to low | |
// Note: Imp I2C address values are integers | |
const TSL2561_ADDR_LOW = 0x29; // ADDR pin ground | |
const TSL2561_ADDR_HIGH = 0x49; // ADDR pin 3v3 | |
const TSL2561_ADDR_FLOAT = 0x39; // ADDR pin floating | |
// Lux calculation constants | |
const LUX_SCALE = 14; // scale by 2^14 | |
const RATIO_SCALE = 9; // scale ratio by 2^9 | |
const B1C = 0x0204; | |
const M1C = 0x01ad; | |
const B2C = 0x0228; | |
const M2C = 0x02c1; | |
const B3C = 0x0253; | |
const M3C = 0x0363; | |
const B4C = 0x0282; | |
const M4C = 0x03df; | |
const B5C = 0x0177; | |
const M5C = 0x01dd; | |
const B6C = 0x0101; | |
const M6C = 0x0127; | |
const B7C = 0x0037; | |
const M7C = 0x002b; | |
const B8C = 0x0000; | |
const M8C = 0x0000; | |
const K1C = 0x0043; | |
const K2C = 0x0085; | |
const K3C = 0x00c8; | |
const K4C = 0x010a; | |
const K5C = 0x014d; | |
const K6C = 0x019a; | |
const K7C = 0x029a; | |
const K8C = 0x029a; | |
// DEFINE FUNCTIONS | |
function calculate_lux(ch_0, ch_1) | |
{ | |
// Calculate the luminosity based on ADC Channel 0 (visible + IR) and | |
// Channel 1 (IR) values. Returns the luminosity. Assumes sensor | |
// integration time is 13ms, gain is 16x | |
local ch_scale = 29975; | |
local channel_0 = (ch_0 * ch_scale) >> 10; | |
local channel_1 = (ch_1 * ch_scale) >> 10; | |
local ratio_1 = 0; | |
if (channel_0 != 0) ratio_1 = (channel_1 << (RATIO_SCALE + 1)) / channel_0; | |
// Round the ratio value | |
local ratio = (ratio_1 + 1) >> 1; | |
local b = 0; | |
local m = 0; | |
if ((ratio >= 0) && (ratio <= K1C)) | |
{b=B1C; m=M1C;} | |
else if (ratio <= K2C) | |
{b=B2C; m=M2C;} | |
else if (ratio <= K3C) | |
{b=B3C; m=M3C;} | |
else if (ratio <= K4C) | |
{b=B4C; m=M4C;} | |
else if (ratio <= K5C) | |
{b=B5C; m=M5C;} | |
else if (ratio <= K6C) | |
{b=B6C; m=M6C;} | |
else if (ratio <= K7C) | |
{b=B7C; m=M7C;} | |
else if (ratio > K8C) | |
{b=B8C; m=M8C;} | |
local temp = ((channel_0 * b) - (channel_1 * m)); | |
// Do not allow a negative lux value | |
if (temp < 0) temp = 0; | |
temp += (1 << (LUX_SCALE - 1)); | |
// Strip off fractional portion | |
local lux = temp >> LUX_SCALE; | |
return lux; | |
} | |
function read_sensor_adc_0(i2c) | |
{ | |
local word = i2c.read(i2c_addr, TSL2561_REGISTER_ADC0_LSB, 2); | |
local lumo = (word[1] << 8) + word[0]; | |
return lumo; | |
} | |
function read_sensor_adc_1(i2c) | |
{ | |
local word = i2c.read(i2c_addr, TSL2561_REGISTER_ADC1_LSB, 2); | |
local lumo = (word[1] << 8) + word[0]; | |
return lumo; | |
} | |
function get_lumo(bool_value) | |
{ | |
if (bool_value) | |
{ | |
// Set command focus to ADC 0 | |
i2c.write(i2c_addr, TSL2561_REGISTER_ADC0_LSB); | |
local lumo_0 = read_sensor_adc_0(i2c); | |
server.log("Light level: " + lumo_0); | |
i2c.write(i2c_addr, TSL2561_REGISTER_ADC1_LSB); | |
local lumo_1 = read_sensor_adc_1(i2c); | |
server.log("IR level: " + lumo_1); | |
local lux = calculate_lux(lumo_0, lumo_1); | |
server.log("Lux: " + lux); | |
} | |
} | |
// PROGRAM START POINT | |
// Set up alias for i2c and set bus to 100kHz | |
i2c <- hardware.i2c12; | |
i2c.configure(CLOCK_SPEED_100_KHZ); | |
// Set sensor's address by shifting 7-bit address 1 bit leftward as per imp I2C spec | |
i2c_addr <- TSL2561_ADDR_FLOAT << 1; | |
// Set command focus to the control register | |
i2c.write(i2c_addr, TSL2561_COMMAND_BIT); | |
// Send power up command | |
i2c.write(i2c_addr, TSL2561_CONTROL_POWERON); | |
// Check the power is on: this will return string '3' or '51' if it is | |
local result = i2c.read(i2c_addr, TSL2561_CONTROL_POWERON, 1); | |
server.log("Power check: "+ result[0]); | |
// Set command focus to the timing register | |
i2c.write(i2c_addr, TSL2561_REGISTER_TIMING); | |
// Set gain to low | |
i2c.write(i2c_addr, TSL2561_GAIN_HIGH); | |
// Register a handler for "sense" messages from the agent | |
agent.on("sense", get_lumo); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment