<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tuning - BlownByTwins</title>
	<atom:link href="https://blownbytwins.co.uk/category/tuning/feed/" rel="self" type="application/rss+xml" />
	<link>https://blownbytwins.co.uk</link>
	<description>Just a tale of one man and his cars...</description>
	<lastBuildDate>Fri, 18 Sep 2026 16:07:56 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://blownbytwins.co.uk/wp-content/uploads/2023/05/cropped-wp20128381-1-32x32.jpg</url>
	<title>Tuning - BlownByTwins</title>
	<link>https://blownbytwins.co.uk</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Erratic Shifts and Idle Overfuelling on the 2JZ: Finding a DBW Feed-Forward Fault</title>
		<link>https://blownbytwins.co.uk/cars/mk4-supra/dbw-feedforward-fault/</link>
		
		<dc:creator><![CDATA[john]]></dc:creator>
		<pubDate>Fri, 18 Sep 2026 16:07:52 +0000</pubDate>
				<category><![CDATA[Engine Management]]></category>
		<category><![CDATA[Mk4 Supra]]></category>
		<category><![CDATA[Tuning]]></category>
		<category><![CDATA[2jz]]></category>
		<category><![CDATA[air model]]></category>
		<category><![CDATA[emtron]]></category>
		<category><![CDATA[feedforward]]></category>
		<guid isPermaLink="false">https://blownbytwins.co.uk/?p=1156</guid>

					<description><![CDATA[<p>Inconsistent torque, delivery and shifts, with nothing obvious in the log. Working outwards from the symptom into the DBW loop, and the arithmetic that showed the integrator was spending its whole authority cancelling a feed-forward error.</p>
<p>The post <a href="https://blownbytwins.co.uk/cars/mk4-supra/dbw-feedforward-fault/">Erratic Shifts and Idle Overfuelling on the 2JZ: Finding a DBW Feed-Forward Fault</a> first appeared on <a href="https://blownbytwins.co.uk">BlownByTwins</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">The car was giving me inconsistent torque readings, inconsistent delivery, and downstream of both, inconsistent shifts. And on rarer occasions the car would overfuel like crazy when returning to idle. It&#8217;s done this maybe 6-8 times in 4000 miles of usage. Nothing in the log made the reason obvious.</p>



<p class="wp-block-paragraph">This is how I worked outwards from the symptom until the log told me where to look, and what the arithmetic said once I got there.</p>



<h2 class="wp-block-heading">Ruling things out</h2>



<p class="wp-block-paragraph"><strong>Status: Verified</strong></p>



<p class="wp-block-paragraph">I expanded the log window out and walked the closed loop items one at a time. First question: was idle control intervening during the downshift? It was not. Verified and set aside.</p>



<p class="wp-block-paragraph">The next thing I noticed was that air mass was going erratic, and that is worth being precise about, because the air mass model on this car is a blend. Below 100 kPa it runs the throttle mass flow model exclusively and blends towards speed density above that. In the region where this fault appears the air mass estimate is therefore a function of throttle effective area and pressure ratio and nothing else. No speed density term diluting it, no trapped mass term in the estimate.</p>



<p class="wp-block-paragraph">So erratic air mass in that region means the blade, or the area characterisation, or both. It cannot mean much else.</p>



<p class="wp-block-paragraph">Pedal throttle demand translation was smooth through the whole event. The driver demand table was not doing this. That left the DBW loop, and the DBW PID was the gold seam.</p>


<p><!-- IMAGE SLOT A: emtron-dbw-pid-instability-log.png --></p>


<h2 class="wp-block-heading">What the loop was doing</h2>



<p class="wp-block-paragraph"><strong>Status: Verified</strong></p>



<p class="wp-block-paragraph">Three things stand out.</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="566" src="https://blownbytwins.co.uk/wp-content/uploads/2026/09/dbw_pid_errors-1024x566.png" alt="" class="wp-image-1160" srcset="https://blownbytwins.co.uk/wp-content/uploads/2026/09/dbw_pid_errors-1024x566.png 1024w, https://blownbytwins.co.uk/wp-content/uploads/2026/09/dbw_pid_errors-300x166.png 300w, https://blownbytwins.co.uk/wp-content/uploads/2026/09/dbw_pid_errors-768x424.png 768w, https://blownbytwins.co.uk/wp-content/uploads/2026/09/dbw_pid_errors-1536x848.png 1536w, https://blownbytwins.co.uk/wp-content/uploads/2026/09/dbw_pid_errors.png 2046w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Proportional output is saturating at minus 100 percent repeatedly, and topping out near plus 63. That asymmetry is not the axis autoscaling being unhelpful. It is the loop reaching its closing clamp over and over while never reaching the opening one.</p>



<p class="wp-block-paragraph">Integral output is sitting around plus 24 percent and climbing slowly across the window. An integrator that keeps accumulating while the proportional term is pinned at its clamp is not doing the job an integrator is for.</p>



<p class="wp-block-paragraph">The motor command is swinging roughly minus 65 to plus 100 percent while the measured blade position only moves a few percent either side of 15. The blade is inertially filtered. It physically cannot follow a command oscillating at that rate, so the engine never sees the full excursion.</p>



<p class="wp-block-paragraph">That last point is the one that connects back to the shift. The engine does not see it, but the model does. Torque estimate comes from air mass, air mass in this region comes from the throttle mass flow model, and that model reads blade position directly. Every percent of blade wobble goes into the torque estimate whether or not the engine produced any of it.</p>



<p class="wp-block-paragraph">The gearbox was reacting to torque noise that did not exist at the crankshaft.</p>



<h2 class="wp-block-heading">The arithmetic</h2>



<p class="wp-block-paragraph"><strong>Status: Verified</strong></p>



<p class="wp-block-paragraph">This is where the log stops being suggestive and starts being conclusive. At the cursor, 38.138s in the screenshot above:</p>



<ul class="wp-block-list">
<li>Servo Position Main: 3.7 percent</li>



<li>Proportional output: 0.9 percent</li>



<li>Integral output: 24.3 percent</li>



<li>Derivative output: 0.0 percent</li>



<li>Motor command: 6.2 percent</li>
</ul>



<p class="wp-block-paragraph">My feed-forward table runs minus 30 at 0 percent and minus 15 at 5 percent. Interpolated linearly, feed-forward at 3.7 percent is minus 18.9.</p>



<figure class="bbt-figure"><div class="bbt-table-wrap"><table class="bbt-table"><thead><tr><th class="bbt-corner" rowspan="2"><span>Contribution</span></th><td class="bbt-axis-x" colspan="6">Controller term, percent motor duty</td></tr><tr><th scope="col">Feed-forward</th><th scope="col">Proportional</th><th scope="col">Integral</th><th scope="col">Derivative</th><th scope="col">Sum</th><th scope="col">Logged</th></tr></thead><tbody><tr><th scope="row">At 3.7% blade</th><td class="c7">-18.9</td><td class="c0">+0.9</td><td class="c9">+24.3</td><td class="c0">0.0</td><td class="c2">+6.3</td><td class="c2">+6.2</td></tr></tbody></table></div><figcaption class="bbt-table-note">Reconstructing the motor command at 38.138 s. Shading is by absolute magnitude, so the two terms doing all the work are the ones that stand out.</figcaption><p class="bbt-scroll-hint">Scroll the table sideways</p></figure>



<p class="wp-block-paragraph">Two things fall out of a match that close. Motor command is the summed controller output rather than a measured position, and feed-forward interpolates linearly between breakpoints.</p>



<p class="wp-block-paragraph">But the finding is the third thing. <strong>At a near steady 3.7 percent blade position, the integral had wound to plus 24.3 for no purpose other than to cancel a feed-forward of minus 18.9.</strong></p>



<p class="wp-block-paragraph">The feed-forward in the 0 to 5 percent band is asking for roughly 25 points of closing duty that the throttle body does not need. The integral is spending its entire authority undoing it. That is a large stored state sitting permanently in the loop, and every time the proportional term saturates and the target moves, that state has to unwind before anything else can settle.</p>



<p class="wp-block-paragraph">It is a far better explanation for a sustained oscillation than any single gain cell.</p>



<h2 class="wp-block-heading">The feed-forward step, and what it actually is</h2>



<p class="wp-block-paragraph"><strong>Status: Provisional</strong></p>



<figure class="bbt-figure"><div class="bbt-table-wrap"><table class="bbt-table"><thead><tr><th class="bbt-corner" rowspan="2"><span>Feed-forward, percent motor duty</span></th><td class="bbt-axis-x" colspan="5">Throttle target, %</td></tr><tr><th scope="col">0</th><th scope="col">5</th><th scope="col">6</th><th scope="col">8</th><th scope="col">10</th></tr></thead><tbody><tr><th scope="row">As found</th><td class="c0">-30</td><td class="c3">-15</td><td class="c9">+10</td><td class="c9">+10</td><td class="c9">+10</td></tr><tr><th scope="row">Revised</th><td class="c0">-30</td><td class="c3">-15</td><td class="c6">-5</td><td class="c8">+5</td><td class="c9">+10</td></tr></tbody></table></div><figcaption class="bbt-table-note">Both rows are shaded against the same range, so the revision reads as a smoothing of the step rather than a change of shape.</figcaption><p class="bbt-scroll-hint">Scroll the table sideways</p></figure>



<p class="wp-block-paragraph">There is a 25 point change in motor duty for a 1 percent movement in target between 5 and 6 percent, and the log crosses that region immediately before one of the instabilities. My first instinct was that this was simply wrong. It is not, and this is the part most likely to be copied badly, so it is worth saying plainly.</p>



<p class="wp-block-paragraph">The return spring on a DBW body pulls the blade towards its limp home position from both directions. Below limp home you need negative duty to hold the blade down against the spring. Above it you need positive duty to hold it open. A feed-forward table that changes sign between two cells is not a tuning error. It is the table telling you where limp home sits.</p>



<p class="wp-block-paragraph">Delete the step and you have not removed the discontinuity. You have removed the compensation for it, and handed the spring preload to the integrator.</p>



<p class="wp-block-paragraph">The real problems are different. First, the magnitude of the low band values, which the arithmetic above says are too negative. Second, a 25 point change interpolated across 1 percent of travel behaves like a gain of 25 through a region the blade is oscillating in.</p>



<h2 class="wp-block-heading">The proportional gain table</h2>



<p class="wp-block-paragraph"><strong>Status: Provisional</strong></p>



<p class="wp-block-paragraph">The low position P gains are aggressive, and lopsided towards the negative error side.</p>



<figure class="bbt-figure"><div class="bbt-table-wrap"><table class="bbt-table"><thead><tr><th class="bbt-corner" rowspan="2"><span>Throttle target, %</span></th><td class="bbt-axis-x" colspan="8">Target error, %</td></tr><tr><th scope="col">-12</th><th scope="col">-8</th><th scope="col">-2</th><th scope="col">-1</th><th scope="col">+1</th><th scope="col">+2</th><th scope="col">+8</th><th scope="col">+12</th></tr></thead><tbody><tr><th scope="row">5</th><td class="c9">12.00</td><td class="c8">11.20</td><td class="c6">10.00</td><td class="c6">10.00</td><td class="c6">10.00</td><td class="c4">8.00</td><td class="c2">6.50</td><td class="c0">5.00</td></tr><tr><th scope="row">15</th><td class="c9">12.00</td><td class="c8">11.13</td><td class="c5">9.02</td><td class="c6">9.84</td><td class="c6">9.84</td><td class="c4">8.00</td><td class="c2">6.50</td><td class="c0">5.00</td></tr><tr><th scope="row">25</th><td class="c5">9.00</td><td class="c5">9.26</td><td class="c5">9.05</td><td class="c6">9.67</td><td class="c6">9.67</td><td class="c3">7.50</td><td class="c1">6.00</td><td class="c0">5.00</td></tr></tbody></table></div><figcaption class="bbt-table-note">Proportional gain as found. Shaded against the same range as the revised table below, so the two are directly comparable.</figcaption><p class="bbt-scroll-hint">Scroll the table sideways</p></figure>



<p class="wp-block-paragraph">Reading negative error as blade above target, the closing correction gets close to twice the gain available for an equivalent opening error, at every row.</p>



<p class="wp-block-paragraph">The spring makes this more interesting than a simple symmetry argument, because the asymmetry it creates flips across limp home. Above limp home the spring already assists closing, so the loop needs more authority to open and less to close. Below limp home it reverses.</p>



<p class="wp-block-paragraph">A table that favours the closing side at every row is therefore directionally right in the 5 percent row and wrong in the 15 and 25 percent rows. The blade sits at 15 to 17 percent through this event.</p>



<figure class="bbt-figure"><div class="bbt-table-wrap"><table class="bbt-table"><thead><tr><th class="bbt-corner" rowspan="2"><span>Throttle target, %</span></th><td class="bbt-axis-x" colspan="8">Target error, %</td></tr><tr><th scope="col">-12</th><th scope="col">-8</th><th scope="col">-2</th><th scope="col">-1</th><th scope="col">+1</th><th scope="col">+2</th><th scope="col">+8</th><th scope="col">+12</th></tr></thead><tbody><tr><th scope="row">5</th><td class="c4">8.0</td><td class="c4">8.0</td><td class="c5">8.5</td><td class="c5">8.5</td><td class="c5">8.5</td><td class="c3">7.5</td><td class="c2">6.5</td><td class="c0">5.0</td></tr><tr><th scope="row">15</th><td class="c2">6.5</td><td class="c3">7.0</td><td class="c4">8.0</td><td class="c4">8.0</td><td class="c4">8.0</td><td class="c3">7.0</td><td class="c1">6.0</td><td class="c0">5.0</td></tr><tr><th scope="row">25</th><td class="c1">6.0</td><td class="c2">6.5</td><td class="c3">7.0</td><td class="c3">7.5</td><td class="c3">7.5</td><td class="c2">6.5</td><td class="c1">5.5</td><td class="c0">5.0</td></tr></tbody></table></div><figcaption class="bbt-table-note">Proportional gain, revised. Same shading range as above. The whole table reads cooler, and the 15 and 25 percent rows now favour the opening side.</figcaption><p class="bbt-scroll-hint">Scroll the table sideways</p></figure>



<p class="wp-block-paragraph">One caveat that anyone copying this needs to take seriously. The whole reading above depends on the error channel being target minus actual. If your ECU signs it the other way, the argument inverts and so does the revision. Confirm it on your own log before you touch a cell: find a step where the blade visibly lags a rising target, and read the sign.</p>



<h2 class="wp-block-heading">What I have not proved yet</h2>



<p class="wp-block-paragraph">I changed two tables at once. Until they are separated, no outcome can be attributed to either.</p>



<p class="wp-block-paragraph">I have not measured the true limp home position. The right way is to unpower the driver and read the TPS, then check whether the feed-forward breakpoints actually straddle it. If limp home sits at 6.5 percent rather than between 5 and 6, the compensation is being applied in the wrong place, and that alone would explain the instability without a single gain change.</p>



<p class="wp-block-paragraph">I have not confirmed the error sign convention from a step.</p>



<p class="wp-block-paragraph">And I left the 0 and 5 percent feed-forward cells alone, which are the two cells the arithmetic actually points at.</p>



<p class="wp-block-paragraph">I&#8217;m not declaring this as &#8220;fixed&#8221; yet. However, the gear change is smoother, particularly the upshift. The lower speed acceleration is cleaner and everything just feels much more refined. Always remember the first few percent of opening on a throttle blade are extremely non-linear, and even more so on a 82mm throttle body.</p>



<h2 class="wp-block-heading">The test that closes it</h2>



<p class="wp-block-paragraph">With the loop stable, park the blade at steady positions across 0 to 25 percent, in 2 percent steps through the 0 to 8 percent band, and log feed-forward and integral at each point.</p>



<p class="wp-block-paragraph">Wherever the integral is non-zero at steady state, the feed-forward is wrong by exactly that amount. That lets the whole low band feed-forward table be built by subtraction rather than by iteration. The position at which feed-forward crosses zero and the integral stays at zero is the true limp home. Any step within the sweep settles the sign convention.</p>



<p class="wp-block-paragraph">Run it on the same road and the same coast down and you also get a genuinely matched before and after, rather than two logs taken a week apart under different load.</p>



<h2 class="wp-block-heading">The principle</h2>



<p class="wp-block-paragraph"><strong>The data is not transferable, but the principle is.</strong></p>



<p class="wp-block-paragraph">A feed-forward table and an integrator are solving the same problem from opposite ends. If the integrator is carrying a large standing value at a steady operating point, the feed-forward is wrong by that amount, and you can read the correction straight off the log instead of iterating towards it.</p>



<p class="wp-block-paragraph">The throttle area table that the whole torque model sits on is covered in <a href="https://blownbytwins.co.uk/engine-management/throttle-body-effective-area/">Throttle Body Effective Flow Area</a>, and the same feed-forward versus PID argument applied to traction control is in <a href="https://blownbytwins.co.uk/engine-management/traction-control-feedforward-pid/">Traction Control on 1,114 whp</a>. Full specification is on the <a href="https://blownbytwins.co.uk/toyota-supra-mk4-delta/">Supra project page</a>.</p>



<p class="wp-block-paragraph">If you run a DBW loop and have taken a different view on any of this, particularly the limp home reasoning or the gain asymmetry, I would like to hear it.</p><p>The post <a href="https://blownbytwins.co.uk/cars/mk4-supra/dbw-feedforward-fault/">Erratic Shifts and Idle Overfuelling on the 2JZ: Finding a DBW Feed-Forward Fault</a> first appeared on <a href="https://blownbytwins.co.uk">BlownByTwins</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Traction Control on 1,114 whp: Feedforward, PID, and Why It Never Cuts</title>
		<link>https://blownbytwins.co.uk/cars/mk4-supra/traction-control-feedforward-pid/</link>
		
		<dc:creator><![CDATA[john]]></dc:creator>
		<pubDate>Thu, 17 Sep 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[Engine Management]]></category>
		<category><![CDATA[Mk4 Supra]]></category>
		<category><![CDATA[Tuning]]></category>
		<category><![CDATA[emtron]]></category>
		<category><![CDATA[feedforward]]></category>
		<category><![CDATA[torque model]]></category>
		<category><![CDATA[traction control]]></category>
		<guid isPermaLink="false">https://blownbytwins.co.uk/?p=1118</guid>

					<description><![CDATA[<p>1,114 whp, 880 lb ft, and a 295 section road tyre on the back. Traction control on this car is not a driver aid. It is the thing that makes&#8230;</p>
<p>The post <a href="https://blownbytwins.co.uk/cars/mk4-supra/traction-control-feedforward-pid/">Traction Control on 1,114 whp: Feedforward, PID, and Why It Never Cuts</a> first appeared on <a href="https://blownbytwins.co.uk">BlownByTwins</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">1,114 whp, 880 lb ft, and a 295 section road tyre on the back. Traction control on this car is not a driver aid. It is the thing that makes the car usable at all.</p>



<p class="wp-block-paragraph">Most discussion of traction control stops at &#8220;it cuts power when the wheels spin&#8221;. That describes about a third of what is actually happening, and it is the least interesting third. The system on this car has a predictive half that tries to never need the reactive half, and the whole design is aimed at keeping the reactive half quiet.</p>



<p class="wp-block-paragraph">This is how it is set up, and why. Every table is reproduced in full.</p>



<h2 class="wp-block-heading">Configuration</h2>



<p class="wp-block-paragraph"><strong>Status: Verified</strong></p>



<ul class="wp-block-list">
<li><a href="https://emtron.world/products/kv12">Emtron KV12</a>, torque based traction control</li>



<li>3.4 litre 2JZ-GTE VVTi, 1,114 whp on E85, torque limited to 880 lb ft</li>



<li>ZF 8HP70, 2.93 final drive, OS Giken LSD</li>



<li>Continental SportContact 7, 265/30/19 front and 295/30/19 rear</li>



<li>Four individual wheel speeds, three axis internal accelerometer</li>



<li>Eight position rotary on the steering wheel, over CAN</li>
</ul>



<p class="wp-block-paragraph">Everything below is my own work. The base calibration on this car came from SRD Tuning, but the traction control strategy is mine start to finish, which is the only reason I can show you the tables.</p>



<h2 class="wp-block-heading">The predictive half: torque feedforward</h2>



<p class="wp-block-paragraph">The core of the system is a table that answers one question: <strong>at what engine torque does this car lose traction?</strong></p>



<figure class="bbt-figure"><div class="bbt-table-wrap"><table class="bbt-table"><thead><tr><th class="bbt-corner" rowspan="2"><span>Slip target error, %</span></th><td class="bbt-axis-x" colspan="13">Engine torque, no reduction applied, Nm</td></tr><tr><th scope="col">50</th><th scope="col">150</th><th scope="col">250</th><th scope="col">350</th><th scope="col">450</th><th scope="col">550</th><th scope="col">650</th><th scope="col">750</th><th scope="col">850</th><th scope="col">950</th><th scope="col">1050</th><th scope="col">1150</th><th scope="col">1250</th></tr></thead><tbody><tr><th scope="row">-8.00</th><td class="c0">45.0</td><td class="c0">75.0</td><td class="c1">95.0</td><td class="c1">115.0</td><td class="c1">130.0</td><td class="c1">140.0</td><td class="c1">145.0</td><td class="c1">150.0</td><td class="c1">150.0</td><td class="c1">150.0</td><td class="c1">150.0</td><td class="c1">150.0</td><td class="c1">150.0</td></tr><tr><th scope="row">-6.00</th><td class="c0">45.0</td><td class="c1">90.0</td><td class="c1">123.2</td><td class="c2">156.3</td><td class="c2">182.5</td><td class="c2">200.0</td><td class="c2">205.0</td><td class="c2">210.0</td><td class="c2">210.0</td><td class="c2">210.0</td><td class="c2">210.0</td><td class="c2">210.0</td><td class="c2">210.0</td></tr><tr><th scope="row">-5.00</th><td class="c0">45.0</td><td class="c1">100.0</td><td class="c1">145.6</td><td class="c2">191.3</td><td class="c2">222.5</td><td class="c3">245.0</td><td class="c3">247.5</td><td class="c3">250.0</td><td class="c3">250.0</td><td class="c3">250.0</td><td class="c3">250.0</td><td class="c3">250.0</td><td class="c3">250.0</td></tr><tr><th scope="row">-4.00</th><td class="c0">45.0</td><td class="c1">110.0</td><td class="c2">170.0</td><td class="c3">230.0</td><td class="c3">275.0</td><td class="c4">305.0</td><td class="c4">307.5</td><td class="c4">310.0</td><td class="c4">310.0</td><td class="c4">310.0</td><td class="c4">310.0</td><td class="c4">310.0</td><td class="c4">310.0</td></tr><tr><th scope="row">-3.00</th><td class="c0">48.0</td><td class="c1">125.0</td><td class="c2">198.1</td><td class="c3">271.3</td><td class="c4">327.5</td><td class="c4">335.0</td><td class="c4">342.5</td><td class="c4">350.0</td><td class="c4">350.0</td><td class="c4">350.0</td><td class="c4">350.0</td><td class="c4">350.0</td><td class="c4">350.0</td></tr><tr><th scope="row">-2.00</th><td class="c0">50.0</td><td class="c1">140.0</td><td class="c2">216.5</td><td class="c3">293.0</td><td class="c5">376.0</td><td class="c5">394.0</td><td class="c5">412.0</td><td class="c5">430.0</td><td class="c5">430.0</td><td class="c5">430.0</td><td class="c5">430.0</td><td class="c5">430.0</td><td class="c5">430.0</td></tr><tr><th scope="row">-1.00</th><td class="c0">50.0</td><td class="c1">148.0</td><td class="c3">236.4</td><td class="c4">324.8</td><td class="c5">411.6</td><td class="c6">447.7</td><td class="c6">483.9</td><td class="c7">520.0</td><td class="c7">520.0</td><td class="c7">520.0</td><td class="c7">520.0</td><td class="c7">520.0</td><td class="c7">520.0</td></tr><tr><th scope="row">0.00</th><td class="c0">50.0</td><td class="c1">150.0</td><td class="c3">245.3</td><td class="c4">340.5</td><td class="c5">430.9</td><td class="c6">478.9</td><td class="c7">527.0</td><td class="c7">575.0</td><td class="c7">575.0</td><td class="c7">575.0</td><td class="c7">575.0</td><td class="c7">575.0</td><td class="c7">575.0</td></tr><tr><th scope="row">1.00</th><td class="c0">50.0</td><td class="c1">150.0</td><td class="c3">256.5</td><td class="c4">363.1</td><td class="c6">476.3</td><td class="c7">529.2</td><td class="c7">582.1</td><td class="c8">635.0</td><td class="c8">635.0</td><td class="c8">635.0</td><td class="c8">635.0</td><td class="c8">635.0</td><td class="c8">635.0</td></tr><tr><th scope="row">2.00</th><td class="c0">50.0</td><td class="c1">150.0</td><td class="c3">269.5</td><td class="c5">389.0</td><td class="c6">503.1</td><td class="c7">565.4</td><td class="c8">627.7</td><td class="c9">690.0</td><td class="c9">690.0</td><td class="c9">690.0</td><td class="c9">690.0</td><td class="c9">690.0</td><td class="c9">690.0</td></tr></tbody></table></div><figcaption class="bbt-table-note">Torque Feed Forward Table, Nm. The torque at which traction is lost.</figcaption><p class="bbt-scroll-hint">Scroll the table sideways</p></figure>



<p class="wp-block-paragraph">It is indexed on engine torque with no reduction applied, against slip target error. The ECU looks up that number and feeds it forward as the torque target before any measurement of actual slip has influenced anything.</p>



<p class="wp-block-paragraph">That is the whole idea of feedforward. If the model is right, the engine never makes more torque than the tyres can take, the slip never happens, and the closed loop has nothing to correct.</p>



<p class="wp-block-paragraph">Look at the first two columns before anything else. At 50 Nm of engine torque the table returns 50, and at 150 it returns 150. Below about 150 Nm it is a pass through: the feedforward is not limiting anything, because at those loads there is nothing to limit.</p>



<h3 class="wp-block-heading">And this is where the normalisation matters</h3>



<p class="wp-block-paragraph">Read along the zero slip error row and the values climb: 245.3, 340.5, 430.9, 478.9, 527.0, 575.0. And then they stop. Flat at 575 Nm from 750 Nm of engine torque all the way to 1,250.</p>



<p class="wp-block-paragraph">That plateau is deliberate and it is the single most important thing in the setup.</p>



<p class="wp-block-paragraph">Extend the slope before the plateau and an unclamped table would be asking for roughly 815 Nm at the top of the range. The engine makes 1,193 Nm. So without the clamp, the feedforward would be handing the PID a target the tyres cannot deliver, and the PID would spend its entire life trying to close a gap that physics will not close.</p>



<p class="wp-block-paragraph">A saturated PID is not a controller. It is an actuator held wide open. You lose all the proportionality that makes traction control feel like assistance rather than interference.</p>



<p class="wp-block-paragraph">Clamping the feedforward at something the tyres can actually deliver means the PID always has authority in reserve. That is what &#8220;normalised&#8221; means here, and it is why the system feels like it is helping rather than fighting.</p>



<h3 class="wp-block-heading">Normalised against third</h3>



<p class="wp-block-paragraph">The feedforward table is written for third gear. Everything else is scaled off it by two correction tables.</p>



<figure class="bbt-figure"><div class="bbt-table-wrap"><table class="bbt-table"><thead><tr><th class="bbt-corner" rowspan="2"><span>Rate of change of engine speed, rpm per second</span></th><td class="bbt-axis-x" colspan="8">Gear</td></tr><tr><th scope="col">1</th><th scope="col">2</th><th scope="col">3</th><th scope="col">4</th><th scope="col">5</th><th scope="col">6</th><th scope="col">7</th><th scope="col">8</th></tr></thead><tbody><tr><th scope="row">750</th><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">-1.0</td><td class="c0">-1.0</td><td class="c1">-2.0</td></tr><tr><th scope="row">1250</th><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">-1.0</td><td class="c1">-2.0</td><td class="c1">-3.0</td><td class="c1">-4.0</td><td class="c1">-5.0</td></tr><tr><th scope="row">1750</th><td class="c0">0.0</td><td class="c0">0.0</td><td class="c1">-2.0</td><td class="c1">-3.0</td><td class="c1">-5.0</td><td class="c2">-6.0</td><td class="c2">-8.0</td><td class="c3">-9.0</td></tr><tr><th scope="row">2250</th><td class="c0">0.0</td><td class="c1">-2.0</td><td class="c1">-5.0</td><td class="c2">-7.0</td><td class="c3">-9.0</td><td class="c3">-11.0</td><td class="c4">-13.0</td><td class="c4">-14.0</td></tr><tr><th scope="row">3000</th><td class="c0">-1.0</td><td class="c1">-5.0</td><td class="c3">-9.0</td><td class="c3">-12.0</td><td class="c4">-15.0</td><td class="c5">-18.0</td><td class="c6">-20.0</td><td class="c6">-22.0</td></tr><tr><th scope="row">4000</th><td class="c1">-5.0</td><td class="c3">-10.0</td><td class="c4">-16.0</td><td class="c6">-20.0</td><td class="c7">-24.0</td><td class="c8">-28.0</td><td class="c8">-30.0</td><td class="c9">-32.0</td></tr></tbody></table></div><figcaption class="bbt-table-note">Correction Table 1, percent applied to the feedforward torque.</figcaption><p class="bbt-scroll-hint">Scroll the table sideways</p></figure>



<p class="wp-block-paragraph">Correction Table 1 is indexed on gear against rate of change of engine speed. In first at low dRPM the correction is zero. By eighth at 4,000 dRPM it is minus 32 percent.</p>



<p class="wp-block-paragraph">Which makes sense once you think about what dRPM means in each gear. Engine speed rising at 4,000 rpm per second in first is normal acceleration. The same rate in eighth means the driven wheels are going somewhere the car is not. The correction is reading the rate of change as evidence of impending slip, and pulling the target down before the slip calculation has caught up.</p>



<figure class="bbt-figure"><div class="bbt-table-wrap"><table class="bbt-table"><thead><tr><th class="bbt-corner" rowspan="2"><span>Correction</span></th><td class="bbt-axis-x" colspan="8">Slip target error, %</td></tr><tr><th scope="col">-64.00</th><th scope="col">-32.00</th><th scope="col">-16.00</th><th scope="col">-8.00</th><th scope="col">-4.00</th><th scope="col">-2.00</th><th scope="col">-1.00</th><th scope="col">0.00</th></tr></thead><tbody><tr><th scope="row">%</th><td class="c9">-40.0</td><td class="c4">-20.0</td><td class="c2">-10.0</td><td class="c1">-4.0</td><td class="c0">-2.0</td><td class="c0">-1.0</td><td class="c0">0.0</td><td class="c2">10.0</td></tr></tbody></table></div><figcaption class="bbt-table-note">Correction Table 2. Note the axis: it runs out to minus 64 percent slip error, far wider than the gain tables further down. These two tables are not directly comparable.</figcaption><p class="bbt-scroll-hint">Scroll the table sideways</p></figure>



<p class="wp-block-paragraph">Correction Table 2 does the same job against slip target error directly, from minus 40 percent at large negative error up to plus 10 at zero. That positive 10 at zero error is worth noticing: when the car is exactly on target, the feedforward is allowed to ask for slightly more than the base table says.</p>



<h2 class="wp-block-heading">The slip target, and what the rotary actually does</h2>



<p class="wp-block-paragraph"><strong>Status: Verified</strong></p>



<p class="wp-block-paragraph">Here is the part I had not seen anyone else do.</p>



<p class="wp-block-paragraph">The target slip table is indexed on <strong>lateral G</strong>, from minus 1.5 to plus 1.5, against the rotary position from the steering wheel.</p>



<figure class="bbt-figure"><div class="bbt-table-wrap"><table class="bbt-table"><thead><tr><th class="bbt-corner" rowspan="2"><span>Rotary position, CAN value</span></th><td class="bbt-axis-x" colspan="21">Lateral G</td></tr><tr><th scope="col">-1.50</th><th scope="col">-1.35</th><th scope="col">-1.20</th><th scope="col">-1.05</th><th scope="col">-0.90</th><th scope="col">-0.75</th><th scope="col">-0.60</th><th scope="col">-0.45</th><th scope="col">-0.30</th><th scope="col">-0.15</th><th scope="col">0.00</th><th scope="col">0.15</th><th scope="col">0.30</th><th scope="col">0.45</th><th scope="col">0.60</th><th scope="col">0.75</th><th scope="col">0.90</th><th scope="col">1.05</th><th scope="col">1.20</th><th scope="col">1.35</th><th scope="col">1.50</th></tr></thead><tbody><tr><th scope="row">0</th><td class="c0">1.0</td><td class="c0">1.1</td><td class="c0">1.3</td><td class="c0">1.4</td><td class="c0">1.6</td><td class="c0">1.7</td><td class="c0">1.9</td><td class="c0">2.0</td><td class="c0">2.0</td><td class="c0">2.0</td><td class="c0">2.0</td><td class="c0">2.0</td><td class="c0">2.0</td><td class="c0">2.0</td><td class="c0">1.9</td><td class="c0">1.7</td><td class="c0">1.6</td><td class="c0">1.4</td><td class="c0">1.3</td><td class="c0">1.1</td><td class="c0">1.0</td></tr><tr><th scope="row">1</th><td class="c0">2.5</td><td class="c0">2.5</td><td class="c1">2.8</td><td class="c1">2.8</td><td class="c1">3.0</td><td class="c1">3.0</td><td class="c1">2.8</td><td class="c1">2.6</td><td class="c0">2.4</td><td class="c0">2.2</td><td class="c0">2.0</td><td class="c0">2.2</td><td class="c0">2.4</td><td class="c1">2.6</td><td class="c1">2.8</td><td class="c1">3.0</td><td class="c1">3.0</td><td class="c1">2.8</td><td class="c1">2.6</td><td class="c0">2.5</td><td class="c0">2.5</td></tr><tr><th scope="row">3</th><td class="c0">2.0</td><td class="c0">2.0</td><td class="c0">2.2</td><td class="c0">2.2</td><td class="c0">2.3</td><td class="c0">2.4</td><td class="c0">2.5</td><td class="c1">2.6</td><td class="c1">2.6</td><td class="c1">2.7</td><td class="c1">2.8</td><td class="c1">2.7</td><td class="c1">2.6</td><td class="c1">2.6</td><td class="c0">2.5</td><td class="c0">2.4</td><td class="c0">2.3</td><td class="c0">2.3</td><td class="c0">2.3</td><td class="c0">2.3</td><td class="c0">2.3</td></tr><tr><th scope="row">5</th><td class="c0">2.0</td><td class="c0">2.0</td><td class="c0">2.0</td><td class="c0">2.0</td><td class="c0">2.2</td><td class="c0">2.4</td><td class="c1">2.7</td><td class="c1">2.9</td><td class="c1">3.2</td><td class="c1">3.6</td><td class="c1">3.8</td><td class="c1">3.6</td><td class="c1">3.2</td><td class="c1">2.9</td><td class="c1">2.7</td><td class="c0">2.4</td><td class="c0">2.2</td><td class="c0">2.0</td><td class="c0">2.0</td><td class="c0">2.0</td><td class="c0">2.0</td></tr><tr><th scope="row">7</th><td class="c1">3.5</td><td class="c1">3.8</td><td class="c1">4.0</td><td class="c1">4.5</td><td class="c1">5.1</td><td class="c2">5.7</td><td class="c2">6.3</td><td class="c2">6.7</td><td class="c2">7.1</td><td class="c2">7.6</td><td class="c2">7.9</td><td class="c2">7.6</td><td class="c2">7.1</td><td class="c2">6.7</td><td class="c2">6.3</td><td class="c2">5.7</td><td class="c1">5.1</td><td class="c1">4.8</td><td class="c1">4.3</td><td class="c1">4.0</td><td class="c1">3.8</td></tr><tr><th scope="row">9</th><td class="c1">5.0</td><td class="c2">5.5</td><td class="c2">6.0</td><td class="c2">7.0</td><td class="c2">8.0</td><td class="c3">9.0</td><td class="c3">10.0</td><td class="c3">10.5</td><td class="c3">11.0</td><td class="c4">11.5</td><td class="c4">12.0</td><td class="c4">11.5</td><td class="c3">11.0</td><td class="c3">10.5</td><td class="c3">10.0</td><td class="c3">9.0</td><td class="c2">8.0</td><td class="c2">7.0</td><td class="c2">6.0</td><td class="c2">5.5</td><td class="c1">5.0</td></tr><tr><th scope="row">10</th><td class="c3">10.0</td><td class="c3">11.0</td><td class="c4">12.0</td><td class="c4">13.0</td><td class="c4">14.0</td><td class="c5">15.0</td><td class="c5">16.0</td><td class="c5">17.0</td><td class="c6">18.0</td><td class="c6">19.0</td><td class="c6">20.0</td><td class="c6">19.0</td><td class="c6">18.0</td><td class="c5">17.0</td><td class="c5">16.0</td><td class="c5">15.0</td><td class="c4">14.0</td><td class="c4">13.0</td><td class="c4">12.0</td><td class="c3">11.0</td><td class="c3">10.0</td></tr><tr><th scope="row">12</th><td class="c8">25.0</td><td class="c8">25.3</td><td class="c8">25.6</td><td class="c8">25.9</td><td class="c8">26.2</td><td class="c8">26.5</td><td class="c9">26.8</td><td class="c9">27.1</td><td class="c9">27.4</td><td class="c9">27.7</td><td class="c9">28.0</td><td class="c9">27.7</td><td class="c9">27.4</td><td class="c9">27.1</td><td class="c9">26.8</td><td class="c8">26.5</td><td class="c8">26.2</td><td class="c8">25.9</td><td class="c8">25.6</td><td class="c8">25.3</td><td class="c8">25.0</td></tr></tbody></table></div><figcaption class="bbt-table-note">Target Slip Table 1, permitted slip in percent. Row labels are the eight discrete CAN values the switch produces, so the ECU never interpolates between settings.</figcaption><p class="bbt-scroll-hint">Scroll the table sideways</p></figure>



<p class="wp-block-paragraph">Almost every row is a dome. Maximum permitted slip in a straight line, tapering symmetrically as lateral load builds in either direction. At the loosest setting the car allows 28 percent slip straight ahead, falling to 25 at 1.5 G. At the tightest, 2 percent straight ahead and 1 percent once the car is properly loaded up.</p>



<p class="wp-block-paragraph">Setting 1 is the exception, and I would rather point at it than pretend it fits. It permits 2 percent straight ahead, rises to 3 percent at around 0.75 G in either direction, and comes back to 2.5 at full lateral load. It is the only row in the table that allows more slip while cornering than it does in a straight line.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1200" height="631" src="https://blownbytwins.co.uk/wp-content/uploads/2026/09/emtron-traction-slip-target-vs-lateral-g.png" alt="Chart of permitted wheel slip against lateral G for three traction control settings, each forming a dome that peaks in a straight line and tapers as cornering load builds" class="wp-image-1120" /><figcaption class="wp-element-caption">The same data plotted. The dome is most pronounced in the middle settings and flattens at both extremes.</figcaption></figure>



<p class="wp-block-paragraph">So the rotary is not a gain switch and it is not an on/off. It selects <strong>how much slip you are allowed as a function of how hard you are cornering</strong>, and the system tightens automatically as lateral load increases without the driver doing anything.</p>



<h3 class="wp-block-heading">And then speed offsets all of it</h3>



<p class="wp-block-paragraph">Lateral G is not the only input to the slip target. A second table offsets it by road speed, and it does a lot of work at both ends.</p>



<figure class="bbt-figure"><div class="bbt-table-wrap"><table class="bbt-table"><thead><tr><th class="bbt-corner" rowspan="2"><span>Rotary position, CAN value</span></th><td class="bbt-axis-x" colspan="12">Front axle speed, average, kph</td></tr><tr><th scope="col">0</th><th scope="col">15</th><th scope="col">25</th><th scope="col">45</th><th scope="col">120</th><th scope="col">160</th><th scope="col">180</th><th scope="col">210</th><th scope="col">240</th><th scope="col">270</th><th scope="col">300</th><th scope="col">330</th></tr></thead><tbody><tr><th scope="row">0</th><td class="c3">9.0</td><td class="c3">9.0</td><td class="c3">9.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">-0.8</td><td class="c0">-1.2</td><td class="c1">-1.4</td><td class="c1">-1.6</td><td class="c1">-1.8</td><td class="c1">-2.0</td></tr><tr><th scope="row">1</th><td class="c3">9.0</td><td class="c3">9.0</td><td class="c3">9.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">-0.8</td><td class="c1">-1.6</td><td class="c1">-2.0</td><td class="c1">-2.4</td><td class="c1">-2.8</td><td class="c1">-3.2</td></tr><tr><th scope="row">3</th><td class="c3">9.0</td><td class="c3">9.0</td><td class="c3">9.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">-0.8</td><td class="c1">-1.8</td><td class="c1">-2.4</td><td class="c1">-3.0</td><td class="c1">-3.6</td><td class="c2">-4.2</td></tr><tr><th scope="row">5</th><td class="c3">9.0</td><td class="c3">9.0</td><td class="c3">9.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">-0.8</td><td class="c1">-2.2</td><td class="c1">-3.0</td><td class="c1">-3.8</td><td class="c2">-4.4</td><td class="c2">-5.2</td></tr><tr><th scope="row">7</th><td class="c3">9.0</td><td class="c3">9.0</td><td class="c3">9.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">-1.0</td><td class="c1">-2.4</td><td class="c1">-3.4</td><td class="c2">-4.4</td><td class="c2">-5.2</td><td class="c2">-6.2</td></tr><tr><th scope="row">9</th><td class="c3">9.0</td><td class="c3">9.0</td><td class="c3">9.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">-1.2</td><td class="c1">-2.8</td><td class="c1">-4.0</td><td class="c2">-5.0</td><td class="c2">-6.2</td><td class="c3">-7.4</td></tr><tr><th scope="row">10</th><td class="c3">9.0</td><td class="c3">9.0</td><td class="c3">9.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">-1.2</td><td class="c1">-3.0</td><td class="c2">-4.4</td><td class="c2">-5.6</td><td class="c3">-7.0</td><td class="c3">-8.4</td></tr><tr><th scope="row">12</th><td class="c9">25.0</td><td class="c9">24.0</td><td class="c8">22.2</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">0.0</td><td class="c0">-1.2</td><td class="c1">-2.8</td><td class="c2">-4.4</td><td class="c2">-6.0</td><td class="c3">-7.8</td><td class="c3">-9.4</td></tr></tbody></table></div><figcaption class="bbt-table-note">Target Slip Offset Table 1, percentage points added to or taken off the slip target by road speed.</figcaption><p class="bbt-scroll-hint">Scroll the table sideways</p></figure>



<p class="wp-block-paragraph">Below 25 kph every setting adds nine percentage points of slip, and the loosest adds twenty five. That is the launch allowance. You cannot get a car like this moving from rest on a target of 2 percent, and without that offset the system would strangle it off the line.</p>



<p class="wp-block-paragraph">Between 45 and 160 kph the offset is zero and the lateral G table stands on its own. Above 180 it goes negative, and by 330 kph it is pulling back between 2 and 9.4 points depending on the setting.</p>



<p class="wp-block-paragraph">Which is the right way round. Wheel slip at 40 kph costs you a bit of time. Wheel slip at 300 kph costs you rather more than that.</p>



<h2 class="wp-block-heading">The reactive half: a deliberately soft PID</h2>



<p class="wp-block-paragraph"><strong>Status: Verified</strong></p>



<p class="wp-block-paragraph">When the feedforward is not enough, the PID takes over. And the gains are the opposite shape to what most people would write. All three share exactly the same breakpoints, so they go in one table.</p>



<figure class="bbt-figure"><div class="bbt-table-wrap"><table class="bbt-table"><thead><tr><th class="bbt-corner" rowspan="2"><span>Gain</span></th><td class="bbt-axis-x" colspan="8">Slip target error, %</td></tr><tr><th scope="col">-25.00</th><th scope="col">-20.00</th><th scope="col">-15.00</th><th scope="col">-10.00</th><th scope="col">-6.00</th><th scope="col">-4.00</th><th scope="col">-2.00</th><th scope="col">0.00</th></tr></thead><tbody><tr><th scope="row">Proportional</th><td class="c9">3.00</td><td class="c7">2.33</td><td class="c5">1.67</td><td class="c3">1.00</td><td class="c2">0.80</td><td class="c1">0.60</td><td class="c1">0.40</td><td class="c0">0.20</td></tr><tr><th scope="row">Integral</th><td class="c0">0.000</td><td class="c2">0.004</td><td class="c4">0.009</td><td class="c6">0.013</td><td class="c8">0.017</td><td class="c8">0.018</td><td class="c9">0.020</td><td class="c9">0.020</td></tr><tr><th scope="row">Derivative</th><td class="c9">3.00</td><td class="c9">3.00</td><td class="c7">2.28</td><td class="c4">1.55</td><td class="c3">0.97</td><td class="c2">0.68</td><td class="c1">0.39</td><td class="c0">0.10</td></tr></tbody></table></div><figcaption class="bbt-table-note">Each row is shaded against its own range, because integral peaks at 0.020 and proportional at 3.00. The colour shows the shape, not the magnitude.</figcaption><p class="bbt-scroll-hint">Scroll the table sideways</p></figure>



<p class="wp-block-paragraph">Proportional gain at zero slip error is 0.20. At minus 25 percent error it is 3.00. Derivative runs the same way, 0.10 at zero, and it saturates at 3.00 from minus 20 onwards.</p>



<p class="wp-block-paragraph">Both are smallest near target and largest far from it.</p>



<p class="wp-block-paragraph">That is a controller designed to be felt as little as possible. Around the target, where you spend almost all of your time, the loop barely reacts and the feedforward carries the car. Only when things run properly away does it bite hard.</p>



<p class="wp-block-paragraph">Tune it the conventional way round, with high gain near target for tight regulation, and you get a car that nibbles at the throttle constantly and feels like it is arguing with you.</p>



<h3 class="wp-block-heading">Integral is almost switched off, on purpose</h3>



<p class="wp-block-paragraph">Look at the integral row against the other two. Peak gain is 0.020, near target. At minus 25 it is <strong>zero</strong>.</p>



<p class="wp-block-paragraph">Zeroing the integral term exactly where the error is worst is anti windup by design. When the car is genuinely out of shape, the integrator stops accumulating instead of building up a correction you then have to unwind on the way out. An integrator that has wound up during a slide gives you a second event when it releases, and the second one is usually the one that catches people out.</p>



<p class="wp-block-paragraph">The rest of the PID setup backs that up:</p>



<ul class="wp-block-list">
<li>Integral control rate: 200 Hz</li>



<li>Integral positive clamp: 50.0 Nm</li>



<li>Integral negative clamp: -50.0 Nm</li>



<li>Minimum torque clamp: 50.0 Nm</li>



<li>Slip target filter: 4</li>
</ul>



<p class="wp-block-paragraph">Fifty Nm either side is a narrow band on an engine making 1,193. The integrator is there to trim, not to intervene.</p>



<h3 class="wp-block-heading">And the PID does not always run</h3>



<figure class="bbt-figure"><div class="bbt-table-wrap"><table class="bbt-table"><thead><tr><th class="bbt-corner" rowspan="2"><span>Driver demand torque, Nm</span></th><td class="bbt-axis-x" colspan="12">Slip target error, %</td></tr><tr><th scope="col">-6.00</th><th scope="col">-5.00</th><th scope="col">-4.00</th><th scope="col">-3.00</th><th scope="col">-2.00</th><th scope="col">-1.00</th><th scope="col">0.00</th><th scope="col">1.00</th><th scope="col">2.00</th><th scope="col">3.00</th><th scope="col">4.00</th><th scope="col">5.00</th></tr></thead><tbody><tr><th scope="row">0.0</th><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td></tr><tr><th scope="row">100.0</th><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td></tr><tr><th scope="row">200.0</th><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td></tr><tr><th scope="row">300.0</th><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td></tr><tr><th scope="row">400.0</th><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td></tr><tr><th scope="row">500.0</th><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td></tr><tr><th scope="row">600.0</th><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td></tr><tr><th scope="row">700.0</th><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td></tr><tr><th scope="row">800.0</th><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c0">0</td><td class="c0">0</td><td class="c0">0</td></tr><tr><th scope="row">900.0</th><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c0">0</td><td class="c0">0</td></tr><tr><th scope="row">1000.0</th><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c9">1</td><td class="c0">0</td></tr></tbody></table></div><figcaption class="bbt-table-note">PID Enable Table. 1 means the closed loop runs, 0 means it does not.</figcaption><p class="bbt-scroll-hint">Scroll the table sideways</p></figure>



<p class="wp-block-paragraph">Below 300 Nm of driver demand it is zero across the whole row. The closed loop simply does not run.</p>



<p class="wp-block-paragraph">Above that it opens up as a staircase. At 300 Nm the loop only runs once slip error is worse than minus 3 percent. Every additional 100 Nm of driver demand brings one more column into play, until at 1,000 Nm it is active everywhere except the far positive corner.</p>



<p class="wp-block-paragraph">So the amount of authority the closed loop has is itself a function of how much the driver is asking for. At low demand, feedforward handles everything alone, which means the PID cannot introduce noise into normal driving, because at normal driving loads it is not switched on.</p>



<h2 class="wp-block-heading">What it is allowed to do about it</h2>



<figure class="wp-block-image size-large"><img decoding="async" width="540" height="195" src="https://blownbytwins.co.uk/wp-content/uploads/2026/09/emtron-torque-limit-actuator-priority.png" alt="Emtron torque limit strategy showing priority 1 throttle area, priority 2 ignition retard, and priority 3 set to OFF so cutting is disabled" class="wp-image-1125" /><figcaption class="wp-element-caption">Priority 1 throttle area, priority 2 ignition retard, priority 3 OFF.</figcaption></figure>



<p class="wp-block-paragraph">Emtron gives you three actuators for torque reduction, in a priority order. Mine reads throttle area, then ignition retard clamped at 11 degrees, then <strong>OFF</strong>.</p>



<p class="wp-block-paragraph">Cutting is disabled. On a car making 1,114 whp, the harshest tool in the box is not in the box.</p>



<p class="wp-block-paragraph">The throttle area minimum clamp bottoms out at 10 percent, so it never closes the throttle fully either. Torque reduction happens by moving the plate and pulling timing, and nothing else.</p>



<p class="wp-block-paragraph">That is a road car decision. Fuel or ignition cutting is fast and effective and it feels like being kicked. On a car that has to be pleasant on a motorway and predictable in the wet, an intervention that arrives as a smooth reduction rather than a hammer blow is worth more than the extra tenth of response.</p>



<h2 class="wp-block-heading">Does it work?</h2>



<p class="wp-block-paragraph">One number from a road log, second gear, full throttle:</p>



<p class="wp-block-paragraph"><strong>Torque reduction by retard: 8.1 percent.</strong></p>



<p class="wp-block-paragraph">Eight percent, in retard, on the second priority, with cutting unavailable and throttle intervention having already done its part. That is the system working gently in the conditions where a badly normalised setup would be reaching for everything it had.</p>



<p class="wp-block-paragraph">It is one data point from one log, so treat it as an illustration rather than proof. But it is the shape of result the whole design is aimed at.</p>



<h2 class="wp-block-heading">The principle, if you take nothing else</h2>



<p class="wp-block-paragraph">A PID is not there to make your feedforward work. It is there to handle what the feedforward could not have known about: a damp patch, a change in surface, a mid corner bump.</p>



<p class="wp-block-paragraph">If your feedforward target is unrealistic, the PID spends its authority correcting your model instead of correcting the road. It saturates, it escalates through the actuator list, and the car feels like it is fighting you.</p>



<p class="wp-block-paragraph">Normalise the target to something the tyres can actually deliver, gate the loop so it only runs when it is needed, keep the gains soft near target, and the reactive half stays quiet almost all the time.</p>



<p class="wp-block-paragraph">Which is the point. The best traction control is the one you do not notice.</p>



<h2 class="wp-block-heading">One thing to be clear about</h2>



<p class="wp-block-paragraph">Every number above is specific to this car: this power, these tyres, this gearbox, this weight distribution. <strong>The data is not transferable, but the principle is.</strong></p>



<p class="wp-block-paragraph">I have published the tables in full because seeing how something is structured teaches you far more than reading a description of it. Copy the structure. Do not copy the values.</p>



<p class="wp-block-paragraph">None of this works without trustworthy wheel speeds, which on a staggered setup is less automatic than it sounds. That is covered in <a href="https://blownbytwins.co.uk/?p=1111">Staggered Tyres and Traction Control</a>. The throttle area table that the whole torque model sits on is covered in <a href="https://blownbytwins.co.uk/engine-management/throttle-body-effective-area/">Throttle Body Effective Flow Area</a>. Full specification is on the <a href="https://blownbytwins.co.uk/toyota-supra-mk4-delta/">Supra project page</a>.</p>



<p class="wp-block-paragraph">If you run torque based traction control and have taken a different view on any of this, particularly the gain shape, the setting 1 anomaly or disabling cut, I would like to hear it. This is the part of the calibration I have changed my mind about most.</p><p>The post <a href="https://blownbytwins.co.uk/cars/mk4-supra/traction-control-feedforward-pid/">Traction Control on 1,114 whp: Feedforward, PID, and Why It Never Cuts</a> first appeared on <a href="https://blownbytwins.co.uk">BlownByTwins</a>.</p>]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
