This device is no match for an Randy's sensor, but it does (minimally) work. Think of this little project as a fun hack more than anything else. But with some tweaking and size reduction someone could probably implement an occasionally working altitude hold sensor for a fixed-wing RC aircraft.
This optical flow sensor uses CdS cells as light sensing elements. Recall that a CdS cell is basically a resistor whose value changes with illumination- more light results in less resistance. The fundamental sensing structure here is a pair of CdS cells connected in series to form a voltage divider. The middle node between the CdS cells forms the output. When both cells are equally illuminated, the output voltage is midway between Power and Ground (assuming the CdS cells are matched). If one cell is illuminated more than the other, the output voltage varies accordingly. An interesting quality of this CdS cell pair is that if you, say, double the amount of light striking both cells, the output changes very little.
Nine of these CdS cell pairs are laid out in a row, as shown in the video. Pay attention to the photo below to see how the CdS cells are placed and how they overlap within the array. The nine resulting outputs go to ports A0 through A8 (analog inputs 0 through 8) of an Arduino Mega. This project required a 'Mega because of the number of analog input signals.
For those of you with an image processing background, you can say that a CdS cell pair forms a simple analog edge detector, and that adjacent edge detectors are 120 degrees out of phase.
As light patterns travel across the CdS array, the nine analog signals will vary accordingly and can be interpreted by a basic one dimensional optical flow algorithm. For example, if a shadow moves left to right across the array, a pulse or step function will appear in sequence across ports A0 through A8 in sequence (or the other direction) which indicates visual motion.
To obtain an image, I just used a slit opening, which is a variation of a pinhole camera. This slit opening was oriented perpendicular to the CdS array, which preserves visual information parallel to the CdS array and smooths out information perpendicular to it. This helps make the array more sensitive to 1D visual motion in the desired direction. (For a rough metaphor, think of a bar code.)
I mounted all the electronics into a shoebox using masking tape. (For a more professional and durable version, use duct tape!) I also placed dark construction paper on the inside of the box to prevent light from bouncing around. I cut a slit opening in the box top as shown to be positioned over the CdS array.
The output can be read in two ways- The Arduino port D3 generates a PWM signal that, when connected to the RC network shown, can generate an analog output representing the optical flow (5V = max positive, 0V = max negative, 2.5V = zero). Alternatively you can read it out using the Arduino environment's Serial display.
The sensor is crude but does work. It needs a lot of light to function- it should work in a bright indoor environment but works better with natural outdoor lighting, say several hundred lux and up.
The Arduino sketch is attached here: CdS_OF_Sensor_r1.pde