-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTrionic7Reference.tex
1900 lines (1693 loc) · 84.8 KB
/
Trionic7Reference.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\RequirePackage[l2tabu, orthodox]{nag}
\documentclass[11pt,a4paper]{book}
\usepackage[english]{babel}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{microtype}
\usepackage{mathtools}
\usepackage{todonotes}
\usepackage{graphicx}
\usepackage{blindtext}
\usepackage[hidelinks]{hyperref}
\usepackage{pdfpages}
\usepackage{fullpage}
\usepackage{csquotes}
\usepackage{booktabs}
\usepackage{standalone}
\usepackage{amssymb}
\usepackage{tcolorbox}
\tcbuselibrary{listingsutf8,breakable,theorems,skins}
%The paper size for this thesis is the Swedish format s5
\usepackage[
binary-units=true,
separate-uncertainty=true,
uncertainty-separator={\pm}
]
{siunitx}
\usepackage{lmodern}
\usepackage{verbatim}
\usepackage{todonotes}
\usepackage{subcaption}
\usepackage[standard]{ntheorem}
\usepackage{paralist}
\usepackage[noabbrev]{cleveref}
\usepackage{braket}
\usepackage{tipa}
\usepackage{multirow}
\usepackage{textcomp}
\usepackage{caption}
\usepackage{mathptmx}
\usepackage[symbol]{footmisc}
\usepackage{makeidx}
\usepackage{helvet}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{rotating}
\usepackage[siunitx]{circuitikz}
\usepackage[section,acronym]{glossaries}
\usepackage[style=numeric-comp,backend=biber,%
firstinits=true,sorting=none,sortfirstinits=true,clearlang=true,%
maxnames=3,minnames=1,uniquename=false,%
maxbibnames=10
]{biblatex}
\usepackage{tablefootnote}
\addbibresource{references.bib}
\graphicspath{{./graphics/},{./WIS/}}
\definecolor{theWhite}{gray}{0.9}
\definecolor{theBlack}{gray}{0.2}
\makeindex
\DeclareSIUnit\combustion{c}
\DeclareSIUnit[per-mode=reciprocal]\mgc{\milli\gram\per\combustion}
\DeclareSIUnit{\rpm}{rpm}
\DeclareSIUnit{\RON}{RON}
%% If the following definition throws an error, you'll need a newer version of your
% Latex distribution (from at least the second half of 2013)
\newtcbinputlisting[]{\commandline}[2][]{%
oversize,
colback=theBlack,
colframe=red!50!white,
coltext=theWhite,
listing only,
listing options={language={bash},aboveskip=0pt,belowskip=0pt,nolol,
basicstyle=\ttfamily\bfseries,extendedchars=true},
enhanced,
breakable,
lines before break=4,
listing file={#2},
arc=8pt,
#1
}
\newtcbinputlisting[]{\tcbexample}[2][]{%
oversize,
colframe=green!50!white,
text only,
enhanced,
breakable,
lines before break=4,
listing file={#2},
arc=8pt,
#1
}
\newcommand{\Mfig}[1]{%
\begin{figure}
\centering
\missingfigure{#1}
\caption{#1}
\end{figure}}
\include{definitions}
\begin{document}
\title{Trionic 7 Documentation}
\author{Dilemma, typeset in \LaTeX by Jonathan Jogenfors}
\maketitle
\clearpage
\frontmatter
\chapter{Introduction}
This document is intended for Saab fanatics and engineers who want to start
understanding the Saab Trionic 7 motor management system. It will give as much
information as possible about the technical part of the system. The only
limitation will be the knowledge of the author. In short the content of this
document will enable you to understand Trionic 7 better and give you hands-on
information about altering the maps it uses. Prerequisites are minor electronics
and computer knowledge and of course some understanding of how a turbo charged
engine works. Throughout the document the T7Suite software will be referenced.
This software will enable you to really \enquote{get into} the Trionic. The T7Suite
software can be downloaded from the T7Suite website.
\chapter{Acknowledgements}
This document is the result of contributions and hard work from many people over
a long time. Version 1.0 was put together by Dilemma in 2010, and he thanks
people on ecuproject for all their help. Dilemma gives special thanks go to General
Failure, J.K. Nilsson, Hook, Hma, Vigge, Mackan, Sandy Rus, JKB, L4staero and
Steve Hayes. Big thanks to solving the checksum calculation, I-bus information,
and P-bus information goes to Tomili and General Failure. L4staero contributed
information on the secondary lambda sensor. Magnus Lirell and David Goncalves
contributed information to the SID text and automatic transmission Canbus
message formats. David Concalves contributed information on the SID text
priority and Audio RDS Canbus message formats.
Beginning in 2015, a rework was started by Jonathan Jogenfors (Etnoy) to typeset
the information using \LaTeX{} and update the information together with other
enthusiasts over at TrionicTuning. Special thanks to chriva and many others.
This project is ongoing and you can check out the current status of the project
at \url{https://github.com/etnoy/t7ref}.
\chapter{Changelog}
\section*{From version 1.0 to 2.0}
Version 1.0 of this document is popularly referred to as
\enquote{\texttt{Trionic7.pdf}} as that was the filename. This is the version
produced by Dilemma and written mainly in Microsoft Word. As the original .doc
files appear to have been lost version 2.0 was created using \LaTeX{}. As a part
of this project, several appendices had to be removed due to copyright reasons.
A reader interested in finding that information is better off reading the actual
technical articles as follows:
\textcite{EstillIntercooler,FerozepuriaTurbocharger,Eriksson1998}.
\listoftodos[Things to be done]
This chapter tracks the todo list for this document. This includes information
that is deemed missing, incorrect, unclear, or needs rework. Also, a lot of
figures and graphs must be manually imported form Dilemma's document, those are
also listed here.
\tableofcontents
\mainmatter
\chapter{Hardware}
The Trionic 7 is built around a Motorola MC68332 (CPU32) microcontroller. This
is a 32-bit controller that handles the entire motor management including fuel
injection, ignition timing and boost pressure control. The processor has a vast
\SI{4}{\mega\byte} (\SI{512}{\kilo\byte}) flash memory for fetching program code
and maps. This flash memory consisting of a AM29F400BT-90SI (AMD) holds the
program memory. There is a coprocessor from Philips, a P83C592FHA/019. This is a
8-bit 8051-based microcontroller with a CAN (Controller Area Network) module. As
the CAN physical line driver there is an Intel AN82527 (same family as used in
Trionic 5). RAM memory is done by two \SI{32}{\kilo\bit} SRAM chips
(U62H256S1K). There is also a special component that would appear to be a
barometric pressure sensor.
\section{Integrated Circuit List}
The table below lists almost all integrated circuits on the board. This is just to give you an idea on what to expect.
\begin{table}
\centering
\begin{tabular}{llll}
Partnumber & Function & Usage & \# on board \\
\midrule
TC55257DFI-85L & SRAM & (working memory) & 1 \\
16233970 & Microcontroller & Main 32-bit CPU & 1 \\
PC83C592 & Microcontroller with CAN contr.& 8-bit coprocessor & 1 \\
AM29F400 & Flash memory & \SI{4}{\mega\bit} & 1 \\
51862 & DA converter & & 1 \\
AN82527 & CAN controller CAN line driver & 1 \\
16238669 0H11 & Pressure sensor? & & 1
\end{tabular}
\caption{}
\label{tab:}
\end{table}
\section{Block Schematic Diagram}
\begin{figure}[]
\centering
\missingfigure{}
\caption{}
\label{fig:}
\end{figure}
\section{DI Cassette}
The DI cartridge has a trigger input for firing the four individual sparkplugs. These are triggered by
signals from the ECU on pin 9, 10, 11 and 12 which are generated in the power driver IC CA3236 on
the Trionic PCB (topside, 16 pin DIL housing). Internally these four pins are connected as shown in
the table and the image below.
\begin{table}
\centering
\begin{tabular}{cccc}
DI cartridge pin & ECU pinnumber & CA3236 pinnumber & Description \\
\midrule
2 & 7 & 1 (OUT A) & Trigger cylinder 1 \\
3 & 8 & 3 (OUT B) & Trigger cylinder 2 \\
4 & 67 & 6 (OUT C) & Trigger cylinder 3 \\
5 & 68 & 8 (OUT D) & Trigger cylinder 4 \\
\end{tabular}
\caption{}
\label{tab:}
\end{table}
\chapter{Flashing}
The Trionic 7 ECU binary images uses several checksums to verify integrity. Most
of them have been easy to figure out, but one of them is so complicated, that it
seems to been done to deter map changing. There are still some unknowns, that
would be nice to figure out. For example, I've discovered some binaries don't
seem to have all four checksums. And of course there could be more checksums
that have gone unnoticed. Two of the checksums are in the end of the binary and
the other two are scattered in the code. The latter ones can be found by using
pattern searching. Again the calculations are pretty simple, and even the harder
checksum is easy to implement.
\section{Checksums}
First of all, there are four different checksums. They have been given names by
Tomi\todo{Who is this?}: \texttt{FB}\index{FB checksum} checksum,
\texttt{F2}\index{F2 checksum} checksum,
\texttt{Misc} checksum\index{Misc checksum}, and \texttt{Area 70000}
checksum\index{Area 7000 checksum}.
\subsection{FB and F2 checksums}\label{sec:FBF2Checksum}
The first two checksums, \texttt{FB} and \texttt{F2}, can be found at the end of
the binary. This end area has been called the file header (footer would be more
logical). See also \todo{Add reference}chapter Trionic 7 file header. The
\texttt{F2} checksum is not present in all binaries, so be aware of this.
Finding the two other checksums is more of a challenge.
\subsection{Misc checksum}
The Misc checksum resides inline within the code. It is usually found somewhere
between \texttt{0x02000} and \texttt{0x05000}. The checksum address can be found
by pattern searching the bin file using a set of hex values along with mask
bits. If a mask bit is not set, the corresponding hex value does not have to
match. Here are the hex values: \texttt{0x48, 0xE7, 0x00, 0x3C, 0x24, 0x7C,
0x00, 0xF0, 0x00, 0x00, 0x26, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x28, 0x7C,
0x00, 0xF0, 0x00, 0x00, 0x2A, 0x7C} and the mask is \texttt{1, 1, 0, 0, 0,
0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1}.
So, we are searching the binary for a string of bytes beginning with
\texttt{0x48, 0xE7, 0x00, 0x3C\ldots}. Then we mask out the bytes that change
from binary to binary. When we've located this pattern, we know where to start.
Now we start primitively disassembling the code. We search for byte patterns
\texttt{0x48, 0x6D}, \texttt{0x48, 0x78}, \texttt{0x48, 0x79}, \texttt{0x2A,
0x7C} and \texttt{0xB0, 0xB9}. The three first patterns reveal addresses and
lengths of checksum areas. There are 15 checksums areas from which the
\texttt{Misc} checksum is calculated. The \texttt{0x2A, 0x7C} pattern gives a
base address for the \texttt{0x48, 0x6D} addresses.
Bear with me. These \texttt{0x2A, 0x7C} addresses are summed with the base
address to make the actual address. This way the address is only 2 bytes long.
On the \texttt{0x48, 0x79} addresses it's 4 bytes long without any base address.
And the \texttt{0x48, 0x78} pattern gives 2 bytes which correspond with the
length of the checksum area. Finally the \texttt{0xB0, 0xB9} pattern is followed
by 4 bytes to the address of the Misc checksum.
\subsection{Area 70000 checksum}
\index{Area 7000 checksum}This checksum refers to an area in the region of
\texttt{0x70000}. Like the \texttt{Misc} checksum, there is no clean way of
finding out the length of the area along with the checksum address. Using
pattern searching with this also has results. There are binaries that are
incompatible with this approach, so this requires some fixing in the future. The
pattern is \texttt{0x20, 0x3c, 0x00, 0x00, 0x11, 0x52, 0x2F, 0x00, 0x20, 0x3C,
0x00, 0x00, 0x09, 0xD0, 0x2F, 0x00, 0x20, 0x3C, 0x00, 0x00, 0x00, 0xCC,
0xD0, 0x9F} and the mask is \texttt{1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1, 1, 1, 0, 0, 0, 0, 1, 1}
After finding that pattern, the masked addresses are summed together. In the
pattern, the original addresses are \texttt{0x00001152}, \texttt{0x000009D0} and
\texttt{0x000000CC}. Summing these gives the \texttt{Area 70000} length of
\texttt{0x1BEE}. At the same time this is the address where to find the \texttt{Area
70000} checksum.
\section{Computing the Checksums}
The \texttt{FB} checksum shares the same calculation method as the \texttt{Misc}
and \texttt{Area 70000} checksums. It's simply a sum of the bytes from the
checksum area. Four bytes are made into a 32 bit value and summed with the next
32-bit value. This goes on until there are fewer than 4 bytes left. The last 1,
2 or 3 bytes are then individually summed together with the checksum.
The \texttt{Misc} checksum is a sum of the individual checksums calculated from
15 areas. The checksum calculation used is the same as with the \texttt{FB}
checksum.
Once you have found the length of \texttt{Area 70000}, you can calculate the
checksum by using the function described in \cref{sec:FBF2Checksum}. The start
address is \texttt{0x70000}. Notice that your binary might not have this area
present.
\chapter{Firmware}\index{Firmware}
Once you are done with dumping the flash contents and you want to do more than
only alter variables and maps you can start analyzing the binary. This is a
difficult task because there are a lot of different firmware versions, stock
ones – maybe different per MY and tuned ones that differ for every manufacturer
and stage. In every case the code can be disassembled using a \texttt{6833x}
disassembler like the one in \texttt{IDA Pro}\index{IDA Pro}. There are scripts
available to automatically disassemble the code and make it more readable by
replacing addresses by variable names that are extracted from the symbol
table\index{Symbol table} inside the binary.
\chapter{Symbol table}
Each Trionic 7 firmware file contains a symbol table describing data structures in the
program. The major problem is that from some point in time SAAB started to
compress the symbol tables in the binary file. Probably just to save space in
the flash memory but it has made tuning a little harder. We actually need these
symbol names because they tell us what a certain memory location means. For
unpacked binaries these symbols can be extracted together with their
corresponding memory addresses (ROM and RAM).
\begin{figure}[]
\centering
\includegraphics{symboltable.png}
\caption{}
\label{fig:}
\end{figure}
While examining the symbol table you can see that the separator is 0x00. In
contrast to T5 where symbol and SRAM addresses reside in the same table, we now
only find the symbol name. In another table in the binary we can find flash
addresses and lengths in the same sequence as the symboltable.
\section{Finding start of symbol table:}
Search binary for string the first sequence of 15 zeros.
\section{Finding start of address lookup table:}
Search binary for 20 00 00 00 XX YY 00 F0 where XX YY is the index of the first
symbol found in the symbollist.
To save you the time to lookup all addresses manually the T7Suite application
will extract all symbol information in one run. Symbol name, flash address and
length will be displayed all together.
This \todo{link}image (6) will give you an idea of what the symbol table should
look like once it has been extracted. See \todo{link}appendix I for a complete
list of known symbols.
\begin{figure}[]
\centering
\missingfigure{}
\caption{}
\label{fig:}
\end{figure}
When the user double clicks one of the symbols that has a flash address attached
to it, T7Suite will display the corresponding symbol in a viewer. This viewer
will display the data in table form was well as in graphical form.
\begin{figure}[]
\centering
\missingfigure{}
\caption{}
\label{fig:}
\end{figure}
\chapter{Mapping}
A lot of maps in Trionic 7 are not only made up of a piece of raw data. It also
includes x-axis and y-axis information. T7Suite will automatically display all
known axis information when a map is opened. In Trionic 7 most symbols have an
English name (Trionic 5 has lots of Swedish names) that explains lots about its
function. Also, the symbols are categorized by name, which makes browsing the
symbols much easier. All torque calibration symbols start with
\enquote{TorqueCal.}. T7Suite groups all symbols by their respective category by
default.
\section{Fuel}
Fuel calculation in Trionic 7 is based on the Airmass entering the engine. In
rough steps this seems to be the flow of the calculation:
\begin{enumerate}
\item Basic calculation of fuel quantity per combustion. The air mass per
combustion in \si{\milli\gram} is converted to fuel mass in
\si{\milli\gram} by dividing by the AFR. This is dependent on fuel type:
\begin{equation}
\text{mGasoline}=\frac{\text{mAir}}{14.7}, \qquad
\text{mE85}=\frac{\text{mAir}}{9.765}
\end{equation}
\item In case of a cold engine, shortly after starting, rapid load changes,
knocking or high loads, the fuel mass is multiplied by a compensation
factor.
\item The closed loop value is used as a multiplier.
\item Correction for purge. Multiply by the value for purge adaptation. The
value is sent to box 5
\item Long term fuel trim. The fuel mass is multiplied by the multiplicative
adaptation value.
\item Additive adaptation. The additive adaptation value is added to the
fuel mass.
\item Starting fuel quantity. If the engine has not yet started, starting fuel is
selected.
\item The fuel quantity per combustion is the amount of fuel to be
supplied to the engine.
\item Computation of injector opening duration. Converts fuel mass to
opening time from a lookup table.
\item Injection takes place twice per combustion until the
camshaft position has been found. Injection duration
is divided by two.
\item Battery voltage correction. Injector opening duration is corrected
by a voltage-dependent factor that is added to the duration.
\item If fuel cut is active, the computed injector duration is replaced by a
fuel cut value.
\end{enumerate}
After this computation, the current injector is opened for the computed duration
of time at a determined crank shaft angle. We will now look at the maps that
control the above computation.
The basic fuel quantity is calculated based on air mass (measured from the air
mass flow sensor) and injector constant
(map \texttt{InjCorrCal.InjectorConstant\index{InjCorrCal.InjectorConstant}}).
\begin{figure}
\centering
\includegraphics[width=.9\linewidth]{injectorconstant.png}
\caption{InjCorrCal.InjectorConstant}
\label{fig:injectorconstant}
\end{figure}
If the engine has reached operating temperature, the standard map
\texttt{BFuelCal.Map} is used. If not, the map is switched out for the cold
start map \texttt{BFuelCal.StartMap}.
\begin{figure}
\centering
\includegraphics[width=.9\linewidth]{startmap.png}
\caption{BFuelCal.StartMap}
\label{fig:startmap}
\end{figure}
\begin{figure}
\centering
\includegraphics[width=.9\linewidth]{fuelmap.png}
\caption{BFuelCal.FuelMap}
\label{fig:fuelmap}
\end{figure}
The areas calibrated to be run in closed loop have a value of \num{1.00(2)}.
Note that the high load part of the maps ramp up to enrich the mixture.
Therefore, adjust the closed loop part of the map first.
To do this, turn closed loop mode off and drive with a wideband lambda sensor.
What you want to achieve is an AFR of 14.7 while driving around under light
loads (i.e. \num{1.00(2)} as per above). What Trionic 7 then does is to compute
an injector duration. If the measured AFR does not achieve the correct value,
the map must be altered. For example, if Trionic 7 computes a duration of
\SI{5}{\milli\second}, a map value of \num{1.1} results in a duration of
$5*1.1=$\SI{5.5}{\milli\second} which means more fuel and a richer mixture.
Conversely, a value below \num{1.1} results in a leaner mixture.
The idea is to get the closed loop area correct first. This will stop any
negative adaption once the tune is finished and allowed to run in closed loop
again. If the closed loop area of your fuel map is too rich it will negatively
adapt over a long period of time. This will have the effect of leaning your
air-fuel ratios across the board.
For example, let's look at a tune with an AFR that is correct in closed loop.
This means that the feedback from the $\textrm O_2$ sensor is enough to
correct the combustion. This can hide a condition where the mixture is too rich
by \SI{13}{\percent} and the $\mathrm O_2$ sensor reduces the fuel mass by
\SI{13}{\percent}. Then, when full power is applied, Trionic 7 enters open loop
mode and the wideband lambda sensor measures an AFR of \num{12.5}.
If this condition remains, Trionic 7 will adjust the long term fuel trim
(multiplicative adaption, \texttt{Amul}\index{Amul}) to be \SI{-13}{\percent}
after a number of weeks. This makes the fuel calculation reduce the fuel
injection by \SI{13}{\percent} over the whole range, including full power.
Here's the danger. At the next full power run, there will be \SI{13}{\percent}
less fuel than ideal, resulting in an AFR of \num{14.0}. The engine now runs
lean and \emph{can fail very quickly, causing massive internal engine damage}.
Now back to fuel mapping. To set closed loop area of fuel map, monitor the AFR
in this light load area and if its wrong after adjusting for large injectors,
start by just adjusting the Injector constant up and down accordingly instead of
altering the closed loop area of the \texttt{BfuelCalMap}. This will affect the
whole map instead of one point. By doing it this way you can almost get AFR spot
on in closed loop area just by a few goes at adjusting the injector constant.
It can be found in \texttt{InjCorrCal.InjectorConst}, the value represents the
injectors flow in mg of fuel (not capacity or cc's as injectors are normally
rated in). The injector constant is a calculation factor used by Trionic 7 to
calculate injection time.
Once closed loop area is done the high load area can be mapped. If its too lean
just increase the values in the relative column relating to what site of the map
you are running in. Once your high load areas are done, activate closed loop
again so you can see how it all runs. Monitor fuel adaptations and AFR etc.
One thing to note is how quickly it drops into open loop under full throttle. By
going into open loop the O2 sensor is "masked" where the ECU listens to what its
saying but ignores it, this allows AFR to go beyond 14.7 and injection
correction is directly taken from the fuel map we just adjusted allowing much
enrichment to cool charge etc.
To alter open loop enrichment you can change at what Airmass flow Trionic 7
switches to open loop in \texttt{LambdaCal.MaxLoadNormTab}. Also, open loop
entry (so, leaving closed loop situation) has a delay attached to it. This way,
short overruns of the maximum load will not immediately result in leaving closed
loop. Stock bins often have this set to 2000 milliseconds which seems quite
long. If you want to ECU to leave closed loop faster after overrunning the load
limit, just decrease the time in \texttt{LambdaCal.TimeOpenLoop}.
\begin{figure}
\centering
\missingfigure{}
\caption{Battery correction values for injector latency}
\label{fig:}
\end{figure}
\begin{figure}
\centering
\missingfigure{}
\caption{Water temperature correction}
\label{fig:}
\end{figure}
\begin{figure}
\centering
\missingfigure{}
\caption{Fuel injection correction map for knock conditions}
\label{fig:}
\end{figure}
\section{Ignition}
\begin{figure}
\centering
\includestandalone{ignition}
\caption{Flowchart for ignition calculation}
\label{fig:}
\end{figure}
\begin{enumerate}
\item Idling speed ignition timing With idle speed control active, the
timing is adjusted to stabilize idle engine speed. The value is sent to
box 3
\item Normal ignition timing When idle speed control is inactive, the
ignition
timing is read from a load and engine speed
depending matrix. The value from the matrix is
optimized for lowest fuel consumption (best engine
torque) and sent to box 3
\item Selection of ignition timing One of the ignition timing calculation is selected
depending on which function is active. The value is
sent to box 6
\item Catalytic converter heating timing In order to heat up the catalytic
converter as fast as possible after start, the ignition will be
retarded. This is a compensation matrix that is added to the value in
box 3. The matrix is dependent on load and
engine speed
\item Engagement of catalytic converter heating timing The function is
active when coolant temperature is above -10 degrees Celsius and below
+64 degrees
Celsius
\item Total The value from box 5 is added to the value of box 3
\item Compensation The ignition timing is corrected depending on engine
coolant temperature and intake air temperature. The
value is sent to box 6.
\item Knock control If knocking occurs, a timing retardation will be
calculated. The value is sent to box 6
\item Total The compensation angle and knock retardation are
totalled to give the current ignition timing. The value
is sent to box 7
\item Selection of ignition timing Starting ignition timing is selected when
the engine has not been started. The value is sent to box 9
\item Starting ignition timing Starting ignition timing is selected when the
engine has not yet been started. The value is sent to box 9
\item Activate relevant trigger At the calculated crankshaft angle, the
microprocessor controls the transistor for the trigger
that is next in firing order
\end{enumerate}
\begin{figure}
\centering
\missingfigure{}
\caption{ignition chart}
\label{fig:}
\end{figure}
\subsection{DI Cassette}
The direct ignition (DI) cassette is mounted on the valve cover on top of the
spark plugs. The DI cassette houses four ignition coils/transformers whose
secondary coil is directly connected to the spark plugs. The ignition cassette
is electrically supplied with battery voltage from the main relay (\texttt{B+})
and is grounded in an earth point. When the main relay is activated the battery
voltage is transformed to \SI{400}{\volt} DC which is stored in a capacitor. The
\SI{400}{\volt} voltage is connected to one of the poles of the primary coil in
the four spark coils. Connected to the DI cassette there are four triggering
lines (from the Trionic ECU, pin 9 (cyl. 1), pin 10 (cyl. 2), pin 11 (cyl. 3)
and pin 12 (cyl. 4)). When the ECU is grounding pin 9, the primary coil for the
first cylinder is grounded (via the \texttt{B+} intake of the DI cassette) and
\SI{400}{\volt} is transformed up to a maximum of \SI{40}{\kilo\volt} in the
secondary coil for cyl. 1. The same procedure is used for controlling the
ignition on the rest of the cylinders. \Mfig{DI Cassette}
\subsection{Idle control}
\Mfig{idlecontrol}
\Mfig{Ignition is normally controlled by the main ignition matrix:
IgnNormCal.Map}
\section{Torque}
Trionic 7 is a torque/Airmass request system instead of a boost request system like Trionic 5 is.
The basic procedure for the Airmass controller is like in the table below.
\begin{enumerate}
\item Driver request The control module reads pedal potentiometer 1 and
converts the voltage to Airmass per combustion (\si{\mgc}). The value is
sent to box 3
\item Cruise control request When cruise control is active, the air mass per
combustion required to maintain the set speed is calculated. The value
is sent to box 3
\item Select highest value The control module selects the highest of the two
values (box 1 or box 2). The value is sent to box 5
\item Engine torque limitation The maximum permissible air mass per
combustion varies depending on the engine type. During operation, the
maximum permissible \si{\mgc} must also be limited to protect the
engine, gearbox, brakes and turbo
\item Select lowest value The control module selects the lowest value and
sends it to box 8
\item Compensation request When the AC compressor is on, and when the heated
rear window or radiator fan is on, the \si{\mgc} required to compensate
for the increased load is calculated. The value is sent to box 8
\item Other air request The control module calculates the \si{\mgc} required
for idle speed control. The value is sent to box 8
\item Totalling values The control module totals all the values. The total
is sent to box 9
\item Total requested \si{\mgc}
\item Total Airmass request
\item Throttle control The requested \si{\mgc} is converted to requested voltage for throttle
position sensor 1. The charge air pressure and intake air temp are
used to correct this conversion. The throttle motor rotates the throttle
until the current voltage for throttle position sensor 1 corresponds with
the requested voltage
\item Current \si{\mgc} The requested \si{mgc} is also compared with the
current \si{mgc} (MAF
reading). If needed the requested voltage for throttle position sensor 1
is finely adjusted
\item Turbo control If \si{\mgc} is too high for throttle alone the turbo control will take over.
The excess is converted to a PWM which controls the charge air
control valve. The absolute pressure sensor is used to correct the
conversion
\item Current \si{\mgc} The requested \si{mgc} is compared to current \si{mgc} and the charge air
control vale PWM is finely adjusted if required
\end{enumerate}
\subsection{Torque request}
When the driver (or cruise control for that matter) presses the accelerator
pedal this is interpreted as a certan airmass request from the system. This
value is fetched from the \texttt{PedelMapCal.m\_RequestMap} shown below.
\Mfig{PedelMapCal.m\_RequestMap}
The table holds Airmass values for each position of the accelerator pedal and
each rpm site. Trionic now looks up the estimated engine output (torque) based
on Airmass and rpm. This is done through map \texttt{TorqueCal.M\_NominalMap} as
shown next.
\Mfig{TorqueCal.M\_NominalMap}
\section{Second lambda sensor}
In the years Trionic 7 was shipped on cars, several things changed in these cars
setups. One of the major changes was the introduction of the second lambda
(oxygen, O2) sensor that is placed after the catalyst to ensure the catalyst is
working properly. If you want to run software from a double lambda sensor car in
a single lambda car, you have to make some changes in the settings.
\subsection{Turning off second lambda sensor}
You can use this procedure in cars having only one lambda sensor and in cars
having two lambda sensors, but with a missing catalyst.
\begin{table}
\centering
\begin{tabular}{lll}
Map & Value& Description \\
\midrule
LambdaCal.ST\_AdapEnable & 0 &Second lambda sensor disabled \\
LambdaCal.ST\_AdapEnable & 1& Second lambda sensor enabled \\
\end{tabular}
\caption{}
\label{tab:}
\end{table}
\subsection{Alternative solution to turning off second lambda}
Change low limit on \texttt{O2heaterPostCal.I\_LowLim} to \SI{0}{\milli\ampere}
to disable sensor heater error, and change \texttt{CatDiagCal.LoadHi} and
\texttt{CatDiagCal.LoadLo} to values never seen normally, like 30 and 20.
\begin{table}
\centering
\begin{tabular}{lll}
Map & Value & Description \\
\midrule
O2HeatPostCal.I\_LowLim& 0& \multirow{3}{*}{Second lambda sensor disabled} \\
CatDiagCal.LoadLo &20 &\\
CatDiagCal.LoadHi &30&\\
O2HeatPostCal.I\_LowLim & 230 & \multirow{3}{*}{Second lambda sensor enabled}\\
CatDiagCal.LoadLo &140 &\\
CatDiagCal.LoadHi &425 &\\
\end{tabular}
\caption{}
\label{tab:}
\end{table}
\section{Calibration of OBD2 and LEV EVAP systems}
If we want to run a file that was developed for OBD2 or a LEV car in an earlier
car we run into problems because the early car is missing a second catalyst, a
tank pressure sensor and a purge canister behind the fuel tank. If you have an
early B205E/L engine you simply couldn’t run a later B205R software version in
it because it would through CEL’s for the missing hardware. We need to make
changes to the file before we can run in on an earlier car (e.g. switch of the
control of the new hardware).
\begin{itemize}
\item
\texttt{OBDCal.OBD2Enabled} This is self explanatory, if car is OBD2
put value at 1 if it's not OBD2 put value at 0.
On this point in later bins(compressed) there is EOBDEnable which is always on
in EC2000 EU files and LOBDEnable which is always on in EC2000 RW files. File
type is shown in firmware information under engine type.
\item \texttt{OBDCal.EnableOBD2Limit} As above but its a 4 byte value. If done
in Hex value for a OBD2 car is 00000001 and for non-OBD2 car is 00000000. As
shown in T7suite is 2 values. OBD2 cars top value is 1 and bottom value is
0. In non OBD2 car both values are 0.
\item \texttt{OBDCal.evapEquipmentExist} If car is equipped with a canister at
rear of tank and a tank pressure sensor value will be 1. If neither exist value
should be set to 0.
\end{itemize}
\subsection{Info on LEV (Low Emission Vehicle)}
For example take a 2001 Saab 9-3 Aero (or SE as called in USA) equipped with a
B205R, Saab's decision to take all "R" engines and clean them so to speak by
developing new emission systems for them leaves them with some differences to
their low level engine relatives. The term LEV(Low emission vehicle) in this
sense refers to Saab's decision to add a second catalytic converter and a tank
pressure sensor and a large purge canister behind fuel tank, as well as adding a
2nd oxy to monitor condition of first cat.
\section{Footer information}
If we look at the footer in the binary (last page in hex viewer) we see a set of
reversed strings. Each of these strings contains an identifier. These
identifiers have a hardcoded meaning.
\begin{table}
\centering
\begin{tabular}{lll}
Identifier & Length & Description \\
\midrule
0x91& 0x09& Ecuid.vehicleidnr \\
0x94 & 0x07 & Ecuid.ecuhardwversnr \\
0x95 & 0x0C & Ecuid.ecusoftwnr \\
0x97 & 0x1E & Ecuid.ecusoftwversnr \\
0x9A & 0x04 & Ecuid.softwaredate \\
0x9C & 0x04 & variable name table crc (not really sure) \\
0x9B & 0x04 & Symboltable (packed table with symbol names) \\
0xF2 & 0x04 & F2 checksum \\
0xFB & 0x04 & Romchecksum.piareachecksum \\
0xFC & 0x04 & Romchecksum.BottomOffFlash \\
0xFD & 0x04 & RomChecksumType \\
0xFE & 0x04 & Romchecksum.TopOffFlash \\
0xFA & 0x05 & Lastmodifiedby \\
0x92 & 0x0F & Ecuid.partnralphacode (IMMO) \\
0x93 & 0x07 & Ecuid.ecuhardwnr \\
0xF8 & 0x02 & ? \\
0xF7 & 0x02 & ? \\
0xF6 & 0x02 & ? \\
0xF5 & 0x02 & ? \\
0x90 & 0x11 & Ecuid.scaletable (VIN) \\
0x99 & 0x06 & Ecuid.testerserialnr \\
0x98 & 0x0D & Ecuid.enginetype \\
0xF9 & 0x01 & Romchecksum.Error
\end{tabular}
\caption{}
\label{tab:}
\end{table}
\Mfig{footer}
\chapter{Tuning Trionic 7}
\section{Tuning with T7Suite}
To get the ECU to produce more engine output, several parameters (maps) have to
altered. This chapter will give you a general idea on what to change – and why –
for getting to an approximate stage II equivalent. The example is a 9-3 B205R.
\subsection{AirCtrlCal.m\_MaxAirTab}
Airmass value from controller where area map has reached max-area and there is
no point to increase the I-part. Resolution is
\SI{1}{\mgc} \Mfig{AirCtrlCal.m\_MaxAirTab}
\Mfig{MaxAirTab}
\subsection{AirCtrlCal.m\_MaxAirE85Tab}
( if running on E85 )
Same as above for E85
\subsection{BoostCal.I\_LimTab}
Load limit tab. to enable the I Part of boost regulator. If the load request
from Airmass master is above this value plus the hysteresis is the I Part
enabled and the throttle closed loop is disabled. If the load request from
Airmass master is below this value is the I Part disabled and the throttle is
allowed to run in closed loop.
\Mfig{ILimTab}
\subsection{BoostCal.P\_LimTab}
Load limit tab. to enable the P Part of boost regulator. If the load request
from Airmass master is above this value plus the hysteresis is the P Part
enabled. If the load request from Airmass master is below this value is the P
Part disabled.
\Mfig{Plimtab}
\subsection{BoostCal.RegMap}
Main constant matrix. Resolution is \SI{0.1}{\percent}.
\Mfig{RegMap}
\subsection{BstKnkCal.MaxAirmass}
(divide by \num{3.1} for approx torque, ignition, airtemp etc affect this!)
Map for max allowed Airmass for manual gearbox, \texttt{m\_nHigh}. Resolution is
\SI{1}{\mgc}.
\Mfig{MaxAirMass}
\subsection{BstKnkCal.MaxAirmassAu}
Map for max allowed Airmass for automatic gearbox, m\_nHigh. Resolution is \SI{1}{\mgc}.
\subsection{FCutCal.m\_AirInletLimit}
If the "MAF.m\_AirInletFuel" is higher than this limit during m\_AirInletTime
will the fuelcut be activated ( pressure guard ).
\Mfig{AirInletLimit}
\subsection{IgnE85Cal.fi\_AbsMap}
( if you want to change the ignition )
Ignition map for E85 fuel. Resolution is 0.1 degrees.
\Mfig{AbsMap}
\subsection{IgnNormCal.Map}
( if you want to change the ignition )
Normal ignition map. Resolution is 0.1 degrees.
\subsection{MapChkCal.CheckSum}
(automatically updated in between every map
change with T7suite!)
\subsection{MaxVehicCal.v\_MaxSpeed}
Speed limiter.
\subsection{PedalMapCal.m\_RequestMap}
Requested Airmass from the driver as a function of rpm and accelerator pedal
position. Resolution is \SI1{\mgc}.
\Mfig{RequestMap}
\subsection{TorqueCal.M\_ManGearLim}
Maximum engine torque limit for each gear in the manual gearbox. Resolution is 1 Nm.
\Mfig{ManGearLim}
\subsection{TorqueCal.m\_AirTorqMap}
(This is where all torque limiters take their data from and therefore needs to
be "fooled" if you are running 400nm+ or an automatic!) Data-matrix for nominal
Airmass. Engine speed and torque are used as support points. The value in the
matrix + friction Airmass (idle Airmass) will create the pointed torque at the
pointed engine speed. Resolution is \SI1{\mgc}. axis to the above map:
TorqueCal.m\_AirXSP
\Mfig{AirTorqMap}
\subsection{TorqueCal.M\_EngMaxTab}
Data-table for maximum engine out put torque for manual cars. Resolution is 1 Nm.
\Mfig{EngMaxTab}
\subsection{TorqueCal.M\_EngMaxAutTab}
Data-table for maximum engine output torque for automatic cars. Resolution is 1 Nm.
\Mfig{EngMaxAutTab}
\subsection{TorqueCal.M\_5GearLimTab}
Data-table for maximum engine output torque for manual cars on fifth gear.
Resolution is 1 Nm.
\Mfig{5GearLimTab}
\subsection{TorqueCal.M\_EngMaxE85Tab} ( if running on E85 )
Data-table for maximum engine output torque when running on E85. Resolution is 1 Nm.
\subsection{TorqueCal.m\_PedYSP}
Air mass support points for (Calc) X\_AccPedalMap. Resolution is \SI1{\mgc}.
\Mfig{PedYSP}
\section{Tuning Boost calibration}
This map holds percentages (0.1\% accurate) of how much air should be passed to
the return hose of the boost control value. The higher the value, to more air is
bled off and the less the wastegate will open (and thus, the more air the turbo
will be spooling). As you can see, the more Airmass is requested (\texttt{x} axis) the
more the wastegate is held shut and thus, the more Airmass the turbo will be
providing. If we want more Airmass from the turbo, we need to keep the wastegate
shut longer and thus we have to enter higher numbers on the right side of the
table.
\Mfig{BoostCal
}
\section{Altering Airmass limiter}
To be able to flow more air though the engine that is allowed in the stock
configuration we will have to modify the Airmass limiter tables as well. Note
that there are two different ones, one for manual gearbox and one for automatic
gearbox. This example will only show the manual gearbox table
(\texttt{BstKnkCal.MaxAirmass}) but for automatic cars
\texttt{BstKnkCal.MaxAirMassAu} needs to be
changed.
\Mfig{MaxAirMass}
As you can see, the maximum amount of Airmass allowed is approximately
\SI{970}{\mgc}. We need to change the table so that it will allow more Airmass.
In this case we just up the table with \SI{25}{\percent} with the math functions
in T7Suite. NOTE: Please do not simply turn off this limiter by setting it way
higher than the actually intended level because it is an important limiter to
provide engine safety.
\section{Altering fuelcut}
Then there’s the fuelcut function to worry about. We need to increase the limit
of what the fuel cut function will accept to prevent it from shutting of fuel
too early.
\Mfig{FuelCut}
NOTE: Please do not simply turn off this limiter by setting it way
higher as the actually intended level because it is an important limiter to
provide engine safety.
\section{Engine speed limiter}
To prevent the system to reduce Airmass above engine speeds that are still
acceptable we need to change \texttt{MaxSpdCal.n\_EngLimAir} as well. Y axis
values are engine temperature (coolant). Please note that \SI{200}{\rpm} above
this limit, the fuel cut mechanism will become active!
\Mfig{Engine speed limit}
\section{Vehicle speed limiter}
An option is to increase the vehicle speed limiter as well. In this stock binary
the vehicle speed is limited to \SI{240}{\kilo\meter\per\hour}. We can change it
to – for example
\SI{280}{\kilo\meter\per\hour}.
\Mfig{Vehicle speed limit}
\section{Airmass request}
To get more from the engine than in the stock configuration we need to actually
request more Airmass for a certain pedal position and rpm site. This can be done
through \texttt{PedalMapCal.m\_RequestMap}. Because we want more power at wide
open throttle (from the drivers perspective) we need to increase the Airmass
request at pedal positions in the high percentage range (top of the table).
\Mfig{Pedal Request Map}
As you can see we increased the top two rows so that a maximum of
\SI{1350}{\mgc} will be requested. In addition we need to alter the y axis
support point for the pedal map that lets Trionic lookup a pedal position for a
given Airmass. This map is called \texttt{TorqueCal.m\_PedYSP}. This axis map
should support the maximum Airmass we’re requesting in the
\texttt{TorqueCal.m\_Requestmap}, so in our case we need to modify the map to
match the \SI{1350}{\mgc} we are requesting as a maximum.
\Mfig{PedYSP}
The map that uses this axis is called \texttt{TorqueCal.x\_AccPedalMap}. It it
shown below with the altered axis values for clarification.
\Mfig{AccPedalMap}
\section{Torque limiter}
To prevent to system to reduce Airmass above a certain engine output, the torque
limiter needs to be increased according to expected engine output.
\Mfig{EngMaxAutTab}
Torque limiter for E85 fuel
\Mfig{EngMaxE85Tab}
Torque limiter for manual gearbox in higher revs
\Mfig{ManGearLim}
Torque limiter in 5th gear
\Mfig{5GearLimTab}
Overboost table
\Mfig{Overboost}
Maximum Airmass for I-part of PID controller (\texttt{AirCtrlCal.m\_MaxAirTab})
\Mfig{MaxAirTab}
\texttt{TorqueCal.m\_AirTorqMap}. This is where all torque limiters take their
data from and therefore needs to be \enquote{fooled} if you are running more
than \SI{400}{\newton\meter} on an automatic!
Data-matrix for nominal Airmass. Engine speed and torque are used as support
points. The value in the matrix + friction Airmass (idle Airmass) will create
the pointed torque at the pointed engine speed. Resolution is \SI1{\mgc}.
\Mfig{AirTorqMap}
Finally, we’re all done!
\chapter{Automatic transmission specifics}
In automatic Trionic 7 cars the TCM (Traction Control Module) sends a torque