Active aero that reacts to grip loss before it happens
I've had this idea for a while now, and it stems from back when I first read about a technology called flexfoil (https://www.flxsys.com/flexfoil). I liked this concept, and began thinking about ways to best utilise it on a car, ultimately coming to the idea of a wing that can completely morph its shape. One possible use-case was a "perfect" DRS system that would allow a wing to both align to local flow and reduce its camber to 0. I didn't pursue this option though, as this was both extremely complex, and having "perfect" DRS is probably not ideal for stability. The next series of ideas revolved around flexible diffusers that could respond in 3D shapes to different roll/pitch angles, ride heights, and slip angles. The problem then was the sheer amount of empirical and/or simulation data needed to predict the required shape for these several thousand potential scenarios. Eventually I abandoned the overly-complex wing and diffuser designs that would simply add too much volume and weight, but the ideas of ways to avoid relying on existing data for active aero kept coming. It didn't take long to arrive at a pretty obvious solution in live pressure readings.
Most active aero systems on existing cars rely on some combination of sensor readings for forces, moments, yaw rates, and suspension readings, and combine them with driver inputs to spit out the ideal total downforce and aero balance for that instant. This method has a few limitations though.
It relies on the car entering a state that requires a shift in aero characteristics before making the appropriate changes
It can't consider external, or otherwise unexpected influences, such as:
wake from other vehicles ahead or alongside
wind
aero or bodywork damage
limited capacity to respond appropriately to adverse VD scenarios (driver error, or an unsettled car from bumps, curbs, or crests)
By incorporating live pressure readings, the aero performance can be monitored live and respond to its own changes rather than just trusting that the car is doing exactly what the onboard computer assumes. It also measures changes due to external factors at the instant they occur, i.e., before the car enters a state where it relies on a pre-determined active aero shift only to find the car doesn't behave as expected because the front wing is 25% down on downforce from dirty air, and rapidly fluctuating from the turbulent nature of the wake and the differing line taken by the car ahead.
A setup that incorporates this functionality would not need to differ fundamentally from normal active aero. It would work with only one moving wing (or wing flap element), although the ideal would be to have adaptability at the front and rear, to allow for control of both total downforce levels and aero balance simultaneously. Adaptive diffuser expansion is an additional option, although the effectiveness of this depends on the size and location of the rear bluff wake region, rear wing interaction strength, the presence of any high energy flow over the top of the diffuser roof, and the reliance on vortices for local suction.
Installing pressure sensors and pneumatic tubing is also a reasonably easy task, so the total mechanical aspect of the system is very achievable. The complexity comes with the control systems, how the respond to different scenarios, and how driveability/predictability is maintained. I'll come back to that.
This concept is also naturally fail-safe, as the active aero will respond not only to the effects of aero damage on downforce and balance, but if the activation of one wing fails, the other adaptive elements on the car will respond accordingly. If a pressure sensor fails or a tube disconnects, all it takes is a check for frozen or ambient pressure readings, and that sensor can be removed from consideration automatically.
The required number and location of pressure taps on the car can be carefully optimised through CFD, and pilot locations can be tested in a wind tunnel or through track testing. Locations should target areas of high pressure magnitudes (positive or negative), biased towards locations at the front and rear of the car that contribute most to the total pitch moment. Locations should also be representative of large areas of similarly-behaving airflow/pressure distribution where possible. Large longitudinal-vertical surfaces could also be considered for calculating yaw moments to enhance aero response fidelity/optimisation. Pitot-static and yaw probes aren't necessary but are likely to be desired equipment for the sort of vehicle that would have this type of setup anyway, and so could be used to provide further VD fidelity and context to the tap data. Here are some example locations:
(More on this car design - see Project 04 )
Locations such as the wings and tea tray should have taps on both the pressure and suction sides. The wings in particular would have a higher density of sensors due to their significant influence on total pitch moment, and their sensitivity to small changes in angle-of-attack and available flow energy. Positioning some taps near supports or endplates may also be beneficial to pick up any effects from changes to cross-flow/yaw angle. In this case, I've ignored the highly curved cockpit shape and the high pressure that will sit in front of the intake, as these are all pretty close to COG and so won't significantly influence the car's balance regardless of their magnitude.
Each tap location will have an associated representative area (converting pressure to force) and a moment lever (converting force to moment), with sign (+/-) depending on the pressure and location forward/aft of COG.
This diagram wasn't really needed as it's an obvious concept, but I love the side profile of this car and this was an excuse to use it. Although not explicitly illustrated above, the surface normal at each tap location needs to be considered when setting its associated pitch or yaw moment lever distance.
The control logic for the wings requires a combination of live pressure readings, and the more typical VD and driver input data. Reaction to live pressure readings is pretty simple: all the wings need to do is adjust their downforce level to maintain a pitch moment that corresponds to the instantaneous desired aero balance. This will all be managed through a control loop such as a PID system that reacts to a difference between the current moment estimate, and the ideal moment. The only slight complexity is introduced with the decision of which aero element/s to adjust, and in which direction. The real complexity comes from figuring out what the desired aero balance at any given instant should be. This is where the more typical sensing methods come in; their job being to know exactly what the vehicle is trying to do. Scenarios/decisions include:
Braking and accelerating
Splitting downforce between front and rear axles depending on brake bias, and the number/location of driven wheels. Braking in particular should favour an increase in total downforce when deciding which element/s to adapt
Steady state cornering
What is the required total downforce level? If the car is not grip-limited at the current downforce level, then reduce downforce to reduce unnecessary drag (I'm calling this "DRS", but with a sliding scale rather than just being on or off). If imbalance occurs, a balance adjustment can be made by either backing off one element, or increase downforce on another (assuming 2 or more adaptable elements), providing options to independently adjust total downforce as required
Yaw moment
More grip is required on the front axle for a snappy turn-in, then the grip requirement transitions to the rear throughout the corner until it is maximised when the rear is used to slow the rotation of the car. See the below image. Consideration is also required for blending with braking and acceleration requirements at entry and exit. Key here is to not reduce downforce, so this re-distribution of grip should only occur if the wings are already in a state of non-zero adjustment (whether by air pressure measurements, or by DRS). I realised after I'd written the code that I was allowing non-zero yaw moments to lower total downforce, but since this had no practical effect for the static model-scale tests I was running, I didn't change it.
Wind
As well as being able to adapt to balance offsets caused by wind, having pressure taps on vertical surfaces means an estimate for yaw moment due to the cross-flow from wind and/or vehicle slip angle can be obtained. If significant, this can be subtracted from the required yaw moment calculation during cornering, and the balance adjusted accordingly.
Lost or gained downforce
In most cases, it is assumed that the effects of wake, wind, or damage will reduce total downforce, and favour a bias towards aero balance adjustments that increase total downforce if possible. In rare cases however, there may be an unexpected increase in downforce, such as a car pulling alongside and creating downwash from its wings. In this case a balance adjustment that reduces the gained downforce is preferred if the car is not in a grip-limited state. Differentiating between lost or gained total downforce isn't possible with a single moment calculation, so for this functionality a reference to individual pressure magnitudes would be required to compare against an expected total downforce value for the current airspeed.
My plan was to run a model-scale test of the idea. This was partly to be a proof-of-concept, but mostly as an excuse to use the wind tunnel again, and as a project to learn the basics of python, dealing with serial communications, and basic control loops. I had avoided coding throughout school, and control systems was only added to the engineering degree after I graduated, so I didn't have any experience in either (besides Matlab, R, and Inventor iLogic on the "coding" front). Communications and live data are very much related to my desire to work in a position dealing with test planning, data collection, and data analysis, so I figured I should probably learn how data is actually collected instead of having to rely on someone handing me pre-built, pre-coded, and pre-connected data collection equipment (especially if it goes wrong or I decide I want some functionality changed or added).
As I mentioned in Project 04, I wanted a cool-looking model to set up the active aero on, even though the size of the wind tunnel meant the model would be too small to achieve flow characteristics even remotely close to an accurate representation of a full-size car. Given I was going to be dealing with ultra-low Reynolds numbers anyway, I decided I'd limit the scale even further based on my 3D printer bed size, so I only had to print two parts. The main considerations then were having sturdy mounts for the wings, and a place to install some cheap servo motors to actuate the wings.
For simplicity, I made the rear wing one single "element" (more of a rectangular prism than an aerofoil, for easier printing), while the adaptive element at the front was a flap aft of the main front wing/splitter hybrid. Given I was dealing with laminar boundary layers, I installed all the pressure taps (three at the rear and three at the front) on positive pressure surfaces. I also ensured good front under-nose extraction in the model design to avoid unwanted pressure build-up as a consequence of the low Reynolds numbers.
One advantage of choosing not to worry about scale-accuracy is I didn't have to put too much effort into cable/tubing routing, which made post-assembly adjustments easy.
Here's the bare model:
And here are various shots of the car with cabling and tubing attached (4 of the 5 images are taken in the wind tunnel). The front extraction and body undercut made for very convenient cable-routing options. Not so ideal was the position of the rear servo motor, which in hindsight should have sat slightly lower to reduce the angle of the connecting wire as well as being a bit more discrete. The black and silver components under the car are the load-cell on the underside of the wind tunnel, which I didn't use for these tests.
Static pressure tap locations are shown below. The three at the rear all move with the rear wing, while the three at the front surround the flap element to avoid undesirable tube routing that would place additional stress on the servo motor if they were attached to the flap itself.
There was no reason why this idea wouldn't work; the real challenge was in the VD and driveability which obviously wasn't being tested here. It's more of a demonstration. For that reason, I wanted to include a couple of settings in the control logic loops that would emulate different VD requirements such as adjusting the ideal available yaw moment or the level of grip-limitation via an adjustable "DRS" system.
The first step though was to connect everything up and get it all working and talking to each other.
First contact was me interfacing directly with the microcontroller software, dragging the positional sliders. For $5 servos, they have pretty good response and no noticeable delay or backlash.
The next step was attaching the wings and connecting wire and finding the servo positions that give the required maximum and minimum wing angles. Attaching the pneumatic tubing to the rear wing at this stage also provided a test of sufficient torque to overcome the slight resistance of the tubes to bending.
Video - Rear wing range of motion
Conveniently, thanks to the adjustable arm length on the servos, the ideal angle change for both front and rear wings was achieved with equal servo motion. The ideal range of motion of the front wing was narrower than the rear, as the front wing was surrounded by the nose and the wheel housings, meaning it had the potential to create an almost perfect seal and produce pressures near Pstag. This meant it was much more sensitive to a.o.a. than the rear wing.
This was all pretty simple. Opening the connection was a single line of code, and sending commands was equally simple thanks to a python function library for the micro controller. Despite the simplicity, I was still expecting hours of failed attempts, so when it worked first try it was a pleasant surprise. The first script stepped each servo through its wing-motion range in 2 degree steps every half second, testing communication, angle conversion, and giving me time to react and stop the code if something went wrong.
Thankfully this was equally as simple. The only additional complexity was having to parse the incoming serial values into individual values for each sensor. The microcontroller on the PCB outputs at a baud of 1,000,000, hence the decision to use a laptop to control everything. A cheap Arduino might not have cut it, and I wasn't going to buy a more capable one just to have a bit more portability. Being able to adjust code on the fly was a big plus anyway.
To combat noise, the incoming data for each sensor was averaged over a short period (initially 0.025s) before converting to a "moment" value. The averaging window had to be kept as small as possible to maintain the advantage of this pressure-based system (that is, "instant" response to required balance shifts).
while True:
values_ch11 = []
values_ch12 = []
values_ch13 = []
values_ch14 = []
values_ch15 = []
values_ch16 = []
start_time = time.time()
#Get rid of any data that's built up (should happen naturally but just to be safe)
ser.reset_input_buffer()
#Gather Pressure Data
while (time.time() - start_time) < avg_window_slider_val:
if ser.in_waiting:
raw = ser.readline().decode('ascii', errors='ignore').strip()
values = raw.split(',') #get individual serial channel values
if len(values) = 20: #ignore lines with any missing data
values_ch11.append(int(values[11]))
values_ch12.append(int(values[12]))
values_ch13.append(int(values[13]))
values_ch14.append(int(values[14]))
values_ch15.append(int(values[15]))
values_ch16.append(int(values[16]))
#Process Pressure Data
avg_F = (sum(values_ch11)+sum(values_ch12)+sum(values_ch13)) / (len(values_ch11)*3)
avg_R = (sum(values_ch14)+sum(values_ch15)+sum(values_ch16)) / (len(values_ch14)*3)
momF = avg_F*lvrF
momR = avg_R*lvrR
#Single moment levers for all senors, as distance from COG is equal
For reference, this is the raw output of the pressure board with me gently pressing on the two ports of each of the 6 sensors being used. Noise levels are effectively non-existent from the sensors themselves, with the only significant noise coming from actual fluctuations in air pressure. How much of this is true compared to how much occurs due to/in the static tap opening is currently unknown, but even these noise levels are typically low, so there hasn't been any need to dive deeper.
At this point I sat down to learn about PID controllers. It turns out there wasn't anywhere near as much to learn as I thought, as it's just a matter of taking P, I, and D, which are all simple calculations, and adding them together.
I set up the main control loop with proportional and integral components, with a small dead zone inside which P was automatically set to 0. Throughout the testing, the gain for P (kp) was gradually increased to improve system response until it was almost an on-of-off reaction, limited only by a maximum angle-change per control loop cycle threshold. Disabling P altogether did lead to some scenarios where the wing would get stuck in a constant see-saw of overshooting, so keeping a finite kp was still necessary. The purpose of I was to allow smooth fine-adjustment of the wing angle when in the dead zone, avoiding the sudden jumps and jitters that would result from keeping P active (due to the small amount of noise). Outside of the dead zone, I was superfluous as most adjustments happened at the maximum rate anyway due to the high kp value.
A finite value of kp meant the response rate of the wings were effectively a function of airspeed, as lower moment offsets are expected at slow speeds (hence a lower value of P+I), while a larger angle delta is required to counteract them, resulting in slower response. Solutions are to either ignore this under the assumption that perfect aero optimisation at slow speeds yields negligible advantage, or to tie kp and ki values inversely to the square of airspeed.
A derivative component wasn't necessary thanks to a combination of the high control loop cycle update rate (required anyway for effective system response), and the inbuilt positional control in the servo controller.
The units in the plot below don't reflect the final system response, as this was before kp was increased massively (a delta of 20 was achieved with ERR as low as 200). E_window was also adjusted. The +/- I values are not exclusive, and are intended to be examples. The discontinuity at the E_window interval bounds is intentional, to provide snappier response.
#Set up Proportional control
ERR = (momF-momR) - 500*(YawMom_slider_val) - 185 #Nm (Last value required tuning in wind tunnel prior to testing)
Kp = Kp_slider_val
if abs(ERR) <= E_window_slider_val:
P = 0
else:
P = Kp * ERR
#Set up Integral control
now = time.time()
I_window.append((now, ERR))
while I_window and now - I_window[0][0] > I_window_slider_val: #check age of value/position 0 (time of oldest sample) against I window
I_window.popleft() #delete old data outside current window
I_sum = sum(e for n, e in I_window)
Ki = Ki_slider_val
I = Ki * I_sum
#Implement PI control
control_function = P+I
#Adjust Target Angles
delta = max(-step_max_slider_val, min(control_function, step_max_slider_val))
The resulting value of P+I was then fed into a list of logical statements to determine which wing should move the calculated amount, and in which direction. Note that in the code below, "moments" are given units of Nm, but they are not really moments nor are they in Nm, as there was no conversion from serial data to pressures to forces, as this was superfluous for the model-scale experiment.
if delta > 0:
if angle1 > a_min_DRS and angle0 == a_min:
angle1 = max(angle1 - delta, a_min_DRS) #Decrease angle1 by delta, from a_max towards a_min_DRS
elif angle1 == a_min_DRS and angle0 != a_min_DRS:
angle0 = min(angle0 + delta, a_min_DRS) #Increase angle0 by delta, from a_min towards a_min_DRS
elif angle1 <= a_min_DRS and angle1 != a_min and angle0 == a_min_DRS:
angle1 = max(angle1 - delta, a_min) #Decrease angle 1 by delta, from a_min_DRS towards a_min
elif angle1 == a_min and angle0 >= a_min_DRS:
angle0 = min(angle0 + delta, a_max) #Increase angle0 by delta, from a_min_DRS towards a_max
else: #should only occur when lateral acceleration/DRS target is changed
if angle0 > angle1:
angle1 = a_min_DRS
angle0 = max(a_min_DRS-(angle0-angle1), a_min)
elif angle0 < angle1:
angle0 = a_min_DRS
angle1 = max(a_min_DRS-(angle1-angle0), a_min)
else:
angle0 = a_min_DRS
angle1 = a_min_DRS
elif delta < 0:
if angle0 > a_min_DRS and angle1 == a_min:
angle0 = max(angle0 + delta, a_min_DRS) #Decrease angle0 by delta, from a_max towards a_min_DRS
elif angle0 == a_min_DRS and angle1 != a_min_DRS:
angle1 = min(angle1 - delta, a_min_DRS) #Increase angle1 by delta, from a_min towards a_min_DRS
elif angle0 <= a_min_DRS and angle0 != a_min and angle1 == a_min_DRS:
angle0 = max(angle0 + delta, a_min) #Decrease angle0 by delta, from a_min_DRS towards a_min
elif angle0 == a_min and angle1 >= a_min_DRS:
angle1 = min(angle1 - delta, a_max) #Increase angle1 by delta, from a_min_DRS towards a_max
else: #should only occur when lateral acceleration/DRS target is changed
if angle0 > angle1:
angle1 = a_min_DRS
angle0 = max(a_min_DRS-(angle0-angle1), a_min)
elif angle0 < angle1:
angle0 = a_min_DRS
angle1 = max(a_min_DRS-(angle1-angle0), a_min)
else:
angle0 = a_min_DRS
angle1 = a_min_DRS
else:
if angle0 > a_min_DRS and angle1 == a_min:
pass
elif angle0 == a_min_DRS and angle1 != a_min_DRS:
pass
elif angle0 <= a_min_DRS and angle0 != a_min and angle1 == a_min_DRS:
pass
elif angle0 == a_min and angle1 >= a_min_DRS:
pass
else: #should only occur when lateral acceleration/DRS target is changed
if angle0 > angle1:
angle1 = a_min_DRS
angle0 = max(a_min_DRS-(angle0-angle1), a_min)
elif angle0 < angle1:
angle0 = a_min_DRS
angle1 = max(a_min_DRS-(angle1-angle0), a_min)
else:
angle0 = a_min_DRS
angle1 = a_min_DRS
Visual summaries of the above code are included below after introduction of the UI and its controls.
The UI consists of controls for both emulation of different vehicle scenarios, and for tuning the control system response.
Control system sliders:
kp
ki
"Damp Zone" (E_window)
"Averaging Window" (the time period over which serial pressure data is collected and averaged for each update cycle
"Integral Window" (the time period over which values of ERR are collected and summed to determine the value of I)
Vehicle scenario sliders:
"Yaw moment target" (unitless multiplier to adjust the ideal aero balance, for optimising corner entry and exit behaviour). As mentioned earlier, this was an over-simplified implementation that allowed the unwanted reduction of total downforce.
ERR = (momF - momR) - 500 * YawMom_slider_val
"DRS active level" (unitless multiplier for the "neutral" wing angle to adjust the overall total downforce target)
a_min_DRS = a_min + (a_max - a_min) * DRS_slider_val
Note that in the code, "min" and "max" refer to servo angles, and are inverse to the maximum and minimum wing angles of attack.
I added a pause button, which reset the wing angles to their maximum angle of attack and set kp and ki to 0. This also doubled as an emergency stop while the UI was the active window, in case my only-briefly-tested code tried to send a servo too far, risking overloading the motor or breaking a mount.
Also included were live system and variable status plots, operating on a five second moving window.
Current servo angles
It wasn't always easy to tell where the wings were in their travel (especially the front), so being able to see this live was very handy
ERR value
Shows a trace of raw moment offset values calculated from the averaged pressure sensor data
P and I plots
Shows the live values of P and I to help with fine-tuning and understanding their different contributions
delta plot
Shows P+I clipped to the maximum allowed angle change per cycle. This is transferred directly to one or other servo depending on the result of the above logic checks.
The image below summarises the first two top-level logic checks (i.e., when delta !=0). The diagram on the left shows the two wings and their three key angles, and the diagram on the right shows how they are adjusted based on delta, and their current position. Current positions are shown as a red line (when angle exactly equals one of the three key positions), and/or a shaded region which is valid for any angle within that range. In the case of this diagram, I've swapped the signs so that positive values imply an increase in a.o.a., which is more intuitive.
For the case when the DRS activation level is adjusted, the wings respond by shifting to the new neutral position while maintaining their current angle difference to each other. This does not guarantee the same balance will be kept, but it acts as an initial guess after which smaller adjustments can be made by delta if necessary, all within a split second. The image below shows one example case, where the DRS value is increased from ~25% to ~75%, and wing 1 is increased above the initial neutral angle.
This functionality all theoretically works fine, but there are some improvements that could (and should) be made to improve operation on a full-scale implementation where VD behaviour is critical.
Currently, the system follows a stepped approach (one wing moves at a time, centred around the neutral angle) as shown above. This regulates total downforce while the wings are in-motion better than adjusting one wing fully, and only then beginning to move the other. This works, but is not perfect and relies on the quick actuation of both wings to avoid noticeable changes to total downforce. A better solution would be to adjust both wings simultaneously if delta exceeds a specific value. This would benefit from the addition of an aero map to estimate the rotation required by each wing to target a reasonable initial guess quickly. Without the step-wise logic though, a reference to pressure magnitudes would be required to avoid having more than one valid "solution" to maintain balance.
A simpler alternative that maintains the clunkier step-based approach but would still reduce transit time significantly is a carry-over of unfulfilled delta value from one wing to the other (if one wing hits its angle limit before moving through the full requested angle delta). No carry-over occurs in the code as-tested, meaning there is up to a full cycle of delay between one wing stopping and the other wing starting to move. Motion of the second wing could perhaps start even a couple of cycles beforehand if P is above a threshold, to eliminate the delay from the acceleration of both motors.
Other implementations would take the form of added functionality for adjustment to the ideal ERR value depending on acceleration, braking, cross-flow induced yaw moment, and obviously converting all the VD-related parameters from emulating sliders to actual live calculations from other vehicle data.
The other thing I'll point out is that with DRS = 0, any adjustment to balance will reduce total downforce. This should still help by creating a more predictable car, but the key idea is that with an automated DRS that maintains balance, cars can be designed/set up with very aggressive wings regardless of the track layout (particularly if they are multi-element). This means that there will be a significant amount of time where DRS is at least somewhat active, where extreme downforce is unnecessary and the extreme drag unwanted, providing additional wing angle to utilise when making these balance adjustments.
After bench-testing to tune everything as well as I could without real pressure values from airflow, all that was left was to put it in the wind tunnel.
I made some "air blocker" tools that I could use to interact with the flow near the wings to trigger pressure differences, which consisted of a piece of wire with two interchangeable attachments: A small circular shape that could be used to interact with individual pressure taps, and a larger rectangle to allow interaction with all three front or rear sensors at once.
Here's the external setup:
The first task was to pick an airspeed. I went with 8m/s, reasoning that since I wasn't going to have realistic flow anyway, I might as well go slow to avoid the risk of detaching cables or wings. The pressure sensors gave very usable data even at this low velocity. Much faster than this and I would have had to secure the tubing and cables more effectively.
Next, I needed to get a value for ERR to calibrate the true neutral value. Obviously, the aero on this model isn't going to behave like a real car, nor do I have anywhere near enough pressure taps on it to accurately determine an overall moment, nor am I assigning a representative surface area to each pressure reading (so I'm not even calculating a real moment). Instead, I just set both wings to their maximum angle or attack and subtracted the resulting value for ERR from the ERR calculation in the code. To check that the sensitivity of the pressures to wing changes was suitable, ERR was recorded for each of the 4 extreme wing position combinations, including the range of observed noise ("full front bias" refers to the front wing at max a.o.a., and the rear at min a.o.a.. The opposite it true for "full rear bias"). Luckily, my estimate on how much each wing should be able to move was perfect; the median value for ERR when both wings were at their minimum angle was within 3% of the "both max" value.
This test also allowed me to tune the averaging window parameter, which I increased from the initial 0.025s to 0.035s to reduce noise slightly. I wanted a minimum update rate of 20hz, so this slight increase was still meeting that requirement. Implementation of more pressure sensors may help reduce the noise without needing to slow the update rate. I expect somewhere in the region of 50 pressure readings would be required for reasonable aero balance estimates across a whole full-size high-downforce car. Too few and the system could be detrimental overall due to inaccurate estimates.
For reference, in all UI videos included below, the absolute maximum range for both Angle0 and Angle1 is 90-144.
This was the simplest test to perform, as all I had to do was drag the UI sliders up and down.
For DRS adjustments the wings should theoretically follow the shifting neutral-angle target, with occasional small adjustments to suit changes in balance due to their new angles, and general unsteadiness in the airflow (the wind tunnel doesn't offer the cleanest of flows, nor perfectly steady velocities). The discrete nature of the UI slider meant the wing angles were constantly catching up and then lagging behind the target value as the slider was dragged, so the response of the wings was quite jagged. The effect of the initial guess not always being perfect can be seen as occasional small spikes, which are exaggerated due to the discrete behaviour mentioned. Notice how the front wing does not quite back-off fully to maintain balance, as expected by the slight offset in ERR value observable in the plot above.
The yaw moment adjustment was even simpler, as it just changed the target ERR value which behaved as expected. The effects of each of these within the UI are shown in the video below (DRS first, then yaw moment). The plots also appear more jagged in the UI than the actual data due to their update rate being only about once every three control cycles.
Video - DRS and yaw moment target adjustment (UI)
Test consisted of alternately blocking different pressure ports from oncoming air flow and observing the results. By only blocking one at a time, the magnitude of the resulting moment offset was kept relatively low. Initially, this led to slow wing response until kp was later increased significantly, at which point I was able to achieve what I thought was some impressive nuance for low-velocity flow by slowly moving the position of the blocker.
Video - Small air blocker (front wing) (Wind Tunnel)
This was functionally the same as the small air blocker test, but by blocking airflow to multiple taps at once, the reaction was more substantial which gave more obvious visual changes. The UI recording shows the effect of first blocking the rear wing (three times), then the front wing (twice). Between the adjustments, the position of the blocker still affected the flow unless completely withdrawn from near the car. The effect of this can be seen as general background fluctuations in wing angles, and occasional inverse spikes where the blocker passed above or behind the wing, contributing to brief increases in positive pressure instead of blocking the flow. ERR does not maintain a value close to 0 at all times here, due to the excessive/unrealistic effect of completely blocking flow to a wing; even full balance adjustment is insufficient to counteract the resulting offset.
Video - Large air blocker (UI)
Like the previous test, but with a non-zero DRS value. This meant that the wing affected by the lost downforce had capacity to increase a.o.a.. The current stepped response means that the front wing does not decrease its angle until the rear wing has reached its limit (assuming delta is still non-zero at that point, else the front wing would not need to move at all), which allows improved accuracy and less risk of overshooting, but significantly increases total adjustment time. It's therefore not the ideal method, but was used here in this first series of tests for simplicity. In the wind-tunnel videos below, the rear wing is blocked and can be seen increasing its angle, after which the front wing can be heard to move as it decreases. The order is inversed when the blocker is removed, to favour higher total downforce whenever possible.
In the front view video, the second time the blocker is introduced, it first sits above and behind the wing slightly, triggering an initial decrease in angle. It then slips off the wing, briefly covering then revealing a small section again, before being steadied into the correct position, causing small corrections in the servo (watch the servo itself rather than the wing). My first thought was it was just a bad/delayed response, until I looked more closely at exactly how the blocker was moving, and how the servo was responding. The response time to everything that is happening actually appears instant; it's only the changeover between front/rear actuation that delays the overall process. After noticing this, I think this is my favourite video that I captured during these tests, as it does a great job of showing both the reaction time, and the fidelity of the response with no noticeable jitter.
Video - Large air blocker (rear wing) top view (Wind Tunnel)
Video - Large air blocker (rear wing) front view (Wind Tunnel)
The UI shows the stepped and inverse response between the front and rear wing angles, and how they both operate about an intermediate "DRS"/neutral value.
Video - Large air blocker DRS (UI)
The effect of this slider is to offset the target ERR value, altering the preferred balance response from the two wings. As mentioned earlier, this is not a correct implementation of this functionality, but it has the expected effect nonetheless, of the wings being offset even when no additional influence/disturbance is acting.
Video - Large air blocker yaw moment (UI)
Both wings now operate about different neutral values (offset from each other, and from their maximum a.o.a.). When there's clean airflow, this seems to be a value of around 120 for Angle0, and 100 for Angle1.
Video - Large air blocker DRS yaw moment (UI)
Nothing to say here other than I waved the blocker around wildly. This did reveal some slight delay in wing response, but was still quite impressive, and a torquier motor would improve this further. This level of rapid adjustment is not realistic either; by rapidly varying between no and near-complete blockage, I'm asking the wing to move through 26 degrees in a tenth of a second or less. In a track scenario, turbulence oscillations would be much less dominant, and the wing may only need to fluctuate through a few degrees, taking much less time and allowing it to more easily keep up.
Video - Turbulence (Wind Tunnel)
While playing around with the DRS and yaw moment sliders towards the end of testing, the wire connecting the front wing to its servo came off. This meant the front wing was stuck at about 75% actuation. This gave an accidental example of the damage-adaption capability of the system: when the DRS and yaw moment sliders are returned to 0 at the start of the recording, the command to the front wing is for max a.o.a. (or at least within a couple of degrees depending on any small corrections required), but it's not getting the pressure it expected and so the rear wing remains backed-off to maintain balance even with the "damage". The pause button functionality is also demonstrated.
To be honest, I have my doubts that this system would actually provide enough benefit in a driver-friendly way to justify installation on a real car. It was a lot of fun to conceive, build, and program though, and as I said at the start, the concept was really a chance to learn a few new things. For a car that already has active aero, it could still be an interesting addition given there's not any retrofitting required other than the pneumatic tubing and some circuitry (assuming the existing actuation motors are fast enough). Maybe one day I'll have the time and money to make a full-scale test to get a proper conclusion...