Overview
The Olin Forceplate project was started by Zachary Borden, Mark Cavolowsky, and Jonathan Tse under the sponsorship of Professors Yevgenia Zastavker and Gill Pratt.
The content from this page was adapted from here. I prepared most of it, save the mechanical engineering and software portions, which were prepared by Mark and Zac, respectively.
What is a force plate?
A force plate is an instrument for measuring force. Typically they are used in biophysics and athletics applications to study the forces involved in human or animal locomotion.
Usually this is done by observing the ground reaction forces (GRFs) at the center of pressure (CoP). The most simplistic force plates are essentially bathroom scales, and only calculate the normal component of the GRF at the geometric center of the plate. Somewhat more advanced forceplates can calculate the normal component of the GRF at the CoP.
Center of Pressure
The CoP arises from the idea that if you place a mass on a surface, the point at which the net force from the interaction between the mass and the surface is the CoP. This net force is essentially the GRF. |
The most advanced force plates can calculate all three components (not just the normal) of the GRF at the CoP, as well as a number of torques about either the CoP or the geometric center of the plate.
How do they work?
Force plates use load cells to read forces. Load cells use what are called strain gauges, which essentially are variable resistors that change their resistance relative to their strain (basically how much they stretch). By measuring the resistance, and calibrating each load cell so that the resistance is meaningful in proportion to force, you can use linear algebra and some knowledge of statics to figure out what the torques, CoP, and GRF are.
So why did you do this anyway?
Our force plate was created to address a need of Olin College. During a first semester freshman mechanics class we (Zachary Borden, Mark Cavolowsky, and Jonathan Tse) saw that the current method of measuring force, a bathroom spring scale, was woefully inadequate for a lab assignment on the GRFs generated by a human jumping.
Essentially the issue was that the bathroom scale not only didn’t have the force range required (jumping multiplies the GRF generated by just your mass by a factor of about 10), but that the bathroom scale’s needle was impossible to read during a jump with a timescale on the order of a second.
When approached about this problem, Professor Yevgeniya Zastavker suggested that a team of undergraduate students could construct a force plate for about $5000. With that in mind, and the support of Professor Zastavker and Professor Gill Pratt, we designed and built a force plate for approximately $2300 in the second semester of freshmen year.
During our sophomore year, we further refined and improved the force plate. Although there was no intent to write a technical paper, there is work currently progressing on an educational paper detailing our experiences during the project.
Why is your force plate so special?
The base design of our force plate is an exciting departure from the ordinary. Typically, force plates are constructed with load cells, all with their axes vertical, supporting a plate. This standard design is adequate for applications where you need the center of pressure and the normal force, but is a poor choice for applications with shear forces.
In such applications, shear forces will apply off-axis loads on the load cells. Off-axis loads can result in bad data from the load cells, which are usually designed only to read forces along their axes. Off-axis loads can also result in damage to load cells.
To solve this problem, Professor Gill Pratt suggested we investigate building a force plate based on a Stewart platform design. Stewart platforms have 6 support struts between the ground or some other immobile object, and a top plate or platform.
Instead of terminating in six different points, the support struts terminate on the ground and plate in sets of two, resulting in three termination points on both the ground and the top plate.
Stewart Platforms
A typical application for Stewart platforms involves replacing the support members with linear actuators. Since the force plate has six degrees of freedom, this is an ideal solution for positioning objects in a wide range of applications, from the microscopic for biology, to the macroscopic for amusement park rides. |
Our design replaces the support members with six load cells, allowing us to gather data in six degrees of freedom. It also has the added benefit of keeping all of the loads axial along the load cells. While we do sacrifice some stiffness in the system because the support members/load cells are not completely vertical, the effects are essentially negligible.
Mechanical Design
The force plate is based off of the standard Stewart Platform hexapod design, with the six legs attached, in pairs, to three points on each plate. This provides a perfectly constrained system, fixing plates in relation to each other in all three translational axes and all three rotational axes. With the load cells mounted in the center of each of the legs, we are able to read the forces and the torques in all directions through axial loads on the load cells.
Each of the plates is actually a series of plates attached together to provide additional stiffness. If the top and bottom plates were deforming as load is applied to the force plate, energy would be absorbed into deforming the force plate rather than the load cells. Since the load cell readings are directly based on the deformation of the load cell frame, this will lead to inaccuracies in our force readings.
We were especially worried about top and bottom plates bending from outward forces applied to the brackets. To help remedy this, we added a reinforcing plate and brackets in between the plates to rigidly fix the two plated together. That way when a large, outward force is applied to the brackets, it would try to bend the top/bottom plate, but the reinforcing plate would be placed in tension. Aluminum is much stronger in tension than in bending, so this would lead to a much stiffer system.
Our original design had a ball and socket joint attaching each of the legs to mounting brackets mounted in a triangle on each plate. These joints allowed the legs of the force plate to align themselves at the appropriate angle. Since the ball and socket joints had the ability to rotate in all three axes, the angle of the legs would be able to change as the plate deformed.
This ensured that the loads would all be along the axis of the load cells, thus eliminating off-axis noise, but it also allowed the angle of the forces to change to change, potentially invalidating our model. Although we felt that the effects of either of these factors would be minimal at best, we decided that minimizing the off-axis loading of the load cells was more important, and that sold us on this design.
Unfortunately, the socket joints that we bought had a lot of "slop" in them. This could cause the readings on the force plate to be inaccurate, so we had to redesign the force plate to incorporate a "slopless" mounting system. Professor Gill Pratt suggested that we look into flexure joints to adjust the angle rather than ball and socket joints. Flexure joints rely on the natural flexibility in the metal to adjust the angles of each of the legs.
However, flexture joints are not nearly as flexible as the ball and socket joints, only being able to move a couple of degrees (without excessive forces being applied, which would cause off-axis loading problems on the load cells).
That means that we needed to create a mounting block with the holes for the flexure joints aligned perfectly with the load cells. Because of the complex angles involved, this block would have to be made with the 4th axis on a CNC mill.
Designing the flexure joints was a tricky matter. They needed to be flexible enough to reduce the off-axis loading to insignificant levels, yet still strong enough not to break as a person jumped on the force plate.
To actually design the flexure joints properly, we used CosmosWorks (a FEM software package) to model the physical response to differing loads. Using this data, we settled on a design that was above the endurance limit of our material as well as flexible enough and strong enough for our needs.
However, in addition to complications with the analysis, we had trouble machining the titanium stock for the flexture joints. Titanium is a very difficult metal to machine due to its hardness. By the time the steel stock arrived on campus, the end-of-semester crunch had rolled around and we were unable to machine the flexture joints.
Why did we choose titanium? Well, say the following out loud: "Titanium Flexture Joints." Cool, huh? We thought so too. |
Unfortunately, in the long run, we did not finish building the flexure joints as the project fell by the wayside in the latter half of our undergraduate careers. However, Mark, our mechanical engineering lead, had this to say:
A collection of our Solidworks CAD drawings is available here.
Electrical and Software Design
Original (Spring 2005) Circuit
The original circuit (Spring 2005) was no more complicated than an AD624 instrumentation amplifier in line with each load cell. The resulting amplified signal was fed through a 9-conductor serial cable to a breakout box, and finally to a PCMCIA data acquisition card which fed data to a laptop computer for manipulation in MATLAB.
For ease of prototyping and time constraints, the Spring 2005 circuitry was implemented on a pair of solderless breadboards. Since solderless breadboards are designed for easy insertion and removal of components, impacts to the projects boxes containing the breadboards could cause components to come loose.
Additionally, the the 50-pin data acquisition card connection was attached using 30 AWG wire, and we had to solder 22 AWG solid core wire to the end of it in order for it to actually stay in the breadboard. Unsurprisingly, we kept losing connection between the 50-pin data acquisition card connector and the breadboard.
Unfortunately, the PCMCIA data acquisition card we were using was woefully inadequate for its intended purpose. Due to age and repeated use, the data output from the data acquisition card has become very noisy and unreliable.
Updated (Fall 2005) Circuit
Because of the problems with the data acquisition card and the breadboards, it was decided that we should move to a PIC microcontroller as a ADC, and a PCB to replace the breadboards.
Because the PIC runs on a 0-5V range, and the output of the AD624s (as configured) ranged from -7.2V to 7.2V, we needed to recenter the output of the AD624s around 2.5V with a maximum of 5V and a minimum of 0V. We were able to accomplish this using a resistor tree, as suggested by Professor Gill Pratt.
By connecting a 20k resistor to 5V, a 65k to GND, a 28.8k to the signal from the AD624s and tying the other ends of the resistors to the input pin on the PIC, we were able to recenter the output signal around 2.5V. These resistor values were chosen very carefully to have an apparent resistance of 10k between the signal and the input to the PIC.
This 10k resistance was used with a 0.022uF capacitor in a RC filter circuit to attenuate signals with a greater than 1kHz frequency, as to filter out any EMI or RFI from outside sources.
Firmware
The firmware for the forceplate is very simple. Essentially all it does is enumerate the PIC as a USB device, and sets up the PIC to do analog to digital conversion for all six load cells. As part of the USB interface, the firmware has several vendor specific requests which do nothing more than request the 10-bit value for each load cell, which correspond to each load cell’s voltage.
The PIC we used is a PIC18F2455. Credit for the original USB code goes to Professor Brad Minch of BMinch fame on Microchip’s forums.
Assembly Main Loop Code
This code goes through the setup of the PIC and runs the program’s main loop. Essentially the main loop calls ADC subroutines and checks to see if there are any waiting vendor requests from the USB host, which is in this case, a computer.
APPLICATION code Main banksel COUNTER for COUNTER, 0x01, 0x1E ; do nothing for a little while next COUNTER ; We need to set up PORTA and PORTB ; to have analog inputs for the loadcells. ; In order to do that, we'll need to turn ; on AN0, AN1, AN2, AN3, AN4, and AN8 ; We set the corresponding bits of TRISA ; and TRISB high to indicate that they are inputs ; and we use ADCON1 to specify which of the ; analog inputs are active. ; We have also right-justified the A/D output ; for easy parsing in the host-side c code clrf PORTA, ACCESS clrf PORTB, ACCESS clrf TRISA, ACCESS clrf TRISB, ACCESS clrf ADCON0, ACCESS clrf ADCON1, ACCESS clrf ADCON2, ACCESS movlw 0x2F movwf TRISA, ACCESS ; Make RA0, RA1, RA1, RA2, RA3, and RA5 ; inputs movlw 0x04 movwf TRISB, ACCESS ; Make RB1, RB2, and RB3 inputs movlw 0x01 movwf ADCON0, ACCESS ; select AN0, enable A/D module movlw 0x0A ; AN0 to AN8 movwf ADCON1, ACCESS ; Turn on 8 A/D inputs. ; bits 0-3 are 0110 movlw 0xAE movwf ADCON2, ACCESS ; configure A/D module result to right ; justified, acquisition time to 32 us, ; and clock period to 2.67 us call InitUSB ; initialize the USB registers and ; serial interface engine repeat call ServiceUSB ; service USB requests... banksel USB_USWSTAT until USB_USWSTAT, ==, CONFIG_STATE ; ...until the host configures ; the peripheral ; Fix Fencepost by grabbing all the values before we start looping call GetLC1Value call GetLC2Value call GetLC3Value call GetLC4Value call GetLC5Value call GetLC6Value repeat call GetLC1Value call GetLC2Value call GetLC3Value call GetLC4Value call GetLC5Value call GetLC6Value call ServiceUSB forever end
ADC Subroutine Detail
This is one of six ADC subroutines. It starts the ADC conversion on a particular pin, and waits until a status flag changes to stop. Once the flag changes, it moves the ADC result into the appropiate buffer.
; Run the A/D on AN0 and store the result in LC_1 GetLC1Value banksel LC_1 movlw 0x03 movwf ADCON0, ACCESS ; Select AN0 and set the ; GO_DONE bit ; to start the A/D Conversion untilclr ADCON0, GO_DONE, ACCESS ; Wait till A/D Conversion done movf ADRESH, W, ACCESS ; Move the 8 most ; significant bits into movwf LC_1, BANKED ; LC_1's most significant 8 bits movf ADRESL, W, ACCESS ; Move the 8 least significant ; bits into movwf LC_1+1, BANKED ; LC_1's least significant bits return
Vendor Request Detail
This is one of six vendor requests. This particular one is a detail of the vendor request for the first load cell. Basically it sets up the buffer for USB transfers, loads the pointer to the actual load cell data into the buffer, and sends the data.
; Vendor Requests Subroutine VendorRequests movf USB_buffer_data+bRequest, W, BANKED select ; Vendor Request to get the current value for LC_1 case GET_LC_1 banksel BD0IAH movf BD0IAH, W, BANKED ; put EP0 IN buffer ; pointer... movwf FSR0H, ACCESS movf BD0IAL, W, BANKED movwf FSR0L, ACCESS ; ...into FSR0 banksel LC_1 movf LC_1, W, BANKED ; put POT_VALUE... movwf POSTINC0 movf LC_1+1, W, BANKED movwf POSTINC0 banksel BD0IBC movlw 0x02 movwf BD0IBC, BANKED ; set byte count to 2 movlw 0xC8 movwf BD0IST, BANKED ; send packet as DATA1, ; set UOWN bit break ;; Note: Vendor Requests for other Load Cells ;; follow and are semantically the same
Software
The point of having software on the computer for this project is to do all of the complicated (for a PIC anyway) linear algebra manipulations on a platform that actually has a FPU, and of course the whole GUI thing.
Original (Spring 2005) Software
The original software was written using MATLAB. It served its purpose admirably, the problem was with the data acquisition card, so we had to scrap it and move to another solution.
Updated (Fall 2005) Software
Since one of the major goals of the semester was to port the force plate over to USB, a different platform for the host code had to be found. The most logical choice was Python due to its large number of freely available modules and its ease of use in designing and implementing GUIs.
The first hurdle to the software development was the desire to implement real time data collection. This problem offers two main challenges. First, it is very difficult to calculate the exact time that a computer calculation will take since it is dependent on what else the computer is doing at the time.
If this problem could not be solved, we would still be able to collect data in real time, but we would not be able to match each data point with the time that it occurred. Fortunately, Python offers a solution to this problem. Python contains a module called time which, when called, returns the time at which the function call was issued. This enabled us to implement real time data collection.
The second challenge offered by real time data acquisition is the problem of frame rate. Most plotting packages offered by Python have relatively low refresh rates, on the order of 10 FPS. This is not nearly high enough to produce the desired resolution in our data. We went through three different plotting utilities before we found one that was able to more reasonably meet our resolution requirements by offering 18 FPS resolution.
After some optimization of the GUI code by reducing the amount of data that needed to be refreshed each cycle, the resolution was again increased to 24 FPS. If plotting in real time is not necessary, it can be turned off and frame rates of around 40 FPS can be reached.