diff --git a/lightmeter.ino b/lightmeter.ino index 7ce6ad4..5d9c1c9 100644 --- a/lightmeter.ino +++ b/lightmeter.ino @@ -28,19 +28,24 @@ BH1750 lightMeter; #define PIN_ON PB9 #define TIME_AUTOPOWEROFF 120000 #define LDRDELAY 50 //minimum delay between ldr readings. Transistor for lower value pulldown resistor switches in between +#define INCIDENTDELAY 100 //minimum delay between incident sensor (BH1750) readings #define DEBOUNCETIME 50 //time to not check for inputs after key press -#define BUTTONTIMEHOLD 1000 //time for button hold +#define BUTTONTIMEHOLD 750 //time for button hold #define voltage_warn 3.4 //voltage per cell //TODO implement warning //float shuttertimes1[]={1,1.0/2, 1.0/4, 1.0/8, 1.0/15, 1.0/30, 1.0/60, 1.0/125, 1.0/250, 1.0/500, 1.0/1000, 1.0/2000, 1.0/4000, 1.0/8000}; float shuttertimes1[]={64,32,16,8,4,2,1,1.0/2, 1.0/4, 1.0/8, 1.0/15, 1.0/30, 1.0/60, 1.0/125, 1.0/250, 1.0/500, 1.0/1000, 1.0/2000, 1.0/4000, 1.0/8000}; +#define SHUTTERTIMES1_MAXINDEX 19 String settingsnameShutterSelectionMode[]={"Analog"}; //names for tables #define MAXIMUM_SHUTTERSELECTIONMODES 1 float aperaturesFull[]={1,1.4, 2, 2.8, 4, 5.6, 8, 11, 16, 22, 32}; +#define APERATURESFULL_MAXINDEX 10 float aperaturesHalf[]={1, 1.2, 1.4, 1.7, 2, 2.4, 2.8, 3.4, 4, 4.8, 5.6, 6.7, 8, 9.5, 11, 13, 16, 19, 22}; +#define APERATURESHALF_MAXINDEX 18 float aperaturesThird[]={1, 1.1, 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.5, 2.8, 3.2, 3.5, 4, 4.5, 5.0, 5.6, 6.3, 7.1, 8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 25, 29, 32, 36, 40, 45}; +#define APERATURESTHIRD_MAXINDEX 33 String settingsnameAperatureSelectionMode[]={"Full","Half","Third"}; //names for tables #define MAXIMUM_APERATURESELECTIONMODES 3 @@ -51,6 +56,7 @@ float isoThird[]={12,16,20,25,32,40,50,64,80,100,125,160,200,250,320,400,500,640 long loopmillis=0; //only use one millis reading each loop long last_ldrReading=0; +long last_incidentReading=0; long millis_lastchange=0; long millis_lastinput=0; @@ -88,6 +94,7 @@ Settings userSettings= {1,1, 1,2}; #define OLED_RESET 4 Adafruit_SSD1306 display(OLED_RESET); +uint16_t incident=0; //incident reading from bh1750 uint16_t analog_low=0; //better for low light uint16_t analog_high=0; //better for bright light (higher pulldown resistor for ldr) float ev=0; //calculated EV from LDR readings (reflected) or from Luxmeter (incident) @@ -112,6 +119,10 @@ String settingStrings[]={"ISO:","F-Stops:","Timetable:","Turn Off"}; #define SETTINGS_SELECTEDITEM_MAX 3 //inclusive. 2 means 3 items available boolean settings_itemActive=false; //item in settings selected to change value +#define METERINGMODE_REFLECTIVE 0 +#define METERINGMODE_INCIDENT 1 +uint8_t meteringmode=METERINGMODE_REFLECTIVE; + char tempstring[16]; //for dtostrf //dtostrf(modefactor,1,3,tempstring); @@ -123,12 +134,13 @@ void setup() { Serial.begin(9600); Serial.println("Started"); - + Serial.println("Init Display"); display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); display.display(); - lightMeter.begin(BH1750_CONTINUOUS_HIGH_RES_MODE_2); + Serial.println("Init BH1750"); + lightMeter.begin(BH1750_CONTINUOUS_HIGH_RES_MODE_2); //max reading=54612 //set measurement time (for higher resolution) http://www.raspberry-pi-geek.de/Magazin/2015/04/Digital-Light-Sensor-BH1750-am-Raspberry-Pi //lightMeter.write8(71); //01000111 //high bit: 01000xxx bits 7,6,5 //lightMeter.write8(126); //01111110 //log bit: 011xxxxx bits 4,3,2,1,0 @@ -157,9 +169,6 @@ void setup() { void loop() { loopmillis=millis(); //read millis for this cycle - - - uint16_t lux = lightMeter.readLightLevel(); handleInputs(); @@ -262,6 +271,7 @@ void handleInputs() //Voltage vbat=map(analogRead(PIN_VBAT), 0,3910,0,8400)/1000.0; //180k and 300k voltage divider. 8,4V -> 3,15V=3910 + //LDR if ( loopmillis-last_ldrReading>LDRDELAY ) { if (!digitalRead(PIN_BRIGHTMODE)){ @@ -274,6 +284,16 @@ void handleInputs() } + + //Lightsensor BH1750 + if ( loopmillis-last_incidentReading>INCIDENTDELAY ) + { + incident = lightMeter.readLightLevel(); //value in lux from sensor + last_incidentReading=loopmillis; + } + + + //Test asdf /* if ( !digitalRead(PIN_TRIGGER) ) { @@ -338,6 +358,13 @@ void handleInputs_Lightmeter() if ( button_hold_center ) { //Go to Settings displaymode=settings; } + if ( button_center ) { //Change Refelctive - Incident + if (meteringmode == METERINGMODE_REFLECTIVE){ + meteringmode = METERINGMODE_INCIDENT; + }else if (meteringmode == METERINGMODE_INCIDENT) { + meteringmode = METERINGMODE_REFLECTIVE; + } + } if (setShutter==0 && setAperature==0){ //Auto //Value Change @@ -479,17 +506,21 @@ float reciprocFloat(float p){ void calculateEV() { - //ev=map(analog_low,500, 3500 ,500, 1400)/100.0; //for testing - double highev=11.7400532 + 0.000216655133*analog_high + 0.00000111372253*pow(analog_high,2) + -0.000000000163800818 *pow(analog_high,3); - double lowev=-0.763427709 + 0.0138031137*analog_low + -0.00000576990095*pow(analog_low,2) + 0.000000000871611285*pow(analog_low,3); - - if (lowev>14){ - ev=highev; - }else if(lowev<12.5){ - ev=lowev; - }else{ //mix of both - float mix=min(1.0, max(0.0,(lowev-12.5)/(14-12.5))); //0 to 1, 0-> use only lowev, 1-> use only highev - ev=lowev*(1-mix)+highev*mix; + if (meteringmode == METERINGMODE_REFLECTIVE){ + //ev=map(analog_low,500, 3500 ,500, 1400)/100.0; //for testing + double highev=11.7400532 + 0.000216655133*analog_high + 0.00000111372253*pow(analog_high,2) + -0.000000000163800818 *pow(analog_high,3); + double lowev=-0.763427709 + 0.0138031137*analog_low + -0.00000576990095*pow(analog_low,2) + 0.000000000871611285*pow(analog_low,3); + + if (lowev>14){ + ev=highev; + }else if(lowev<12.5){ + ev=lowev; + }else{ //mix of both + float mix=min(1.0, max(0.0,(lowev-12.5)/(14-12.5))); //0 to 1, 0-> use only lowev, 1-> use only highev + ev=lowev*(1-mix)+highev*mix; + } + }else if (meteringmode == METERINGMODE_INCIDENT){ + ev = luxToEv(incident); } if (setAperature>0){ //Aperature Priority @@ -506,6 +537,16 @@ void calculateEV() } +double evToLux(double ev) { + return pow(2, ev) * 2.5; +} +double luxToEv(uint16_t lux){ + if (lux <= 2){ + return 0; + } + return log (lux/2.5) / log (2); +} + float calculateShutter(float pEv, uint16_t pIso, uint16_t pAperature) //returns calculated Shutter speed given Ev, ISO and Aperature { //EV = log2 ( 100* Aperature^2 / (ISO * Time )) @@ -590,9 +631,26 @@ uint8_t findAperatureIndex(float pAperature,uint8_t pMethod) //find index of clo float _minDistance=90000; float _lastminDistance=100000; uint8_t _index=userSettings.minimumAperatureIndex; + uint8_t _maxindexpossible=0; + + switch(pMethod){ + case 1: + _maxindexpossible=APERATURESFULL_MAXINDEX; + break; + case 2: + _maxindexpossible=APERATURESHALF_MAXINDEX; + break; + case 3: + _maxindexpossible=APERATURESTHIRD_MAXINDEX; + break; + } while (_lastminDistance>_minDistance) //until distance increases { + if (_index>_maxindexpossible){ //this index will be out of bounds + return _maxindexpossible; + } + _lastminDistance=_minDistance; switch(pMethod){ @@ -608,7 +666,8 @@ uint8_t findAperatureIndex(float pAperature,uint8_t pMethod) //find index of clo } _index++; //next } - return _index-2; + + return _index-2; //use index with closest value } @@ -641,10 +700,21 @@ uint8_t findShutterIndex(float pShutter,uint8_t pMethod) //find index of closest float _minDistance=abs(pShutter-shuttertimes1[0]); float _lastminDistance=_minDistance; uint8_t _index=0; + uint8_t _maxindexpossible=0; + + switch(pMethod){ + case 1: + _maxindexpossible=SHUTTERTIMES1_MAXINDEX; + break; + } while (_lastminDistance>=_minDistance) //until distance increases { + if (_index>_maxindexpossible){ //this index will be out of bounds + return _maxindexpossible; + } + _lastminDistance=_minDistance; switch(pMethod){ @@ -654,7 +724,8 @@ uint8_t findShutterIndex(float pShutter,uint8_t pMethod) //find index of closest } _index++; //next } - return _index-2; + + return _index-2; //use index with closest value } void changeISO(int8_t pchange){ //pchange>0 means more light exposure (brighter image), higher iso @@ -801,6 +872,13 @@ void updateDisplay_Lightmeter() //Lightmeter display display.print("V "); display.print("Ev="); display.print(ev); + display.print(" |"); + display.print(incident); + + display.setTextSize(1); + display.setCursor(10,10); + display.print(meteringmode); + } void updateDisplay_Settings()