Formula SAE Racecars have a lot going on, and unlike normal cars their functionality cannot be taken for granted nearly as often. Like any car, an FSAE car should give the driver as much information as they need to properly handle the vehicle, while also alerting the driver of any issues detected by the car's various sensors and providing controls functionality for the car's various systems. In its simplest form, this can be implemented using a set of lights and buttons attached to the car's chassis; however, this leaves a lot of room for improvement when it comes to ease of use as well as testing and data acquisition.
With a more detailed dashboard setup, other systems on the car become more practical to implement. For example, with the implementation of paddle shifters, drivers might find it difficult to tell what gear they are in as they approach a corner, and might subsequently be in too high or low a gear during the mid-corner and exit (especially if shifting is unreliable, as would be expected during the implementation of a brand new system). A display which shows the driver their current gear solves this issue, as the driver will definitively know exactly how many gear changes to make every single time.
Closeup of TR25's Custom Hand-Cut Stickers
TR24's Dashboard in Operation on the Dyno
CAD Image of TR24's Dashboard Panel Design
Early Implementation of TR24's Dashboard Panel
TR24's Dashboard in Operation (Driver View)
When I joined Terps Racing in the fall of 2022, the team's previous car had used a fairly simple form of dashboard, consisting of a few LEDs, buttons, switches, and a brake bias knob embedded into a panel which was mounted to the car's monocoque. The team's idea for TR23 involved a new panel design with additional switches and a data display, all mounted to a set of trapezoidal standoffs which positioned the panel offset from the chassis. This design would serve as the basis from which the designs for TR24 and TR25 would evolve.
The issues with the TR23 dashboard became clear as the design was used: the switches were mostly just there for show, the mounting solution sucked and made the panel almost impossible to remove, and the screen essentially never worked. Additionally, the angle of the panel in the chassis made the warning lights (which were critical given that the data display could not serve this function) hidden from taller drivers.
For TR24's dashboard, I collaborated with the team's electronics lead to implement fixes for most of these issues, and added a few extra features to further the car's functionality. For starters, we replaced the trapezoidal mounts for the panel with a set of through-bolts/standoffs which could be removed with an allen key. This allowed the somewhat unique stood-off design of our dashboard to reap the full serviceability benefits that come with not being imbedded in the car's chassis; the panel can be easily removed and electrical components are easy to replace. We also moved the position of the warning LEDs slightly to allow for better visibility for taller drivers, and added a knob to adjust the newly implemented traction control settings for our car (which was also suggested by me). Lastly and most importantly, we replaced the programmable CAN display with a basic HDMI display connected to a Raspberry Pi running our datalogger's built in app. The old display was a massive pain to program; it rarely turned on much less displayed any data. The new display by comparison worked well straight out of the gate, and allowed us to customize the driver's UI by simply plugging in a keyboard and mouse.
This design proved substantially more useful during testing as it allowed drivers to monitor the engine coolant temperature while driving, and it also allowed the realtime detection of misbehaving sensors.
Moving ahead to TR25, we sought to trim the remaining fat on the design by making sure that the placement of every button, switch, light, and screen element was carefully considered, and that there were no extraneous switches or lights. We started by assigning functionality to some of the switches which went unused on TR23 and 24's panels. These switches would now be used to toggle the car's new active aerodynamics system. We added an additional knob to the panel to adjust the car's fuel mix settings (depending on whether we wanted extra power or extra efficiency), and rearranged the LEDs to be closer to the center of the panel so that the knobs would be more accessible on the sides. We also reassigned the oil pressure warning light to be a traction control indicator light. The oil pressure warning was essentially useless (the ECU automatically stops the engine if oil pressure is too low, plus the actual value of the pressure is shown on the display), and the ability for the driver to see whether traction control is interfering while driving is useful for adjusting their driving technique.
We also updated the display to show information regarding the car's new systems (Active Aero, Fuel Mix, Tire Pressures, etc...), taking care to color-code and size different data readouts so that important information could be gleaned while the driver focused on driving. For the finishing touch, I designed and printed a custom set of labels for the dashboard to clearly indicate what function each button and switch performed.
The dashboard is very close to the heart of the car as far as the driver is concerned. A lot of care must be taken when deciding what controls and information should appear on it. Controls that the driver is more likely to use should be more accessible and close to the sides, and information that the driver is likely to view while driving should be large and easy to interpret at a glance. Working on this project has served as an excellent way to learn about the car's various systems, and it also provides an excellent thinking platform to brainstorm new additions that can improve the car's functionality and performance.
TR25's Dashboard Early in Manufacturing
TR25's Custom Controls Label Sheet
TR25's Dashboard Installed
Early prototype of the TR26 dashboard display layout using randomized values. Programmed from the ground up using PyQt5.
For TR26 I wanted to move to a new, custom programmed software that would read directly off the CAN bus for the dashboard. This would be more versatile and customizable overall, albeit at the sacrifice of real-time adjustability which was a substantial benefit of the premade software. It would also run much faster than the packaged software we had been using before, which has been a minor issue with the previous iterations which would sometimes experience stutters. This system also made sense with the increasing prevalence of CAN on our car, as such a system could be more closely tied into the car's CAN bus than the Datalogger (from an output perspective). This would allow us to centralize the data display, alerts system, and controls onto a more customizable and broadly spanning system.
Early features that were added included a popup alert system that could clearly indicate car setting changes, an ambient alert system that would show warnings without obscuring the view of the rest of the dashboard, and a page system to allow for multiple views and layouts.
I also considered moving the gear calculation code from our data unit onto the dashboard itself, as it would allow for more robust calculation compared to the built in script with our data unit.
After designing an initial GUI, I moved to the CAN implementation as the next logical step. I specified all information that would need to me transmitted to the dashboard over CAN, chose addresses at which the various information would be sent, and documented the various units and data types that information would be sent as. I also created a spreadsheet that could keep track of the car's CAN bus as it changed (arbitration ID, byte ordering, units, special formulas, etc...), including action items to mark unimplemented or redundant information on the bus. After implementing this in the dashboard code, it was ready to be loaded onto a microprocessor to get the physical CAN bus set up.
Setting it up on the Raspberry Pi was a mostly straightforward albeit time consuming process. Essentially it just involves installing the OS, setting up auto-login, installing packages and libraries, and then setting up an auto-start script for the graphics environment, CAN bus, and the program itself. It took me about half a day to get through. Once the program was ready and the GUI was verified working, the last step was to connect it to CAN and see if the system works, at which point I could set up a boot partition to protect the SD card from corrupting during an unexpected power-off (which it will see frequently in the car).
Creating the CAN protocol and testing the connection went quite smoothly. The only two issues were a small issue in the protocol on the data unit side (a small typo in the lua script which prevented it from running properly) and a mismatch in the byte-ordering between the DAQ transmission and what the python program was expecting. Once those two issues were addressed, the system worked flawlessly and was ready to be partitioned and tested on the moving car.
The changed display program met very positive feedback from the team, with positive comments on the layout, feature set, or just general appearance. In particular, other drivers on the team applauded the new program's responsiveness compared to the old system, as it updates more smoothly due to much lower overhead from the operating system and a much simpler program. One change that was made later to further improve the smoothness was implementing threading for the CAN bus, so that a large volume of CAN messages would not stall the GUI (we had issues with this when adding a few high rate sensors to the bus for end-of-life testing). The powertrain team was also quite appreciative of the function-based oil pressure warning, as our previous system was generally unable to warn the driver save for a complete loss of oil flow throughout the system.
The physical panel layout was also given a major redesign. We liked the layout from TR25, but we had a few new/different controls that we wanted to add support for. This included:
Additional control for active aero balance adjustment where the wing angles could be manipulated to shift the aero balance forward or rearward.
Implementation of a front anti-roll bar adjustment designed to work in combination with our Vehicle Dynamics team's new front arb design. This would make the anti-roll bar cockpit adjustable while driving.
Replacement of our old brake bias knob with a new digital brake bias adjuster which displayed the current brake bias setting. This was designed in conjunction with a deep analysis of our braking system to find our preferred standard brake bias.
TR26 Panel Design
All of these additional features to the dashboard and its software also warranted an overhaul to the controls and interface aspects of the dashboard as well.
Firstly, the upgraded on-screen ambient warning alerts were a fantastic addition, but there was concern about their visibility in bright daylight. Most of our fall testing for the new display program had been at night where the screen was very bright and there was no glare to worry about, and although we knew that the screen was daylight visible, we worried that the ambient alert system would not be as eye-catching as it needed to be in a daytime testing or competition environment.
Therefore, I decided to implement an array of addressable LEDs as a part of the new dashboard construction. These LEDs would replace the old LED implementation and would allow for much more versatility in terms of the LED color and behavior. The whole philosophy of this new LED array was for it to catch the driver's attention and alert them if they needed to check for issues. With such a complicated car and potentially inexperienced (certainly non-professional) drivers, it would be a bit unreasonable to expect them to memorize every alert or warning light behavior, so the goal was to catch their attention using color and brightness to indicate that they needed to check the screen for warnings.
Similarly to the philosophy for the LEDs, with the increasing number of controls on the car, adding more knobs, switches, and buttons becomes un-sustainable as a control scheme. It leads to extra wiring and a confusing layout for the driver (TR25 had big issues with this, as most drivers were unfamiliar with most of its non-essential controls). To combat this, I decided to move every single adjustable setting in the car onto a pair of rotary encoders. One encoder would select the setting, the other would adjust it. Settings would be kept track of on the dashboard and would be broadcast to their necessary destinations via CAN bus.
This came with numerous advantages as well as a few drawbacks:
Pros
Simplifies the control system to be consistent for all settings - more intuitive
System is more ergonomic, as controls are not distributed all around the dashboard.
Gives an exact digital representation for what settings should be (some settings were calculated from an analog voltage converted to digital via a knob potentiometer, which was noisy)
Centralized the control scheme so adjustments are made and kept track of in one place
Granularity of control can be adjusted to our liking via software.
Allows for the creation of full car setting presets to suit specific drivers, events, or driving conditions
Much more modular system for settings adjustment; new settings can be implemented digitally with no new control hardware.
Cons
If this system fails, then we lose all setting control; need to create a safe redundancy that can override the system
System may be technically slower to adjust certain settings as you have to navigate to the correct one before being able to change it.
Certain settings require conversion to analog in order to be read correctly on the receiving device (this is actually a benefit but it does add extra steps).
Increased overall system complexity
No ability (or at least added difficulty) to remember certain settings after reboot WITHOUT a preset (could be fixed by adding an EEPROM)
Slightly increased weight mostly due to support hardware needed for LEDs (although we also lose weight from needing less control hardware)
After careful planning and consideration with the team (including multiple meetings to discuss fail-safes, controls requirements, etc...), we decided to go forward with this new modular dashboard design. The LED array would be easily modifiable and we could test alert behaviors before committing to them, and the new controls scheme offered enough convenience and modularity that we were willing to work with the drawbacks.
Since the LEDs are digitally controlled, I was also able to implement brightness control so that the array would always be visible. This is important as our competition takes place in the morning/afternoon as do some of our testing sessions, but we also frequently test at night time where the default brightness would be far too distracting (we had this issue with the singular neutral LED from TR25's dashboard which would annoy drivers while they sat waiting in the car between runs).
The alert array was designed to use a familiar layout to our previous year's iteration, but with an additional column to the left of the screen to add symmetry for the column on the right (6 LEDs in total). Behaviors are divided into rows, and the color choice is chosen specifically to reflect what the behaviors mean: the neutral indicator is white as white is a neutral color. The warnings follow the increasing severity convention of yellow, orange, red. Other informational alerts use colors that are distinct and recognizable while not overlapping.
In software, alerts have their own data type which stores the color, whether the alert should blink and how fast, and then a priority level which allows the unit to decide which alert to display if multiple share the same physical position. High priority alerts like oil pressure override everything to make sure the driver won't miss them, even despite the fact that having multiple warnings at once is fairly unlikely. This system makes sure that behaviors are easy to add and change, providing a framework for future development.
Info-Alert LED Behavior Table
In addition to the info-alert LED array, I also included a 10-LED tachometer, as this would help build audio-visual muscle memory for the driver to help time their gear changes, and would generally add accessibility to the car for new drivers. For this, I decided to use a sides-to-center style tachometer where lights illuminate on the sides of the bar first, progressing towards the center as the engine approaches the shift RPM. The choice to do this versus the more common left-to-right style is a little complicated, but the main considerations were how far the driver turns their head for tight corners (symmetry is desirable) and the fact that this style centralizes the shift point which can help improve reaction time. For the color selection, I used a typical green (outer 4) to yellow (middle 4) to red (center 2) color schema as it provides decent contrast at different points in the RPM range. I also set all LEDs on the tachometer to begin blinking a cyan-blue color at the shift RPM, as the large contrast change also helps with the driver reaction. Other designs use different color patterns, such as Formula 1 which often uses green, red and blue, or LMP2 (specifically the Oreca 07) which uses a variety of different color schemes even on the same model of car including green, yellow, red or green, yellow and then all LEDs blue. All of that is to say that the exact tachometer setup is largely down to driver preference, but I tried to choose a setup that would work well for inexperienced drivers to help make it clear when the best time to shift is.
One other small detail to go with this is the inclusion of thresholds based on the engine gear. This will allow the driver to shift at the best RPM for each gear to keep the engine in the power band. It's a small detail as the best RPM does not change by much, but it is technically better than not including it as long as the system isn't disruptive to the driver.
As mentioned before, the dashboard control unit does not simply display information, and the controls on the physical panel are no longer distinct from each other and from the screen. The multi-position settings on the car have all been consolidated to a single processing unit, which broadcasts them to the necessary destination (engine calculations back to the ECU, active aero and front anti-roll settings to the active aero/servo control unit, extra calculations and settings data to the data unit). Due to this, the dashboard controller was renamed to "VMU" (Vehicle Management Unit) for its TR26 iteration.
As an additional bonus, with the implementation of digital to analog converters talking from the dashboard unit to the ECU, the traction control and fuel mix settings could be set more consistently. This also presented the opportunity to send other, more complex signals to the ECU, which was difficult before as the ECU is only able to transmit CAN signals and not receive them. Now that a real-time controller has the ability to send these signals, we have a few new easy opportunities for performance gains.
The first and easiest of these to implement is shift cut by gear. One of the major goals for TR26 was to improve the build quality and reliability of performance components compared to TR25 (which sounds like an obvious goal but we really wanted to prioritize it this year rather than seeking raw performance gains). Shift by gear is a big help to our reliability as it helps with the compromise between shift time and shifting reliability. We have difficulty shifting from first to second gear in particular, which is not helped by the fact that a failed shift between those gears puts the car into neutral. With shift by gear, we can increase the shift cut time for the first to second gear shift to make it more reliable, while at the same time decreasing the cut time for all other gears to gain some performance. I discuss cut-by-gear more on the pneumatic shifting page.
For TR26 we decided to only add cut by gear as an additional input back to the ECU, but we at least considered a few other datapoints to send including steering angle to improve traction control, and shifting commands to automate the shifting process entirely.
Early In-Car Full-System Test
Post-Installation
In-Car During Testing
With the design finalized we moved to manufacturing the panel and assembling the hardware. The main panel is waterjet cut out of carbon fiber with cutouts for mounting all of the hardware accessories. All of the components are spaced with careful attention to detail to allow space for labels and to prevent controls from being too cramped. Even the orientation of the switches was carefully considered, with the VMU kill switch being installed upside-down relative to the rest to make the switch behavior consistent for users (VMU kill is the hardware override that cuts off the VMU from the ECU, and it does this by opening a circuit powering the DACs whereas the other two switches close a circuit to send a signal).
With the wiring connectors assembled I was able to test the electronics and software on the live car which had recently completed its first power-up. There were of course the typical software teething issues causing a few crashes in the software initially, but once those were resolved the interface portion of the dashboard worked as expected. The screen showed data properly, and the LEDs illuminated correctly. Additionally, the CAN output worked as expected, which meant half of the vehicle management portion was also functioning correctly. The VMU to ECU communication had some issues with grounding on the I2C data lines which related to some poor soldering, so that portion had to be remade before it could be calibrated with the ECU's analog inputs.
As we began our testing season the dashboard proved of immediate and critical use. Long story short, the unit's first act on the car during actual running was to prevent catastrophic engine failure:
In our preparation to run the car on a dyno, we performed some brief verification on our set of rollers in the shop. During our first time revving the engine, the dashboard immediately revealed an issue in the oil system via its oil pressure warning. We were quickly able to observe a sort of 'cap' in the oil pressure built by the engine, which was below the level we had deemed acceptable for oil pressure (oil pressure capped at around 40PSI when we normally expect it to exceed 60 at 10,000 RPM). Investigation revealed an improper seal on the oil pump which prevented oil from flowing properly.
This allowed us to have a successful and issue-free trip to the dyno the next day, the footage of which you can view on the right.
Following our test on the dyno, we conducted a brief shakedown of the car to bed the brakes. During this test the remainder of the dashboard's alert system was verified working. We idled the car to the testing site from our workshop where we verified that the rolling neutral alert worked as expected. Then, when driving the traction control alert revealed that the traction control system was activating when it was not supposed to (it had not been calibrated yet), leading us to temporarily disable it. Lastly, the fuel pressure warning activated during cornering after some running. Since we had not filled the car up since the dyno, this was a good opportunity to get an idea of when sloshing would occur in the fuel tank, an issue our previous fuel tank struggled with and against which the new tank required validation. We immediately stopped running and brought the car back to the shop to measure the remaining fuel, which was found to be only 0.25L. Needless to say, this provided much needed validation on the new fuel tank design.
TR26 Dyno Pull (WOT)
Aside: engine produced 74 BHP at 12,800 RPM. The dashboard allowed another team member to run the car on the dyno while I worked on the tune. A combination of a smoother fuel table and a redesigned intake meant that the car made 15 more horsepower at 8,000 RPM compared to the previous year, despite making slightly less peak power.
This is where I will take a brief aside to discuss the process of developing the gear calculator. The original classifier I used simply divided RPM by the vehicle output speed, then checked if it was close enough to a known transmission ratio (non-parametric buckets). This system worked okay, but there were two main issues: signal noise (from transmission shock loads during gear changes, throttle changes, or braking), and an anomaly in the output shaft speed sensor.
I took the data from our first few testing sessions into MATLAB to analyze what was going on, and the first thing I found was that the data anomaly was actually a sort of overflow. After around 2500 RPM of output shaft speed, the signal would wrap back around do 1250 RPM. I solved this by simply checking if the car's wheel speeds were above a certain threshold, and adding back 1375 RPM if it was less than 2000 RPM at or above that speed (I will explain why 1375 instead of 1250 shortly). Doing this resulted in a nice continuous graph for the output shaft that fixed this overflow issue from a software side, which was really the only solution due to the lack of documentation on the data types on the data unit.
For the signal noise, I tried a few different things to counteract this. First, I tried a moving window average, but this didn't end up working very well since it couldn't debounce the signal when the transmission and engine were settling after a shift quickly enough and would fluctuate. From intuition, I came up with another type of filter I would try, which uses the formula
EWMA = EWMA(1 - (1/K)) + new_sample(1/K)
From my usage of the variable name EWMA (and the formula), you may be able to tell that this actually an Exponentially Weighted Moving Average, which I learned after I looked up the name for the formula I had derived. Even before doing any research, there were two things I liked about this filter.
It technically considers ALL of the previous data samples, but gives more weight to the newest one (I initially named this a "pull filter" because the new samples pull the filter to converge at a new value).
It always runs in O(1) time, even with a very small weight (large K). This is better than the moving window average which runs in O(K) for a K sample window.
I build a System-In-Loop simulator in MATLAB where I tested these different filter ideas using real car data we gathered from our first test with shifting. I quickly realized that K was a tradeoff between response time and accuracy, and after tweaking the bucket thresholds and trying different values of K, I was eventually able to end up with a highly accurate classifier that generalized pretty well to any data file I tried while still responding pretty fast (200-300ms or about 4-6 ticks of the dashboard). It makes a few mistakes here and there, but in all of the actually important areas (mainly during acceleration but also during downshifting) it is spot on. The mistakes it makes are largely due to shock loads in the transmission after a failed shift. Below you can see the graphs of how the classifier does with real car data. (Note that the graphs include my corrected output shaft values!)
Graphs of Calculated Transmission Ratio, Speed, RPM, Output Shaft, and TPS vs Time with Gear Color Axis
Zoomed-in View of Previous Graph, showing upshifts from 2nd to 4th and back down to 3rd
As we continued testing, we collected footage from onboard the car to review. Here is some of that footage.
First Test of new Gear Calculator + TC Alert
Onboard Footage Showing Tachometer
Full Autocross Testing Lap