Light Following

Share for us

How It Works

The light follower module detects light sources in the surroundings, and transfers the data to the processor. The processor analyzes the data and finds the direction of the light resource, so it will send a command to control the movement of the front and rear wheels to approach the resource.


This light follower module applies phototransistors as photosensitive components. Similar to common transistors, the phototransistor can amplify current, but the current at the collector terminal is controlled not only by the circuit and current of the base area, but also by light emission. Usually, the base terminal is not exposed, but some may still do for temperature compensation and extra control.

Phototransistor, also known as photodiode, is a device that converts light to current. Currents are generated when photons are absorbed in the P-N junction. When a reverse voltage is applied, the reverse current in the device will change with the light luminance. The stronger the light is, the larger the reverse current will be. Most phototransistors work this way.

The ADC chip on the HATS can receive 8-bit analog signals and convert them into integers, and transfer the signals to the Raspberry Pi. The Raspberry Pi will analyze the data to determine the direction of the brightest area (the light source), and further control the steering and movement of the four wheels to approach the light source.

You may need a light focused flashlight in this experiment. At least, the spot size of the torch should not be too big to reach all the 3 phototransistors on the module at the same time. Well, you can also shine the flashlight closer to the car to get a small spot size.


Step 1 Assembly

Connect the light follower to the Sensor Connector with M3*10 screws and M3 nuts, and then assemble them to the car with two M3*10 screws and two M3 nuts. You’re suggested to hold the nuts underneath with your fingers.

Step 2 Wiring

Connect the light follower to the Robot HATS with a 5-pin anti-reverse cable as shown below.

Light FollowerRobot HATS

Note: You may wonder why we connect 5V to 3.3. Well, since the working voltage of the STM8 chip on the light follower is 2.7-5.5V, we can connect it to 3.3V here. DO NOTconnect 5V to 5V!All the analog ports on the Robot HATS are led from the PCA8591, which is powerd by 3.3V. Therefore, if the voltage is between 3.3V-5V, the output value will always be 255, thus the PCA8591 may be damaged if connected to 5V. Remember to connect to 3.3V.

The wiring is shown as below:

Test for Light Follower

Let’s test the light follower first.

Get into the directory example

cd ~/SunFounder_PiCar-S/example/

Run the test code


pi@raspberrypi:~ $ cd ~/SunFounder_PiCar-S/example/pi@raspberrypi:~/SunFounder_PiCar-S/example $ python[237, 233, 237][236, 230, 236][232, 238, 246][237, 240, 251][145, 175, 200][228, 234, 74][219, 226, 23][220, 192, 21][233, 238, 23][236, 241, 22]

Expose the phototransistors to the light spot of the flashlight. When you increase the light intensity, more LEDs light up, and the ouput values decrease. Here we can rotate the blue adjustable resistor to change the values under the same light luminance. If there is no light, only one LED will light up with the output value as 255; if the light is the brightest, all the LED will light up, and it would be better to adjust the output value to 10-25 under this circumstance.

Place the module in an open field with even light exposure so the experiment can be free of the interference of unsteady ambient light thus the sensor is more sensitive. Check this way: expose the light follower module under the natural light (or other bright conditions) to get the output value; then shine the flashlight on the phototransistors to get another output value. A place with a gap of 20+ between these two values would be a better choice, so that we can get an obvious effect when the car follows light.

Step 3 Run the Code

Get into the directory

cd ~/SunFounder_PiCar-S/example

Run the code


Calibrate the light following

The car will enter the light following configuration mode when we run the code above. It will keep turning to the right in a circle to gather the information of light condition in different directions. So just place the car in an open field and wait.

Picar-S follows light

When the calibration is done, the car will stop temporarily. Shine a flashlight on the light follower module, and the car will just follow the light spot as you moves it.

Software Flow

1. Light-sensitive sensors need to be calibrated before actual use because of complex light conditions in the environment. It gathers the information of the ambient light luminance. The car can follow light only when the light source is brighter than the surroundings.

2. Here write two main functions/modules including light following calibration and light following in the main program.

Subflow of Light Follower Calibration Function

We need to configure three light-sensitive components separately, so we set three lists to store the values in A0, A1, and A2 collected for multiple times. Then pick out the minimum values, which are the ouput analog values in the brightest conditions.

Since the light source we use is much brighter than the ambient light, we should take the output values in the brightest conditions as reference.

Besides, we should set a threshold value – when the gap between the collected value of the light source and that of the environment is beyond the threshold, trigger the value switching to 0 or 1. Here we use [0,0,0] to represent the three photoresistors’ status when they are not triggered. “0” will become “1” when the value detected of the corresponding photoresistor is higher than the threshold. Thus we can set the related action of the car according to the three-element list.

If there is light detected, the car will move and follow it; if there is no light detected, the car will stop temporarily and keep turning to detect in a circle.

Subflow of Light Following Function

The light follower includes three phototransistors, thus its status list is composed of three elements which represent 8 statuses (based on permutation and combination). And here we need to set related responses to these statuses.

The three elements show the status of the three probes: 1 represents light detected, and 0, for none. For example, [1,0,0] shows that light is detected only by the left probe, meaning th light source is at the left of the car, thus setting the car’s response action as turning left; [1,1,0] means that light is detected on the left and central probes, thus its response action should be set turning left too; and set it as turning right the same way according to the corresponding status. When there is no light detected, the status is [0,0,0], so we set the response action to stop and return to the standby mode.

Here, we need to set another variable – the steering angle – to distinguish between the large-angle and small-angle turning. If the light is at the central left side (status [1,1,0]), we should apply a small-angle turning; if the light is at the edge of the left side (status [1,0,0]), we should apply a large-angle turning.

Code Explanation

To understand the code, take the software subflows above for reference.

Three Python modules are used in the code including the imported light_follower_modulefront_wheels, and back_wheel previously. They are drivers for this kit, respectively for light following, front wheels and rear wheels.

The related classes have been defined here. When the modules are applied to use, objects will be created for related classes, and different parts of hardware will be driven by calling a function by the class object.

For example, for the light following module, we create an object named lf:

lf = Light_Follower.Light_Follower()

Then we can call the function by a class object.

A0 = lf.read_analog()[0]

This functionread_analog() will return a list with three elements, which stores the detected analog values of three probes. Here we use A0 = lf.read_analog()[0]A1 = lf.read_analog()[1], and A2 = lf.read_analog()[2] to store three elements of returned value separately into the variables A0-A2.

for() loop is used here cycling 10 times, that is the car will acquire the analog values ten times when the car drives in a circle under the calibration mode. The minimum values will be taken as reference here. If you need more samples, just increase the times of the loop.

Store the detected values to a list in each loop by the env0_list.append(A0) function. When the loop ends, the built-in list function reference[0] = min(env0_list) in Python will pick out the minimum in the list.

lt_status_now = lf.read_flashlight()

This is to read the status of the module, which will return a 3-element list. This function is used to solve the possible problem caused by brightness-adjustable flashlights. They blink repeatedly due to brightness change by PWM method, so we add this function to the driver library to prevent the car from moving and stopping repeatedly when the light source lights up and goes out quickly or changes luminance by ON/OFF ratio.


Function for front wheels steering. The main program will call this function if the front wheels are applied for steering. The parameter is the turning angle.



Here we need two functions for rear wheels. The first function is to control the rotating direction as forward (the function for backwards is bw.backward()). The second one is to set the rotating speed of the wheels; the parameter is the speed value (range: 0-100). The bigger the parameter is, the faster the wheel rotates.