The following is a picture of the pendulum apparatus.  The bulky top assembly contains the electronics, laser beams and sensors used to detect the motion and speed of the pendulum.  The data is then processed and sent to a computer for analysis.

Pendulum Experimental Apparatus

The three long bolts in the top assembly are the mirror alignment bolts.  By adjusting these three bolts we adjust the reflected laser beam to perform multiple reflections between the two mirrors and to be aligned properly to be received by the receiver.  The bottom laser is the reference laser.  It is interrupted at the bottom of each swing.

The following short video shows the internal structure of the detector assembly, where the lasers are in correlation to each other and how the beam is broken by the connecting rod of the pendulum.

The reference laser is picked up by the following sensor circuit card.  All components are through hole and the board is a prototype board with through hole pads.

The mirror laser is picked up the the second sensor board mounted on the front of the pendulum assembly.  All parts are through hole using a through hole prototype board.

Primary Parts Used In the Design

Of all the parts used in this design, most are readily available at low cost.  Some of the primary specialized parts in the design are:

Laser Module


Being a small black hermetically sealed unit, the laser modules use is simple and direct, requiring an external DC voltage from 3-5V for proper operation.  The module emits a beam of light at 5mW power and 650nm wavelength.

Light Sensor

A standard photo transistor.  Maximum sensitivity sits around 630nm.  The laser is not right on the maximum sensitivity, but the light sensor dynamic range is 390-700nm.  Making it usable in our project.

Opal Kelly FPGA Module

Not enough good things can be said about Opal Kelly’s FPGA modules.  These modules interface directly to a computer via either USB 2.0 or USB 3.0.  The FPGA can be programmed from the computer via the provided API.  The API provides both the PC side interface and the firmware communications modules needed to allow data to be sent to and from the PC and the FPGA module.  If you are just learning how to use FPGA’s (Field Programmable Gate Array’s).  I highly recommend these modules for their ease of use and rapid development cycle, enabled by the stream lined API provided.  We are using the XEM-7001 module in this project.  Coming in at a cost of $200.00.  This is the most expensive item of our project, but well worth the cost.  There modules are available on the web at:

Construction Of the Pendulum Frame

The frame design started with a drawing/print created using Microsoft Visio and Converted into PDF.  The following is the frame design.  Construction was using 3 1/2 inch deck screws, allowing for easy disassembly if required.

Construction/Operation Of The Pendulum Sensor Assembly

The Sensor Assembly contains the reference laser and the mirror laser along with associated sensor elements.  Two mirrors, mounted on opposite sides of the assembly allow for a laser beam to be bounced back and forth multiple times providing us the position information of the pendulum with respect to the reference laser.  The reference laser, has no mirrors but travels across the assembly and thus being interrupted by the pendulum rod twice for each complete swing.  The following video shows the overall construction/design of the sensor assembly.

Mirror Laser Receiver Circuit Operation

Mirror Laser Receiver Schematic

Power is routed in from a standard 9V battery to J1.  U1 is a linear 5V regulator, providing 5V power to the rest of the circuit.  R1 increases stability of the regulator by providing a small additional load.  Q1 is the primary sensor photo-transistor.  R2 allows us to adjust the first stage output voltage based on ambient light levels vs the laser light level.  The final circuit used 200K resistance for good operation.  U2 provides analog to digital conversion of the pulse and provides noise elimination and cross-over distortion via high feedback hysteresis provided by R5.  When the sensor is not detecting the laser beam, the input to U2 is below the upper threshold of 2/3 of 5V or about 3.33V upper threshold.  Using a sense resistor of 200K this comes out to a sensor current of around 16uA trigger current.  Once U2 triggers, the threshold is then pulled to the lower limit of 1/3 of 5V or about 1.67V lower threshold, thus after tripping the current from the photo-transistor must drop below around 8uA.  Any noise or slow rising signals from the photo transistor are thus eliminated by the large hysteresis of U2.  U3 provides the necessary translation from 5V logic to the XEM7001 3.3V logic.  The XEM7001 provides 3.3V to R9, with the LM311 being an open collector device, the digital signal level is thus set to 3.3V for compatibility with the XEM7001, the output signal and ground are then also supplied to the XEM7001.  Note that when the beam is interrupted by the pendulum rod, the output is low, thus negative pulses are generated by the circuit when the beam is broken by the pendulum rod during it’s motion.

Reference Laser Receiver Circuit Operation

Reference Laser Receiver Schematic

5V Power is tapped off from the Mirror Laser Receiver circuit to J1, thus providing 5V power to the circuit.  Unlike the previous circuit, the laser is traveling a short distance and not losing power due to multiple reflections as in the Mirror Laser Receiver Circuit.  Because of this a significantly higher current is provided by Q1 photo-transistor, thus R2 is significantly smaller that the other circuit.  This makes the circuit less sensitive to ambient light levels.  Also the logic is inverted here.  When Q1 is on U2 output is a logic high.  The operation of U2 is identical to the Mirror Laser Receiver Circuit as well as U3.  As in the Mirror Circuit, 3.3V logic power is supplied to R9 from the XEM7001 module.  Thus the behavior of this circuit is pretty much identical to the Mirror Laser Receiver circuit with the exception that the signal is positive logic when the beam is broken by the pendulum rod.


An Ethernet cable (CAT6) was used to route the logic signals from the board to the XEM7001.  The RJ-45 connectors where cutoff from the cable and ran to the Sensor Assembly, the other end has 0.1″ on center header single wire slip on connections to the XEM7001.  We soldered two 2×25 0.1″ headers to the XEM7001 allowing us to connect the cable to the board as shown here.

Sensor Assembly To Opal Kelly Connection

Here the signals are wired to JP2 connector on the XEM7001 as follows:



Xilinx Vivado version 2018.1 is used for the firmware.   All of the firmware is written in VHDL.  The XEM7001 contains an Artix-7 FPGA.  Part number:


The XDC file (Constraints File) Routes two logic input signals into our project as shown here from a snippet of the XDC file:

The TopLevel.vhd file provides the high level interface module to the Sensor Laser Assembly.  The following presentation reviews the Top Level design entity, how it operates with the Sensor Assembly and how it interfaces to the PC via Opal Kelly’s IP.

The DDBBusRegister Entity allows for the reading and writing to an address on the bus that acts like a single read/write value.  The following is the code snippet and a discussion of it’s operation.

Click on the Image to Download the Source File

Starting with the entity declaration at line 7.  The REGISTER_ADDRESS is a unique address selected in the top level design.  Each register address must be unique to avoid bus conflicts.  The clk is supplied for the USB 2.0 host running at 48Mhz.  The bus signals themselves are next.  The only custom output used at the top level is the register value (i.e. reg_val).

Moving on to the architecture lines 31-43.  If the address_bus matches this REGISTER_ADDRESS and read is true, the output data bus is assigned the value of the register.  If the address_bus matches the REGISTER_ADDRESS and write is true, the register is assigned the value of the input bus.  In all cases the output databus remains not driven in high Z if the address_bus does not match the REGISTER_ADDRESS.

The DDBBusReadOnlyRegister Entity allows for transferring single word data to the bus.  The following is the code snippet and a discussion of it’s operation.

Click on the Image to Download the Source File

The operation is similar to the DDBBusRegister with the exception that no write capability is available and the supplied custom register is an input to the entity.  The address bus stays off in high Z unless it matches the target address for this register.  If there is an address match and read is high, the output databus is assigned the register value.

The DDBBusReadFifo Entity allows for reading back large amounts of data from on bus address.  A snippet of the code and a discussion of its operation follows.

Click on the image to download the source code.

This is mostly a wrapper around a Xilinx IP provided FIFO.  The FIFO is 16 bits wide and 1023 elements deep.  The unique required code to make it compatible to our bus is on lines 66 and 67.  The data out only gets the FIFO’s data out if the address matches the target address, otherwise it remains off in high ‘Z’.  The read signal is gated through to the FIFO if the target address matches the register address.

The ClockDivider Entity is pretty straight forward.  Here is the code snippet.

Click on image to download source code

One of the primary core entities in this design is the PulseWidthDetector.  When the laser beam is broken by the pendulum rod, a pulse is generated, the width of the pulse is inversely proportional to the speed of the pendulum.  The detector senses these pulses and provides count output that represents the width of the pulse.  A one shot ready signal is provided that allows the pulse to be captured into a FIFO at the next higher level.  Here is the entity declaration of the PulseWidthDetector, the source code may be downloaded by clicking on the image.

VHDL Code Snippet
Click on the image to download the source code.


VHDL ‘code’ has to be converted into an actual digital hardware equivalent of logic gates, look up tables, and registers.  The transformation from a textual based code to this format requires certain rules be followed by the developer.  I will only mention here one such rule:
“Keep it simple”

Synthesis tools struggle at converting complex VHDL into actual hardware.  If you find yourself developing a rather complex looking set of structures in VHDL, there is likely an easier more elegant way to achieve the result.  Sometimes this complex code will not synthesize properly or if it does will not operate properly or create what the author intended.  Enter, RTL (Register Transfer Logic).  It is wise to look at the RTL that is developed from the VHDL code.  You can tell a lot about the design from the RTL.  The following shows the RTL schematic generated by Vivado for this code body and walks through it briefly.

RTL Schematic For This Project

PC Side Software Design and Operation

Visual Studio 2017.1 was used for the software design.  The project is a Windows Forms application using the C# language.  Here is the software in action, collecting data from the pendulum:

The data is collected and stored to the file PendulumData.csv.  The left pane displays the calculated speed of the pendulum bob from each interruption of the mirror laser.  Because this beam is bouncing between two mirrors, there is a lot of interruptions for each swing of the pendulum.

The following is the top level design of this application and how it interfaces to the Opal Kelly USB 2.0 Device driver.  Each item is summarized below.

Software Top Level Components

OKDDBBus.dll Description

The OKDDBBus.dll is a .NET Assembly designed to provide an easy to use bus like topology interface to the Opal Kelly Firmware.  Reading and Writing to the bus is via the following interface

Click on Image to download source code

In all cases the address is 16 bits (thus ushort).  A single item can be read or written to the bus.  Or a List of items written or read from the bus.  Each item is a 16 bit (ushort).  When reading or writing multiple items, the target in the firmware is typically a FIFO.  ReadFIFOAll method reads all the data out of the FIFO.  It assumes the standard that the first address contains the number of items in the FIFO and address+1 contains the FIFO itself.

Implementation of the Interface

An instance of the interface is created by calling: DDBBusLib.Create(“TopLevel.bit”);

This string passed in is the name of the FPGA bit file to be loaded.  Construction of the object loads the bit file into the FPGA Module.  The following shows the constructor  of the DDBBus class that implements the IDDBBus interface.

Using Opal Kelly’s Front Panel Interface is straightforward.  The first line creates a new FrontPanel Object.  The second line opens the first Opal Kelly Module it finds connected to the computer.  The third line loads the default PLL Configuration.  ConfigureFPGA method loads the FPGA with the specified bit file.

The DDBBus class uses three private members to implement the interface.  Discussed next…

The LastAddress is the last one sent out.  If it matches the current one, there is no need to set the address again as it is retained from a previous call.  SetWireInValue method sets the actual address.  UpdateWireIns method causes all Wire Ins in the design to be updated.  Because this is a costly call in processor time, we only set the address if it has actually changed.

Writes data to the pipe in.  Because the data for the Pipe is in byte format, we must first convert the 16bit data to an array of 8 bit data items, thus the foreach loop.

Reads data from a pipe out.  Note the data is a byte array when read back from the Pipe and must be converted into a 16 bit array.

The rest of the code for the DDBBus class is rather straight forward, you can access it via this link:

DDBBus Class

Pendulum Application Discussion

The Pendulum Application uses the DDBBus .NET assembly to get the reference laser pulse width along with the mirror laser pulses and associated widths. 
The DDBBus object is constructed in the Pendulum Class constructor.  The pendulum class abstracts away a lot of the details with getting the data from the DDBBus object.  The following code snippet is from the Pendulum Constructor:


The first line constructs the Bus.  Second and third lines set default values.  The Averager is used to take an average of the Pendulum Period with a rolling average of 6.  Smallest Vector looks at the mirror pulse counts for every two and selects the smaller one.  The difference being the number of pulses to the right of the reference pulse or left of the reference pulse are usually off by one or two from one another.  The time tracker allows for the determination of the period of swing.

The Update Method is called from the main GUI and is responsible for updating the data from the Pendulum.  The following code snippet shows the update method and a discussion of how it works:

The update method first Reads the Fifo for the reference pulse.  If the reference pulse has not occurred yet, the FIFO count will be zero and the method returns directly after that as there is nothing further to do.  If the reference count occurred, the number of swings is incremented and the reference pulse count is added to the Averager.  After this the swing pulses is acquired.  If the swing pulses is zero.  There is nothing to do.  If the swing pulses is greater than zero, they are added to the smallest vector tracker object.

The main application uses a Windows Forms Timer to call the Update method approximately every 10 milliseconds.   Because the period of swing is around 1.5 seconds, most of the time the Update method has nothing to do, otherwise it updates the data on the GUI.

If you want to understand the software further, I have included the project here as a zip file:

The project firmware using Vivado is also included as a zip file for download:

Analysis of Data Collected

The collected data is compared to that of the theoretical predictions for a pendulum in the following report.

Project Summary

The experimental data matches the theoretical data to within about 5%.  This is not bad considering the errors that can creep in on this experiment.  The width of the rod is critical to know with high accuracy to determine the speed.  Also the laser beam width plays a role.  We treated the laser as a ‘line’ source with no width.  Even so the data matched pretty close to what was expected.  Energy loss was not bad, allowing for about 500 swings before the pendulum came to a rest point.

This article covered a lot of different disciplines, from carpentry, mechanical design, software programming, firmware development, circuit design, to mathematics involved in the transformations of the raw data.

If you are inclined to believe formulas from physics without actually proving them to yourself via experimentation, then my goal was to move you more towards the skeptical mind of not taking anyone’s word for it and finding out for yourself.  If you already has such an attitude I hope this article may inspire some experimentation of your own in physics.  I enjoy input from others.  You may contact me at:

or post a comment on this site 🙂