Introduction: Light Detecting and Positioning Unit

This is an intermediate level difficulty Field Programmable Gate Array project. Once complete, this device will be able to detect where the most light is being shined and, using a servo, move a solar panel towards the highest concentration of light.This project's goal is to optimize the energy gathered by a solar panel. Below is a parts list:

  • Basys 3 FPGA board
  • USB to Micro USB cable
  • Program to write Hardware Description Language on (this instructable uses Vivado and VHDL)
  • 12 photo resistors
  • 12 2,000 Ω resistors
  • RC Servo
  • protoboard
  • 2 JRC 4558 Op Amps

Step 1: System Outline

The hardware portion of the project consists of the sensor array, the muxes, and the comparators. Each sensor in the sensor array should generate an analog voltage between 0 and 5 volts that is directly proportional to the intensity of light shining on the sensor. The sensors are wired into the different inputs of the muxes and multiplexed using a select signal from the FPGA board before going into the comparators. This reduces the number of inputs from 24 to 3. The comparators are then used to compare the voltages to a reference voltage produced by the FPGA board in order to generate a digital signal that the FPGA board can use.

This project also requires an FPGA in order to work. In our build, we used a Nexus Basys 3 board. The board must take in sensor data from the external comparators. The board has to scan in the sensor data by outputting a varying select signal to the external muxes, which allows it to scan in all the sensor values. The reference voltage needs to be controlled by the board as well. The board then must find which sensor is receiving the most light and store the position of the sensor. Finally, the board has to convert this position value into instructions for the external servo. The picture above shows our initial idea for the system architecture for the FPGA board.

Step 2: Board Modules

In order to perform the actions outlined in the previous step, the FPGA board needed multiple modules which performed the necessary tasks sequentially. This meant that most of the modules would have to share the same clock signal, and be timed so that they operate in sync. This is done by linking the inputs and outputs of multiple finite state machine modules. This meant that our final implementation was much different from our initial envisioning. Included below are in-detail descriptions of what each module does, as well as example VHDL files for the modules, along with some modules designed to test the functionality of the circuit.


The CONTROL module controls the other finite state machines on the board. This ensures everything is timed correctly so that no infinite loops that prevent the circuit from operating occur. This is done by having the control block send a signal to another module (the SCAN module), telling it to do something. The control block waits for a response from the other module before continuing. It then calls the next module (the FIND module) once it receives a response to continue the process. Then, depending on the success of the FIND block, the control block then either decrements or resets the reference voltage of the comparators. This ensures that the other modules only perform an action when it is absolutely necessary.


The SCAN module is the one that scans in the sensor data from the external sensors. It does this by controlling the SEL signal that is output to the external muxes, and by controlling the internal DMFLOP module using an EN and SEL signal. The module waits for a signal from the control block, and starts the scan when it receives it. It goes through all the valid SEL values, and enables the DMFLOP module so that it stores the values in a register. Once all the values are stored, it returns a DONE signal to the control block.


The FIND module finds a maximum sensor value from the scanned in sensor data. Once it receives a signal from the CONTROL block, the find module searches for a ‘1’ value in the sensor values, which indicates the sensor voltage was higher than the reference voltage for that specific sensor. It then outputs a 7-bit value that is related to the position of the ‘1’ value in the sensor data array. If it does find a ‘1’, it returns a success to the control block. If no ‘1’s are found in the data, a failure signal is sent back to the control block.


The DMFLOP module is a specialized flip flop register that takes an EN and SEL input from the SCAN block. It uses these signals to demux the inputs from the external muxes and store them in the register. This module is important because both the SCAN and FIND blocks require it for the circuit to work.


The MAIN module encapsulates the CONTROL, SCAN, FIND, and DMFLOP modules into one single module. This ensures the modules all receive the same clock signal, and makes the modules much easier to incorporate into other circuits. The MAIN module only requires a single clock signal and the 3-bit input from the external comparators. Its outputs are the SEL signal and two 7-bit DUTY signals for the motor and reference voltage PWM signals.


The REF module takes outputs from the CONTROL module to determine what the 7-bit DUTY value of the reference voltage PWM should be. It is able to either decrement the voltage or reset it to it's maximum voltage, depending on the output of the CONTROL module.


The PWM module generates a pulse-width modulated signal which is outputted to one of the board outputs directly. The module takes in a 7-bit DUTY signal that represents the duty cycle of the PWM signal. The frequency of the PWM signal is determined by the clock signal supplied to the module. This module is used to generate the reference voltage and the motor PWM signals.


The CLK_DIV module is a clock divider. It outputs a clock signal with a frequency that is equal to the input clock frequency divided by an integer. The integer value can be changed by changing a value inside the clock divider vhdl file. A clock divider is needed for the main module clock signal, as well as for the motor PWM module. Credit for creating the CLK_DIV module goes to Bryan Mealy.


The TEST and MUX modules are testing modules for the circuit.

Step 3: Hardware

There are many components on the board, but it is not as difficult to build as it appears. Our prototype was built for the possibility of using 24 sensors, 12 for an X direction and 12 for a Y direction. It therefore contains three 8 to 1 analog muxes and 2 dual op amps functioning as three comparators.

Sensor Array

The sensor array was built by poking the photo resistors through some Styrofoam bent into an arch shape. One side of each photo resistor is connected to the power supply, and the other side is hooked to a wire that goes to the prototype PCB. The other half of the sensor consists of a simple resistor and these are mounted to the board, between the multiplexer inputs and ground.


Following the schematic connect each sensor to each multiplexer input. The multiplexers also connect to the SEL signal from the FPGA. The select inputs on each mux is connected to the same pin on the other muxes. The output of each multiplexer goes to the corresponding comparator input. The enable pins are active low. They are connected together and grounded through a resistor to enable all the chips. The resistor is there in case the pin was needed to be driven high later.The 0.1uF capacitor provides some power supply filtering for these chips.


For comparators we are using the JRC4558 dual op amp. It is not typically a good idea to use op amps as comparators, but these can tolerate a large common mode voltage and do not latch-up if an input goes above or below the power supply, which are the most common problems encountered when not using a real comparator.

The input of each comparator features a noise filter to help stabilize the reading from the sensors. The PWM goes to an identical filter to obtain the stable reference voltage to be compared against. There is some additional power supply filtering to help with the quick transients caused by the fast switching from low to high voltage.

The output from each comparator goes to an input on the FPGA board.

Additional Details

  • The circuit ground need to be connected to the FPGA ground to function properly.
  • Ribbon cable with a 0.1" spacing was used to simplify some of the multi-wire connections. This cable will plug right into the connectors on the Basys3 dev board we were using.
  • The sensors are input to the muxes so that the output of the comparators is all X values or all Y values. This allows the FPGA to use a different reference voltage and distinct select values when scanning in the X and Y sensor data.

Step 4: Troubleshooting and Additional Information


Make sure that the ground of the external circuitry is connected to the FPGA board ground.

Make sure that all signal-carrying wires are plugged into the correct pinholes on both the FPGA board and the external circuit.

If you are having trouble getting the reference voltage PWM to work correctly, you may want to consider using an alternative method for generating the reference voltage. Instead of using a pulse-width modulated signal, remove the reference voltage PWM module and modify the VHDL modules to output the 7-bit duty signal instead. From there, an external summing amplifier can be used as a Digital to Analog Converter to generate an analog reference voltage.

Additional Information

All VHDL resources provided in this Instructable are free for use as part of the Public Domain.