Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 8df9770
Showing
1 changed file
with
308 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,308 @@ | ||
#include <Wire.h> | ||
//this library is used to read out the light sensors (tsl 2561) data | ||
//more info: https://github.com/adafruit/TSL2561-Arduino-Library | ||
#include <TSL2561.h> | ||
#include <Servo.h> | ||
#include <string.h> | ||
|
||
|
||
|
||
void addLight(); | ||
void autoExpose( struct FilmType ); | ||
void autoExpose( long duration, struct FilmType ); | ||
void expose( long exposureTime); | ||
|
||
|
||
//Hardware | ||
Servo servo; | ||
TSL2561 tsl(TSL2561_ADDR_FLOAT); | ||
int button = 8; | ||
//LiquidCrystal lcd(7, 8, 9, 10, 11, 12); | ||
|
||
//Messung mit Canon, f20, autozeit, iso100... Zeit 5 Sekunden | ||
//Messung gleiche Zeit 5 Sekunden bei Sensor = 175 (accumulatedLight) | ||
//also 35 Lichteinheiten pro Sekunden sind optimal laut dieser Messung (für die Canon) | ||
//müssen dies nun für die Lochkamera berechnen + Film | ||
|
||
//die Lochkamera habe eine Lochgröße von 0.25mm, eine Brennweite von 25mm, somit eine Blende von f100 | ||
//mit der Formel (gemessene Zeit bei SLR) * (lochkamerablende / SLR-Blende)^2 | ||
//ergibt sich eine optimale Belichtungszeit von __125 Sekunden__ in diesem Fall (5sekunden) * (100 / 20)^2 | ||
|
||
//anschliessend muessen wir noch den Schwrzschildeffekt beachten, der die Belichtungszeit erhöht (eine Blendenstufe == doppelte Belichtungszeit | ||
//bei CHS100 | ||
//Gemessene Belichtungszeit (s) 1/10000 - 1/2 1 10 100 | ||
//Belichtungskorrektur (Blenden) 0 +1.2 +1.3 +1.5 | ||
|
||
//also bei 125 Sekunden etwa: 125 * (1.5*2) = 375 | ||
//Aufgrund von Tests reicht aber dieser Wert noch nicht ganz aus, es empfiehlt sich das Ergebnis noch mit 1,5 bis 2.1 zu multiplizieren | ||
//also 375 * 2 = 750 sekunden (12,5 minuten) | ||
//nun berechnen wir also 750sekunden * 35 Lichteinheiten (die pro sekunde als optimal gemessen wurden) | ||
// == 26250 Lichteinheiten | ||
|
||
//wenn wir also 35 Lichteinheiten pro sekunde bekommen, haben wir nach den 12,5 minuten (die wir als optimal ausgerechnet haben, anhand der Daten von Lochkamera | ||
//und mit der DSLR gemessenen Zeit) die 26250 Lichteinheiten gesammelt und müssten ein optimal Belichtetes Negativ haben | ||
|
||
//somit Stellen wir fest: unser Maximalwert für einem chs100 bei Blende 100 sind ~27000 (27k) | ||
|
||
boolean checkExposure(FilmType); | ||
|
||
struct FilmType{ | ||
float maxLight; | ||
float reciprocityFailure1s; | ||
float reciprocityFailure10s; | ||
float reciprocityFailure100s; | ||
float reciprocityFailure1000s; | ||
}; | ||
|
||
int exposureTime=0; | ||
short autoExposure=0; | ||
short i=0; | ||
short isOpen=0; | ||
|
||
unsigned long maxLight=0; | ||
float lichtWert; | ||
float accumulatedLight = 0.0; | ||
struct FilmType chs50, chs100; | ||
|
||
long time = 0; | ||
int buttonState = 1; | ||
|
||
char buffer[128]; | ||
char commandB; | ||
|
||
|
||
/* TODO! | ||
Belichtung für Orthopan anpassen (ca. 1/3 längere Belichtungszeit weil Rot fehlt | ||
*/ | ||
|
||
|
||
|
||
void setup() { | ||
|
||
//setup film types | ||
//siehe erklaerung oben | ||
chs50.reciprocityFailure1s = 1.2; | ||
chs50.reciprocityFailure10s = 1.3; | ||
chs50.reciprocityFailure100s = 1.5; | ||
chs50.reciprocityFailure1000s = 1.8; | ||
chs50.maxLight = 35000; | ||
|
||
chs100.reciprocityFailure1s = 1.2; | ||
chs100.reciprocityFailure10s = 1.3; | ||
chs100.reciprocityFailure100s = 1.5; | ||
chs100.reciprocityFailure1000s = 1.9; | ||
chs100.maxLight = 27000; | ||
|
||
Serial.begin(9600); | ||
pinMode(button, INPUT); | ||
if (tsl.begin()) { | ||
Serial.println("Found sensor"); | ||
//lcd.print("found sensor!"); | ||
|
||
} else { | ||
Serial.println("No sensor?"); | ||
while (1); | ||
} | ||
|
||
servo.attach(2); | ||
// You can change the gain on the fly, to adapt to brighter/dimmer light situations | ||
// tsl.setGain(TSL2561_GAIN_0X); // set no gain (for bright situtations) | ||
tsl.setGain(TSL2561_GAIN_0X); // set 16x gain (for dim situations) | ||
|
||
// Changing the integration time gives you a longer time over which to sense light | ||
// longer timelines are slower, but are good in very low light situtations! | ||
//tsl.setTiming(TSL2561_INTEGRATIONTIME_13MS); // shortest integration time (bright light) | ||
tsl.setTiming(TSL2561_INTEGRATIONTIME_101MS); // medium integration time (medium light) | ||
//tsl.setTiming(TSL2561_INTEGRATIONTIME_402MS); // longest integration time (dim light) | ||
|
||
|
||
|
||
servo.write(0); | ||
|
||
|
||
} | ||
|
||
|
||
void reset(){ | ||
servo.write(0); | ||
digitalWrite(4,LOW); | ||
accumulatedLight = 0.0; | ||
lichtWert = 0; | ||
maxLight = 0; | ||
time = 0; | ||
} | ||
|
||
void addLight(){ | ||
accumulatedLight = (accumulatedLight + (float) (tsl.getLuminosity(TSL2561_VISIBLE) / 4.95) ); | ||
// /4.95 because every 202ms or ~1/5s second checks for light ... 10.1s because tsl needs 101ms to sense light x 2 , so 202ms | ||
//if newLight is not greater 0, then newlight is atleast 1 | ||
time = time + 202; | ||
|
||
} | ||
|
||
boolean checkExposure(struct FilmType *filmType){ | ||
|
||
float maxl = filmType->maxLight; | ||
|
||
|
||
//returns true if the accumulated Light is still less then our maximum | ||
if (time >= 1000 && time <= 10000){ | ||
return (accumulatedLight <= (maxl * filmType->reciprocityFailure1s)); | ||
|
||
} else if (time >= 10000 && time <= 100000){ | ||
return (accumulatedLight <= (maxl * filmType->reciprocityFailure10s)) ; | ||
|
||
} else if (time >= 100000 && time <= 10000000){ | ||
return (accumulatedLight <= (maxl * filmType->reciprocityFailure100s)) ; | ||
|
||
|
||
} else if (time >= 1000000 && time <= 100000000){ | ||
return (accumulatedLight <= (maxl * filmType->reciprocityFailure1000s)) ; | ||
|
||
} else if (time >= 100000000){ | ||
//versuchen schwarzschildeffekt vrherzusagen mit faktor 0.2 zu addieren je 10000sekunden | ||
return (accumulatedLight <= (maxl * (filmType->reciprocityFailure100s + 0.2 * (time / 10000) ))) ? true : false ; | ||
} else if (time <= 1000){ | ||
return (accumulatedLight <= maxl) ? true : false ; | ||
} | ||
} | ||
|
||
|
||
//this is only a testing function to check if the light sensor and the motor are working | ||
//it will open/close the aperture depending on light intensitivity | ||
void changeApertureByLight(){ | ||
lichtWert = tsl.getLuminosity(TSL2561_VISIBLE); | ||
Serial.print(lichtWert); | ||
Serial.print("\n"); | ||
if(lichtWert > 350){ | ||
digitalWrite(4,HIGH); | ||
servo.write(0); | ||
} | ||
else{ | ||
digitalWrite(4,LOW); | ||
servo.write(170); | ||
} | ||
} | ||
|
||
void expose(long duration){ | ||
reset(); | ||
Serial.print("\ntime exposure\n shooting for milliseconds: "); | ||
Serial.print(duration); | ||
Serial.print("\n"); | ||
|
||
digitalWrite(4,HIGH); | ||
servo.write(-20); | ||
|
||
while(time < duration){ | ||
addLight(); | ||
Serial.print(duration/time*100); | ||
Serial.print("%\n"); | ||
|
||
} | ||
|
||
Serial.print("\nfinished\naccumulated light in "); | ||
Serial.print((float) time/1000); | ||
Serial.print(" seconds = "); | ||
Serial.print((float) accumulatedLight); | ||
Serial.print(" \n "); | ||
reset(); | ||
|
||
} | ||
|
||
void autoExpose(struct FilmType *filmType){ | ||
Serial.print("shooting now, auto light, no time limit"); | ||
digitalWrite(4,HIGH); | ||
Serial.print(filmType->maxLight); | ||
servo.write(90); | ||
while(checkExposure(filmType)){ | ||
addLight(); | ||
Serial.print((float) (accumulatedLight/filmType->maxLight) * 100); | ||
Serial.print("%\n"); | ||
} | ||
|
||
Serial.print("Exposure time ins seconds: "); | ||
Serial.print(time/1000); | ||
reset(); | ||
|
||
|
||
} | ||
|
||
void autoExpose(long duration, struct FilmType *filmType){ | ||
Serial.print("shooting now, auto light, but with time limit"); | ||
digitalWrite(4,HIGH); | ||
servo.write(90); | ||
|
||
while(checkExposure(filmType) && (time <= duration)){ | ||
addLight(); | ||
Serial.print((float) (accumulatedLight/filmType->maxLight) * 100); | ||
Serial.print("%\n"); | ||
} | ||
Serial.print("Exposure time ins seconds: "); | ||
Serial.print(time/1000); | ||
reset(); | ||
|
||
} | ||
|
||
int receiveMessage(){ | ||
memset(buffer,'\0',128); | ||
Serial.readBytesUntil('!',buffer,120); | ||
delay(50); | ||
|
||
if(buffer[0] == 'E') { | ||
sscanf(buffer,"E%d %d %d",&exposureTime,&autoExposure, &maxLight); | ||
|
||
Serial.print(exposureTime); | ||
return 1; | ||
//exit(0); | ||
} else if (buffer[0] == 'A'){ | ||
|
||
return 2; | ||
} else { | ||
return 0; | ||
} | ||
|
||
} | ||
|
||
|
||
void loop() { | ||
/* | ||
checking for serial/usb input | ||
to start exposure via usb send: | ||
E<maxTime> <maxExposure> <maxLight> | ||
or for full automation depending on the film type: | ||
A | ||
*/ | ||
|
||
if(Serial.available()){ | ||
int erg=receiveMessage(); | ||
if (erg == 1 ){ | ||
if (autoExposure && exposureTime > 0){ | ||
Serial.print("autoexpose\n"); | ||
autoExpose(exposureTime,&chs100); | ||
} else if (autoExposure && exposureTime == 0){ | ||
autoExpose(&chs100); | ||
}else { | ||
Serial.print("timeExposure\n"); | ||
expose(exposureTime); | ||
} | ||
} else if (erg == 2 ){ | ||
Serial.print("total automatik"); | ||
autoExpose(&chs100); | ||
|
||
} | ||
|
||
} | ||
|
||
} | ||
|
||
|
||
|
||
|
||
|