xdd44, Nov. 6, 2024
This week I decided to do a preliminary test of my final project idea, i.e. building the core part - film projector. I happened to have an IMAX film sample for the movie Joker: Folie à Deux. Since I failed to do RGB sensor last week, I decided to incorporate a distance sensor, which is easier to use, for an auto focusing feature.
The IMAX film sample copy of Joker 2
I happened to have some simple glass convex lenses for another course: one of 200mm focal length, one of 300mm, and one of 500mm. Image will be too large or not forming if the film gets closer to focal point, which will make my system meters long even if I use the 200mm one. However, I found a simulator to see if combined lens can get the distance down.
It turned out I can get my film as close as ~130mm to the lens if I stack 200mm and 300mm one.
Simulation of stacking 200mm and 300mm lenses, the bottom right intersection is where the image focuses.
Then I realize I have to calculate image distance in any ways since I need to get it focused. Through google I learned that the lens formula 1 / f = 1 / o + 1 / i
(f
for focal length, o
for object distance, i
for image distance) can be applied one by one to each lens in the stack. That is, I calculate the image position for the first lens i1 = 1 / (1 / f1 - 1 / o1)
, and carries i1
as the object for the second lens (even if the image is not really formed) to get i2 = 1 / (1 / f2 - 1 / o2) = 1 / (1 / f2 - 1 / (d - i1))
(d
for distance between the two lens).
With such calculation, I can calculate the position range of the focused image given the moving range of my lenses.
A film projector is basically a reversed analog camera - the film is the object to be captured, and the content of the film forms image at the image plane.
Diagram of the system
I did some research and bought some parts: a NEMA 17 motor to move the lens, a lead screw nut set to turn rotation to linear motion, a flashlight bulb as light source. I decided to 3d print all supporting parts I need for convenience, and apply the lead screw's moving range to calculate image range.
Modeling of the system (blue = to 3d print, left frames indicate range of image distance and size)
After I finished setting up my system, I realized that my light bulb is too bright but also too concentrated. It lit up the surrounding of the image, while leaving a bright point at the image center.
Projection result of my first try.
Therefore, I added layers of frosted window film in between light and film to spread the light more, and an extra board around the lenses to block exceeded light, which slightly improved the result, but showed that a single bulb's light is too weak for such a large film.
The light box with frosted layers in between.
Slightly improved image quality
After all the setup, I realized that instead of calculating image position based on object and lens positions, my system should be calculating lens position given image position (position of the screen board). However, with all those fractions in the formula, I can't figure out how to solve the variable.
When testing the stepper motor, I came up with a new approach: by iterations, move the lens for a small distance, then calculate if the current image position aligns with the board's position. The core code block is shown below:
double distance = (double)sensor.read() * 0.9537;
if (distance != -1) {
double imageTotalDistance = calcImgDistDouble(nearLensFocus, farLensFocus, objectBaseDist + objectAdditionalDistance, lensDist);
double expectedSensorDistance = imageTotalDistance - (sensorBaseDist - objectAdditionalDistance - lensDist);
if (abs(expectedSensorDistance - distance) > 10) {
double distanceToMove = 4;
double movedDistance = objectAdditionalDistance + distanceToMove * (expectedSensorDistance < distance ? -1 : 1);
if (movedDistance > 0 && movedDistance < 155) {
rotateMotor(distanceToMove / mmPerRev * 360, 60, expectedSensorDistance - distance < 0);
objectAdditionalDistance = movedDistance;
imageTotalDistance = calcImgDistDouble(nearLensFocus, farLensFocus, objectBaseDist + objectAdditionalDistance, lensDist);
expectedSensorDistance = imageTotalDistance - (sensorBaseDist - objectAdditionalDistance - lensDist);
}
}
}
It worked as I expected! However I do realize I didn't stablize my power source, so whenever the motor moves, the light bulb will flash/dim.
Auto Focus Film Projector