Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 58 additions & 10 deletions src/light.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ Light::Light()
// Configure I2C //
TWI_Master_Initialise();
lastSeconds = 0;
//Timer for nightEv() updates
nightSeconds = 0; //J.R. 9-30-15
initialized = 0;
integrationActive = false;
lockedSlope = 0.0;
Expand Down Expand Up @@ -102,6 +104,8 @@ void Light::stop()
TWI_Start_Read_Write(I2C_Buf, 3);
lcd.backlight(255);
lastSeconds = 0;
//Timer for nightEv() updates
nightSeconds = 0; //J.R. 9-30-15
paused = 0;
lockedSlope = 0.0;
integrationActive = false;
Expand Down Expand Up @@ -202,6 +206,16 @@ float Light::readIntegratedSlopeMedian()
return value;
}

//This function is similar to "light.readIntegratedEv()" except that it calculates the
//midpoint-median light value for the last 3 hours.
//So "nightLight" is set wherever "lightReading" is set in shutter.cpp
float Light::readNightEv() //J.R. 10-11-15
{
if(!integrationActive) return 0.0; //J.R. 10-11-15
float value = arrayMedian50(nightEv, NIGHT_INTEGRATION_COUNT - 1); //J.R. 10-11-15
return value; //J.R. 10-11-15
}

void Light::task()
{
if(!initialized || !integrationActive) return;
Expand Down Expand Up @@ -232,23 +246,34 @@ void Light::task()
}
iev[LIGHT_INTEGRATION_COUNT - 1] = readEv();
slope = readIntegratedSlopeMedian();

if(iev[LIGHT_INTEGRATION_COUNT - 1] <= NIGHT_THRESHOLD)

//The following 4 instructions were moved up so the "integrated" variable wold be available
//for the lightThreshold (or NIGHT_THRESHOLD) comparison.
median = arrayMedian50(iev, LIGHT_INTEGRATION_COUNT); //J.R. 10-13-15

float sum = 0.0; //J.R. 10-13-15
for(uint8_t i = 0; i < LIGHT_INTEGRATION_COUNT; i++) sum += iev[i]; //J.R. 10-13-15
integrated = sum / (float)(LIGHT_INTEGRATION_COUNT); //J.R. 10-13-15

//No need to based the comparison on a single value of iev[LIGHT_INTEGRATION_COUNT]
//since all light readings in the TL+ are based on the average of iev[], which is "integrated".
//
//Instead of comparing "integrated" to "NIGHT_THRESHOLD", "conf.lightThreshold" should be used,
//which is the settable threshold value, rather than fixed.
//
//if(iev[LIGHT_INTEGRATION_COUNT - 1] <= NIGHT_THRESHOLD)
if(integrated <= conf.lightThreshold) //J.R. 10-13-15
{
underThreshold = true;
if(lockedSlope == 0.0 && slope) lockedSlope = slope;
}
else if(iev[LIGHT_INTEGRATION_COUNT - 1] > NIGHT_THRESHOLD + NIGHT_THRESHOLD_HYSTERESIS)
//else if(iev[LIGHT_INTEGRATION_COUNT - 1] > NIGHT_THRESHOLD + NIGHT_THRESHOLD_HYSTERESIS)
else if(integrated > conf.lightThreshold + NIGHT_THRESHOLD_HYSTERESIS) //J.R. 10-13-15
{
underThreshold = false;
lockedSlope = 0.0;
}

median = arrayMedian50(iev, LIGHT_INTEGRATION_COUNT);

float sum = 0.0;
for(uint8_t i = 0; i < LIGHT_INTEGRATION_COUNT; i++) sum += iev[i];
integrated = sum / (float)(LIGHT_INTEGRATION_COUNT);

if(conf.debugEnabled)
{
Expand Down Expand Up @@ -282,6 +307,19 @@ void Light::task()
//DEBUG(STR(" #######\r\n"));
}
}
//The same kind of loop is used here to update nightEv[] that was used for updating iev[].
//Of course the time between updates is much longer.
if(nightSeconds == 0 || (clock.Seconds() > (nightSeconds + NIGHT_COUNT_DELAY))) //J.R. 9-30-15
{
nightSeconds = clock.Seconds();

for(uint8_t i = 0; i < NIGHT_INTEGRATION_COUNT - 1; i++) //J.R. 9-30-15
{
nightEv[i] = nightEv[i + 1];//J.R. 9-30-15
}
//No need to do a readEv() all over again, as for iev[] above.
nightEv[NIGHT_INTEGRATION_COUNT - 1] = iev[LIGHT_INTEGRATION_COUNT - 1]; //J.R. 9-30-15
}
}

void Light::integrationStart(uint8_t integration_minutes)
Expand All @@ -290,15 +328,25 @@ void Light::integrationStart(uint8_t integration_minutes)
//DEBUG(STR(" ####### LIGHT INTEGRATION START #######\r\n"));
integration = (uint16_t)integration_minutes;
lastSeconds = 0;
//Timer for nightEv() updates
nightSeconds = 0; //J.R. 9-30-15
for(uint8_t i = 0; i < LIGHT_INTEGRATION_COUNT; i++)
{
iev[i] = readEv(); // initialize array with readings //
wdt_reset();
}
median = arrayMedian50(iev, LIGHT_INTEGRATION_COUNT); //J.R. 9-30-15
//This is where nightEv() is loaded with the current darkness level at the start:
for(uint8_t i = 0; i < NIGHT_INTEGRATION_COUNT; i++) //J.R. 9-30-15
{
nightEv[i] = median; // initialize night array with readings //J.R. 9-30-15; //J.R. 9-30-15
}
integrationActive = true;
slope = 0.0;
median = iev[0];
integrated = iev[0];
//No need to set median and integrated to iev[0], since better values were obtained.
//median = iev[0]; //J.R. 10-13-15
//integrated = iev[0]; //J.R. 10-13-15
integrated = median; //J.R. 9-30-15
lockedSlope = 0.0;
task();
}
Expand Down
20 changes: 17 additions & 3 deletions src/light.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@
#define I2C_ADDR_WRITE 0b10001000

#define LIGHT_INTEGRATION_COUNT 32
#define FILTER_LENGTH 3

#define NIGHT_THRESHOLD 20
//nightEv() has same array size as iev(LIGHT_INTEGRATION_COUNT)
#define NIGHT_INTEGRATION_COUNT 32 //J.R. 9-30-15
//338 is the number of seconds between updates to nightEv()
//so the 32 readings in nightEv(NIGHT_INTEGRATION_COUNT) will span the previous 3 hours
#define NIGHT_COUNT_DELAY 338 //J.R. 9-30-15

#define FILTER_LENGTH 3
//This definition isn't needed because it is a settable parameter
//define NIGHT_THRESHOLD 20 //J.R. 10-11-15
#define NIGHT_THRESHOLD_HYSTERESIS 5
#define OFFSET_UNSET 65535

Expand All @@ -21,6 +28,8 @@ class Light
void setRangeAuto();
float readEv();
float readIntegratedEv();
//This is the function that determines the best EV value for middle-of-the-night darkness.
float readNightEv(); //J.R. 9-30-15
float readIntegratedSlope();
float readIntegratedSlopeMedian();
void integrationStart(uint8_t integration_minutes);
Expand All @@ -32,13 +41,18 @@ class Light

private:
float iev[LIGHT_INTEGRATION_COUNT];
//This is an array that contains 32 light readings spanned over the last 3 hours
float nightEv[NIGHT_INTEGRATION_COUNT]; //J.R. 9-30-15
float filter[FILTER_LENGTH];
int8_t filterIndex;
int8_t wasPaused;
uint16_t integration;
uint32_t lastSeconds;
//This is the seconds timer value that decides when to put a new value in nightEv().
//This variable is similar to "lastSeconds" for updating iev().
uint32_t nightSeconds; //J.R. 9-30-15
uint8_t initialized;
uint16_t offset;
bool integrationActive;

};
};
43 changes: 36 additions & 7 deletions src/shutter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,8 @@ char shutter::task()
status.rampStops_f = 0.0;
light.integrationStart(conf.lightIntegrationMinutes);
lightReading = status.lightStart_f = light.readIntegratedEv();
//"nightLight" is set in a similar way as for "lightReading"
nightLight = light.readNightEv(); // J.R. 10-13-15

if(current.nightMode == BRAMP_TARGET_AUTO)
{
Expand Down Expand Up @@ -695,6 +697,17 @@ char shutter::task()
status.rampTarget_f = status.lightStart_f - (float)status.nightTarget_i8;
}

//When starting the bulb-ramping in the dark, change lightReading and status.lightStart
//to status.nightTarget instead of light.readIntegratedEv().
if(light.underThreshold && current.nightMode != BRAMP_TARGET_AUTO) //J.R. 10-11-15
{
//DEBUG(STR(" -----> starting at night target\r\n")); //J.R. 10-11-15
lightReading = status.lightStart_f = status.nightTarget_i8;
status.rampTarget_f = 0; //J.R. 12-03-15
//This flag maintains night2day bulb ramping once the light reaches a certain point //J.R. 10-11-15
Night2Day = false; //J.R. 10-11-15
}

status.preChecked_u8 = 2;
}

Expand Down Expand Up @@ -972,7 +985,14 @@ char shutter::task()
{
if(light.underThreshold && current.nightMode != BRAMP_TARGET_AUTO) // holding night exposure
{
if(current.nightMode == BRAMP_TARGET_CUSTOM)
//respond during night-to-day once we see light or continue once it's started
if(Night2Day == true || (rampRate ==0 && status.rampStops_f == status.rampTarget_f && lightReading > (nightLight + (conf.lightThreshold/(4 * P_FACTOR))))) //&& lightStart == status.nightTarget) //J.R. 10-1-15
{
status.rampTarget_f = status.lightStart_f - lightReading; //J.R. 10-1-15
//This flag maintains night to day algorithm once it starts
Night2Day = true; //J.R. 11-16-15
}
else if(current.nightMode == BRAMP_TARGET_CUSTOM)
{
status.rampTarget_f = (float)status.nightTarget_i8 + ((float)current.nightND * 3) / 10.0;
}
Expand All @@ -985,6 +1005,8 @@ char shutter::task()
{
// using light sensor target
status.rampTarget_f = (status.lightStart_f - lightReading);
//No need to maintain night to day algorithm at this point
Night2Day = false; //J.R. 10-16-15
}

if(status.rampTarget_f > status.rampMax_i8) status.rampTarget_f = status.rampMax_i8;
Expand Down Expand Up @@ -1022,12 +1044,15 @@ char shutter::task()
}

rampRate = (int8_t) delta;

if(rampRate == 0 && light.underThreshold && current.nightMode != BRAMP_TARGET_AUTO && status.rampStops_f == status.rampTarget_f)
{
// if we've met the night target, switch to guided mode to hold exposure
switchToGuided();
}

//Delete the 'switchToGuided' function:
//This is taken care of in the two "if" statements above under "BRAMP_METHOD_AUTO"

//if(rampRate == 0 && light.underThreshold && current.nightMode != BRAMP_TARGET_AUTO && status.rampStops_f == status.rampTarget_f)
//{
// // if we've met the night target, switch to guided mode to hold exposure
// switchToGuided();
//}
}
//####################################################

Expand Down Expand Up @@ -1179,6 +1204,8 @@ char shutter::task()
{
exps++;
lightReading = light.readIntegratedEv();
//"nightLight" is set in a similar way as for "lightReading"
nightLight = light.readNightEv(); // J.R. 10-13-15

shutter_bulbEndFinish();

Expand Down Expand Up @@ -1562,6 +1589,8 @@ void shutter::switchToAuto()
{
light.integrationStart(conf.lightIntegrationMinutes);
lightReading = status.lightStart_f = light.readIntegratedEv();
//"nightLight" is set in a similar way as for "lightReading"
nightLight = light.readNightEv(); // J.R. 10-13-15
current.brampMethod = BRAMP_METHOD_AUTO;
current.nightMode = BRAMP_TARGET_AUTO;
}
Expand Down
4 changes: 4 additions & 0 deletions src/shutter.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ class shutter
int8_t rampRate, apertureEvShift;
uint32_t last_photo_ms;
float lightReading;
//This variable is the precise median/average EV value for the darkest part of the night
float nightLight; //J.R. 11-30-15
//This flag maintains night2day bulb ramping once the light reaches a certain point
bool Night2Day; //J.R. 10-11-15
float pastErrors[PAST_ERROR_COUNT];
volatile uint8_t paused, pausing, apertureReady;
int8_t evShift;
Expand Down