arduino/light.c

246 lines
5.2 KiB
C

#define TSL_FREQ_PIN 2 // output use digital pin2 for interrupt
#define TSL_S0 5
#define TSL_S1 6
#define TSL_S2 7
#define TSL_S3 8
// 1000ms = 1s
#define READ_TM 1000
unsigned long pulse_cnt = 0;
// two variables used to track time
unsigned long cur_tm = millis();
unsigned long pre_tm = cur_tm;
// we'll need to access the amount
// of time passed
unsigned int tm_diff = 0;
// need to measure what to divide freq by
// 1x sensitivity = 10,
// 10x sens = 100,
// 100x sens = 1000
int calc_sensitivity = 10;
// set our frequency multiplier to a default of 1
// which maps to output frequency scaling of 100x
int freq_mult = 100;
void setup() {
// attach interrupt to pin2, send output pin of TSL230R to arduino 2
// call handler on each rising pulse
attachInterrupt(0, add_pulse, RISING);
pinMode(TSL_FREQ_PIN, INPUT);
pinMode(TSL_S0, OUTPUT);
pinMode(TSL_S1, OUTPUT);
pinMode(TSL_S2, OUTPUT);
pinMode(TSL_S3, OUTPUT);
digitalWrite(TSL_S0, HIGH);
digitalWrite(TSL_S1, LOW);
digitalWrite(TSL_S2, HIGH);
digitalWrite(TSL_S3, HIGH);
}
void loop() {
// check the value of the light sensor every READ_TM ms
// calculate how much time has passed
pre_tm = cur_tm;
cur_tm = millis();
if( cur_tm > pre_tm ) {
tm_diff += cur_tm - pre_tm;
}
else if( cur_tm < pre_tm ) {
// handle overflow and rollover (Arduino 011)
tm_diff += ( cur_tm + ( 34359737 - pre_tm ));
}
// if enough time has passed to do a new reading...
if( tm_diff >= READ_TM ) {
// re-set the ms counter
tm_diff = 0;
// get our current frequency reading
unsigned long frequency = get_tsl_freq();
// calculate radiant energy
float uw_cm2 = calc_uwcm2( frequency );
// calculate illuminance
float lux = calc_lux_single( uw_cm2, 0.175 );
print(lux);
}
}
void set_scaling ( int what ) {
// set output frequency scaling
// adjust frequency multiplier and set proper pin values
// e.g.:
// scale = 2 == freq_mult = 2
// scale = 10 == freq_mult = 10
// scale = 100 == freq_mult = 100
int pin_2 = HIGH;
int pin_3 = HIGH;
switch( what ) {
case 2:
pin_3 = LOW;
freq_mult = 2;
break;
case 10:
pin_2 = LOW;
freq_mult = 10;
break;
case 100:
freq_mult = 100;
break;
default:
// don't do anything with levels
// we don't recognize
return;
}
// set the pins to their appropriate levels
digitalWrite(TSL_S2, pin_2);
digitalWrite(TSL_S3, pin_3);
return;
}
unsigned long get_tsl_freq() {
// we have to scale out the frequency --
// Scaling on the TSL230R requires us to multiply by a factor
// to get actual frequency
unsigned long freq = pulse_cnt * freq_mult;
// reset the pulse counter
pulse_cnt = 0;
return(freq);
}
void add_pulse() {
// increase pulse count
pulse_cnt++;
return;
}
void sensitivity( bool dir ) {
// adjust sensitivity in 3 steps of 10x either direction
int pin_0;
int pin_1;
if( dir == true ) {
// increasing sensitivity
// -- already as high as we can get
if( calc_sensitivity == 1000 )
return;
if( calc_sensitivity == 100 ) {
// move up to max sensitivity
pin_0 = true;
pin_1 = true;
}
else {
// move up to med. sesitivity
pin_0 = false;
pin_1 = true;
}
// increase sensitivity divider
calc_sensitivity *= 10;
}
else {
// reducing sensitivity
// already at lowest setting
if( calc_sensitivity == 10 )
return;
if( calc_sensitivity == 100 ) {
// move to lowest setting
pin_0 = true;
pin_1 = false;
}
else {
// move to medium sensitivity
pin_0 = false;
pin_1 = true;
}
// reduce sensitivity divider
calc_sensitivity = calc_sensitivity / 10;
}
// make any necessary changes to pin states
digitalWrite(TSL_S0, pin_0);
digitalWrite(TSL_S1, pin_1);
return;
}
float calc_uwatt_cm2(unsigned long freq) {
// get uW observed - assume 640nm wavelength
// calc_sensitivity is our divide-by to map to a given signal strength
// for a given sensitivity (each level of greater sensitivity reduces the signal
// (uW) by a factor of 10)
float uw_cm2 = (float) freq / (float) calc_sensitivity;
// extrapolate into entire cm2 area
uw_cm2 *= ( (float) 1 / (float) 0.0136 );
return(uw_cm2);
}
float calc_lux_single(float uw_cm2, float efficiency) {
// calculate lux (lm/m^2), using standard formula:
// Xv = Xl * V(l) * Km
// Xl is W/m^2 (calculate actual receied uW/cm^2, extrapolate from sensor size (0.0136cm^2)
// to whole cm size, then convert uW to W)
// V(l) = efficiency function (provided via argument)
// Km = constant, lm/W @ 555nm = 683 (555nm has efficiency function of nearly 1.0)
//
// Only a single wavelength is calculated - you'd better make sure that your
// source is of a single wavelength... Otherwise, you should be using
// calc_lux_gauss() for multiple wavelengths
// convert to w_m2
float w_m2 = (u_cm2 / (float) 1000000) * (float) 100;
// calculate lux
float lux = w_m2 * efficiency * (float) 683;
return(lux);
}