<<

EXPERIMENTAL INVESTIGATION OF OCTANE REQUIREMENT RELAXATION IN A

TURBOCHARGED SPARK-IGNITION ENGINE

Thesis

Submitted to

The School of Engineering of the

UNIVERSITY OF DAYTON

In Partial Fulfillment of the Requirements for

The Degree of

Master of Science in Mechanical Engineering

By

Jacob A. Baranski

Dayton, Ohio

August, 2013

EXPERIMENTAL INVESTIGATION OF OCTANE REQUIREMENT RELAXATION IN A

TURBOCHARGED SPARK-IGNITION ENGINE

Name: Baranski, Jacob Anthony

APPROVED BY:

Scott D. Stouffer, Ph.D. Frederick R. Schauer, Ph.D. Advisory Committee Chairman Committee Member Senior Research Engineer Head Energy and Environmental Engineering Advanced Concepts Group University of Dayton Research Institute U.S. Air Force Research Laboratory

Sukh S. Sidhu, Ph.D. John L. Hoke, Ph.D. Committee Member Committee Member Head Senior Mechanical Engineer Energy Technologies and Materials Division Innovative Scientific Solutions Inc. University of Dayton Research Institute

John G. Weber, Ph.D. Tony E. Saliba, Ph.D. Associate Dean Dean, School of Engineering School of Engineering & Wilke Distinguished Professor

ii

1. ABSTRACT

EXPERIMENTAL INVESTIGATION OF OCTANE REQUIREMENT RELAXATION IN A

TURBOCHARGED SPARK-IGNITION ENGINE

Name: Baranski, Jacob Anthony University of Dayton

Advisor: Scott D. Stouffer, Ph.D.

Wide adoption of unmanned aerial systems (UAS) powered by spark ignition (SI) engines that require high-octane has triggered an increase in fuel costs incurred by the U.S.

Department of Defense (DoD). Most current United States Air Force (USAF) vehicles are fueled with JP-8, a low-octane -like fuel that is well suited for turbine engines. A relaxation in octane requirement is required to fuel current SI engines with a low-octane fuel like JP-8 and avoid destructive end-gas knock. In this thesis, a two-phase octane requirement study is conducted using a 914 four- turbocharged SI engine. In phase one, net indicated mean effective (IMEPn) is characterized at typical cruise speeds as fuel octane number

(ON) is varied on-the-fly using a dual port-fuel-injection (PFI) system. IMEPn is compared among dual-PFI blends from 20 to 87 ON, neat n-heptane, neat JP-8, and JP-8/iso-octane blends. A JP-

8/iso-octane demonstration is conducted to show the volume proportion of JP-8 that could be used to sustain flight. Results for typical cruise operation using JP-8/iso-octane blends show that a maximum volume flow proportion of 88% JP-8 at low-load cruise, and 40% at high-load cruise could be used to sustain flight. Although an impractical configuration, these results reveal

iii that low-load neat JP-8 cruise is a possibility if the octane requirement of the can be relaxed.

The second phase of testing focuses on achieving full-load takeoff performance on 87

ON, since high-load operation is impractical with JP-8. The effects of air

(IAT), equivalence ratio, , and dual-simultaneous ignition on knock are investigated. The combination of delayed combustion phasing with dual-simultaneous-ignition and increased equivalence ratio enables greater maximum IMEPn on 87 ON than the base configuration on 100 ON. To offset the additional fuel used for takeoff, a cruise fuel consumption study is conducted to characterize the reduction in indicated specific fuel consumption (ISFC) with an optimized fuel-lean, dual-simultaneous-ignition, and advanced ignition timing configuration compared to base conditions. The ISFC reduction in the optimized cruise configuration can directly offset the additional fuel used in the optimized 87 ON take-off configuration for flights as short as 4 hours. The 87 ON optimized cruise and take-off configurations can be combined to allow up to 3.5 additional hours of cruise.

iv

2. ACKNOWLEDGMENTS

This work would not have been completed without all the help that I have received along the way. I would like to thank John Hoke, Fred Schauer, and Sukh Sidhu of my committee for their encouragement and guidance throughout this process, especially my advisor Scott

Stouffer. I would also like to thank the guys of SERL for all of their hard work: Paul Litke and

Keith Grinstead for your technical guidance and making sure that things “just make sense” in the lab; Adam Brown for pushing me to keep fighting my engine gremlins even when they were winning and for not fat-fingering the controls too many times when we were running; Eric

Anderson for pursuing high-quality data; Rich Ryman for coming through for me when I really needed it and putting up with me being so particular about everything; Sheldon (Joseph)

Ausserer for your help with the PIC32, MATLAB code, and your general grammatical prowess.

Thanks as well to Dave Burris, JR Groenewegen, Ben Naguy, Curtis Rice, and Justin Goffena for all of your help.

A special thank you goes to my lovely wife Sarah Baranski for all of her support and encouragement throughout the last two years. I truly appreciate it. I would also like to thank the rest of my family for their love and support, and for not getting too upset when I wasn’t able to attend all of the family gatherings. Thanks to my dad, Ed Baranski, for always explaining how things work and for helping me develop “the knack”. Finally I would like to thank my Savior,

Jesus Christ, for seeing fit to give me the skills and abilities to do this work, and for putting me in a place to do it.

v

3. TABLE OF CONTENTS

1. ABSTRACT ...... iii

2. ACKNOWLEDGMENTS ...... v

4. LIST OF FIGURES ...... x

5. LIST OF TABLES ...... xvi

6. LIST OF ABBREVIATIONS AND NOTATIONS ...... xviii

1. 1. INTRODUCTION ...... 1

2. 2. BACKGROUND ...... 4

2.1 Engine Performance Metrics...... 4

2.1.1 ...... 4

2.1.2 Specific Fuel Consumption ...... 6

2.2 SI Combustion ...... 7

2.2.1 Classification of Combustion ...... 7

2.2.2 Combustion Progress Characterization ...... 7

2.2.3 Normal SI Combustion ...... 9

2.2.4 Abnormal SI Combustion ...... 11

2.3 Homogeneous Charge Compression Ignition Combustion ...... 36

2.4 Engine Control ...... 38

vi

2.4.1 Control ...... 38

2.4.2 Spark Ignition Control ...... 42

2.4.3 Automotive Engine Control Units ...... 43

2.4.4 Flexible Research Engine Control Units ...... 44

3. 3. RESEARCH OBJECTIVES – PHASE ONE ...... 46

4. 4. EXPERIMENTAL SETUP – PHASE ONE ...... 47

4.1 Rotax 914 Research Engine ...... 47

4.2 Engine Research Cell ...... 49

4.3 ...... 55

4.3.1 PIC18 Microcontroller ...... 55

4.3.2 Timing Signals ...... 56

4.3.3 Interrupts ...... 58

4.3.4 Spark Ignition Program ...... 59

4.3.5 Main Fuel Injection Program ...... 60

4.3.6 Dual-fuel Injection Program ...... 62

4.4 Data Acquisition ...... 63

4.4.1 Low-Speed Data Acquisition ...... 63

4.4.2 High-Speed Data Acquisition ...... 66

5. 5. RESULTS – PHASE ONE ...... 76

5.1 PFI Blend Verification ...... 76

5.2 PFI Blend Testing ...... 80

vii

5.3 JP-8 Evaluation and Octane Estimation ...... 82

5.4 JP-8 PFI Blends ...... 83

6. 6. RESEARCH OBJECTIVES – PHASE TWO ...... 86

7. 7. EXPERIMENTAL SETUP – PHASE TWO ...... 87

7.1 PIC32 Microcontroller ...... 87

7.2 XMOS xCORE Microcontroller ...... 90

8. 8. RESULTS – PHASE TWO ...... 101

8.1 Full-Load Benchmark ...... 101

8.2 Intake Temperature Study ...... 103

8.3 Ignition Timing Study ...... 105

8.4 Equivalence Ratio Study ...... 112

8.5 Engine Replacement ...... 118

8.6 Second Engine 87 ON Benchmark ...... 120

8.7 Dual-Simultaneous-Ignition Study ...... 121

8.8 Dual-Simultaneous-Ignition and Equivalence Ratio Study ...... 125

9. 9. SUMMARY AND CONCLUSIONS ...... 132

10. 10. RECOMMENDATIONS FOR FUTURE WORK ...... 137

11. REFERENCES ...... 138

12. APPENDIX A – ENGINEERING DRAWING OF INTAKE PORT FLANGE ...... 147

13. APPENDIX B – ENGINEERING DRAWING OF ADDITIONAL PFI PORT ...... 148

14. APPENDIX C – SCHEMATIC OF DUAL-PIC18 CIRCUIT BOARD ...... 149

15. APPENDIX D – PIC18 ECU IGNITION CONTROL PROGRAM ...... 150

viii

16. APPENDIX E – PIC18 ECU FUEL INJECTION CONTROL PROGRAM ...... 156

17. APPENDIX F – PIC18 DUAL-FUEL INJECTION CONTROL PROGRAM ...... 166

18. APPENDIX G – PIC32 ECU IGNITION CONTROL PROGRAM ...... 176

19. APPENDIX H – XMOS XCORE IGNITION AND INJECTION CONTROL PROGRAM ...... 185

20. APPENDIX I – LAYOUT AND SCHEMATIC FOR JABTRONIC INBOARD V1.0 ...... 227

21. APPENDIX J – LAYOUT AND SCHEMATIC FOR JABTRONIC OUTBOARD V1.0 ...... 229

ix

4. LIST OF FIGURES

Figure 1. Plot of pressure vs. volume over an entire four- cycle...... 5

Figure 2. Factors affecting BSFC shown on performance map for a 2.0 L four-cylinder SI engine

with constant BSFC contours in g/kW-h. Adapted from Heywood [1]...... 6

Figure 3. Plot of mass fraction burned with normal combustion pressure trace...... 8

Figure 4. Plots of typical cylinder pressure during: (a) light, (b) medium, and (c) heavy knock,

with normal combustion trace in a Rotax 914...... 17

Figure 5. Plot showing effect of improvements in refining techniques on fuel .

Adapted from Obert [4]...... 21

Figure 6. Plot of historical trend of average in the US. Adapted from

Amann [39]...... 22

Figure 7. Pictorial outline of dual-fuel HCCI/PPCI/RCCI hybrid control scheme. Adapted from

Choi [68]...... 38

Figure 8. Modes of port fuel injection operation: (a) simultaneous, (b) group, and (c) sequential.

Adapted from BOSCH [69]...... 39

Figure 9. Schematic of UEGO sensor. (a) Sensor structure. (b) Sensor operational principle.

Adapted from Ladommatos [71]...... 41

Figure 10. Picture of the SERL Rotax 914 research engine in the PFI configuration...... 49

Figure 11. Picture of 190 kW eddy-current wet-gap Midwest Dynamatic and

pneumatic engine starting system...... 50

x

Figure 12. Diagram of test cell showing fluid flow through engine support systems...... 51

Figure 13. Pictures of: (a) 20 L, (b) 40 L, and (c) 60 L damping chambers during on-engine flow

damping characterization...... 52

Figure 14. Pictures of dual-fuel PFI system installed on test cylinder with Fuel A and Fuel B

systems labeled. Left: First iteration with second injector port welded to original intake

runner. Right: Second iteration with thicker wall tubing and reverse engineered intake

port flange...... 54

Figure 15. Picture of dual-PIC18 Microcontroller ECU circuit board...... 55

Figure 16. Picture of mounting boss welded to cylinder-two valve cover for addition of Hall

Effect sensor to produce engine-cycle phase signal...... 57

Figure 17. Diagram of engine timing signals in relation to engine cycle timing...... 57

Figure 18. Schematic of the passive first-order low-pass filter circuit used for noise rejection on

external interrupt inputs on the PIC18 ECU...... 59

Figure 19. Picture of National Instruments Compact RIO data-acquisition hardware...... 63

Figure 20. Image of Labview low-speed DAQ program user interface...... 66

Figure 21. Picture of AVL Indismart indicating combustion measurement system with engine

selection switches...... 67

Figure 22. Picture of the Kistler 6115B measuring in-cylinder pressure transducer. . 68

Figure 23. Picture of typical AVL Indicom measurement window during engine testing...... 71

Figure 24. Plot of in-cylinder pressure vs. CA over 100 consecutive cycles with high degree of

combustion variability...... 72

Figure 25. Plot of IMEPn over 100 consecutive engine cycles showing a high degree of

combustion variability...... 73

xi

Figure 26. Plot of knocking cylinder pressure trace with order-10 moving average smoothed

trace and resulting MAPO used to quantify knock intensity...... 74

Figure 27. Plot of knock-limited IMEPn of PFI blends compared to that of PRF pre-blend of the

same ON...... 79

Figure 28. Plot of maximum IMEPn of PFI blends compared to that of neat JP-8, neat n-Heptane,

and load at typical cruise conditions...... 81

Figure 29. Plot of maximum IMEPn as a function of fuel ON for 3500-5800 RPM...... 81

Figure 30. Plot of maximum JP-8 volume percentage of PFI blend at vehicle-cruise engine loads.

...... 83

Figure 31. Plot of maximum IMEPn of JP-8 PFI blends at vehicle cruise-engine loads compared to

that of PFI blends, neat JP-8, and neat n-Heptane...... 84

Figure 32. Picture of XMOS sliceKIT demonstration board with XS1-L16A-128 xCORE dual core

processor...... 92

Figure 33. Diagram of XMOS ECU program outline showing the program functions divided

between both cores with various threads...... 93

Figure 34. Diagram of initial XMOS ECU program core, thread, and channel communication

structure with streaming channels in blue...... 94

Figure 35. Diagram of full scale XMOS ECU program core, thread, and channel communication

structure with streaming channels in blue...... 97

Figure 36. Layout of JABTRONIC Inboard v1.0 XMOS ECU input card...... 100

Figure 37. Picture of JABTRONIC Inboard/Outboard input cards and XMOS GPIO slice connected

to XMOS sliceKIT mainboard...... 100

Figure 38. Plot of Full load IMEPn with 100 ON at 49, 69, and 88°C intake air temperature

including knock-limited IMEPn with 87 ON at 49°C intake temperature...... 103

xii

Figure 39. Plot of knock-limited IMEPn with 87 ON at 38, 49, 69, and 88°C IAT, including knock-

free IMEPn benchmark with 100 ON at 69°C IAT...... 104

Figure 40. Plot of knock-limited IMEPn with 87 ON as a function of IAT at various engine speeds.

...... 105

Figure 41. Plot of knock-limited IMEPn with 87 ON at 49°C IAT at retarded, base, and advanced

MBT timing, including knock-free IMEPn benchmark with 100 ON at 69°C IAT and base

timing...... 106

Figure 42. Plot of cylinder pressure as a function of angle averaged over 100 cycles with

87 ON at 49°C IAT and 4000 RPM with varied combustion phasing...... 107

Figure 43. Surface plot of achievable CA50 as a function of engine speed and IMEPn with 87 ON

at 49°C IAT...... 108

Figure 44. Plot of ISFC as a function of CA50 with 87 ON at 49°C IAT and various engine speeds.

...... 108

Figure 45. Plot of FDA as a function of CA50 with 87 ON at 49°C IAT and various engine speeds.

...... 109

Figure 46. Plot of RBA as a function of CA50 with 87 ON at 49°C IAT and various engine speeds.

...... 110

Figure 47. Plot of COV of IMEP as a function of CA50 with 87 ON at 49°C IAT and various engine

speeds...... 111

Figure 48. Surface plot of exhaust gas temperature as a function of CA50 and engine speed with

87 ON at 49°C IAT...... 111

Figure 49. Plot of knock-limited IMEPn with 87 ON at 49°C IAT at lean (ϕ = 0.9), base (ϕ = 1.0),

and rich (ϕ = 1.6) conditions, including knock-free IMEPn benchmark with 100 ON at

69°C IAT and base equivalence ratio (ϕ = 1.0)...... 112

xiii

Figure 50. Plot of IMEPn as a function of equivalence ratio with 87 ON at 49°C IAT and various

engine speeds...... 113

Figure 51. Plot of COV of IMEP as a function of equivalence ratio with 87 ON at 49°C IAT and

various engine speeds...... 114

Figure 52. Plot of CA50 as a function of equivalence ratio with 87 ON at 49°C IAT and various

engine speeds...... 115

Figure 53. Plot of FDA as a function of equivalence ratio with 87 ON at 49°C IAT and various

engine speeds...... 116

Figure 54. Plot of RBA as a function of equivalence ratio with 87 ON at 49°C IAT and various

engine speeds...... 116

Figure 55. Plot of ISFC as a function of equivalence ratio with 87 ON at 49°C IAT and various

engine speeds...... 117

Figure 56. Surface plot of exhaust gas temperature as a function of equivalence ratio and engine

speed with 87 ON at 49°C IAT...... 118

Figure 57. Picture of Cylinder-head of test-cylinder modified to accept flush-mounted in-

cylinder pressure transducer...... 120

Figure 58. Plot of knock-limited IMEPn with 87 ON at 49°C IAT, ϕ = 1.0, 26 °CA ATDC ignition

timing with engines 1 and 2, including knock-free IMEPn benchmark with 100 ON at 69°C

IAT, ϕ = 1.0, and 26 °CA ATDC ignition timing with engine 1...... 121

Figure 59. Plot of knock-limited IMEPn with 87 ON at 49°C IAT, ϕ = 1.0, dual-simultaneous-

ignition with advanced and retarded timing, including knock-free IMEPn benchmark with

100 ON at 69°C IAT, ϕ = 1.0, and 26 °CA ATDC ignition timing...... 122

Figure 60. Plot of knock-limited IMEPn as a function of CA50 with 87 ON at 49°C IAT and various

engine speeds comparing dual-simultaneous-ignition and single ignition...... 123

xiv

Figure 61. Plot of FDA as a function of CA50 with 87 ON at 49°C IAT and various engine speeds

comparing dual-simultaneous-ignition and single ignition...... 124

Figure 62. Plot of RBA as a function of CA50 with 87 ON at 49°C IAT and various engine speeds

comparing dual-simultaneous-ignition and single ignition...... 124

Figure 63. Plot of ISFC as a function of CA50 with 87 ON at 49°C IAT and various engine speeds

comparing dual-simultaneous-ignition and single ignition...... 125

Figure 64. Plot of knock-limited IMEPn with 87 ON at 49°C IAT, dual-simultaneous-ignition with

retarded timing, and ϕ = 1.3-1.5, including knock-free IMEPn benchmark with 100 ON at

69°C IAT, ϕ = 1.0, and 26 °CA ATDC ignition timing with single ignition...... 126

Figure 65. Plot of knock-limited IMEPn as a function of equivalence ratio with 87 ON at 49°C IAT

and dual-simultaneous-ignition with retarded ignition timing at various engine speeds.

...... 127

Figure 66. Plot of CA50 as a function of equivalence ratio with 87 ON at 49°C IAT and dual-

simultaneous-ignition with retarded ignition timing at various engine speeds...... 128

Figure 67. Plot of FDA as a function of equivalence ratio with 87 ON at 49°C IAT and dual-

simultaneous-ignition with retarded ignition timing at various engine speeds...... 129

Figure 68. Plot of RBA as a function of equivalence ratio with 87 ON at 49°C IAT and dual-

simultaneous-ignition with retarded ignition timing at various engine speeds...... 129

Figure 69. Plot of ISFC as a function of equivalence ratio with 87 ON at 49°C IAT and dual-

simultaneous-ignition with retarded ignition timing at various engine speeds...... 130

Figure 70. Plot of ISFC with 87 ON at 49°C IAT for base single ignition, dual-simultaneous-

ignition with MBT timing at ϕ = 1.0, and dual-simultaneous-ignition with MBT timing at

ϕ = 0.9...... 131

xv

5. LIST OF TABLES

Table 1. Acoustic vibration modes showing natural radial and circumferential nodes with

corresponding wave number. Adapted from Galloni [25]...... 14

Table 2. Test conditions for RON and MON determination in CFR engine. [36] [37] ...... 20

Table 3. Factors affecting ONR of SI engine. Adapted from Attard [44]...... 25

Table 4. Rotax 914 and specifications. [76] ...... 48

Table 5. Outline of National Instruments Compact RIO hardware modules employed for low-

speed DAQ...... 64

Table 6. Test conditions, their variation during testing and impact on ONR precision...... 77

Table 7. Fuels used to achieve desired PFI blend ON...... 78

Table 8. 100 ON full load test conditions...... 102

Table 9. Test conditions for intake air temperature investigation of knock-limited performance

with 87 ON...... 104

Table 10. Test conditions for ignition timing investigation of knock-limited performance with 87

ON...... 106

Table 11. Test conditions for equivalence ratio investigation of knock-limited performance with

87 ON...... 112

Table 12. Test conditions for dual-simultaneous-ignition investigation of knock-limited

performance with 87 ON...... 122

xvi

Table 13. Test conditions for dual-simultaneous-ignition and equivalence ratio investigation of

knock-limited performance with 87 ON...... 126

xvii

6. LIST OF ABBREVIATIONS AND NOTATIONS

100LL 100 Low- ABDC After Bottom Dead Center ATDC After Top Dead Center AFRL Air Force Research Laboratory ASTM American Society for Testing Materials ADC Analog to Digital Converter AKI Anti-Knock Index ASIC Application Specific Integrated Circuit ALU Arithmetic Logic Unit Gasoline BTDC Before Top Dead Center BMEP Brake Mean Effective Pressure BSFC Brake Specific Fuel Consumption CN Cetane Number COV Coefficient of Variation CR Compression Ratio CI Compression-Ignition CAI Controlled Autoignition CFR Cooperative Fuel Research Committee CA Crank Angle CA50 Crank Angle of 50% Mass Fraction Burned DAQ Data Acquisition DELCO Dayton Engineering Laboratories Company

xviii

DoD Department of Defense DI Direct Injection ECU Engine Control Unit ETBE Ethyl Tertiary-Butyl Ether EGR Exhaust Gas Recirculation ETC Exothermic Center FPGA Field Programmable Gate Array FDA Flame Development Angle FMEP Friction Mean Effective Pressure GDI Gasoline Direct Injection HCCI Homogeneous Charge Compression Ignition IMEP Indicated Mean Effective Pressure ISFC Indicated Specific Fuel Consumption I/O Input/Output IAT Intake Air Temperature ISR Interrupt Routine KLIMEP Knock-Limited Indicated Mean Effective Pressure KLIP Knock-Limited Intake Pressure KLSA Knock-Limited Spark Advance KLCR Knock-Limited Compression Ratio MAF Mass Airflow Meter MFB Mass Fraction Burned MAPO Maximum Amplitude of Pressure Oscillations MBT Maximum Break MEP Mean Effective MTBE Methyl Tertiary-Butyl Ether MMT Methylcyclopentadienyl Manganese Tricarbonyl MIPS Million Instructions Per Second Mogas Motor Gasoline

xix

MON Motor Octane Number MDU Multiply-Divide Unit ON Octane Number ONR Octane Number Requirement OBDII On-Board Diagnostics II PPCI Partially Premixed Compression Ignition PFI Port Fuel Injected p-V Pressure-Volume PRF Primary Reference Fuel RBA Rapid Burn Angle ROHR Rate of Heat Release RCCI Reactivity Controlled Compression Ignition RON Research Octane Number S Sensitivity SERL Small Engine Research Laboratory SAE Society of Automotive Engineers SI Spark-Ignition SFC Specific Fuel Consumption TEL Tetraethyl Lead TML Tetramethyl Lead TDC Top Dead Center TJI Turbulent Jet Igniter USAF United States Air Force UART Universal Asynchronous Receiver/Transmitter UEGO Universal Exhaust Gas UAS Unmanned Aerial Systems VR Variable Reluctance WOT Wide-Open-

A/Fa Actual Air-Fuel Ratio

xx

A/Fs Stoichiometric Air-Fuel Ratio

AFRf corrected Air-Fuel Ratio Corrected for Fuel

AFRmeasured Air-Fuel Ratio Measured

AFRp corrected Air-Fuel Ratio Corrected for Pressure B Cylinder c Local Speed of Sound fc Frequency fm,n Natural Frequency

IMEPn Net IMEP k Polytropic Coefficient mHC Fuel Hydrogen to Carbon Ratio N Speed nOC Fuel Oxygen to Carbon Ratio nR Number of Revolutions Per Cycle p Pressure

Pb Brake pex Exhaust Pressure

Pi Indicated Power

Pi,g Gross Indicated Power

Pf Friction Power T Temperature

Vd Displaced Volume

Wi Indicated Work

Wi,g Gross Indicated Work Per Cycle

Wi,n Net Indicated Work Per Cycle

Wp Pumping Work Per Cycle

 Air-Fuel Equivalence Ratio ϕ Fuel-Air Equivalence Ratio

ρm,n Wave Number

xxi

τ Instantaneous Autoignition Delay

τc RC Circuit Time Constant

xxii

CHAPTER 1

1. INTRODUCTION

Increased use of unmanned aerial systems (UAS) powered by spark-ignition (SI) engines has generated interest in reducing associated operating costs by utilizing the current fuel supply employed by the U.S. Department of Defense (DoD). Most current United States Air Force

(USAF) vehicles are fueled with JP-8, a low-octane kerosene-like fuel that is well suited for turbine engines. The large quantities of turbine fuel required by the DoD along with established logistics paths result in a relatively low cost compared to other possible fuels. Although high power densities are achievable with small, high-overall-pressure-ratio turbine engines, they are generally unable to match the low power-specific fuel consumption of Otto/Diesel-cycle-based internal combustion engines. While compression-ignition (CI) engines can operate reliably with low-octane heavy fuels, their higher compression ratios and pressure-rise rates necessitate increased structural strength and mass, which decreases power density relative to SI engines.

Currently, small-scale propulsion and power systems utilized in DoD UAS (< 750 kW) typically employ commercially available off-the-shelf propulsion solutions. These propulsion systems may be modified to better suit the needs of a specific flight system, but typically are not fully optimized for DoD performance. Recent trends in the aerospace community have involved improving the power density and specific fuel consumption of these small-scale propulsion systems, with the aim of extending UAS range/endurance.

In the 75-kW class, UAS engines can require a high octane number (ON) gasoline such as

1

100 low-lead (100LL) aviation gasoline (avgas) to achieve the high compression ratios or supercharging levels needed to enable the mission-required range and power density. The high

ON fuels used with SI engines reduce the operating restrictions caused by the tendency to suffer from destructive end-gas knock. In many parts of the world, such high ON fuel is either not readily available or not cost effective to use. An engine that could operate on available motor gasoline (mogas) or kerosene-based while maintaining power density and would potentially reduce the cost of UAS operation world-wide.

In an effort to achieve this goal, a two-phase study was conducted to experimentally investigate octane requirement relaxation in an engine that requires high ON fuel. The first phase of work focused on expanding the cruise-operation knock-limit to enable JP-8-fueled cruise. The dual-fuel engine-research stand described in this work was established to allow knock-limited performance to be characterized on a wide variety of fuels with different ON ratings. This research tool enables on-the-fly, in-situ control and evaluation of fuel-blending performance and the effect on combustion, with the goal of exploring cruise-condition enhancements to enable the use of JP-8.

The second phase of work focused on increasing the engine knock-limited mean effective pressure at full-load takeoff conditions on reduced-octane fuels (such as unleaded pump gas, which is in large supply worldwide). The effect on knock-limited performance of engine parameters that can be altered without major engine hardware modifications was characterized. A combination of these operational parameters was optimized to enable full- load operation on 87 ON gasoline.

The Rotax 914 was chosen as a test platform for this work because it powers one of the most prominent and heavily used UAS in the USAF, and the military version requires 100LL

Avgas. Because of the aforementioned drawbacks of using high-octane fuels, engine technology

2 modifications are being explored to improve the engine knock-limited performance and relax the fuel ON requirement. Although many knock reducing technologies would be expensive, heavy, and time consuming to integrate into a well-established aircraft SI engine platform, operating parameters like ignition timing and fuel equivalence ratio can be altered without significant modification of the engine.

3

CHAPTER 2

2. BACKGROUND

This chapter is intended to provide a technical background to the current work and a review of salient research from the SI combustion field. Basic engine performance metrics are presented along with a method to characterize combustion progress in SI engines. The topics of normal and abnormal combustion are discussed in detail. Finally, a background on engine controllers and their importance in a research setting are included at the end of this chapter.

2.1 Engine Performance Metrics

2.1.1 Mean Effective Pressure

The pressure-volume (p-V) diagram is one of the most important pieces of information used to quantify engine performance (Figure 1). The area enclosed within the p-V trace represents the work performed during an engine cycle. Integrating to sum the area enclosed in the upper portion of the diagram gives the gross indicated work per cycle (Wi,g). The area enclosed in the lower portion of the diagram, along with the area on the right between the upper and lower portions, represents the pumping work per cycle (Wp). Subtracting Wp from

Wi,g yields the net indicated work per cycle (Wi,n). The indicated power (Pi) per cylinder corresponding to each of the work terms is determined using the crankshaft speed (N) and the number of revolutions per cycle (nR) as shown in Eq. (1).

4

Wi N P = (1) i n R

25

20

15

10 Pressure Pressure ()

5

0 0 100 200 300 400 3 Volume (cm )

Figure 1. Plot of pressure vs. volume over an entire four-stroke cycle.

While, work and power output are useful performance parameters for matching an engine to an application, they provide no indication of how well an engine uses its displaced volume (Vd) to develop that work and power. Dividing the indicated work (Wi) by Vd gives the indicated mean effective pressure (IMEP). Since the indicated work per cycle is normalized by displacement volume, IMEP facilitates comparison of engines independent of size. The net IMEP

(IMEPn), calculated from Wi,n, is the primary measure of engine power output in this work.

Torque and speed measurements from a dynamometer provide sufficient information to calculate the brake power (Pb) output from an engine at the crankshaft. This power is less than the gross indicated power (Pi,g) by the power required to overcome friction (Pf). These power quantities can be normalized to their corresponding mean effective pressures (MEP) by applying

Eq. (2); the resulting quantities are brake mean effective pressure (BMEP) and friction mean effective pressure (FMEP).

P nR MEP = (2) N Vd

5

2.1.2 Specific Fuel Consumption

While MEP provides a normalized metric for comparing engine power output, specific fuel consumption (SFC) provides a metric for comparing fuel efficiency between engines.

Dividing the rate at which fuel is consumed by the power the engine produces yield the SFC.

The brake specific fuel consumption (BSFC) and indicated specific fuel consumption (ISFC) can be calculated by using the appropriate power quantities, Pb or Pi. The ISFC is employed as the primary measure of fuel efficiency in this work because testing was focused on one cylinder, rather than the whole engine. Figure 2 shows BSFC as a function of engine speed and load for a

2.0 L four-cylinder SI engine, and is referred to as a performance map. A performance map generally has an efficiency island corresponding to the operating conditions that yield minimum

SFC. SFC increases in all directions from that point as engine speed and load change.

Performance maps typically include the maximum load curve as an upper bound on the engine operating range. Figure 2 also lists the effects that speed and load changes have on overall engine operation which influence SFC.

Figure 2. Factors affecting BSFC shown on performance map for a 2.0 L four-cylinder SI engine with constant BSFC contours in g/kW-h. Adapted from Heywood [1].

6

2.2 SI Combustion

2.2.1 Classification of Combustion

The topic of combustion can be categorized many different ways, each having some nuance lending it to a specific application. One way to categorize combustion is by the flame type. When a homogeneous mixture of fuel and oxidizer are present, as in the ideal case of a port fuel injected (PFI) spark ignition engine, the combustion is described as a premixed flame

[2]. In contrast, in a CI engine the fuel and oxidizer mix as they burn, forming a diffusion flame.

Combustion may also be categorized by the confines of the space in which it occurs. Constant pressure combustion like that occurring in engines is classified as unconfined combustion, whereas SI and CI combustion are described as confined combustion [1]. Flames may also be grouped by their structure and speed. The structure of the flame front as it consumes the unburned mixture may be classified as laminar or turbulent [3]. If the flame moves through the reactants at subsonic speeds the flame is a deflagration. In contrast, a detonation flame moves at supersonic speeds [4].

2.2.2 Combustion Progress Characterization

In order to completely describe the way combustion progresses in an IC engine it is first necessary to introduce a method to quantify how much of the reaction is completed at any point in the process. The metric used to characterize the evolution of the combustion process in current literature is the mass fraction burned (MFB) profile. The MFB is the dimensionless ratio of the mass of the reactants that have been consumed in the reaction to the total mass of all reactants before the beginning of combustion. Figure 3 shows the characteristic S-shape of the

MFB profile. The MFB begins at zero at the time of ignition and moves toward unity as combustion progresses. However, unity is never reached because the flame is quenched when

7 the exothermic reaction is overpowered by the rate of external heat transfer at the cylinder wall.

60 1 RBA 0.9 50 0.8 FDA 0.7 40 0.6 Cylinder 30 0.5 Pressure 0.4 MFB 20

0.3 Cylinder Pressure Cylinder Pressure (bar) 0.2 10 CA50 0.1 0 0 -30 -20 -10 0 10 20 30 40 50 60 70 80 90 Crank Angle (°CA ATDC)

Figure 3. Plot of mass fraction burned with normal combustion pressure trace.

There are three main stages of combustion in an SI engine that are defined using the

MFB. The first stage of combustion, called the flame development period, is the time between ignition and when MFB reaches 10%. The flame development angle (FDA) is defined as the number of degrees of crank angle (CA) rotation that take place during the flame development period. The second portion of combustion, where the majority of the reaction takes place, is called the rapid burn period. The rapid burn angle (RBA) corresponds to the rapid burn period where MFB increases from 10% to 90%. The CA duration of SI combustion is usually well divided between the flame development and rapid burn phase with typical values for FDA and RBA around 25° CA each. As the reaction slows in the final stage of combustion, Combustion termination, MFB slowly increases from 90% to its final value for the cycle [5]. The method used in this work to experimentally determine the MFB profile is presented in 4.4.2.

8

2.2.3 Normal SI Combustion

Combustion in an SI engine can generally be classified as a confined, premixed, turbulent deflagration. In a PFI configuration fuel for the next cycle is usually injected onto the back of the hot intake valve that is still closed from the previous cycle so that the fuel has more time to evaporate and mix with the air before it is inducted into the cylinder. The intake valve opens roughly 20° CA before top dead center (BTDC) of gas exchange and the mixture is drawn into the cylinder as the piston changes directions and travels toward the bottom of its stroke.

The intake valve closes roughly 40° CA after bottom dead center (ABDC) of the compression stroke as the premixed fuel and air are compressed in the cylinder. Turbulence in the cylinder continues to mix the fuel and air, which typically never reaches complete homogeneity.

Normal combustion begins as the fuel-air mixture is ignited by an electrical discharge from the spark plug. This discharge takes the form of a high-temperature plasma that only ignites the mixture in close proximity. Note that slightly fuel-rich mixtures are easier to ignite.

The amount of time that it takes for the flame kernel to appear following the creation of the spark plasma channel is called the ignition delay period, or induction period, which usually lasts about 6° CA. Once the flame kernel is formed, the beginning stage of combustion proceeds slowly because of the large amount of heat energy required to heat the relatively cool fuel-air mixture. During the flame development period there is not a substantial rise in cylinder pressure above the normal increase from compression [6].

The flame front moving radially outward from the spark plug begins to move much faster as it makes the transition from the flame development period to the rapid burn period around 10% MFB. The surface area of the flame is greatly increased by turbulence in the cylinder, which causes the wrinkled flame to consume the mixture at a much higher rate than if it were a laminar flame. The laminar flame speed for stoichiometric mixtures of iso-octane and

9 air is approximately 0.5 -1 m/s, depending on pressure and temperature. The speed of the wrinkled flame front in an SI engine is closer to 10 - 30 m/s, although it varies greatly with flow conditions [7]. The unburned mixture ahead of the flame front is compressed by the expanding burned gas. Although the pressure in the burned and unburned regions remains relatively well equilibrated throughout the combustion process, there can be large temperature gradients.

Radiation dominates conductive and convective heat transfer processes to the burned and unburned gas throughout the rapid burn phase. The higher temperature of the burned gas causes its density to be less than that of the unburned gas. This compression of the unburned gas by the burned gas expedites the combustion reaction [6].

At the CA of 50% MFB (CA50), as much as 80% of the volume may be occupied by the burned gasses. The CA50 point is the main indicator used to characterize combustion phasing in SI engines. Optimum combustion phasing occurs when ignition timing is set at the maximum break torque (MBT) ignition timing, which corresponds to a CA50 of around

7-8° CA after top dead center (ATDC) of combustion [7]. If CA50 occurs much earlier than 7-8°,

IMEP will suffer because the increased pressure before top dead center (TDC) will work against the piston before it changes directions from compression to expansion. If CA50 occurs much later than optimum, IMEP will suffer because the combustion volume is increasing ATDC, and consequently, the pressure produced by combustion will decrease.

Following the rapid burn phase, combustion begins to slow during the combustion termination period [8]. Since the remaining reactants, called the end gas, have been compressed, the remaining 10% of the unburned mixture (by mass) occupies only a few percent of the combustion chamber volume. The end gas is forced into closer contact with cylinder wall and heat transfer to the relatively cool metal begins to play a significant role in slowing the reaction [5]. The speed of the flame front also slows as turbulence is reduced as the flame

10 reaches the boundary layer. The combustion termination period occupies a larger time than the flame development period, generally leaving a small fraction of the initial air-fuel mixture mass unreacted due to cold boundary layers near cylinder walls and crevices [9].

2.2.4 Abnormal SI Combustion

2.2.4.1 History of Knocking Combustion

One of the main limitations to SI engine performance is that combustion does not always progress as intended. Engineers and researchers noticed the effects of abnormal combustion soon after Nikolaus Otto’s original four-stroke engine was introduced [10]. While, an unusual sound coming from the engine was the main indication that there was a problem, the “clinking” sound that we now refer to as knock was often confused with the “thumping” or

“pounding” sound of worn bearing [11, 12]. Therefore some engineers attributed the majority of symptoms encountered with knock to the engine simply being too worn [13]. Although the exact cause of the problem was not yet known, by the early 1900s the operating parameters that made the knocking sound more prevalent were well documented. Advanced ignition timing and low engine speed with high load were avoided to keep engines from knocking [14, 15].

Another form of abnormal combustion that began to be better understood around the same time was called a “pre-explosion” or “pre-ignition” [15]. It was found that carbon deposits would build up in the engine and cause hot spots that would ignite the fuel-air mixture before the spark plug could initiate combustion. These hot spots were also found on projecting points or corners in the combustion chamber [16]. Surface ignition as it is now called was generally grouped with knock because it produced the same characteristic sound. Sir Harry Ricardo, a researcher at Cambridge University, was among the first to determine that knock and surface- ignition are two very different phenomena [17].

11

2.2.4.2 Knocking Combustion

Although the symptoms and general engine operating parameters that are associated with knock have now been known for over a century, the actual phenomenon at work has been subject to many different theories. The two main theories held have been the detonation theory and the autoignition theory [18]. In some literature, the term “detonation” is used interchangeably with “knock” or “ping” even though all describe the same phenomenon [19].

Both the detonation and the autoignition theories have supporting evidence that indicates that they could both be involved in knock [20]. The mechanism of knock presented in this work is in agreement with the current literature on knocking combustion that includes both theories, but is more in line with Ricardo, who is credited with being the first to propose the autoignition theory [18, 21] .

A knocking cycle begins much the same way as a normal combustion cycle, with the spark igniting the charge and a wrinkled flame front appearing soon thereafter. As in normal combustion, the temperature of the unburned gasses ahead of the flame front is increased from compression by the burned gasses and by heat transferred by means of radiation. If the flame front is not able to consume the fresh mixture rapidly enough, some or all of the remaining end gas will autoignite when the Livengood-Wu integral, Eq. (3), is satisfied. In this equation τ is representative of the instantaneous autoignition delay time of the end gas as a function of local temperature and pressure, which has been empirically correlated with an Arrhenius rate equation, Eq. (4), with constants A, n, and B depending on the fuel [21].

1 ∫ dt = 1 (3) τ(T, p)

B τ = Ap−neT (4)

12

During the autoignition delay, the end gas goes through a series of pre-reactions leading to autoignition. Each hydrocarbon fuel goes through a slightly different process based on its chemistry. In iso-octane the pre-reactions lead to a two-stage ignition process. Once the mixture reaches 300-400°C and a certain time interval passes, a cool flame is produced that is only slightly exothermic and is shortly quenched [22]. After another small time interval there is a transition to a hot flame that initiates a rapid reaction. If the initial temperature of the mixture is high enough, it will exhibit a single stage reaction where only the high temperature reaction takes place [1]. If the wrinkled flame consumes the end gas before the autoignition delay time has passed, then autoignition will not take place. When autoignition does occur, the exothermic reactions happen very rapidly, causing the remaining heat release rate to be much higher than normal combustion [20].

The rapid heat release produced by autoignition generates pressure waves that drive resonant acoustic oscillations within the combustion chamber. Some of the energy in the acoustic waves is reflected as it hits the cylinder wall, some energy causes vibrations at the cylinder wall and is dissipated as heat, and some energy is transmitted through the engine structure as external sound waves [20]. The frequency spectrum of the acoustic waves usually corresponds to the radial and circumferential modes of the combustion chamber, with the circumferential modes being more prominent. A simplified formulation for the natural frequency fm,n of the resonance can be found using Eq. (5).

c f = ρ (5) m,n m,n πB

The variables m and n denote the numbers of the radial and circumferential nodes respectfully. The wave number, ρm,n, represents the zeroes of the derivative of the Bessel function of the 1st kind that correspond to each of the natural modes; c is the local speed of sound, and B is the cylinder bore [23, 24]. Table 1 shows the shape of the in-cylinder acoustic

13 vibration modes and the corresponding wave number. Knocking combustion in an SI engine generally produces sound waves in the 6 – 20 kHz range [25]. Previous Rotax 914 knock testing has shown knocking cylinder pressure frequencies centered around the first and second radial modes at 7.5 and 12.5 kHz.

Table 1. Acoustic vibration modes showing natural radial and circumferential nodes with corresponding wave number. Adapted from Galloni [25].

The severity of the reaction upon autoignition is divided into three main modes of knocking combustion: deflagration, thermal explosion, and developing detonation. Each mode is created by a different set of conditions in the end gas centered around hot spots in the mixture, called exothermic centers (ETCs), where autoignition begins [26]. ETCs are generated by inhomogeneities in the mixture caused by the in cylinder mixing processes between the residual exhaust, fuel, and air, as well as temperature gradients caused by heat transfer to the chamber walls and valves. The size, property gradients, and special distribution of the ETCs govern the transition from autoignition to knock [27].

Deflagration as a result of autoignition is the least severe form of knocking combustion.

The deflagration autoignition to knock transition is characterized by very steep temperature gradients (>100 K/mm) [21], and small ECTs. Once autoignition occurs at one of these ETCs, combustion proceeds with a normal wrinkled flame front and very minimal evidence of pressure oscillations in the cylinder. Therefore, there is little to no knock damage [27].

14

The second manifestation, thermal explosion, is somewhat more severe than deflagration, but usually creates only small amounts of knock damage. ETCs that generate a thermal explosion are much larger than deflagrative ECTs and have very shallow temperature gradients (<1.25 K/mm) [21, 27]. Due to these shallow gradients, once one ETC has passed its autoignition delay, adjacent ECTs will also be nearly finished with their delay periods. Once one

ETC autoignites, adjacent ECTs begin to autoignite in a chain reaction that produces moderate pressure oscillations in the cylinder [20]. Autoignition delay generally decreases with increasing temperature and pressure, with temperature being the more dominant factor in knocking combustion [28]. Thus the temperature rise from autoignition in one ETC tends to accelerate auto ignition in adjacent ETCs.

The third mode of autoignition to knock transition, the developing detonation, is the most violent mode. The developing detonation mode is characterized by intermediate sized

ETCs with moderate temperature gradients (about 12.5 K/mm) [21, 27]. In this mode, the flame front produced by autoignition is coupled to a shock wave to create a detonation wave. This mode supports the gradual growth of the strong pressure waves that are damaging to the engine structure [20, 27].

In any given knocking combustion cycle all three transition modes may be present, and it is possible that one mode may initiate another mode. This interaction of classic autoignition detonation as a consequence of autoignition, possibly occurring during the same cycle, explains why both theories have, historically, been so fiercely championed. It is conceivable that researchers running very similar experiments with only minor differences could have seen drastically different results. While some researchers commonly saw detonation waves in their experiments, others remained skeptical [4, 28]. The two bodies of thought remained at odds

15 until 1946, when Miller unified both theories into a single working theory of knocking combustion in SI engines [18].

Many different methods used to quantify the magnitude of knock are presented in literature. The most straightforward way to quantify the severity of knock is to measure the maximum amplitude of pressure oscillations (MAPO) generated in the combustion chamber

[25]. MAPO amplitudes of 5, 10, and 20 bar roughly correspond to light, medium, and heavy knock [29, 30, 31] . Figure 4 shows a plot of these three knock levels with a normal combustion pressure trace. Light knock is usually non-damaging, and the faint acoustic waves generated can be difficult to hear. Prolonged medium knocking can cause pitting and erosion of the piston crown and , but usually does not cause severe damage [10]. The pitting is caused by increased heat flux to the engine during knocking combustion, which is roughly two or three times higher than normal combustion [1]. Heavy knock can be greatly destructive over a matter of just a few engine cycles. Damage from heavy knock is usually mechanical in nature, although it does cause the same thermal pitting associated with less severe knock. The most common engine damage associated with heavy knock is the fracture of the piston’s top ring land, which can break off and cause additional damage to the engine [32]. Mechanical damage from heavy knock is expected when the pressure rise rate exceeds 10 bar/°CA [20].

16

100 100 Light Knock Medium Knock 90 90 80 Normal 80 Normal 70 combustion 70 Combustion 60 60 50 50

40 40 Pressure Pressure (bar) Pressure Pressure (bar) 30 30 20 20 10 10 0 0 -30 -20 -10 0 10 20 30 40 50 60 70 80 -30 -20 -10 0 10 20 30 40 50 60 70 80 Crank Angle (°CA ATDC) Crank Angle (°CA ATDC)

a. b.

100 Heavy Knock 90 80 Normal 70 Combustion 60 50 40 Pressure Pressure (bar) 30 20 10 0 -30 -20 -10 0 10 20 30 40 50 60 70 80 Crank Angle (°CA ATDC) c.

Figure 4. Plots of typical cylinder pressure during: (a) light, (b) medium, and (c) heavy knock, with normal combustion trace in a Rotax 914.

2.2.4.3 Factors That Influence Knock

There are many factors that affect the temperature, pressure, residence time, and homogeneity of the end-gas, leading to engine knock. By measuring the highest value of a certain parameter that can be attained before knocking begins, the knock limit of the engine with respect to each parameter can be quantified. The main knock limit performance parameter chosen for this work is the knock-limited indicated mean effective pressure (KLIMEP).

17

KLIMEP can be measured at different engine operating conditions to characterize the effect of the various parameters on knock [33].

Compression Ratio

Although the compression ratio in all but a few research engines is fixed at a certain value, the compression ratio has a large influence on the susceptibility of an engine to knock.

On engines that do have the ability to change compression ratio, another knock limit performance parameter, the knock-limited compression ratio (KLCR), can be measured as operating conditions are varied [4]. Knock is the main reason that compression ratios are lower than the optimal value to maximize thermal efficiency in SI engines. Increasing compression ratio directly reduces the autoignition delay times of fuel-air mixtures by increasing their temperature and pressure, in turn increasing the tendency to knock [22]. Variations in the compression ratio between engines of the same model and from the same manufacturer due to manufacturing tolerances have been shown to cause measurable variations in knock-limited performance [34].

Fuel Anti-Knock Qualities

The main factor preventing SI engine designers from increasing compression ratio is the ability of the intended fuel to resist knocking. As engine technology and fuel quality improved, the average compression ratio in SI engines went from around 2.5 in Nikolaus Otto’s 1876 engine to around 4 in the 1920s [35]. In 1921 Thomas Midgley Jr. and Thomas Boyd, working at

Dayton Engineering Laboratories Company (DELCO) under the direction of Charles Kettering, found that the addition of tetraethyl lead (TEL) to gasoline significantly increased the fuel’s anti- knock characteristics. Midgley also found that adding ethylene di-bromide to the TEL reduced the lead deposits plaguing engines running with TEL in the fuel. Working together with Graham

18

Edgar, they developed a process of removing ethylene di-bromide from sea water to create their

“ethyl fluid” [17].

In order to rate the anti-knock characteristics of various fuels, Edgar devised a scale that compared the engine’s performance on the fuel under testing to performance on a standard fuel. Edgar selected iso-octane (2,2,4-trimethyl pentane), a highly knock resistant branched hydrocarbon, as the upper limit to the scale. He suggested n-heptane, a straight chain alkane first synthesized by Ricardo as the lower limit to the scale since it showed very little knock resistance. He suggested rating the standard fuel from 0 to 100 based on the volume proportion of iso-octane and n-heptane, which are now called primary reference fuels (PRFs)

[17, 34]. Edgar’s scale became widely used, and it is now known as the fuel ON rating. The creation of the ON scale to rate fuels was only part of the problem in producing repeatable and accurate results.

With the ON scale established, fuels were tested to find their rating, but the rating differed tremendously based on the engine and operating conditions. The Cooperative Fuel

Research Committee (CFR) (formed by the Society of Automotive Engineers (SAE), the American

Petroleum Institute, and the National Bureau of Standards) designed a standard test engine which was very rugged, and allowed the compression ratio to be changed during operation to find the knocking performance limit [17]. The CFR engine, manufactured by Waukesha Motor

Company (a CFR committee member), was available with a that would allow the operator to switch between multiple fuels on-the-fly to determine fuel ON rating by comparing the performance of the fuel under test to performance using PRFs. With the precision to allow the operator to determine the octane rating to the nearest 0.1 ON, this engine became the standard test engine for fuel ON rating [34].

19

With the fuel rating scale and the CFR engine standardized, the only remaining aspects to standardize were the test conditions. The American Society for Testing Materials (ASTM) published a set of standards to determine ON rating in 1933, which are the foundation for the two main standards used today [17]. The research octane number (RON) (ASTM D2699) [36] standard was developed to simulate normal engine operating conditions, and the motor octane number (MON) (ASTM D2700) [37] standard was created to mimic more severe automotive operating conditions. The operating conditions for these standards are presented in Table 2.

Table 2. Test conditions for RON and MON determination in CFR engine. [36] [37] Parameter RON MON Intake Air Temperature 52°C 149°C Intake Air Pressure atmospheric atmospheric Coolant Temperature 100°C 100°C Engine Speed 600 RPM 900 rpm Spark Timing 13° CA BTDC 14-26° CA BTDC Compression Ratio 4-18 4-18

The current ON rating shown at the in the United States is called the anti- knock-index (AKI). The AKI is the average of the RON and MON ratings. Lower intake air due to improved thermal management on modern engines cause their performance to align better with the RON scale than the MON scale. Entirely new scales have been suggested to better match modern engines and operating conditions [38]. Sensitivity (S) is a measure of a fuel’s performance change based on the severity of ON test used (Eq. (6)). The sensitivity of any PRF blend is zero by definition, but most motor gasoline (mogas) has a sensitivity of roughly 8 [38].

푆 = RON − MON (6)

Since the discovery of TEL, fuel knock resistance and engine compression ratio have increased as developments have been made in both fields. Figure 5 shows how fuel ON has

20 increased within the introduction of new refining practices. Figure 6 shows how compression ratio has followed the increase in ON as fuel anti-knock quality improved. Around 1960, when the benefits from increasing compression ratio began to diminish, manufacturers turned to increasing to develop more power. Manufacturers began to reduce compression ratio around 1970 when TEL was removed from the majority of fuels due to environmental standards. While fuel quality continued to increase through the 1970s, compression ratio did not begin to increase again until the 1980s with the introduction of fuel injection systems to replace and the increase from two to four valves per cylinder

[38].

Figure 5. Plot showing effect of improvements in refining techniques on fuel octane rating. Adapted from Obert [4].

21

Figure 6. Plot of historical trend of average compression ratio in the US. Adapted from Amann [39].

The main goals of refineries over the mid-1900s were to increase production by finding new ways to use a wider cut of the crude distillate to produce gasoline and to increase the anti- knock qualities of the gasoline they produced. For instance, the introduction of thermal cracking allowed more gasoline to be made from the crude and had a positive effect on fuel ON.

The fuel anti-knock qualities were shown to improve as the straight chain hydrocarbons of the crude were cracked to form olefinic compounds which contain a double bond in the chain.

More improvement was shown with the introduction of isomerization and alkylation processes used to produce branched chain compounds. These short highly branched compounds show much greater knock resistance than long straight chain compounds.

Although Midgley stumbled onto the effects of TEL almost by accident and did not entirely understand the mechanism that caused the reduction in knock, the mechanism has since been studied in detail. The TEL in the fuel decomposes at the elevated temperature in the

22 combustion chamber to combine with oxygen to form lead oxide [40]. This cloud of lead oxide particles provides catalytic surfaces which react with the active radicals acting as intermediate species in the chain-branching reactions that precede autoignition [41]. TEL is more effective in paraffinic fuels where more of these chain-branching reactions take place. Tetramethyl lead

(TML) is also used as an anti-knock agent, and has a greater effect on fuels with high aromatic hydrocarbon content.

The Army Air Corps specified a high-grade gasoline in 1930 that had to be a minimum 65

ON, which was raised to 87 ON with no more than 6 ml of TEL per gallon [17]. As technology developed, the ON requirements exceeded 100 ON. Octane numbers in excess of

100 ON were generally characterized by the amount of lead added to iso-octane to achieve the same performance. Today, 100 octane low-lead (100LL) or avgas is the most popular aviation fuel for SI engines with a fuel AKI rating of roughly 105. Unleaded replacements to avgas have been researched by the CRC, but the effects of TEL have been challenging to replicate with other less toxic compounds. The use of methyl tertiary-butyl ether (MTBE), ethyl tertiary-butyl ether

(ETBE), m-toluidine, and methylcyclopentadienyl manganese tricarbonyl (MMT) are under consideration as TEL replacements in aviation fuel [42].

Lamp oil, also known as kerosene, was chosen to be the fuel for turbine engines in the early 1940s because of its broad availability when gasoline was already in very high demand.

Kerosene fuel represents the refinery distillation product between and gasoline [42,

43]. Despite many refining improvements and additive packages, USAF JP-8 and commercial aviation’s Jet A/A-1 are quite similar to kerosene. The high paraffin and napthene content of these fuels make them ideal for use in rapid continuous constant pressure combustion. These fuels do not perform well in SI engines because of their tendency to autoignite, even though they possess higher flashpoints than gasoline fuels. Baral and Raine conducted a study of

23 gasoline fuels diluted with less costly kerosene in an SI engine showing a reduction in knock- limited performance at 10% kerosene by volume, with an even greater performance reduction at 20% [23]. Previous research by Anderson et al. has shown the KLIMEP of an SI engine running

JP-8 is reduced by as much as 75% compared to running on avgas [30].

Another way to quantify knock-limited engine performance is to find the octane number requirement (ONR) for the engine to operate at a certain condition. The octane requirement method is quite useful since it isolates the knocking tendency of a single operating variable without requiring one to adjust other parameters to incite knock. The main drawback to using

ONR for knock performance rating is the cost in time and money of using PRFs [22]. William

Attard assembled a table of various engine operating parameters and their effects on ONR during his PhD work at the University of Melbourne. Adapted here in Table 3, this information serves as a helpful starting place when selecting a strategy to reduce knock. The influence on knock of a majority of the parameters in Table 3 will be addressed in the remainder of this section.

24

Table 3. Factors affecting ONR of SI engine. Adapted from Attard [44].

Octane-Number Requirement Parameter Range Tested (ONR) Increase 1 ONR/1° knock-limited Spark Advance 0 – 30 °CA BTDC spark advance [45] [46] Intake Air Temperature Increase 1 ONR/7°C [45] [46] 20 – 90°C Air-Fuel Equivalence Ratio Peaks around 5% rich of () stoichiometric, Decreases 2 0.8 – 1.6  ONR/0.1  [46] [47] [48] Decrease 3-4 ONR/10% mass Dilution: Cooled EGR 0 – 20% mass diluent diluent [49] Manifold Absolute Pressure Increase 3-4 ONR/10 kPa [46] [48] 85 – 135 kPa Increase 5 ONR/CR [45] [46] [47] Compression Ratio (CR) 5 – 12 CR [50] [51] Exhaust Back Pressure Increase 1 ONR/30 kPa [46] 0 – 65 kPa Coolant Temperature Increase 1 ONR/10°C [46] 70 – 110°C Altitude Decrease 1.4 ONR/300 m 0 – 1800 m Decrease 2.5 ONR/300 m [45] 1800 – 3600 m Humidity Decrease 1 ONR when increasing relative humidity from 40% to 50% - at 30°C [45] Increase 6-9 ONR over life of Engine Deposits 0 – 250000 km engine [45] Increase up to 12 ONR, depending Excessive Oil Consumption - on engine operation [45] Decrease 4 ONR when DI used Type of Fuel Injection - over PFI [52] Decrease up to 5 ONR as squish Increasing Squish 0 – 67% squish area area increases [22] Combustion-Chamber Decrease up to 15 ONR from Shape cylindrical to modern-type 7.8 – 11 CR chamber [50]

Hydrogen (H2) Addition Decrease 1 ONR/1% H2 added [48] 0 – 12% H2 added

Ignition Method and Timing

Once the compression ratio and fuel anti-knock rating are selected, the primary method used to reduce knock is to adjust ignition timing. Although MBT timing is the optimal timing for best thermal efficiency, knock may preclude such an advanced timing. The most advanced

25 knock free timing, which is still less advanced than MBT timing, is called the knock limited spark advance (KLSA). When knock is encountered, retarding the ignition timing delays the start of combustion, reducing the time that the mixture spends at the elevated temperatures and pressures inside the combustion chamber. This reduction in residence time at high temperature, which aims to keep the residence time less than the autoignition delay time for the end gas, mitigates the onset of knock. For instance, Anderson et al. showed a roughly 4 bar increase in BMEP with 10° CA ignition timing retard from MBT [30].

The path of the flame front from ignition to the end gas region should be kept as short as possible to avoid subjecting the end gas to more residence time ahead of the flame front than necessary. Since most combustion chambers are circular in shape, the spark plug is usually placed at the center of the combustion chamber for this reason. In combustion chambers that do not allow for a centrally located ignition source, it is generally advisable to add a second spark plug opposite of the first to minimize the distance between the ignition and the end gas regions. These dual spark plug ignition systems generally perform comparably to systems with one centrally located spark plug [4, 22]. Many SI aircraft engines employ a dual plug design. In the event of a failure, the engine will continue to operate on a single plug, effectively retarding combustion phasing [22, 53].

One ignition technique that has recently regained popularity is a pre-chamber called a turbulent jet igniter (TJI) [29, 54, 55] . The turbulent jet igniter consists of a small pre-chamber cavity that houses a spark plug, and is connected the main chamber through a number of small orifices. Combustion is initiated by the spark plug inside the TJI. As pressure and temperature build, the hot initial combustion products and their active radical species are forced through the orifices into the main chamber. As the radicals are forced through the orifices, the flame is quenched. When the radicals reach the mixture in the main chamber, they

26 accelerate the reaction in the main charge and rapidly ignite a large portion of the mixture. The

TJI produces a relatively fast and repeatable ignition process. When the TJI is fitted with an auxiliary fuel injector, it can be used in a stratified configuration where a very lean global fuel-air mixture is ignited using a locally rich mixture inside of the pre-chamber [1].

The TJI can reduce knocking by allowing combustion phasing to remain closer to optimal

(CA50 of 7-8° CA), but with retarding ignition timing. Since the TJI facilitates a faster ignition, the ignition timing from a standard spark ignition system would be too advanced for a TJI system, causing the end gas to spend a much longer time at elevated temperatures and pressures. Retarding the ignition time but burning faster leaves less time for the end gas to exceed its autoignition delay time.

Intake Air Temperature

The temperature of the air entering the cylinder has a strong effect on knock. As the temperature of the air inducted into the cylinder increases, the fuel-air mixture temperature following adiabatic compression increases as well. This increase in temperature shortens the autoignition delay time and hastens the onset of knock. Taylor shows that a 1 bar KLIMEP increase can be gained with a 57°C reduction in intake air temperature for a low-sensitivity fuel

[22].

Intake Air Pressure and Turbocharging

In much the same way as intake air temperature, intake air pressure has a strong effect on knock. The higher the pressure in the cylinder is before compression, the higher the pressure will be following compression, which to shorter autoignition delay times. Intake air pressure has been used to quantify knock limited performance with a parameter called the knock limited intake pressure (KLIP) [22]. Since SI engines control their power output by

27 increasing and decreasing manifold pressure, there is a greater tendency to knock at increased engine operating load.

The turbocharged performance of SI engines is mainly limited by knocking induced by increasing manifold pressure. For this reason many turbocharged engines are designed with a lower compression ratio to compensate for the knock penalty associated with turbocharging

[56]. also increase the intake air temperature. This temperature increase compounds the knock limit penalty associated with turbocharging. The temperature increase can be overcome by routing the compressed air through a heat exchanger to reduce the intake air temperature, which, as an added benefit, further increases the density of the air entering the engine.

Turbocharging is essential in SI aircraft engines because it allows them to operate at higher altitudes without a reduction in power output [57]. Gear-driven were first developed precisely for this purpose [22]. Up to a certain altitude, called the turbo- normalization altitude, the allows the engine to compensate for the decreasing pressure by closing the waste gate [56]. As the aircraft climbs above the turbo-normalization altitude, the waste gate is fully closed and the engine produces progressively less power. It is important to note, however, that the lower ambient pressure works in favor of the exhaust turbine even reducing the fall-off in performance of a turbocharged engine as compared to a naturally aspirated engine [56].

Operating Speed

The rotational speed of the engine directly dictates the residence time of the reactants and products inside of the combustion chamber. The faster the engine is rotating, the less likely the reactants in front of the flame front will exceed the autoignition delay time. Therefore,

28 operating conditions at low speed and high load are generally the most susceptible to knock [22].

Heat Transfer

The heat transfer characteristics of the engine cylinder play a significant role in knock limited performance. The engine structure adds heat to the incoming mixture as it enters the cylinder and removes heat from reactants and products during combustion. Knock limited performance is improved as heat transfer away from the reactants and products increases. Data from Taylor show a 1 bar improvement in KLIMEP with a 42°C reduction in engine coolant temperature [22]. Initial low-load testing with the Rotax 914 has shown a 0.1 bar improvement with each 10°C reduction in head temperature. The lesser effect of engine temperature on knock with the Rotax may be due to the cylinder liner being air cooled. The structure of an air- cooled engine, like that found on an aircraft, generally runs hotter than that of water cooled engines. As with turbocharging, the compression ratio on air-cooled engines is usually reduced to avoid knock [58].

Just as knock is the main restriction on the compression ratio of an SI engine, knock also affects the amount of heat that needs to be rejected to the engine coolant. Some research has been done on high temperature materials for use as cylinder liners instead of the standard cast and aluminum parts. These high temperature insulating materials transfer less heat away from the hot combustion gasses, allowing them to do more work on the piston.

However, these high temperature walls heat the incoming fresh charge to the point that knock- limited performance severely decreases. The engine coolant is required to keep the engine structure cool to avoid significantly pre-heating the fuel-air mixture and increasing the tendency to knock [1].

29

On the opposite end of the heat transfer spectrum, some small engines transfer so much heat away from the combustion gasses that the autoignition delay is increased substantially. The loss of heat to the environment causes a thermal efficiency penalty, but it also allows these small engines to run on a wide array of fuels. Groenewegen et al. and Wilson et al. have shown that it is possible to operate a Fuji Imvac 34cc, 4-stroke, SI engine on JP-8 with little modification [59, 60]. The combustion chamber surface area to volume ratio of these very small engines is substantially larger than that of a standard automotive engine.

Intake Air Humidity

Although the humidity of the intake air is not usually controllable while running an engine in the field, it does have a positive effect on knock reduction. Taylor shows that a roughly 1 ONR reduction can be achieved with each 15% increase in the relative humidity of the intake air at a temperature of approximately 25 °C [22]. The heat energy in the cylinder is required to heat the water vapor as well as the air, reducing the amount of energy available to heat the air. The effect on combustion gas temperature is magnified by the high heat capacity of water vapor. A greater cooling effect can be achieved if the water is injected as a liquid, using its latent heat of vaporization to reduce the charge temperature. Historically, this method was used with aircraft engines to reduce the tendency to knock under high power takeoff conditions.

However, the amount of water needed can reach 50% of fuel flow rate, so the duration must be kept short to save weight [22].

Oil Consumption

Since oil is composed of long straight-chained paraffins, it generally has a very short autoignition delay. When oil gets drawn into the fuel-air mixture in the combustion chamber, it can exceed its autoignition delay much sooner than the rest of the mixture. If allowed to

30 autoignite in the end gas, the oil will increase the temperature and pressure of the nearby mixture, possibly causing additional autoignition before the end-gas is fully consumed. Knock initiated by oil droplets is one possible cause of the “mega knock” or “super knock” phenomena often encountered in highly boosted gasoline direct injection (GDI) engines; MAPO amplitudes over 100 bar having been recorded [32, 61] .

Fuel-air Mixture Preparation

Knock is very sensitive to changes in equivalence ratio φ, which is defined in Eq. (7) in terms of the actual air-fuel ratio (A/Fa) and the stoichiometric air-fuel ratio (A/Fs).

A/F푠 ϕ = (7) A/F 푎

An equivalence ratio of unity indicates that the stoichiometric ratio of fuel and air has been provided to the engine. An equivalence ratio greater than unity means that there is excess fuel

(fuel rich); an equivalence ratio less than unity means that there is excess air (fuel lean).

SI engines usually operate quite close to an equivalence ratio of unity under normal conditions, although operation less than unity, around φ = 0.9, may be desirable if fuel conservation is a priority. Under conditions requiring maximum power output, operation around φ = 1.1 is common to ensure that all of the air is able to react with fuel [22]. Fuel rich operation also cools the engine, removing the heat required to vaporize the fuel from the air and engine structure.

The cooling effect of over-fueling is beneficial in knock reduction because it lowers the temperature of the end gas. Although automotive engines generally do not operate much beyond φ = 1.1 in order to meet emissions regulations, aircraft engines are not always subject to the same restrictions. Taylor shows that for a low sensitivity fuel an increase of around 3 bar

KLIMEP can be realized by increasing φ from 1.0 to 1.6. A 6 bar gain in KLIMEP was achieved in

31 more sensitive fuels using the same level of over-fueling. Beyond φ = 1.6 the reduction in thermal efficiency from cooling the mixture begins to dominate and KLIMEP is reduced.

Although rich operation is not optimal for all conditions, it applies particularly well to aircraft engines during takeoff when high power output is required for a relatively short period of time

[22].

Evaporative cooling of the intake charge and engine structure does not necessarily require fuel-rich operation. PFI engines generally inject the required amount of fuel on the back of the hot intake valve to evaporate the fuel and create as homogeneous a mixture as possible.

DI engines have even greater cooling potential because they inject fuel directly into the cylinder

[62]. This allows DI engines to remove heat directly from the intake air rather than from the engine structure. This configuration is especially effective as a knock mitigation technique in turbocharged engines where the intake air temperature can be very high. Anderson et al. showed a 1 bar increase in knock limited BMEP with DI over PFI on a turbocharged SI engine

[30]. Even greater benefits of charge cooling can be realized with alcohol based fuels, which have a heat of vaporization around 1000 MJ/kg compared to roughly 300 MJ/kg for gasoline

[21].

Combustion Chamber Geometry

The design of the combustion chamber has a pronounced effect on knock limited performance. As stated previously, the surface area to volume ratio of the combustion chamber plays an important role in transferring heat away from the hot end gas; hence a smaller bore can alleviate knock. A smaller bore will also shorten the path that the flame needs to travel in the combustion chamber before it reaches the end gas. Taylor shows a reduction in KLIMEP of roughly 2.5 bar for each inch of increased bore at a compression ratio of 8 [22]. Reduction in

32 knock through decreased bore diameter must be balanced against the reduction in thermal efficiency that also occurs with decreasing bore size.

Another important aspect of combustion chamber geometry is the placement of components within the chamber. As noted previously, in order to minimize the flame path, the spark plug should be located near the majority of the fuel-air mixture, which is generally at the chamber’s center [22]. The spark plug should also be located within close proximity of the exhaust valve so that the heat of the exhaust valve is not transferred to the end gas [41].

Although many combustion chamber shapes and configurations have been used in SI engines, the most popular contemporary shape is the pent-roof type, which locates the majority of the fuel-air mixture near a centrally located spark plug [62]. This type of combustion chamber also promotes turbulence in the chamber, which can greatly reduce knock.

In-cylinder Turbulence

Increasing in-cylinder turbulence has two main effects that improve knock limited performance: mixture homogenization and flame front acceleration. Turbulence as fuel and air are entering the cylinder and during the compression stroke makes the fuel-air mixture more homogeneous with regard to local equivalence ratio and temperature. The homogeneity of the mixture is important because autoignition in the end-gas will occur in the most favorable location with increased temperature, a slightly rich fuel-air mixture, or both. A more homogeneous mixture reduces in-cylinder variation, which can create pockets favorable to autoignition, in turn facilitating increased knock limited performance. The same trend applies to multi-cylinder engines, where knock limited performance can be improved by reducing mixture discrepancies between cylinders [22].

The effect of turbulence in accelerating the flame front in SI engines has undergone a great deal of study. The turbulence creates a more wrinkled flame front, and more flame area

33 will consume the charge at a faster rate. Since the fuel-air mixture is consumed more rapidly, the end-gas residence time will be lower and ideally not exceed the autoignition delay. An increase of nearly two KLCR points can be achieved with high levels of in-cylinder turbulence [63].

Exhaust Back Pressure

Compared to other factors that influence knock, exhaust back pressure does not have as dramatic of an effect, but it is still worthwhile to consider. As backpressure increases more of the exhaust gasses remain trapped in the cylinder when the exhaust valve closes. Since these residual exhaust gasses are hotter than the fresh charge, they increase the bulk temperature in the combustion chamber. If this were the only effect, increasing exhaust back pressure would surely lead to knock. However, there is another competing effect: the residual gasses are already combusted and are therefore much less reactive than the fresh charge in the cylinder.

This tends to slow the pre-reactions that lead to autoignition, essentially offsetting the effect of increased gas temperature [22].

Exhaust pressure interactions between cylinders are hard to optimize when turbocharging a four-cylinder engine. The high-pressure blow down from one cylinder will overlap with the low pressure end of exhaust of another cylinder and consequently increase the trapped mass of hot exhaust gas in the low pressure cylinder. Although this trapped mass of hot exhaust is generally non-reacting, it heats the incoming charge, which can reduce the KLIMEP.

One solution is to separate groups of cylinders with overlapping exhaust processes to operate on different turbochargers. An alternative is to employ a turbocharger with exhaust inlet passages that are separate until they reach the turbine. Pulse converters can also be added to keep pressure pulses from traveling to the other cylinders [56].

34

One method that was developed to control nitrogen oxide (NOx) emissions, called cooled exhaust gas recirculation (EGR), or wide-open-throttle (WOT) EGR, can also be used as method for knock reduction [21]. By using a heat exchanger to cool the hot exhaust gasses, the effect of heating the fuel-air mixture when they are reintroduced is greatly reduced. This strategy allows the diluent effect of the exhaust gasses to be isolated from their increased temperature, in order to slow the pre-reactions that lead to autoignition. Recent work from

Wheeler et al. shows that EGR cooled to match the intake air temperature and introduced at a proportion of 20% of the intake air was able to extend the KLIMEP by roughly 1 bar.

Unfortunately, such a high level of EGR increases the flame development period, causing increased variation in flame development leading to overall combustion instability [64].

Combustion Chamber Deposits

Although combustion chamber deposits are most notable for their role as hot-spots in pre-ignition, they can also play various roles in end-gas knock. As combustion chamber deposits develop they can block heat transfer through the cylinder walls and increase end-gas temperatures. Knocking will often break lose these deposits, heating them further and possibly causing pre-ignition during the next cycle. Although the effect is usually small, combustion chamber deposits decrease the clearance volume slightly, causing increased peak cylinder pressures, which also foster knock. Work by Brussovansky, Heywood, and Keck suggests that active species from the end-gas are absorbed in the deposits and are carried over to the next cycle where they are reintroduced in the end-gas. These active species reduce the autoignition delay time by accelerating the pre-reactions, again leading to knock [65].

35

2.3 Homogeneous Charge Compression Ignition Combustion

Although research solely focused on knock reduction has waned considerably with the introduction of higher quality fuels and more advanced engine technology, a fundamentally similar area of study has gained popularity within the last decade: homogeneous charge compression ignition (HCCI). HCCI combustion, also called controlled autoignition (CAI) combustion, uses a homogeneous fuel-air charge similar to normal SI combustion. By employing a high compression ratio the mixture is intentionally autoignited. The controlled autoignition can permit more uniform and repeatable combustion for lean or dilute mixtures and improve part-load fuel economy. Since HCCI does not require a spark to ignite the mixture, engines operating in HCCI mode can run at equivalence ratios much lower than SI engines, and are able to leave the intake passage un-throttled to reduce pumping losses [7].

HCCI is intended to operate in the thermal explosion regime [5]. Since the amount of fuel is the primary load control mechanism, the severity of the autoignition increases as load increases. Once the maximum pressure rise rate for the engine (3-5 bar per °CA for modern SI engines) is reached, the engine must change to a different mode of operation to avoid damage

[21]. Current HCCI combustion research engines usually switch to normal SI mode above the maximum pressure rise rate limit. SI operation is generally also required at low idling loads because with little additional heat available, the mixture tends not to autoignite, leading to misfire and incomplete combustion [5]. The use of both CI and SI modes of operation necessitate that some compromise is required between a fuel that will autoignite easily under

HCCI operation, and resist end gas knock under high-load SI operation.

Without using the spark plug to initiate combustion, or timing a fuel injection event to initiate combustion like CI engines, HCCI engines must rely on mixture temperature and reactivity to control combustion phasing. In order to control the temperature of the intake air,

36 some experimental HCCI engines are equipped with heat exchangers to remove heat from the exhaust and engine coolant to heat the intake air. Fast acting control valves have been implemented to control combustion phasing by changing the intake air temperature during transient operation [21]. Another control method called residual gas storage uses fully variable to reintroduce exhaust gas directly back into the fresh charge to heat and dilute it.

Control methods including variable compression ratio, supercharging and turbocharging, and stratified fuel injection have all been successful to some degree [5].

Two additional HCCI control methods have been developed that offer a more direct approach to controlling combustion phasing on a cycle-by-cycle basis. Researchers from Oak

Ridge National Laboratory and the University of Wisconsin-Madison have shown reactivity controlled compression ignition (RCCI) to be very effective at controlling combustion phasing. In

RCCI two separate fuel systems, a gasoline PFI system for homogenous injection, and a diesel DI system operated in the early injection mode, are used for combustion control. The proportion of each fuel is adjusted to vary the autoignition delay to achieve the targeted combustion phasing [66, 67]. The second strategy operates in the same gasoline PFI/diesel DI configuration.

In this configuration the majority of the fuel is gasoline and late diesel injection is used to initiate autoignition to control combustion phasing, as outlined in Figure 7 [68]. Instead of HCCI, this strategy might better be described as a partially premixed compression ignition (PPCI) and

RCCI hybrid.

37

Figure 7. Pictorial outline of dual-fuel HCCI/PPCI/RCCI hybrid control scheme. Adapted from Choi [68].

2.4 Engine Control

2.4.1 Fuel Injection Control

Since the 1980s advances in engine control have offered some of the most significant improvements to SI engine technology. The move from carburation and throttle body injection to PFI ended the wall wetting in the intake manifold that could cause very uneven fuel distribution [62]. With PFI, the amount of fuel sent to each cylinder could be directly controlled and trimmed on-the-fly. DI added another dimension of control where fuel injection could be delayed until after the gas exchange valve overlap phase, so there is no way for fresh fuel to be drawn directly through the exhaust port, enabling complete exhaust . The remaining discussion will focus on PFI, since that is the fuel injection system employed on the engine in this work. A thorough discussion of DI technology and its use in IC engines can be found in

Zhao [21].

38

There are three main modes of operation employed in PFI systems: simultaneous, group, and sequential. In simultaneous injection, the most basic PFI implementation, all of the fuel injectors open and close at the same time, which leads to differences in evaporation time for each cylinder. To even out the evaporation time between cylinders, half of the fuel required for one complete cycle is often injected once each revolution. Group injection splits the cylinders into two groups, injecting fuel for the entire cycle for one group during one revolution, and the other group during the next revolution. Group injection still causes uneven evaporation times between cylinders, although it generally performs better than simultaneous injection because the fuel is never sprayed directly at the open intake valve. Rather, it allows some amount of time for the fuel to evaporate before the intake valve opens. Sequential fuel injection remedies the timing problems with simultaneous and group injection by injecting the fuel required for one complete cycle onto the back of the hot intake valve at the same °CA for each cylinder. A subset of sequential fuel injection and cylinder-individual fuel injection adds another level of control that allows the °CA and time duration of injection to be varied for each cylinder. Figure 8 gives a graphical representation of these three main modes of operation.

Figure 8. Modes of port fuel injection operation: (a) simultaneous, (b) group, and (c) sequential. Adapted from BOSCH [69].

39

Feedback to the engine control unit (ECU) is required in order to correctly meter the amount of fuel injected under changing operation conditions. Initially, the ECU received a signal from a narrowband oxygen sensor that would indicate if the engine was currently running at either a rich or lean condition, and the ECU would compensate, always oscillating around stoichiometric. Advancements to oxygen sensor technology brought about the wideband oxygen sensor, also called the universal exhaust gas oxygen sensor (UEGO), which is able to determine the degree to which combustion is lean or rich.

Wideband oxygen sensors are constructed from an yttria (Y2O3)-stabilized zirconia (ZrO2) substrate attached to electrodes forming the oxygen pumping cell, the oxygen sensing cell, and the oxygen reference chamber wall [63, 70]. Figure 9 shows a UEGO sensor schematic including a pictorial representation of the operational principle. Exhaust gas enters the detection chamber through a diffusion passage. The partial pressure of oxygen in the detection chamber is compared to the partial pressure of oxygen in the reference chamber by reading the oxygen sensing cell voltage. If the partial pressure of oxygen in the detection chamber is higher than that in the reference chamber, a current is applied to the pumping cell to remove oxygen from the detection chamber [71]. This corresponds to a lean condition. If the partial pressure of oxygen in the detection chamber is lower than that in the reference chamber, a current in the other direction is applied to the pumping cell to add oxygen to the detection chamber. This corresponds to a rich condition, and the oxygen pumped into the chamber combines with CO,

H2, and hydrocarbons. When the partial pressures of oxygen in the reference and detection chambers are equal, a stoichiometric mixture is present and the pump current is zero. The magnitude and sign of the current applied to the oxygen pumping cell directly correlates to the equivalence ratio of the gas in the detection chamber [61, 69, 71]. The O2 sensor controller

40 scales its output relative to the air-fuel ratio of gasoline corresponding to the required pump current in the sensor.

Figure 9. Schematic of UEGO sensor. (a) Sensor structure. (b) Sensor operational principle. Adapted from Ladommatos [71].

Temperature and pressure both play an important role in receiving an accurate signal from a wideband oxygen sensor. Constant temperature is required to keep the response of the pumping and sensing cell constant [61]. In order for temperature changes in the exhaust gas to not adversely affect the measurement, an integrated heater circuit heats the sensor elements to

650-900 °C, depending on the sensor. The sensor generally requires around 30 seconds to reach a stable operating temperature, during this time the engine must operate without closed-loop

41 feedback [69]. Increased exhaust back-pressure (when installed in configurations such as upstream of a turbocharger) will cause the sensor to read proportionately leaner or richer as the equivalence ratio deviates from stoichiometric. The increased exhaust pressure allows diffusion through the sensor’s diffusion passage at an increased rate. This causes the pump cell to operate at a higher pumping rate to account for the increased amount of gas in the detection chamber [72]. The increase in pump current can be accounted for if the exhaust pressure is monitored, and the output from the oxygen sensor controller adjusted according to the manufacturer’s pressure correction curve.

2.4.2 Spark Ignition Control

Improvements to modern spark ignition systems began as far back as 1910, when

Charles Kettering had perfected so called battery ignition enough to install it on a Cadillac.

Battery ignition used an inductive powered from the ’s battery, and was a welcomed replacement to the standard ignition systems that had become quite costly

[69]. Kettering’s battery ignition system produced a powerful spark regardless of the engine speed, causing some to associate the new system with knock, although they likely just needed to retard their ignition timing for the new system. Ironically, these accusations prompted

Kettering’s interest in finding what was actually causing knock in these early engines [17].

Throughout most of the mid 1900s battery ignition systems relied on a mechanical to control the high voltage ignition energy. The distributorless ignition systems of the 1980s brought a new level of control and removed all of the moving parts from the ignition system [69]. Modern ignition systems are now able to adjust spark advance to individual cylinders based on real-time sensor feedback. This is of great importance when the engine is operating in conditions that are conducive to knocking combustion. When knock is detected by the knock sensor vibration passing a predetermined threshold, ignition timing for the knocking

42 cylinder is usually retarded by 3 °CA on the next cycle. If the knock sensor signal has fallen below the knocking threshold, the timing is advanced in increments of 1 °CA per second until the normal ignition timing is reached or the knocking threshold is again passed [73]. This level of control allows the engine to operate as close as possible to the optimum combustion phasing.

2.4.3 Automotive Engine Control Units

The advances in fuel injection and spark ignition technology were enabled by advances in engine control unit technology. Many of the original fuel injection and spark ignition control units of the 1980s used a microcontroller from Intel called the 8051, one each for fuel and spark.

The 8051 was an 8-bit microcontroller clocked at 12 MHz, but with only 1 instruction cycle every

12 clock cycles. This meant the 8051 could perform 1 million instructions per second (MIPS), although not all of its operations could be completed in one instruction cycle. 16-bit processers became the norm during the mid-1990s, with 32-bit processors running over 50 MIPS becoming popular in the early 2000s.

As the ECU developed it took on more tasks than just timing fuel injection and ignition events. It began diagnosing problems with the engine and peripheral systems with a system called on-board diagnostics II (OBDII). This has led Basshuysen to posit that up to 50% of the software in a modern ECU does not actually control the engine function [62]. The trend of increasing software in the ECU has caused the size of the programs contained to double about every three years [62]. Since the computing power of the on-board microcontrollers are quite limited, many of the standard ECU functions have been allocated to application specific integrated circuits (ASICs) in order to free up microcontroller processing overhead [69].

43

2.4.4 Flexible Research Engine Control Units

ECUs used in laboratories for engine research serve a different purpose than those developed for the automotive industry. ECUs intended for engine research are designed to be flexible, allowing the user to change operating parameters during a test. Also, the ability to add and configure entirely different engine systems can drastically speed up testing and allow new ideas to come to fruition more easily. For instance, adding a fuel injector that requires multiple injection pulses, or programming a second ignition output on the same cylinder with slightly different timing, both of these tasks would require an advanced ECU. This level of end user control is generally out of the question with standard automotive ECUs and aftermarket systems from companies like AEM, Haltech, and Motec. Researchers from Oak Ridge National

Laboratory and the University of Wisconsin-Madison have been able to demonstrate a high level of configurability using their National Instruments Labview based Drivven control system to conduct dual-fuel-injection experiments similar to those described in this work [74].

The second benefit of using a research ECU for testing is the increased computing power and input/output (I/O) timing precision. Although modern automotive ECUs can perform I/O operations with reactions around 10 microseconds, the corresponding resolution of 0.35 °CA at an engine speed of 5800 RPM may introduce too much error for a research application [62]. For instance when studying knock, a tolerance of 0.35 °CA on spark timing will likely introduce an error of 0.35 ONR into the results. Many research ECUs run on high speed field programmable gate array (FPGA) systems that outperform automotive units in I/O operations and real-time numerical calculations.

Cost is the main drawback in employing a research ECU. Both the initial hardware cost and the cost in the development time required to program and/or configure an advanced engine controller can be prohibitive. Flexible research controllers and necessary calibration

44 software packages including the MotoHawk by New Eagle, the Drivven system by National

Instruments, and the MS 5.0 from Bosch range in cost in the tens of thousands of dollars. Since an ECU is required for each research , this cost multiplied by the number of test stands can cause costs to escalate sharply. These factors have led some researchers to take the problem upon themselves and design their own flexible research ECU. Engineers at MAHLE

Powertrain have designed the MAHLE Flexible ECU using the AFT PROtroniC prototyping platform with proven success [75].

45

CHAPTER 3

3. RESEARCH OBJECTIVES – PHASE ONE

The current work was performed in two separate phases, each with different objectives.

After the first phase of work was complete, the engine research stand was refined to improve the quality of data for the second phase of testing. The objectives, setup, and results for the two phases of work have been separated in order to provide a cohesive progression of the research. The description of the second phase of work begins in Chapter 6.

The objectives specific to the first phase of work are as follows:

• Establish and verify the satisfactory operation of a dual-fuel PFI system to allow in-situ

octane adjustment.

• Determine the KLIMEP as a function of fuel ON for the Rotax 914 engine with the dual-

fuel PFI system.

• Determine the KLIMEP for the Rotax 914 engine operating on JP-8 and estimate the ON

of the JP-8 sample.

• Evaluate the required relaxation of the Rotax 914 engine’s ONR to enable JP-8 cruise

with the PFI configuration.

46

CHAPTER 4

4. EXPERIMENTAL SETUP – PHASE ONE

4.1 Rotax 914 Research Engine

The engine used for gathering the experimental data in this work is a retired Rotax 914 with roughly 1000 hours of operational service (Figure 10). The Rotax 914 is classified as a horizontally-opposed four-cylinder four-stroke turbocharged SI engine. Each cylinder head and cylinder of the Rotax is independent and is separately attached to the block allowing for of the cylinders, although the heads are water cooled. The engine also has an integrated speed reducing gearbox with an output shaft to which the would be attached.

Although the Rotax 914 comes in a carbureted configuration, the engine in this work was previously converted to PFI. The configuration and specifications of the engine are outlined in Table 4.

47

Table 4. Rotax 914 engine configuration and specifications. [76] Parameter Configuration Basic Design Horizontally Opposed Working Cycle Four-Stroke Number of Cylinders 4 Aspiration Turbocharged Combustion Chamber Bathtub Valve Location, Actuation Overhead, Pushrod Valves per Cylinder 2 Fuel Gasoline Fuel Delivery PFI Ignition SI, Dual-side Ignition Cooling Air Cooled Cylinders, Water Cooled Heads Oil System Dry Total Displacement 1.21 L Bore 79.5 mm Stroke 61.0 mm Compression Ratio 9:1 Gearbox Ratio 2.43 Weight (Dry) ~70 kg Intake Valve Open 0° CA TDC of Gas Exchange Intake Valve Close 132° CA BTDC of Combustion Exhaust Valve Open 132° CA ATDC of Combustion Exhaust Valve Close 0° CA TDC of Gas Exchange Maximum Recommended Speed 5800 rpm Maximum Rated Power Output 84.5 kW @ 5800 rpm Maximum Intake Manifold Pressure 1.37 bar Maximum Intake Air Temperature 88°C Maximum Cylinder Head Temperature 135°C Maximum Oil Temperature 130°C Maximum Exhaust Gas Temperature 950°C Minimum Recommended Fuel Octane 91 AKI Mogas

48

Figure 10. Picture of the SERL Rotax 914 research engine in the PFI configuration.

4.2 Engine Research Cell

The output shaft of the Rotax gearbox is coupled to a 190 kW, eddy-current, wet-gap

Midwest Dynamatic dynamometer via a conventional driveshaft with two universal joints

(Figure 11). The power applied to the dynamometer field coils is controlled by a DyneSystems

Dyne-Loc IV dynamometer controller, which receives torque feedback from a 500 lbf strain- gauge load-cell attached between the dynamometer base and the center body, which is free to rotate. A variable reluctance (VR) sensor is mounted near a 60-tooth trigger wheel and is used for post-gearbox speed feedback to the dynamometer controller. The dynamometer is fitted with a heavy duty pneumatic engine starting motor, which is able to motor the engine at roughly 1000 rpm.

49

Figure 11. Picture of 190 kW eddy-current wet-gap Midwest Dynamatic Dynamometer and pneumatic engine starting system.

Air is supplied at 100 psi to the facility air storage by a 50 Kaeser rotary screw compressor with an integrated dryer (Figure 12). Air from the facility storage tanks is routed to a remotely operated pressure control valve, which controls the differential air pressure across a sonic nozzle. Air is supplied to a 15 kW Chromalox heater, which is controlled by a process temperature controller mounted remotely at the engine control panel. The outlet of the heater is ducted to surround the engine intake , and is not sealed so the flow rate of the air system does not need to be precisely controlled once the required temperature is achieved. The heated air system can also be bypassed when heating is not required.

50

Figure 12. Diagram of test cell showing fluid flow through engine support systems.

A Bosch HFM 5 hot-film mass airflow meter (MAF) is installed downstream of the intake- air filter. Following the MAF, the air enters a 60 L damping chamber required to smooth air-flow pulsations before it enters the turbocharger compressor inlet. The inlet damping chamber was sized according to a general guideline which specifies a chamber volume equal to 50 times the displacement of the engine [22]. Chambers of lesser volume shown in Figure 13 were tested on the engine and allowed flow oscillations upstream of the damping chamber, as measured by the

MAF, under low-speed, high-load conditions. Downstream of the turbocharger compressor a

51

65mm Bosch electronic throttle body, which is controlled by a Pololu Jrk DC motor controller, is used to control airflow into the intake manifold. A linear actuator is used to modulate the turbocharger waste-gate, which controls the flow through the turbocharger and in turn intake manifold pressure under boosted conditions. The DC motor of the linear actuator is controlled by another Pololu Jrk DC motor controller, which receives a 0-5 V analog signal from the low- speed data acquisition (DAQ) program.

(a) (b) (c)

Figure 13. Pictures of: (a) 20 L, (b) 40 L, and (c) 60 L damping chambers during on-engine flow damping characterization.

A 50/50 mixture of and water is circulated by the engine’s water pump through all four heads and the liquid-to-air heat exchanger. An electric is mounted to the coolant heat exchanger to provide a forced air flow for increased heat transfer. A relay controlled by the low speed data acquisition system modulates the fan to keep the cylinder head temperature at 85 ± 5˚C. Engine oil is circulated by the engine’s oil pump through the , gearbox, and turbocharger, and then routed to the flat-plate oil-to-process-water heat exchanger. It then flows back to the oil reservoir. This system maintains the engine oil temperature well below the maximum set forth by Rotax of 130˚C, generally around 90˚C. The exhaust gasses are routed out of the turbocharger and into a fan driven exhaust extraction

52 system that removes the exhaust from the test cell. A carbon monoxide monitoring systems is installed and monitored by the low-speed data acquisition system for operator safety.

The number two cylinder was used as the test cylinder to simplify the data collection process and to reduce the possibility of engine damage under knocking conditions. The other three cylinders were run at non-knocking operating conditions during all engine testing by supplying them with high octane fuel and retarding ignition timing when necessary. The original

PFI configuration consisted of two fuel rails supplying fuel to cylinders two and four on one rail and cylinders one and three on the other. The cylinder four intake manifold was modified so that its injector would receive fuel from the fuel rail supplying cylinders one and three. With the other cylinders separated from the test cylinder, a second PFI port was added to the cylinder- two intake runner opposite the original PFI port (Figure 14). This second port would allow two injectors to be operated at the same time and on the same cylinder, both directed at the back of the intake valve.

The first iteration of this design, with a second PFI port welded to the original intake manifold began to crack in the heat affected zone of the weld after a few hours of testing.

Welding the cracks to repair them only fixed the problem for another hour of testing before the cracks reappeared adjacent to the weld. To remedy the problem, a thicker-walled tube with a similar bend radius was welded to a CNC machined intake port flange that was reverse engineered from the original intake runner. Two PFI ports were welded to this new intake runner to enable the dual-fuel capability. This design allowed testing to continue without further intake runner cracks. Engineering drawings of the Intake port flange and the additional

PFI port are included in APPENDIX A and APPENDIX B respectively.

53

Figure 14. Pictures of dual-fuel PFI system installed on test cylinder with Fuel A and Fuel B systems labeled. Left: First iteration with second injector port welded to original intake runner. Right: Second iteration with thicker wall tubing and reverse engineered intake port flange.

Three different fuel supply systems were employed in the dual-fuel PFI configuration.

The non-test cylinders were plumbed to the facility avgas fuel system, with fuel pressure controlled by a head of nitrogen in the supply set at 3 bar gauge pressure. The test- cylinder was plumbed to two dedicated fuel systems, one for each PFI injector. Each of the test- cylinder fuel systems was pressurized with a pump, one pneumatic and one electric, plumbed to an intake manifold referenced pressure regulator in order to keep the differential pressure across each of the test-cylinder injectors at 3 bar gauge pressure. Both of the test-cylinder fuel systems were fitted with a Max Machinery piston-type positive-displacement flow meter to monitor and record the proportion of each fuel used during engine operation. Bosch

0280155771 185-cc/min (~17-lbm/hr) port fuel injectors were used to allow finer low-load fuel- flow control compared to that of the 260-cc/min (~24-lbm/hr) injectors used for full-load operation on avgas.

54

4.3 Engine Control Unit

The majority of the experimental setup effort was devoted to developing the ECU used in the current work. The limitations of an original equipment or performance aftermarket ECU discussed previously necessitated a flexible research oriented engine controller for this work.

The PIC18 microcontroller was selected based on past projects completed at the Air Force

Research Laboratory (AFRL). ECU development had already begun to a limited degree by Cpt.

Wesley Anderson when the author took-over further development of the Rotax ECU. The circuit board shown in Figure 15 was designed to accommodate two PIC18 microcontrollers, one for ignition control and the other for fuel injection control. A schematic of the dual-PIC18 ECU circuit board is included in APPENDIX C.

Figure 15. Picture of dual-PIC18 Microcontroller ECU circuit board.

4.3.1 PIC18 Microcontroller

The 16-bit PIC18F542 operates on a 40 MHz external clock, but only performs 1 instruction cycle every 4 clock cycles for an overall performance of 10 MIPS. This is comparable with the performance level of automotive ECUs from the mid-1990s [69]. The PIC18 is

55 programmed in a C environment, with many of the math operations taking several instruction cycles to complete. For instance, 16 bit division can take 38 instruction cycles because there is no hardware support for division. An integrated 8-channel 10-bit analog to digital converter

(ADC) is available to process external analog signals. Three onboard timer modules are available along with 3 external interrupt pins, which can be used for timing from external digital inputs.

The remaining 22 pins on the 40 pin chip can be configured for either digital input or output as required.

Many different versions of the ignition and fuel injection control programs were created as ECU development progressed. The first iteration of the fuel program allowed the user to specify fuel injection pulse-width by adjusting an analog input which was controlled using the low-speed DAQ. In this program, fuel injector output was controlled in the simultaneous injection configuration outlined in Figure 8. The first version of the ignition program did not allow the user to adjust the spark timing because it was hard-coded in the program at 26° CA

BTDC. Further modifications enabled the PIC18 ECU to control fuel pulse-width in closed-loop sequential mode and vary ignition timing using the analog input from the low-speed DAQ in a waste-spark configuration. For dual-fuel operation, a third PIC18 was added and a new program was written to control the two test-cylinder injectors in conjunction with the three standard injectors.

4.3.2 Timing Signals

The ECU requires timing signals from the engine in order to precisely orient the ignition and injection events. The Rotax 914 research engine provides two of the required signals without any hardware modification. The 36-1 encoder, a encoder wheel with 35 slots spaced in 10 degree increments and one missing slot, is read with a Hall Effect sensor and provides CA timing input to the ECU. A separate VR sensor is installed and configured to send a

56 pulse once per crankshaft revolution, near top dead center. The information provided by this sensor could be computed from the missing space on the 36-1 encoder, but using a second sensor reduces the signal processing required on the microcontroller. The final signal required for ECU timing is an engine phase signal, which tells the ECU which phase of the cycle the engine is currently in. This signal is necessary for sequential fuel injection operation. A sensor mounting boss shown in Figure 16 was added to the cylinder-two valve cover. The Hall Effect sensor installed in this boss reads when the cylinder-two exhaust valve is open, allowing the ECU to appropriately orient its output signals to the engine cycle. A diagram showing engine timing signals in relation to the engine cycle is included in Figure 17.

Figure 16. Picture of mounting boss welded to cylinder-two valve cover for addition of Hall Effect sensor to produce engine-cycle phase signal.

Figure 17. Diagram of engine timing signals in relation to engine cycle timing.

57

4.3.3 Interrupts

The PIC18 microcontroller uses program exceptions called interrupts to control program flow when handling time critical events [70]. These exceptions cause the execution of the main program to pause, read which interrupt was triggered, and run a small section of code called an interrupt service routine (ISR) specific to that interrupt. When the ISR has completed, the microcontroller resumes the main program precisely where it was interrupted. There are two types of interrupts, internal and external. Internal interrupts can be triggered from various modules on the microcontroller if they require immediate attention from the program. The internal interrupt used in the ECU programs is the timer interrupt that is triggered when the onboard timer reaches a pre-set value. This “timer increment” can be used to link external events to the time domain, executing I/O after a set amount of time has elapsed. The fuel- injection pulse-width and spark-ignition coil charge time are set with a timer interrupt.

The engine timing signals are read by the PIC18 through external interrupts, separately triggered through three external interrupt pins on the microcontroller. The 36-1 encoder, TDC, and phase signals are each attached to an interrupt pin that is tied to a specific ISR. Using external interrupts frees the microcontroller from having to querying digital inputs at finite intervals to assess whether they are high or low, a technique known as polling [77]. By using interrupts, the microcontroller is free to continue executing the main program until it receives the signal on an external interrupt pin. Interrupt priorities can also be assigned so that the microcontroller knows which interrupt should be serviced first when two interrupts are triggered simultaneously. If a higher priority interrupt is triggered while the microcontroller is servicing a lower priority interrupt, the lower priority interrupt is paused until the ISR of the higher priority interrupt has completed.

58

Since external interrupts are immediately triggered when they occur, it is important to eliminated signal noise that could cause false triggering. A passive first-order low-pass filter circuit was necessary when using external interrupts on the PIC18 ECU to prevent false triggering from switching noise generated by various other electrical systems used during testing (Figure 18). The time constant (τc) of the RC circuit can be used to determine the cutoff frequency fc of the filter, with τc = RC (Eq. (8)). A 10 kΩ resistor and 100 pF capacitor were used on the PIC18 ECU, which attenuated signal frequencies above 160 kHz.

Figure 18. Schematic of the passive first-order low-pass filter circuit used for noise rejection on external interrupt inputs on the PIC18 ECU.

1 푓푐 = (8) 2휋푅퐶

4.3.4 Spark Ignition Program

A description of the functional workings of the spark ignition program is included here with the program included in APPENDIX D in its entirety. The inputs to the PIC18 used in this program are: one analog input for varying ignition timing, one external interrupt for the TDC signal, one external interrupt for the 36-1 encoder, and one digital input to enable and disable ignition. The digital outputs used in the program are: one ignition output for cylinders one and two, one ignition output for cylinders three and four, an engine speed output to the low speed

DAQ, an output to relay the TDC signal as a diagnostic, and an output to relay the 36-1 encoder as a diagnostic. The ignition outputs are connected to a MSD DIS-4 capacitive discharge Ignition controller, which directs the charging and firing of the ignition coils.

59

The main program loop is consists of two blocking-while-loops that wait for the encoder- count to be equal to a specific number before they execute. Inside of the loop for cylinders one and two the time elapsed during 60 degrees of engine rotation is calculated, the ignition angle

ADC is read, and the ignition output angle is scaled to occur at some fraction of that 60 degree window. This time is then added to another 60 °CA slice of time to position the spark timing window from 50 °CA BTDC to 10 °CA ATDC. The second loop operates the same way, but with the addition of a 180 °CA slice of time to offset the timing for the other two cylinders.

Three interrupts control the timing of the program. The microcontroller executes the timer interrupt code each time the timer completes its 17.5 μs count. The timer interrupt runs most often, checking the current time increment against the high and low speed limit values and against the “spark time” values. If the time is equal to either of the spark time values, the corresponding ignition output is switched from high-to-low for one timer cycle, which is long enough to trigger the ignition system. The two external interrupts run less often. At 5800 RPM the encoder interrupt triggers approximately every 16 timer interrupts at 10 °CA increments.

The encoder interrupt compares its current encoder-count value to the values set in the main program to calculate the spark timing. The TDC interrupt is used to reset the count of the encoder interrupt to sync the count with the engine cycle.

4.3.5 Main Fuel Injection Program

A description of the functional workings of the main fuel injection program is included here with the program included in APPENDIX E in its entirety. The fuel injection program uses more inputs and outputs than the spark ignition program, and is slightly more complex. The inputs to the PIC18 used in this program are: one analog input for selecting fuel-air equivalence ratio, one analog input to read air-flow from the MAF, one analog input to read feedback from the wideband O2 sensor, one external interrupt for the TDC signal, one external interrupt for the

60

36-1 encoder, one external interrupt for the phase signal, one digital input to hold the fuel pulse-width constant, and one digital input to enable and disable ignition. The outputs used in the program are: 4 individual digital outputs for injection on each cylinder, a digital output to relay the TDC signal as a diagnostic, and an output to relay the 36-1 encoder as a diagnostic.

The main program loop calculates the number of timer counts that each injector needs to be held open to supply the desired amount of fuel. The ADC pins for the MAF, desired equivalence ratio, and O2 sensor are read in the main loop while other calculations are not being performed. The MAF ADC is read at four equally spaced intervals throughout one revolution and averaged to remove any effects of any pulsations in the air flow. The base injection duration value shown in Eq. (9) is calculated by finding the correct amount of fuel to react with the air flow value read from the MAF, at stoichiometric proportions.

퐶푦푐푙푒 퐷푢푟푎푡푖표푛 ∗ 푀퐴퐹 ∗ 퐹퐴푆푇푂퐼퐶퐻 ∗ 푂2 푀푢푙푡푖푝푙푖푒푟 퐼푛푗푒푐푡푖표푛 퐷푢푟푎푡푖표푛 = (9) 퐼푛푗푒푐푡표푟 퐹푙표푤 푅푎푡푒 푀푎푥 ∗ 푁푢푚푏푒푟 표푓 퐶푦푙푖푛푑푒푟푠

This value is then adjusted based on the desired equivalence ratio and feedback from the O2 sensor. If the O2 sensor indicates a mixture other than what is selected, the O2 multiplier is adjusted by 0.001 (incremented if the mixture is lean and decremented if the mixture is rich).

If a high signal is read on the “pulse-width hold” input, the fuel pulse-width for all injectors is held constant so the user may take data with the injectors set at a constant pulse-width. When in pulse-width hold mode, the “desired equivalence ratio” input can be used to adjust the held pulse-width if fine-tuning is required to reach the desired test condition. When the pulse-width hold input returns to a low logic level, the pulse-width is returned to its pre-hold value and operation reverts to closed-loop mode.

The interrupts in the fuel program are similar to those of the spark-ignition program except for the addition of the engine phase signal that is required for sequential fuel injection.

The phase signal is only required as the engine begins to spin, to orient the ECU to the engine

61 cycle. The TDC input is used to reset the encoder increment counter after two complete revolutions to time the events for one complete engine cycle. The timer interrupt of the fuel program behaves similarly to that of the spark ignition program except that the output signals are active for more than one clock cycle, requiring precise timing of the rising edge and the falling edge of the pulse.

4.3.6 Dual-fuel Injection Program

A description of the functional workings of the dual-fuel injection program is included here with the program included in APPENDIX F in its entirety. The dual-fuel injection program is adapted from the main fuel-injection program with two injector outputs removed and one additional feature added. An additional ADC input allows the proportion of the required fuel calculated by the program to be split between the two injector outputs. This enables on-the-fly blending of fuels with different octane rating.

In the dual-fuel configuration the main fuel-injection microcontroller is active along with the dual-fuel microcontroller. Therefore, there are two closed-loop O2 corrections occurring simultaneously. The ECM FA1500 O2 controller is connected to its O2 sensor which is upstream of the turbocharger in the exhaust stream of the test-cylinder. The NGK AFX O2 controller is connected to its O2 sensor which is downstream of the turbocharger, reading the exhaust gas from all four cylinders. If the desired equivalence ratio for the main fuel-injection microcontroller is changed, it does not affect the feedback for the test-cylinder since the test- cylinder O2 sensor is located upstream. If the desired equivalence ratio of the test cylinder is changed, the feedback to the main fuel-injection chip will try to compensate, even if a change is not actually required. To avoid any feedback problems the desired equivalence ratio input is transmitted between both controllers in order to keep them operating at the same equivalence ratio.

62

4.4 Data Acquisition

4.4.1 Low-Speed Data Acquisition

Steady-state engine operating data were taken using National Instruments Compact RIO data-acquisition hardware running an engine-monitoring program developed in Labview at

AFRL. The NI cRIO-9024 real-time controller with an 800 MHz processor, 512 MB of ram, and 4

GB of storage is pictured in Figure 19. The real-time controller is connected to the interchangeable I/O modules via an 8-slot chassis. The modules are listed in Table 5 along with a brief description of each module’s functional capabilities and the parameters measured or controlled in the experimental setup.

Figure 19. Picture of National Instruments Compact RIO data-acquisition hardware.

63

Table 5. Outline of National Instruments Compact RIO hardware modules employed for low- speed DAQ. Mod. Mod. Mod. Function Parameters Measured /Controlled No. Model 4-Channel, 24-Bit NI 9239 None - Previously Used as High Speed DAQ 1 Analog Input 4-Channel, 24-Bit NI 9239 None - Previously Used as High Speed DAQ 2 Analog Input 8-Channel, Solid-State Cooling Fan, Fuel Pump Power, Fuel Shutoff NI 9485 3 Relay Valve, Instrumentation Power 4-Channel, 24-Bit None – Previously Used for Strain-Gauge Type NI 9237 4 Wheatstone Bridge Pressure Transducers Spark Timing, Equivalence Ratio, Dual-fuel 16-Channel, 16-Bit NI 9264 Proportion, Fuel Enable, Spark Enable, Throttle, 5 Analog Output Turbocharger Wastegate, Fuel Pulse-width Hold Dynamometer Cooling Water In & Out, Ambient, 16-Channel, 24-Bit NI 9213 Fuel 1 & 2, Head 1 & 2, Intake Manifold, 6 Thermocouple Input Turbocharger Oil Outlet, Exhaust 1-4 8-Channel, 10 MHz Engine Speed Input, Fuel Flow-meter 1 & 2 NI 9401 7 Digital I/O Counter Oil Pressure, Fuel Pressure 1 & 2, Intake Manifold Pressure, O2 Sensor 1 & 2, MAF, 21-Channel, 12-Bit Drivven Dynamometer Speed, Dynamometer Torque, Analog/Digital Input AD Dynamometer Water Flow-meter, Turbocharger, 8 With VR & Hall Effect Combo Throttle Position, Wastegate Position, Exhaust Sensor Inputs Pressure, Ambient Pressure, Carbon Monoxide Monitor, Relative Humidity

The Labview program written to interface with the Compact RIO allows all monitored parameters to be displayed during testing and data files to be recorded when the user selects the “Write Low Speed” button shown in the image of the program’s user interface in Figure 20.

Although recording sensor voltages and even scaling them to meaningful units of pressure, flow, etc. and recording them is useful, the main advantage of the compact RIO hardware is the ability to perform complex calculations on the data as they are acquired, and display the result of these calculations to the user in quasi-real-time, hence the name “real-time controller”. One important piece of data that requires real-time processing during testing is the reading from the

O2 sensor. As outlined in section 2.4.1, the O2 sensor value needs to be adjusted for fluctuations

64 in exhaust pressure to produce accurate results when operating at mixture conditions other than stoichiometric. The DAQ program reads and scales the exhaust pressure and air-fuel ratio from the O2 sensor controller, displays the scaled values to the user and applies the formula in

Eq. (10) to correct the O2 sensor reading for pressure. AFRmeasured is the scaled air-fuel ratio value for gasoline and pex is the exhaust pressure in mmHg referenced to ambient pressure. B and C are calibration coefficients that change based on whether the mixture is rich or lean. After the pressure correction is applied, a fuel type correction is applied as shown in Eq. (11) where mHC is the hydrogen to carbon ratio and nOC is the oxygen to carbon ratio of the fuel.

퐴퐹푅푚푒푎푠푢푟푒푑 + 퐵푝푒푥 퐴퐹푅 = (10) 푝 푐표푟푟푒푐푡푒푑 1 + 퐶푝 푒푥

푚퐻퐶 − 2푛푂퐶 + 4 퐴퐹푅 = 2.368 ∙ 퐴퐹푅 ∙ ( ) (11) 푓 푐표푟푟푒푐푡푒푑 푝 푐표푟푟푒푐푡푒푑 푚 + 16푝 + 12 퐻퐶 푂퐶

During dual-fuel experiments, two fuels with different chemical properties are being injected at the same time. Therefore, an additional set of calculations needs to be completed in real-time by the DAQ program in order to correctly compute the equivalence ratio of the mixture. The program reads the output frequency from both fuel flow-meters and converts the reading to the volumetric flow rate using the calibration of 1000 pulses per cm3. This volumetric flow rate is converted to a mass flow rate using each fuel’s characteristic expansion curve and the fuel temperature reading from a K-type thermocouple. The proportion of mass flow of each fuel is then used to calculate the stoichiometric air-fuel ratio of the combined fuel flow on a mass basis and calculate the equivalence ratio based upon the air-fuel ratio read from the O2 sensor. The volume flow rate of each fuel is also used to create a real-time readout of fuel octane rating so that it can be adjusted on-the-fly by the user through the PIC18 engine controller.

65

Figure 20. Image of Labview low-speed DAQ program user interface.

4.4.2 High-Speed Data Acquisition

In-depth analysis of combustion performance in a requires data acquisition hardware and software that is capable resolving the data to small increments of engine crankshaft rotation. The AVL Indismart indicating combustion measurement system pictured in Figure 21 and employed in this work is able to resolve data up to 0.1 °CA and display calculated results in quasi-real-time during testing. The Indismart receives a digital signal from a

BEI optical encoder with 3600 pulses per engine revolution, and one index pulse per revolution, in order to synchronize its data to engine rotation. Unlike the ECU, the Indismart does not require a separate digital phase signal because it uses in-cylinder pressure data from Kistler

6115B indicating spark plug pressure transducers to automatically determine which portion of

66 the cycle the engine is performing. The Indismart has provisions to analyze and record up to 8 channels of 14-bit, ±10 V, 0.1 °CA resolved signals and 8 time-based “recorder channels” that can be sampled at up to 10 kHz with 12-bit resolution. Additional recorder channels can be added through supplemental National Instruments data acquisition cards installed in the host computer which is connected to the Indismart over a Gigabit network connection. If additional

CA resolved channels are required, 3 additional Indismart units can be added in a cascade configuration using a pair of Gigabit network ports. To minimize costs at the Small Engine

Research Laboratory (SERL), the signals of each research engine are connected to a set of three data switches that allow the Indismart to be interchanged between engines without re-wiring.

Figure 21. Picture of AVL Indismart indicating combustion measurement system with engine selection switches.

Since the characteristic pressure oscillation frequencies associated with knock are in the range of 6-20 kHz and the AVL resolves its data to the engine crank angle domain, it is necessary to ensure that the acquisition rate is suitably high. The Nyquist-Shannon sampling theorem requires that the sampling frequency be at least twice that of the signal being sampled, while others suggest a sampling rate of up to 10 times the highest frequency desired [78]. A resolution of 0.1° CA or 3600 pulses per revolution is generally recommended for studying knock [78, 79]. With the 0.1° CA resolution of the BEI optical encoder, the sampling rate at 0.1°

CA is at least 120 kHz even at lower engine test speeds of around 2000 rpm, which is more than fast enough to resolve the 20 kHz pressure oscillations. At high engine speeds around 6000 rpm

67 the sampling rate increases to 360 kHz, which is still less than the 800 kHz maximum for the ADC on each analog input. The optical encoder provides a high level of electrical noise immunity, and is capable of a maximum speed of 12,000 rpm. The Indicom software used to interface with the Indismart is capable of multilevel sampling windows, which allow small portions of the cycle to be sampled at a high sampling rate of 0.1° CA, while the majority of the cycle is sampled at 1°

CA in order to reduce data file size.

Cylinder pressure indication has improved tremendously since the mechanical indicators of late 1800s and Midgley’s bouncing pin indicator of the 1920s [7]. Current high-pressure combustion indication is performed using piezoelectric pressure transducers that are either embedded in a spark plug or inserted directly into the combustion chamber. Measuring spark plugs have traditionally employed a long passage from the transducer diaphragm to the combustion chamber due to packaging constrains and to reduce heat transfer to the sensor [78].

This long passage made these sensors prone to oscillatory “ringing” in the output signal which made them unsuitable for knock investigation. New material technology has enabled measuring spark plugs to employ diaphragms that are flush with the combustion chamber to eliminate sensor ringing. The Kistler 6115B measuring spark plug used in this work and pictured in Figure

22 is a flush-diaphragm type transducer with a natural frequency of roughly 65 kHz, which is well above the maximum 20 kHz oscillations associated with end-gas knock.

Figure 22. Picture of the Kistler 6115B measuring spark plug in-cylinder pressure transducer.

68

The piezoelectric crystal in the measuring spark plug produces an electrical charge proportional to the stress applied to the diaphragm by the pressure of the combustion chamber gasses. The high impedance charge signal is converted to a useable output voltage by a charge amplifier that amplifies and inverts the signal so that it is proportional to the pressure applied to the sensing element. Piezoelectric sensors are dynamic sensors, so they only produce a charge when the stress applied to the sensing element is changing. Therefore, piezoelectric sensors are not used for static pressure measurements, but can be pegged to a static pressure by referencing them to the output of another transducer that measures absolute static pressure.

The AVL Indicom software performs this zero-level correction by referencing the intake manifold pressure sensor to peg the in-cylinder pressure sensor during the intake stroke when both sensors are measuring close to the same pressure. Multiple readings of the intake manifold pressure are taken over roughly 5 °CA and averaged in order to reduce the effects of noise on the signal.

It is of upmost importance that signals from the crank angle encoder and the in-cylinder pressure transducers are correctly synchronized to the engine geometry. This synchronization is accomplsihed by determining the true TDC position of the test cylinder in relation to the index pulse of the encoder. The difference between the true TDC postion and the index pulse can be entered into the Indicom program, which will record the offset and use it to correct the measured data. The instantaneous cylinder volume, found using the current CA postion read from the encoder signal, is used by the Indicom software to perform various engine performance calculations during testing. If the assumed postion of TDC (and in turn the assumed position of the crankshaft relative to the actual postion) is in error by 1 °CA, the calculated IMEP from the pressure data will be in error as much as 5% [80]. The discrepency will

69 cause an erroneously low IMEP if the acual postion comes before the assumed position, and erroneously high IMEP if the assumed position comes before the actual position.

The traditional TDC determination method of rotating the engine to equally spaced postions on each side of TDC, using a dial guage to find the piston height, and bisecting the two points is difficult to execute with the required accuracy. This method does not take into account torsional deflections of the crankshaft, which can be appreciable when the engine is at speed and under load, nor does it allow TDC to be easily referenced to the engine encoder [80]. A more accurate alternative is to use capactive probes have been designed that install in the spark plug port to determine TDC while the engine is running on the remaining cylinders. Although capacitive probes can be acurate to within 0.1 °CA, they are quite expensive.

The TDC determination method employed in this work utilizes a motored cylinder pressure curve determination in which the in-cylinder pressure is monitored while the engine is motored using the . Although the smallest cylinder volume occurs at TDC, imperfect compression and expansion processes due to heat loss and gas blow-by cause the peak of the measured pressure trace to lead the actual location of TDC by a small angle referred to as the thermodynamic loss angle. Thermodynamic loss angles have been characterized for various automotive spark ignition engines with the average being around 0.7 °CA [78]. Therefore,

0.7 °CA is assumed as the thermodynamic loss angle in this work. The AVL Indicom software allows the user to input the thermodynamic loss angle and motor the engine to find and store the correct TDC offset from the encoder.

With the ordinate of the pressure / CA relationship adjusted using manifold pressure referenced zero-level correction and the abscissa adjusted using the thermodynamic loss angle in conjunction with the motored pressure trace, the Indicom software can accurately calculate combustion and engine performance results. The main engine performance metric used in this

70 work, IMEPn, can be displayed in real-time along with IMEPg and PIMEP. With brake torque added as an input to the Indismart hardware and parameterized in the Indicom software, BMEP and FMEP can also be calculated and displayed. A typical measurement window showing in- cylinder pressure, mean effective pressures, injection pulse-width, ignition timing, and various other performance parameters displayed in the Indicom software is shown in Figure 23.

Figure 23. Picture of typical AVL Indicom measurement window during engine testing.

Combustion is a stochastic process; even when operating conditions are controlled with great precision, the turbulent nature of SI combustion causes each cycle to progress differently than the last. The Indicom software allows the user to average most of the results over many engine cycles to determine how overall performance changes based on operating conditions.

The data presented in this work is the result of an average of 100 consecutive engine cycles at a steady state operating condition. The Indicom software has the capability to quantify the variability in the data. The most accepted measure of combustion variability is the coefficient of

71 variation (COV) of IMEP. The COV of IMEP is calculated by dividing the standard deviation of

IMEP by the average of IMEP as show in Eq. (12).

(퐼푀퐸푃 − 퐼푀퐸푃)2 √푛 ∑푛 푖 푖=1 (푛 − 1) (12) 퐶푂푉 표푓 퐼푀퐸푃 = × 100 퐼푀퐸푃

General drivability problems are usually noticed by operators of SI engine vehicles with a

COV of IMEP over 3-5%. High combustion variability can lead to knock on fast-burn cycles if additional spark retardation or another knock reduction strategy is not implemented when operating in near-knocking conditions. Poor mixing and lean operation both cause combustion variability to increase. Factors that promote mixing and faster burning generally decrease combustion variability [79]. Figure 24 shows pressure vs. CA data over 100 consecutive cycles at an engine condition which caused the COV of IMEP to reach 5.1%. Figure 25 shows the change in calculated IMEP for the same 100 cycles.

Figure 24. Plot of in-cylinder pressure vs. CA over 100 consecutive cycles with high degree of combustion variability.

72

15

14

13

12 (bar)

n 11

IMEP 10

9

8

Cycle Number

Figure 25. Plot of IMEPn over 100 consecutive engine cycles showing a high degree of combustion variability.

The AVL Indicom software allows for the classification of abnormal combustion phenomena, specifically misfire and end-gas knock. Many knock detection methods including vibration sensors, exhaust gas temperature, intermediate species analysis, heat transfer analysis, and ion probe sensing have all been shown to detect knock [81]. The method used in this work, cylinder pressure analysis, is a direct measurement technique that is well suited to research applications [82]. There have also been many different methods proposed to quantify the magnitude of knock based on heat release, the integral of the area under the pressure oscillations, and the amplitude of the pressure oscillations. The most widely accepted method which is used in this work is the MAPO method [78]. This method, also known as the maximum knock overpressure method, correlates well with the engine damage caused from the peak pressures occurring during knock.

To find the MAPO, the knocking pressure trace must first be passed through a filter to remove the high frequency components associated with knock. A basic low-pass filter is applied by the AVL Indicom software in the form of an order-10, centered-moving-average filter. This

73 filter creates a smoothed version of the original pressure trace that can be compared to the raw knocking trace. The simple moving-average filter reduces the computational time, allowing the analysis to be done in quasi-real-time cycle-by-cycle. The smoothed pressure trace is then subtracted from the knocking pressure trace, and the absolute value is taken to find the MAPO.

A plot showing the pressure trace from a knocking cycle, the filtered trace, and the resulting

MAPO is shown in Figure 26. The peak MAPO value chosen to signify knock in this work is 5 bar, which is classified as light knock that is unlikely to cause engine damage. Once one cycle in the queue of 100 cycles being analyzed by the Indicom software shows a MAPO greater than 5 bar, data is saved for the entire 100 cycles to capture the average engine operating conditions at the point of knock onset.

70

60

50

40 Knocking Cycle 30

Mean Value Filtered Pressure Pressure (bar) 20 Rectified Difference

10

0 0 10 20 30 40 50 Crank Angle (°CA ATDC)

Figure 26. Plot of knocking cylinder pressure trace with order-10 moving average smoothed trace and resulting MAPO used to quantify knock intensity.

Combustion phasing plays an influential role in determining whether knock will occur during a given cycle, and is one of the parameters that is recorded when a knocking cycle is encountered. A fast-burn cycle, with a CA50 that occurs much earlier than the bulk of cycles, is more likely to develop into a knocking cycle. Heat-release analysis is used to find the mass

74 fraction burned profile and to calculate the CA50. The AVL Indicom software uses a thermodynamic first law model to calculate the rate of heat release (ROHR) using Eq. (13), where n is the interval in °CA, k is the polytropic coefficient, p is cylinder pressure, V is cylinder volume, and K is a unit conversion constant [78].

퐾 푄푖 = [푘푝푖(푉푖+푛 − 푉푖−푛) + 푉푖(푝푖+푛 − 푝푖−푛)] (13) 푘 − 1

For SI PFI engines the polytropic coefficient is generally 1.32 during compression and

1.27 during expansion, which the Indicom software applies appropriately. The ROHR is then integrated to find the total gas mass burned, from which the CA50, FDA, and RBA can be found.

More sophisticated heat release models including complex variations of the Rassweiler and

Withrow algorithm can account for changes in gas properties during combustion and additional heat losses more completely, but these methods are too computationally intensive to be run in real-time with the current combustion measurement hardware and must be executed during data post-processing.

75

CHAPTER 5

5. RESULTS – PHASE ONE

The first phase of testing began once the experimental setup was completed. The first phase of testing was focused on characterizing KLIMEP for fuels of various ON at low to mid- range engine loads. The dual-PFI system was installed to expedite the transition between fuels.

Verification of satisfactory performance of dual-PFI system was required before the main

KLIMEP characterization could begin.

5.1 PFI Blend Verification

Knock-limited engine performance using the dual-PFI on-the-fly fuel blending configuration was compared to that of a single-PFI configuration using a pre-blended PRF to determine the capabilities of the dual-PFI system. The Fuel-A system was plumbed to the inner

PFI injector, and the Fuel-B system to the outer PFI injector on the intake runner of Cylinder 2, as shown previously in Figure 14. The Fuel-A system was disconnected for the PRF blend testing. The Fuel-B system was drained, and 87, 70, and 50 ON PRF blends were each mixed and flushed through the system for each PRF-blend test.

A simple procedure was followed once the engine had warmed up and all of the pertinent test conditions outlined in Table 6 were met. The engine was operated at constant speed while intake manifold pressure was increased to find the maximum KLIMEP produced with each of the pre-blended PRF fuels at the previously defined knock limit. Table 6 shows how closely each of the test conditions were able to be held throughout testing with the current

76 experimental setup. The variation in each of the test conditions over this test was compared to those outlined in Table 3 to estimate their effect on ONR. The desired error limit for this work was to measure ONR within 1 ON. Variations in equivalence ratio, spark angle, and humidity have been found to have the greatest effect on the ability of the current experimental setup to measure ONR precisely. The variations in spark angle and equivalence ratio are indicative of an

ECU that is not able to control these outputs to the level of accuracy desired for this work. The variation in intake manifold pressure is likely due to the cable actuation system of the throttle sticking in its travel. The impact of humidity on ONR looks to be a significant source of error in this test, but the facilities used do not allow it to be directly controlled.

Table 6. Test conditions, their variation during testing and impact on ONR precision.

TEST PARAMETER TEST CONDITION VARIATION ONR IMPACT ENGINE SPEED 2500 – 5800 RPM ± 10 RPM << 1 ON INTAKE MANIFOLD PRESSURE 0.5 – 1.37 bar ± 0.02 bar ± 0.6 – 0.8 ON INTAKE AIR TEMPERATURE 49 °C ± 2 °C ± 0.3 ON EQUIVALENCE RATIO 1.0 ± 0.1 ± 2 ON HEAD TEMPERATURE 85 °C ± 5 °C ± 0.5 ON SPARK ANGLE 26 °CA BTDC ± 3 °CA ± 3 ON START OF INJECTION ANGLE 350 °CA BTDC ± 3 °CA << 1 ON INJECTION PULSE-WIDTH 1.3 – 7.0 ms ± 0.3 ms See Equivalence Ratio Uncontrolled / EXHAUST PRESSURE ± ~0.1 bar ± 0.3 ON Unmeasured Uncontrolled / HUMIDITY ± ~20% ± 2 ON Measured?

With the PRF-blend knock limits established, the next step was to verify the ability of the dual-PFI system to deliver the desired in-situ fuel blending. Initial low-load testing of the dual-

PFI system showed that the allowable fuel proportions during operation were 100% Fuel-A (or

Fuel-B) and from 70% Fuel-A/30% Fuel-B to 30% Fuel-A/70% Fuel-B. A fuel-volume flow proportion selected outside of these bounds generally commanded an injector pulse-width that was lower than allowable for predictable injector/relay operation (~1.25 ms). ON pre-blend

PRF. To achieve an ON of 87, isooctane was injected from the Fuel-A system at 57% of volume

77 flow, and 70 ON PRF was injected from the Fuel-B system at 43% of volume flow. A similar procedure was followed for the 70 and 50 ON verification tests.

Table 7 shows the fuels and blend proportions used to achieve the desired dual-PFI blends. Iso-octane and 70 ON PRF were selected for blending to achieve a PFI blend with an ON of 87 for comparison with 87 ON pre-blend PRF. To achieve an ON of 87, isooctane was injected from the Fuel-A system at 57% of volume flow, and 70 ON PRF was injected from the Fuel-B system at 43% of volume flow. A similar procedure was followed for the 70 and 50 ON verification tests.

Table 7. Fuels used to achieve desired PFI blend ON.

PFI BLEND FUEL A FUEL B PROPORTION [ON] FUEL-A/FUEL B [%] 87 Iso-octane 70 ON PRF 57/43 70 Iso-octane n-Heptane 70/30 60 Iso-octane n-Heptane 60/40 50 Iso-octane n-Heptane 50/50 40 Iso-octane n-Heptane 40/60 30 n-Heptane 50 ON PRF 40/60 20 n-Heptane 50 ON PRF 60/40

The dual-PFI verification-test results, shown in Figure 27, indicate a maximum difference of 0.56 bar IMEPn between dual-PFI and PRF-fueled single-PFI at low engine speed for the 70 ON tests. The fuel volume-flow data show that the dual-PFI system was able to maintain the fuel blend to within two ON points at low engine speed (2500-3000 RPM). This error at low speeds indicates the limitations of the current injection system. For the 70 ON tests, the 70% Fuel-

A/30% Fuel-B proportion is at the limit of reliable injector operation at low speed and load.

Beyond this 70/30 proportion, performance of the lower flowing injector was undesirable and difficult to control reliably, which shows that a more balanced volume-flow proportion is desirable with the current fuel-injection system. Perhaps a selection of 50 ON PRF for Fuel B

78 with a proportion of 40% isooctane/60% 50 ON PRF would produce dual-PFI results that follow the single 70 ON PRF operation more closely.

14 13 87 12 11 10 70 9 8 7 50 6

IMEPn[bar] 5 4 3 PRF Splash Blends 2 PFI Blends 1

0

4500 2000 2500 3000 3500 4000 5000 5500 6000

Engine Speed [rev/min]

Figure 27. Plot of knock-limited IMEPn of PFI blends compared to that of PRF pre-blend of the same ON.

The differences between the dual-PFI and PRF-fueled single-PFI results throughout the midrange engine speeds (3500-4500 RPM), which are the focus for the remainder of this section of testing, were minimal and established the validity of the dual-PFI configuration. The maximum IMEPn difference over this speed range was 0.37 bar at 3500 RPM. The volume-flow data reveal that the dual-PFI system was able to maintain the fuel blend to within one octane point at 3000 RPM and above which was within the desired error of the test. It is important to note that for both 87 ON tests, the engine was air-flow limited at 3000 RPM and below, and knock limited at 3500 RPM and above.

79

5.2 PFI Blend Testing

The Rotax 914 engine is ultimately used in an aircraft application, which means that the propulsion-system design criteria are different than those for automotive applications. The research focus can be constrained in a useful way through definition of a specific area of interest on the engine map. As far as potential JP-8 cruise-enabling technology is concerned, defining a characteristic range for aircraft cruise operation is of primary importance. The typical cruise- operation range defined for this work is power output in the range of 25-50% of maximum power (roughly 25-50 hp) at engine speeds in the range of 3500-4500 RPM. These cruise assumptions are based on typical Rotax 914 operation and typical general-aviation requirements

[76]. The assumed cruise speed and load range is shown in Figure 28 through Figure 31.

Once the dual-PFI system was shown to adequately reproduce the results of single-PFI with PRF pre-blends (87, 70, and 50 ON), the remainder of the PFI blends in ON pre-blend PRF.

To achieve an ON of 87, isooctane was injected from the Fuel-A system at 57% of volume flow, and 70 ON PRF was injected from the Fuel-B system at 43% of volume flow. A similar procedure was followed for the 70 and 50 ON verification tests.

Table 7 were tested. These remaining blends were tested with the volume-flow percentage of each fuel between 40% and 60% to minimize the effects of the fuel-injection- system limitations. N-heptane was tested to determine the lower bound of maximum IMEPn with reference to ON in the current engine-testing configuration. JP-8 was tested to generate an ON estimate since the anti-knock characteristics of JP-8 are not deliberately controlled.

The results of the PFI blend testing are shown in Figure 28. The additional maximum knock-limited IMEPn values of the PFI blends not included in the dual-PFI verification all fall within the general trend, with n-heptane being the lower bound at 0 ON. The increase in maximum IMEPn achieved with increasing fuel ON tends to rise with fuel ON, except in the case

80 of the low-speed 87 ON tests that are air-flow-limited and not knock-limited, as noted previously. This trend is shown in Figure 29, where the lowest engine speed and air-flow-limited points have been removed for the sake of clarity.

14 13 12 11 10 87 9 70 8 60 7 50

6 40 30

IMEPn[bar] 5 20 4 3 PFI Blends JP-8 2 n-Heptane 1 Typical Cruise

0

2000 2500 3000 3500 4000 4500 5000 5500 6000

Engine Speed [rev/min]

Figure 28. Plot of maximum IMEPn of PFI blends compared to that of neat JP-8, neat n-Heptane, and load at typical cruise conditions.

Figure 29. Plot of maximum IMEPn as a function of fuel ON for 3500-5800 RPM.

81

The results in Figure 29 offer an alternative perspective on the maximum IMEPn data above 3500 RPM. At each fuel ON rating, there is some variation in maximum IMEPn, which is attributed to the flow and combustion changes associated with increasing engine speed. But the general increasing ONR with increasing IMEPn is to be expected. When the cruise-IMEP range is overlaid on these data, the results show that an ON value of at least 30 is required to sustain the aircraft in flight for the current test conditions at the lowest cruise load and that a minimum value of 66 ON is required at achieve the highest cruise engine load. Note that these cruise requirements are for the baseline engine, and the fuel ON required for cruise conditions can be lowered with operation modifications such as those presented in Table 3.

5.3 JP-8 Evaluation and Octane Estimation

The JP-8 sample used in testing was the AFRL JP-8 reference fuel POSF-6169. POSF-6169 is among the reference jet fuels used at AFRL for combustion and emissions testing. The precise chemical properties and physical characteristics of POSF-6169 have been documented previously [43] [83]. Since JP-8 is a neither the cetane number (CN) nor ON of JP-8 is controlled. Previous MON testing of reference JP-8 samples estimated the apparent MON to be

21 [84]. Using the maximum IMEPn results from the PRF pre-blends and PFI-blends in Figure 28, the maximum IMEPn of the Rotax 914 running on JP-8 proves the ON of JP-8 to be roughly 20.

The maximum IMRPn of JP-8 was within 0.2 bar of the 20 ON PFI-blend data for all except the lowest engine speed. The midrange speed results for JP-8 fell below the lowest cruise-engine load by 0.39 bar, which means that at these conditions the engine would not be able to sustain an aircraft in flight.

82

5.4 JP-8 PFI Blends

Since it was concluded that neat JP-8 was not sufficiently knock-resistant to allow low- load cruise operation the dual-fuel PFI-blend configuration was used to investigate a strategy to allow high-load cruise operation where a second fuel with higher knock resistance is injected simultaneously. Iso-octane was chosen as the second fuel for this test to maintain the volume- flow proportion close to 50% for each fuel in the dual-PFI configuration. This test was also chosen to provide verification of the conclusion that a value of 66 ON is needed to allow high- load cruise operation. The engine was operated with the proportion of each fuel being varied to keep IMEPn at 7.0, 8.0, and 8.7 bar to characterize high load cruise operation. The results are shown in Figure 30.

80 20

70 30

60 40

50 50

40 60

30 70

8 Volume Volume 8Flow [%] -

20 80 JP 8.7 bar IMEPn Isooctane Volume Isooctane Volume Flow[%] 10 8.0 bar IMEPn 90 7.0 bar IMEPn

0 100

3250 3500 3750 4000 4250 4500 4750

Engine Speed [rev/min]

Figure 30. Plot of maximum JP-8 volume percentage of PFI blend at vehicle-cruise engine loads.

The results indicate that for high-load cruise operation at 3500 RPM the JP-8 volume- flow percentage was at its minimum, an average of 40%, as indicated in Figure 30. JP-8 with an

ON of roughly 20 combined with iso-octane in these proportions yields an estimated ON value

83 of 68. This JP-8 blend estimate is two ON points higher than the previous estimate of cruise octane requirement from the PFI blends. As stated previously, the measured error in octane control at this speed was roughly one ON. The additional error is attributed to the variability in ignition timing, equivalence ratio, and other factors according to those outlined in Table 6. The

ON estimates for remaining JP-8 blends are also similar to the PFI-blend results. Figure 31 shows how each of the JP-8 PFI blends (indicated by their average JP-8 volume-flow percentage) compares to the previous results. Although low-load JP-8 blends were not tested, it is estimated that a volume flow of up to 88% JP-8/12% iso-octane would sustain low-load cruise operation at an ON of 30.

12

11 87 10 70 9 40%

8 60 50% 7 50 40 6 30 20

5 IMEPn [bar] 4 3 PFI Blends JP-8 PFI Blends 2 JP-8 1 n-Heptane Typical Cruise

0

3000 3200 3400 3600 3800 4000 4200 4400 4600 4800 5000

Engine Speed [rev/min]

Figure 31. Plot of maximum IMEPn of JP-8 PFI blends at vehicle cruise-engine loads compared to that of PFI blends, neat JP-8, and neat n-Heptane.

If 100LL Avgas, the fuel currently used in some aircraft with this engine, were to be used as the primary fuel in a dual-PFI configuration, the acceptable volume-flow proportion of JP-8 would be expected to increase from these results since the ON of avgas is around 5 points higher than iso-octane. If the flight octane requirement for this engine were to be relaxed to 87

84

ON, the acceptable volume-flow proportion would be expected to drop to 28% JP-8/72% 87 ON for high-load-cruise and 85% JP-8/15% 87 ON for low-load-cruise operation.

85

CHAPTER 6

6. RESEARCH OBJECTIVES – PHASE TWO

With the ONR for medium load and cruise operation established, the focus shifted to achieving maximum load performance with 87 ON fuel. Of the various factors that affect engine operation, changing parameters like compression ratio or combustion chamber shape would require complete changes to engine hardware that would be very costly to change on a fielded propulsion system. On the other hand, knock factors linked to engine operation conditions like intake air temperature or equivalence ratio would be easier to change with minimal impact to other hardware. The goal of this second phase of work is to focus on these operational parameters that can be adjusted, with the goal of shifting the knock-limit to enable full-load operation on 87 ON fuel. The individual objectives for this phase are as follows:

 Improve engine research stand for finer control of test conditions, specifically ignition

timing and fuel pulse-width variability.

 Characterize the maximum IMEPn of the Rotax 914 fueled by 100 ON to establish

maximum non-knocking performance in the original configuration.

 Investigate the impact of ignition timing, intake air temperature, equivalence ratio, and

dual-simultaneous-ignition on knock-limited IMEPn for the Rotax 914 fueled by 87 ON.

 Determine the optimal combination of operational parameters to enable full-load

performance of the Rotax 914 fueled by 87 ON.

86

CHAPTER 7

7. EXPERIMENTAL SETUP – PHASE TWO

During the first phase of testing it became clear that certain engine operating parameters were not controlled sufficiently well to achieve the desired maximum error of less one ON in the test data. In an effort to meet this goal, the engine research stand underwent various improvements to reduce uncertainty in the data stemming from variability in ignition timing and injection pulse-width which are addressed in the next section of this chapter.

Improvements in other areas were also performed to improve the testing capabilities. An was also added to enable operation at a greater range of intake manifold temperatures, and to allow higher load testing at the base intake air temperature of 49°C. The low-speed DAQ program was modified to allow more precise data collection, taking individual data points during each of the 100 cycles, rather than 10 second average at 1 Hz used previously. Individually controlled ignition coils were added to allow the ignition timing of the test cylinder to be adjusted separately from the other cylinders. An ASME corner-tap orifice plate and 1psi differential pressure transducer were added to measure intake-air volume-flow to the entire engine, to compare to the MAF readings. Lastly, a water-cooled turbocharger was installed to replace the air-cooled unit for increased longevity, and to allow for longer testing cycles without the lengthy cool-down periods required with the air-cooled unit.

7.1 PIC32 Microcontroller

With the PIC18 ECU not performing well enough for precise control in a research setting,

87 a more capable microcontroller was required. As with the selection of the PIC18, previous project experience at AFRL with another microcontroller, the Microchip PIC32MX360F512L, suggested that it might be able to perform well as part of an ECU. The Microchip PIC32 is a 32- bit microcontroller capable of single instruction cycle 16-bit addition and subtraction, with up to

33 instruction cycles required for 32-bit division. At a clock speed of 80 MHz, the PIC32 achieves a performance of 125 MIPS through 5-stage pipelining and the parallel use of its arithmetic logic unit (ALU) and Multiply-Divide Unit (MDU). The PIC32 has five external interrupt pins to allow it to interface with time sensitive inputs without slowing performance of the main program [85].

The PIC32 also has five onboard timer modules, a 16-channel 10-bit ADC module that can sample at up to 500 ksps, and two Universal Asynchronous Receiver/Transmitter (UART) modules with RS-232 support.

In addition to reduced variation in the ignition angle and fuel pulse-width output signals from the ECU, increased flexibility was also required. With the PIC18 ECU, any additional operational parameters required the use of additional analog inputs or digital I/O which required additional wiring to the low-speed DAQ for user control. A UART interface where additional commands could be added in software would increase the flexibility of the ECU tremendously. The PIC18 microcontroller has support for UART communication, but with the controller already being taxed with the number of interrupts in the current program its performance would reduce even more with the UART module enabled. The increased performance of the PIC32 could possibly allow the addition of UART communication and increased timing precision.

Since the PIC18 and PIC32 microcontrollers both have the same general functional components and overall architecture, the PIC18 ignition program was ported to the PIC32 with little difficulty. The main differences between the two programs are in the additional

88 configuration registers required to operate the PIC32 at maximum performance. Otherwise, the

PIC32 ignition program included in APPENDIX G is functionally identical to the PIC18 ignition program. Operation of this program on the PIC32 would allow for an assessment as to whether the PIC32 would perform well enough for UART module to be used while the engine control program was running.

The goal with respect to precision was to reduce variation in spark timing so that its error would produce much less than a 1 ONR variation in the engine test data. To test the performance of the PIC32, the period of the main timer in the PIC32 program was reduced until operation became unstable. The results of bench testing showed that the timer period was able to be reduced to 3.0 μs, beyond which the program would fail to update the ignition angle from the main loop because the entirety of its operations were taking place in the timing interrupts.

3.0 μs corresponds to roughly 0.1 °CA at the maximum engine speed of 5800 RPM. Bench testing showed the output signal to have a variation of roughly ± 10 μs (~0.3 °CA at 5800 RPM) because of the fact that the interrupt itself takes a finite time to execute, along with time required to set and clear the I/O pin bits and change the outputs. The PIC32 can spend up to 43 instruction cycles pausing the main program before entering the interrupt service routine.

Engine testing showed the ignition output to vary ± 0.5 °CA which could produce an error of roughly 0.5 ONR in the engine data. Although the PIC32 performed more favorably than the

PIC18, this level of variation was already at the acceptable limit without the addition of the

UART module to the program.

A new strategy was devised that would allow the microcontroller to operate with fewer interrupts by synchronizing its operation with the engine encoder rather than the microcontroller timer interrupt, hence freeing the PIC32 to operate faster. The 0.1 °CA output of the BEI optical encoder would provide a timing signal that would allow the microcontroller to

89 operate with small enough variation to have only a small impact on ONR during knock testing relative to other factors. A program was written in which the BEI encoder was read by an external interrupt which incremented the encoder pulse counter. The once-per-revolution index pulse from the encoder was used to reset the encoder count back to zero after 3600 pulses. The ADC was read and scaled to allow the user to select an ignition angle from 70.0 °CA

BTDC to 10.0 °CA ATDC in 0.1 °CA increments. This value was used to calculate the angle at which the ignition output signal would need to go high in order to begin to charge the ignition coil 3.0 ms before ignition. The encoder interrupt compared the current encoder count to these

“ignition charge” and “ignition discharge” angles to determine when to set or clear each of the output pins.

This encoder referenced PIC32 ignition program was bench tested with results showing that it was able to produce an ignition output with ± 0.1 °CA variation. Engine testing showed the output to be closer to ± 0.2 °CA at 5800 RPM, likely because of the slight timing variations in the encoder signal on a running engine. It was decided that this level of variation would be acceptable for knock-limit testing. The next step was to add UART communication.

Unfortunately, the addition of the UART module code running on the microcontroller reduced performance noticeably. With the addition of the code for the UART module the microcontroller was no longer able to process each interrupt pulse from the encoder. A different solution was needed if precision and flexibility were to be attained simultaneously.

7.2 XMOS xCORE Microcontroller

The PIC32 provided a great improvement from the PIC18, but lacked the available overhead required for UART communication and room for additional functions that would surely be desired in the future. A survey of the available microcontrollers was conducted to find a

90 more suitable product for this application. Many current microcontroller platforms including the Raspberry Pi and BeagleBone have shifted toward the classification of microprocessor.

These 700 MHz ARM platforms both operate on a stripped down version of Linux which requires a large amount of their limited resources to run. Experience with popular Arduino boards showed that they are well suited for basic I/O operations, but do not offer any performance improvements over the PIC32. An FPGA was considered, but only as a “last resort” due to the added cost and complexity over a conventional microcontroller. Microcontrollers intended specifically for powertrain applications like the Freescale Qorivva were considered as possible solutions, but they were found to lack end-user flexibility as well as support for low-volume customers.

The XMOS xCORE microcontroller provided an alternative to both conventional microcontrollers and FPGAs, with some advantages of each. Like an FPGA, all of the peripheral functions of the XMOS are configured in software modules, rather than with the peripheral hardware modules common to microcontrollers. The XMOS software modules called xSOFTip modules are provided as open source tools to allow the end user to tailor each module to their specific requirements. Similar to conventional microcontrollers, the XMOS is programmed in language similar to C called XC that contains the additional commands and structures required to take advantage of the features of the XMOS hardware. The XMOS xCORE architecture is best described as “event driven,” with the processor cores being directly connected to the output ports through “hardware response ports” for decreased I/O latency. The event driven architecture operates in a serial fashion, doing away with the interrupts that are required with a traditional microcontroller.

The advantage of the XMOS xCORE over traditional microcontrollers is its modular design that allows multiple xCOREs to be integrated to work together. Each xCORE also has the

91 ability to execute multiple program threads in parallel to improve performance. The XMOS xCORE XS1-L16A-128 is a dual-core processor clocked at 500 MHz per core with the ability to process a total of 16 threads at an overall performance of 1000 MIPS. This level of performance is roughly equivalent to running 8 PIC32 microcontrollers in parallel. The decreased I/O latency of the XMOS coupled with its support for parallel threads could allow for the increased performance and flexibility desired in the research ECU. The XS1-L16A-128 was selected for testing to investigate further the possibility of using XMOS hardware for an ECU. The XS1-L16A-

128 is available on a pre-populated demonstration board called the sliceKIT pictured in Figure 32 that would reduce prototyping time with the new microcontroller. The sliceKIT board connects each I/O pin from the processor to a card slot which accommodates various expansion cards called slices.

Figure 32. Picture of XMOS sliceKIT demonstration board with XS1-L16A-128 xCORE dual core processor.

An ECU program outline was created that would split the various engine control tasks and communications tasks onto separate processor cores. The tasks were further divided within the cores to separate threads to allow each task to receive as much of the processor’s resources as possible. A diagram of the initial XMOS ECU program outline is included in Figure 33.

92

Figure 33. Diagram of XMOS ECU program outline showing the program functions divided between both cores with various threads.

The tasks in each of the threads communicate to each other through an XC abstraction called a channel. Two-way communication on a channel requires that each end of the channel declare a variable called a channel-end. The xCORE processors allow a maximum of 32 channel- ends per core therefore the dual-core XS1-L16A-128 is able to use 32 total channels, with 64 total channel-ends. There are two main types of channels, standard channels and streaming channels. Standard channels negotiate with the data switch each time they are called in the program to transfer data, where streaming channels are left open without the need to renegotiate. One limitation in channel communication is that the data switch between cores allows for only four channels to be active between two cores at one time, although all channels contained on a single core can be active simultaneously. The benefit of using standard channels is that they allow for more than four channels to be declared between cores. Each standard channel negotiates with the data switch which allows only four to be active at one time.

Streaming channels can be used between threads on the same core to reduce negotiation time

93 without any penalty. Figure 34 shows a diagram of the initial channel structure employed in the

XMOS ECU program.

Figure 34. Diagram of initial XMOS ECU program core, thread, and channel communication structure with streaming channels in blue.

94

The main arbitrating construct used in the XC programming language within a thread is the select/case statement. Each case in the select statement corresponds to an event that triggers a certain section of code to run when it occurs. These events include: data becoming available on a channel, data becoming available in the UART receive buffer, timer values comparisons, input pin logic comparisons, and general variable comparisons. Once a case is selected it is generally executed in a serial manor to completion, with the code breaking back to the select statement, ready for the next case. If a second case statement becomes true before the previous case has finished execution, the second case is queued to begin execution once the first completes.

The initial XMOS ECU program was developed to control one fuel injector and one ignition coil to test the performance of XMOS hardware with all of the various threads active.

The ECU program was based upon the structure of the SliceKit COM port GPIO Demo example provided by XMOS in its open source xSOFTip programs. User desired fuel injector pulse-width and end of injection (EOI) angle were controlled by text commands entered in a serial communication terminal running on a PC and connected to the XMOS through the addition of an

XMOS GPOI slice which provided a convenient way to interface with a DB-9 port. Commands for

Ignition firing angle and coil charge duration were added. All Injection and ignition outputs were separately able to be controlled in unison, or with individual commands to each injection or ignition output. A calibration command was added to allow the angle between the TDC index pulse and true TDC to be specified to synchronize the ECU output to true engine position during the cycle. A command to allow the user to enable or disable ignition and injection together or separately was also added.

The initial program was bench tested using a signal generator and oscilloscope with each of the necessary pins connect to a ribbon cable adapted to interface with the sliceKIT. The

95 program and hardware showed promising results. Each of the threads was able to function independently without interrupting the execution of the other threads. At a worst-case engine speed of 6000 RPM, the ignition output was constant at the tenth of a °CA desired, executing within tens of nanoseconds after the specified encoder pulse was received. Further testing shows that the XMOS hardware was able to perform even faster. With the microcontroller set to trigger on both the rising and falling edges of the encoder pulse, ignition angle was able to be controlled to within 0.05 °CA. The injection pulse-width output also performed well, holding its output to within 10 μs of desired.

After the successful bench-test of the initial program, development began on a full scale test which included all required ignition and injection outputs. Since flexibly and performance were the main goals, an additional set of injection and ignition outputs would need to be added into the program for availability in future engine research. A total of eight ignition outputs and eight fuel injector outputs were implemented in the program, allowing for future expansion. In the initial single injection and ignition program an individual channel was used for setting the beginning and end of each pulse on each output. Although this channel communication method was very simple to implement, it used two channels per output. With the 16 outputs of the full scale program all of the channel resources would be consumed, leaving none for the other communication tasks in the program.

A different communication scheme was implemented that used one channel per type of parameter and transmitted in a two word series. The first word sent over the channel would be an array index, telling the receiving thread which ignition or injection output to apply the value to, with the second word transmitted being the actual value. This reduced the total number of channels devoted to output parameters to four. There is a channel for the start angle and stop angle for injection and ignition outputs. If even less channels were desired, these parameters

96 could be further consolidated into one channel for injection parameters and one for ignition parameters since they both operate in different threads. A diagram of the full scale program structure showing the consolidated communication channels is included in Figure 35.

Figure 35. Diagram of full scale XMOS ECU program core, thread, and channel communication structure with streaming channels in blue.

Bench testing of the full scale ECU program revealed that the program outputs behaved erratically, unlike the initial simplified program. The additional time required to service all 16 outputs in the encoder thread caused it to execute more slowly, causing the timing of the entire program to become unstable. To remedy the problem, the encoder thread was reverted to

97 triggering only on the falling-edge of each pulse, for a resolution of 0.1 °CA. This solution corrected the output signals, causing them to behave predictably as in the simplified program.

Additional program optimization was performed to ensure stability in on-engine tests, and as new features are added. The TDC index pulse thread and phase pulse thread were combined in order to reduce the total number of threads on each core to four, since the XMOS can only achieve its maximum performance of 125 MIPS per thread with a maximum of four threads per core. Beyond four threads per core, instruction cycles are divided between threads on the same core as required. The program was optimized by further consolidating the communication channels running between cores to only four channels using the method outlined previously. Reducing the number of channels using the core data switch to four allowed these channels to be specified as streaming channels rather than standard channels, permitting communication to take place as quickly as possible between cores. The final XMOS

ECU program used in the remainder of this work is included in APPENDIX H in its entirety.

Engine testing showed that the ignition timing variation was reduced less than ± 0.1 °CA with the XMOS Flexible ECU. The ignition angle error was less than could be observed using the

AVL Indicom software with its data collection referenced to the same encoder pulses. The fuel pulse-width signal variation was reduced to ± 0.03 ms. This amounted to an order of magnitude improvement over the PIC18 system.

During program development each of the I/O pins on the XMOS required for timing input signals and ignition and injection output signals were accessed by inserting the pins of a ribbon cable into the rows of a solder-less breadboard. This solution worked well enough for bench testing, but was not robust enough for on-engine use. XMOS includes a number of different slice cards with the sliceKIT demonstration board, but none with a screw terminal interface that would allow the user to integrate the XMOS board into an existing system. The

98

XMOS is a 3.3 V system that was not able to interface directly with some of the 5 V systems used in the engine research lab. The XMOS also did not include any filtering for any of the pins, since they can all be configured by the user for various functions. A new interface board was needed to address these problems in order to integrate the XMOS ECU with the Rotax.

The interface cards were designed using Cadsoft Eagle, a circuit board design and layout editing program. One card was designed to primarily handle the output signals and another for input signals. Both cards employed the Texas Instruments SN74LVC245AN 8-channel bus transceiver to perform the 3.3 V to 5 V conversion. Both cards also employed the same passive first-order low-pass RC circuit used with the PIC18 to filter out high frequency noise from other engine systems, particularly the ignition coils. Each board was designed with four layers, the two outer layers being the signal layers, with the two inner layers used as plains for power and common. A screw-terminal connector was added for each signal with additional screw-terminal connectors routed to the ground and power plains to provide a system reference available for future expansion. These I/O boards became known as JABTRONIC boards. A picture of the layout schematic of the JABTRONIC Inboard v1.0 XMOS ECU input card is included in Figure 36.

Schematics and layouts for the JABTRONIC Inboard and Outboard are included in APPENDIX I and APPENDIX J respectively. The finished system with both I/O cards and the GPIO slice connected to the XMOS slicekit mainboard is pictured in Figure 37.

99

Figure 36. Layout of JABTRONIC Inboard v1.0 XMOS ECU input card.

Figure 37. Picture of JABTRONIC Inboard/Outboard input cards and XMOS GPIO slice connected to XMOS sliceKIT mainboard.

100

CHAPTER 8

8. RESULTS – PHASE TWO

Full take-off load testing could begin once the capabilities of the test stand had been improved. The increased ignition timing and fuel pulse-width precision enabled by the XMOS flexible ECU would provide higher quality knock-limit data for the second phase of testing. The addition of an intake air intercooler would allow the knock reducing effects of cooler intake air temperatures to be tested. One final area that was considered before the second phase of testing began was the health of the engine.

The engine was verified to be in acceptable condition following the initial low-load testing, free from major knock damage. A motored compression test was performed soon after shutting down the engine with the head of the test-cylinder up to operating temperature. The

9.7 bar test result was above the 9 bar lower limit for acceptable compression. A cylinder pressure leak-down diagnostic test was also performed with favorable results. The upper spark plug was removed to visually inspect the test-cylinder with a borescope. The pictures showed evidence of carbon deposits as well as small orange-colored deposits likely lead oxide from previous operation on leaded fuel. The visual inspection showed no signs of knock damage.

8.1 Full-Load Benchmark

A control test was designed to characterize full-load performance of the base engine configuration on a fuel that would resist knock under these conditions. Iso-octane was chosen for this test so that the ON of the fuel would be explicitly known. Previous testing has shown

101 that iso-octane is sufficiently knock-resistant to allow full-load performance with fixed 26 °CA

ATDC ignition timing, φ = 1.0, and an intake air temperature of 49°C. Full-load IMEPn test data would provide a way to verify the success of the various octane relaxation techniques inachieving full-load performance. Full-load performance at high intake air temperatures was also of interest, since the base engine controller allows operation up to 88°C before the waste- gate is opened to reduce temperature. Full-load data was collected at 49°C, 69°C, and 88°C intake air temperatures to show the performance reduction with the drop in intake air density

[41].

Since the engine was not knocking, load was increased by increasing intake manifold pressure until the limit of 1.370 bar was reached. The test conditions are shown in Table 8. The original 260-cc/min (~24-lbm/hr) injectors were installed to allow full-load operation.

Performance on 87 ON PRF at the base air temperature of 49°C was also tested. Manifold pressure was increased at a stoichiometric equivalence ratio until the knock-limit was reached for the 87 ON test. The results of both tests are shown in Figure 38.

Table 8. 100 ON full load test conditions.

TEST PARAMETER TEST CONDITION ENGINE SPEED 4000 – 5800 RPM INTAKE MANIFOLD PRESSURE 1.0 – 1.40 bar INTAKE AIR TEMPERATURE 49 - 88°C EQUIVALENCE RATIO 1.0 HEAD TEMPERATURE 85°C IGNITION TIMING 26 °CA BTDC END OF INJECTION ANGLE 270 °CA BTDC INJECTION PULSE-WIDTH 5.25 – 8.25 ms

102

16

15

14

13 100 ON 49°C IAT

12 100 ON 69°C IAT

IMEPn(bar) 100 ON 88°C IAT 11 87 ON 49°C IAT 10

9 3500 4000 4500 5000 5500 6000 Engine Speed (RPM)

Figure 38. Plot of Full load IMEPn with 100 ON at 49, 69, and 88°C intake air temperature including knock-limited IMEPn with 87 ON at 49°C intake temperature.

Maximum IMEPn decreased as intake air temperature increased for the 100 ON test.

The large drop in IMEPn at the 4000 RPM point for the 88°C 100 ON case was caused by the turbocharger not being able to sufficiently compress the intake to reach the maximum intake manifold pressure. The shape of the maximum IMEPn curves show changes in airflow as the of the engine changes with speed. The 69°C 100 ON case is characteristic of engine performance with 100 ON at standard ambient conditions without intercooling. This case was chosen to be the benchmark to which performance on 87 ON should be raised to provide full operational capability. The 87 ON profile shows that knock-limited IMEPn at 49°C intake temperature, which is characteristic at standard ambient conditions without intercooling, is 1.5 to 2.5 bar lower than the benchmark 100 ON full-load test.

8.2 Intake Temperature Study

The effect of intake air temperature (IAT) on knock-limited performance was of interest since IAT directly influences combustion chamber temperature. Temperatures of 49°C, 69°C,

103 and 88°C were chosen to match the 100 ON tests, as well as 38°C to show heavily cooled performance. The test conditions are listed in Table 9. A test at 32°C IAT was attempted, but the intercooler was unable to maintain IAT at all engine speeds. The results of the 87 IAT testing are shown in Figure 39.

Table 9. Test conditions for intake air temperature investigation of knock-limited performance with 87 ON.

TEST PARAMETER TEST CONDITION ENGINE SPEED 4000 – 5800 RPM INTAKE MANIFOLD PRESSURE 1.10 – 1.28 bar INTAKE AIR TEMPERATURE 38, 49, 69, 88°C EQUIVALENCE RATIO 1.0 HEAD TEMPERATURE 85°C IGNITION TIMING 26 °CA BTDC END OF INJECTION ANGLE 270 °CA BTDC INJECTION PULSE-WIDTH 4.60 – 7.95 ms

16

15

14 100 ON 69°C IAT 13 87 ON 38°C IAT 12

87 ON 49°C IAT IMEPn(bar) 11 87 ON 69°C IAT 87 ON 88°C IAT 10

9 3500 4000 4500 5000 5500 6000 Engine Speed (RPM)

Figure 39. Plot of knock-limited IMEPn with 87 ON at 38, 49, 69, and 88°C IAT, including knock- free IMEPn benchmark with 100 ON at 69°C IAT.

The results show that knock-limited IMEPn is improved roughly 0.6 bar by reducing IAT to 38°C. Raising IAT to 69 and 88°C reduces knock-limited IMEPn 0.2 – 0.9 bar in each case.

Figure 40 shows that, on average, knock-limited IMEPn falls 0.75 bar with each 20°C increase in

104

IAT. The data show that IAT has a greater impact on knock-limited performance than knock-free performance.

16

15

14 4000 RPM

13 4500 RPM 5000 RPM 12

IMEPn(bar) 5500 RPM 11 5800 RPM

10

9 20 30 40 50 60 70 80 90 100 Intake Manifold Temperature (°C)

Figure 40. Plot of knock-limited IMEPn with 87 ON as a function of IAT at various engine speeds.

8.3 Ignition Timing Study

The next test was to characterize the influence of Ignition timing on knock-limited

IMEPn. Ignition timing was set at each speed from MBT (CA50 7-8 °CA ATDC) to the maximum retarded timing as manifold pressure was increased until the knock-limit was reached. The maximum timing retard was dictated by the limits set on COV of IMEP and exhaust gas temperature. The generally accepted maximum COV of IMEP limit of 3-5% was used. The Rotax specified maximum exhaust gas temperature shown in Table 4 is 950°C. The results of this test are shown in Figure 41.

105

Table 10. Test conditions for ignition timing investigation of knock-limited performance with 87 ON.

TEST PARAMETER TEST CONDITION ENGINE SPEED 4000 – 5800 RPM INTAKE MANIFOLD PRESSURE 1.04 – 1.42 bar INTAKE AIR TEMPERATURE 49°C EQUIVALENCE RATIO 1.0 HEAD TEMPERATURE 85°C IGNITION TIMING 16.5 – 34.5 °CA BTDC END OF INJECTION ANGLE 270 °CA BTDC INJECTION PULSE-WIDTH 4.41 – 9.57 ms

16

15

14 100 ON 69°C IAT (26° BTDC Timing) 13 87 ON 49°C IAT 12 Retarded Timing

IMEPn(bar) 87 ON 49°C IAT 11 (26° BTDC Timing)

10 87 ON 49°C IAT MBT Timing 9 3500 4000 4500 5000 5500 6000 Engine Speed (RPM)

Figure 41. Plot of knock-limited IMEPn with 87 ON at 49°C IAT at retarded, base, and advanced MBT timing, including knock-free IMEPn benchmark with 100 ON at 69°C IAT and base timing.

The data show that a knock-limited IMEPn improvement of roughly 0.75 bar at low speeds and 0.25 bar at high speeds can be achieved by retarding ignition timing. On average,

Ignition timing was able to be retarded to 18 °CA BTDC yielding a CA50 of around 25 °CA ATDC.

Compared to the MBT timing cases, the base 26 °CA BTDC ignition timing is already quite retarded, providing a roughly 1 bar improvement in knock-limited IMEPn. Operation at MBT timing without retarding timing as knock is reached would severely limit performance on 87 ON.

Although the retarded case offers an improvement over the base ignition timing, an additional

106 improvement of 1 bar IMEPn at low speed and as much as 2 bar at high speed is required to achieve full-load performance.

Figure 42 shows how the shape of the in-cylinder pressure profile changes as combustion phasing is varied. Although the highest peak pressure is achieved for the MBT timing case at CA50 of 7.1 °CA ATDC, it produced the lowest IMEPn. As combustion is delayed the tendency to knock is reduced which allows the intake manifold pressure to be increased with each step of combustion phasing delay. In this case intake manifold pressure begins slightly above atmospheric at MBT and is increased to the maximum manifold pressure limit with full ignition timing retard. Although the peak pressure decreases, the area under the pressure profile increases in each case to provide a higher IMEPn albeit with reduced thermal efficiency.

60

50

40 CA50 7.1 °CA ATDC 30 CA50 10.6 °CA ATDC CA50 15.5 °CA ATDC

Pressure Pressure (bar) 20 CA50 20.3 °CA ATDC

10 CA50 25.4 °CA ATDC

0 -60 -30 0 30 60 90 120 Crank Angle (°CA ATDC)

Figure 42. Plot of cylinder pressure as a function of crank angle averaged over 100 cycles with 87 ON at 49°C IAT and 4000 RPM with varied combustion phasing.

Figure 43 shows the relationship between CA50, IMEPn, and engine speed for 87 ON.

Below 11 bar IMEPn CA50 of 7-8 °CA ATDC can be achieved for optimal combustion phasing at

MBT. To increase IMEPn above 11 bar, ignition timing must be retarded which delays

107 combustion phasing beyond optimal. Late combustion phasing has a negative impact on thermal efficiency, and ultimately fuel efficiency. Figure 44 shows that on average ISFC increases 20 g/kW-h for each 10 °CA of combustion phasing delay beyond 7-12 °CA where ISFC is nearly constant.

Figure 43. Surface plot of achievable CA50 as a function of engine speed and IMEPn with 87 ON at 49°C IAT.

320 310 300 290 280 4000 RPM 270 4500 RPM

260 5000 RPM ISFC ISFC h) (g/kW 250 5500 RPM 240 5800 RPM 230 220 0 5 10 15 20 25 30 35 CA50 (CA ATDC)

Figure 44. Plot of ISFC as a function of CA50 with 87 ON at 49°C IAT and various engine speeds.

108

Delaying combustion by retarding ignition timing causes ignition to take place at a higher cylinder temperature and pressure. Higher temperature and pressure at ignition causes the flame to develop more quickly. Figure 45 shows how FDA changes with combustion phasing. The trend shows that a 1 °CA reduction in FDA can be achieved with each 5 °CA increase in CA50.

38 36 34 32 30 4000 RPM 28 4500 RPM

FDA FDA (CA) 26 5000 RPM 24 5500 RPM 22 5800 RPM 20 18 0 5 10 15 20 25 30 35 CA50 (CA ATDC)

Figure 45. Plot of FDA as a function of CA50 with 87 ON at 49°C IAT and various engine speeds.

The opposite trend holds true for RBA. Figure 46 shows that retarding combustion phasing directly causes RBA to increase. As with ISFC, RBA increases increasingly as combustion phasing is delayed and less of combustion is taking place in the confined volume of the combustion chamber close to TDC. Combustion proceeds more slowly at lower peak temperatures and pressures, with increased heat transfer to the cylinder wall. The lower peak temperatures and pressures reduce the tendency to knock, but the increased end-gas residence time as the opposite effect. These competing effects hold knock-limited IMEPn to a linear relationship with increasing CA50.

109

38 36 34 32 30 4000 RPM 28 4500 RPM

RBA RBA (CA) 26 5000 RPM 24 5500 RPM 22 5800 RPM 20 18 0 5 10 15 20 25 30 35 CA50 (CA ATDC)

Figure 46. Plot of RBA as a function of CA50 with 87 ON at 49°C IAT and various engine speeds.

The 20% increase in ISFC at maximum combustion retard is undesirable, but combustion phasing is ultimately limited by combustion variability and exhaust temperature. Combustion phasing was limited by high COV of IMEP at 4500 RPM and below, and high exhaust temperature at 5000 RPM and above. Figure 47 shows that COV of IMEP is directly impacted by delaying combustion. As combustion is allowed to occur later, the gasses have more space to react in a wider flow field so there is a larger variation in how the reaction progresses. Figure 48 shows that like RBA, exhaust gas temperature increases as CA50 increases from MBT. As combustion phasing is retarded, a smaller fraction of the energy of the reaction is imparted to the piston as the gases expand, causing the exhaust gas temperature to be higher.

110

6

5

4 4000 RPM 3 4500 RPM 5000 RPM 2 COV COV IMEP of (%) 5500 RPM

1 5800 RPM

0 0 5 10 15 20 25 30 35 CA50 (CA ATDC)

Figure 47. Plot of COV of IMEP as a function of CA50 with 87 ON at 49°C IAT and various engine speeds.

Figure 48. Surface plot of exhaust gas temperature as a function of CA50 and engine speed with 87 ON at 49°C IAT.

111

8.4 Equivalence Ratio Study

The effect of equivalence ratio on knock-limited IMEPn was investigated with 87 ON at

49°C IAT and 26° CA BTDC ignition timing to compare to the base 87 ON testing. The test conditions are listed in Table 11. Intake manifold pressure was adjusted to reach the knock limit with various equivalence ratios at each engine speed. Knock-limited performance results are shown in Figure 49.

Table 11. Test conditions for equivalence ratio investigation of knock-limited performance with 87 ON.

TEST PARAMETER TEST CONDITION ENGINE SPEED 4000 – 5800 RPM INTAKE MANIFOLD PRESSURE 1.08 – 1.39 bar INTAKE AIR TEMPERATURE 49°C EQUIVALENCE RATIO 0.9 – 1.6 HEAD TEMPERATURE 85°C IGNITION TIMING 26 °CA BTDC END OF INJECTION ANGLE 270 °CA BTDC INJECTION PULSE-WIDTH 5.21 – 14.23 ms

16

15

14 100 ON 69°C IAT (φ = 1.0) 13 87 ON 49°C IAT Rich (φ = 1.6) 12

IMEPn(bar) 87 ON 49°C IAT 11 Base (φ = 1.0) 87 ON 49°C IAT 10 Lean (φ = 0.9)

9 3500 4000 4500 5000 5500 6000 Engine Speed (RPM)

Figure 49. Plot of knock-limited IMEPn with 87 ON at 49°C IAT at lean (ϕ = 0.9), base (ϕ = 1.0), and rich (ϕ = 1.6) conditions, including knock-free IMEPn benchmark with 100 ON at 69°C IAT and base equivalence ratio (ϕ = 1.0).

112

IMEPn is improved by 0.75 bar at 4000 RPM up to 1.7 bar at 5500 RPM under rich conditions as compared to stoichiometric. Knock-limited performance shows mild improvement with slightly lean operation at the lower engine speeds. Figure 50 shows how IMEPn is affected at each of the equivalence ratios tested. For most engine speeds IMEPn is at a minimum at φ =

1.1 and increases as in both directions as discussed in Obert [4]. An equivalence ratio of 1.1 is generally desired to achieve maximum knock-free IMEP because of the corresponding maximum flame speed [1]. The knock reduction in the current case comes from increasing the autoignition delay as equivalence ratio is adjusted above and below φ = 1.1. At equivalence ratios above stoichiometric the high heat capacity of the excess fuel contributes to the cooling effects of additional fuel, reducing the maximum temperature of the gas [22].

16

15

14

13 4000 RPM

12 4500 RPM

IMEPn(bar) 5000 RPM 11 5500 RPM 10

9 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 Equivalence Ratio

Figure 50. Plot of IMEPn as a function of equivalence ratio with 87 ON at 49°C IAT and various engine speeds.

The extent of lean operation is limited by combustion variability. Figure 51 shows that

COV of IMEP increases dramatically as equivalence ratio is reduced below φ = 1.0. The mildly delayed combustion of the base 26 °CA ATDC ignition timing exacerbates the combustion variation as compared to the CPV of IMEP at MBT timing as shown previously in Figure 47.

113

Much of this variability is likely a product of the variation in local equivalence ratio near the spark plug as equivalence ratio is reduced. The improvement in IMEPn seem to be nearing a maximum as equivalence ratio increases, although further testing would need to be conducted to verify this observation. COV of IMEP increases only slightly as equivalence ratio is increased.

5 4.5 4 3.5 3 4000 RPM 2.5 4500 RPM 2 5000 RPM

COV COV IMEP of (%) 1.5 5500 RPM 1 0.5 0 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 Equivalence Ratio

Figure 51. Plot of COV of IMEP as a function of equivalence ratio with 87 ON at 49°C IAT and various engine speeds.

The results of the equivalence ratio study could have been further separated from the combustion phasing study by holding CA50 constant at 15 °CA ATDC to match the base case.

The decision to allow CA50 to vary and setting ignition timing to 26 °CA BTDC was made to expedite data collection, and to show the effects relative to the base engine configuration with its fixed 26 °CA BTDC ignition timing. Figure 52 shows how CA50 varies with equivalence ratio with fixed ignition timing. CA50 increases in both directions from φ = 1.3 similar to COV of IMEP in Figure 51. These inflection points match the inflection point in Figure 50 where the rate of

IMEPn improvement begins to decrease. This point corresponds to location where charge cooling by over-fueling and the increasing combustion chamber volume begin to dominate the autoignition delay. A peak in IMEPn at equivalence ratios greater than φ = 1.6 would be

114 expected as thermal efficiency is further reduced by the cooling effect of over-fueling and combustion phasing is additionally delayed.

25 23 21 19 17 4000 RPM 15 4500 RPM 13 5000 RPM CA50 CA50 (CA ATDC) 11 5500 RPM 9 7 5 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 Equivalence Ratio

Figure 52. Plot of CA50 as a function of equivalence ratio with 87 ON at 49°C IAT and various engine speeds.

The trend of CA50 with changing equivalence ratio can be partially attributed to the corresponding changes in FDA as shown in Figure 53. With a similar minimum at φ = 1.3, FDA increases in both directions as equivalence ratio is varied. FDA is highest at lean mixtures where ignition delay is longest. The corresponding trend to the CA50 data is also shown in Figure 54 for RBA. These data show again how combustion at the knock-limit is slowed as equivalence ratio is varied from φ = 1.3.

115

38 36 34 32 30 4000 RPM 28 4500 RPM

FDA FDA (CA) 26 5000 RPM 24 5500 RPM 22 20 18 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 Equivalence Ratio

Figure 53. Plot of FDA as a function of equivalence ratio with 87 ON at 49°C IAT and various engine speeds.

38 36 34 32 30 4000 RPM 28 4500 RPM

RBA RBA (CA) 26 5000 RPM 24 5500 RPM 22 20 18 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 Equivalence Ratio

Figure 54. Plot of RBA as a function of equivalence ratio with 87 ON at 49°C IAT and various engine speeds.

The acceptable ISFC increase as equivalence ratio is increased would be the limiting factor in applying the results of this study to a fielded engine. Figure 55 shows that for the modest increase of 0.75 - 1.7 bar IMEPn, ISFC is increased by roughly 185 g/kW-h (70%). This is a dramatic increase, but operation in this manner would be limited to takeoff conditions, where

116 maximum power output is required. Minimum ISFC is achieved just lean of stoichiometric for conditions that do not required maximum power output.

550

500

450

400 4000 RPM

350 4500 RPM

ISFC ISFC (g/kWh) 5000 RPM 300 5500 RPM 250

200 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 Equivalence Ratio

Figure 55. Plot of ISFC as a function of equivalence ratio with 87 ON at 49°C IAT and various engine speeds.

The benefits to IMEPn with increasing equivalence ratio would pair well with retarded ignition timing to achieve higher knock-limited performance. Exhaust temperature would need to be reduced In order to retard combustion further at high engine speeds. Figure 56 shows how exhaust temperature is reduced as equivalence ratio is increased from stoichiometric. A

35°C reduction in exhaust gas temperature is realized with each 0.1 increase in equivalence ratio at 5500 RPM. The combination of increasing equivalence ratio and delaying combustion would have a profound effect on knock-limited performance at 5000 RPM and above, where operation was limited by exhaust gas temperatures. Rich operation with retarded timing would also improve combustion variability, allowing for further increases knock-limited performance at speeds below 5000 RPM.

117

Figure 56. Surface plot of exhaust gas temperature as a function of equivalence ratio and engine speed with 87 ON at 49°C IAT.

A preliminary test case of increasing equivalence ratio with combustion phasing retard was performed at 4000 RPM with 87 ON at 49°C IAT. Equivalence ratio was increased from

φ = 1.0 to φ = 1.5. The results showed that knock-limited IMEPn peaked at 13.54 with φ = 1.3 where intake manifold pressure reached the maximum limit. This 0.5 bar increase in IMEPn leaves less than 0.5 bar to achieve the full load benchmark.

8.5 Engine Replacement

Unfortunately, the coupler between the crankshaft and BEI encoder failed while testing the final 5800 RPM points at increased equivalence ratio. The coupler remained slightly engaged, still connected between the two, but at an angular offset. This offset allowed the

XMOS ECU to continue injecting fuel albeit at a different location in the cycle. The ignition timing was offset enough to keep the engine from firing as it shut down. With the coupler

118 replaced, the resistance from large amount of fuel trapped in the cylinders caused the pressed crankshaft of the Rotax to distort as the pneumatic starter was engaged. The in-cylinder pressure transducers showed a difference of 385 °CA between TDC of cylinders one and two, a

25 °CA distortion. A post-mortem inspection of the piston and cylinder-head of the test cylinder showed no signs of knock-damage. The lack of damage after the thousands of knocking cycles encountered during testing shows that the knock-limit used in this work is conservative, and correctly classified as light-knock as discussed in Section 2.2.4.2.

A second high flight-hour Rotax 914 engine that had been re-built from a similar failure was on-hand. The first engine was removed, and the second engine was installed in the test stand. The modified cylinder-head shown in Figure 57 with provisions for a pressure transducer to be flush-mounted in the combustion chamber was installed on the test-cylinder. The Kistler

6041A flush-mounted water-cooled pressure transducer would allow pressure data to be collected during tests where two standard spark-plugs are fired simultaneously. Initial dual- simultaneous-ignition testing using spark-plug pressure transducers has shown that they do not perform identically to standard spark plugs of the same heat range. A HAAKE DC3 water temperature controller was plumbed to the sensor’s cooling passages and set to maintain the cooling water temperature at 50°C.

119

Figure 57. Picture of Cylinder-head of test-cylinder modified to accept flush-mounted in-cylinder pressure transducer.

8.6 Second Engine 87 ON Benchmark

A test was conducted to verify similar knock-limited IMEPn between the first and second engines. A spark-plug pressure transducer was installed in the upper spark-plug port with a standard spark plug in the lower port. The flush-mounted and spark-plug in-cylinder pressure transducers were both connected to the Indismart combustion analysis hardware and configured in the Indicom software. Figure 58 shows the knock-limited IMEPn for engine 2 compared to engine 1 and the knock-free benchmark with 100 ON.

120

16

15

14 100 ON 69°C IAT 13 Engine 1 12 87 ON 49°C IAT

IMEPn(bar) Engine 2 11 87 ON 49°C IAT Engine 1 10

9 3500 4000 4500 5000 5500 6000 Engine Speed (RPM)

Figure 58. Plot of knock-limited IMEPn with 87 ON at 49°C IAT, ϕ = 1.0, 26 °CA ATDC ignition timing with engines 1 and 2, including knock-free IMEPn benchmark with 100 ON at 69°C IAT, ϕ = 1.0, and 26 °CA ATDC ignition timing with engine 1.

The results show that the knock-limits for engines 1 and 2 are nearly identical at 5000

RPM and below. The data show a discrepancy at 5500 RPM and above due to retarded combustion phasing with engine 2 at these speeds. This benchmark for performance on 87 ON at base conditions will be used for comparison in the remaining test with this engine. The data show close agreement between the spark-plug and flush-mounted in-cylinder transducer in determining the knock-limit. The flush-mounted transducer will be solely used in the remainder of testing.

8.7 Dual-Simultaneous-Ignition Study

The effect of dual-simultaneous-ignition on knock-limited IMEPn was investigated with

87 ON at 49°C IAT and φ = 1.0 to compare to the base 87 ON testing with the second engine.

The test conditions are listed in Table 12. Intake manifold pressure was adjusted to reach the knock limit while ignition timing was adjusted from MBT to fully retarded at each engine speed.

Knock-limited performance results are shown in Figure 59. The level of combustion phasing

121 delay was limited by the maximum intake manifold pressure, maximum combustion variability, and maximum exhaust gas temperature outlined previously.

Table 12. Test conditions for dual-simultaneous-ignition investigation of knock-limited performance with 87 ON.

TEST PARAMETER TEST CONDITION ENGINE SPEED 4000 – 5800 RPM INTAKE MANIFOLD PRESSURE 1.00 – 1.42 bar INTAKE AIR TEMPERATURE 49°C EQUIVALENCE RATIO 1.0 HEAD TEMPERATURE 85°C IGNITION TIMING 10.0 – 29.5 °CA BTDC END OF INJECTION ANGLE 270 °CA BTDC INJECTION PULSE-WIDTH 4.70 – 9.42 ms

16 100 ON 69°C IAT (26° BTDC Timing) 15 (Engine 1) 14 87 ON 49°C IAT 13 Retarded Timing (Engine 2) 12

IMEPn(bar) 87 ON 49°C IAT 11 (26° BTDC Timing) (Engine 2) 10 87 ON 49°C IAT 9 Dual Ignition 3500 4000 4500 5000 5500 6000 MBT Timing (Engine 2) Engine Speed (RPM)

Figure 59. Plot of knock-limited IMEPn with 87 ON at 49°C IAT, ϕ = 1.0, dual-simultaneous- ignition with advanced and retarded timing, including knock-free IMEPn benchmark with 100 ON at 69°C IAT, ϕ = 1.0, and 26 °CA ATDC ignition timing.

The data for dual-simultaneous-ignition with delayed combustion phasing show a 2.2 bar improvement at 4000 RPM, 1.0 bar from 4500 – 5500 RPM, and 0.39 bar at 5800 RPM compared to the base 87 ON configuration. The improvement at 4000 RPM was enough to surpass knock-free performance for the 100 ON benchmark by 0.58 bar. The improvement with dual-simultaneous-ignition nearly double that of the single-ignition with delayed combustion.

122

Figure 60 shows that the knock-limited IMEPn improvement as a function of CA50 with dual- simultaneous-ignition displays a trend similar to the single ignition results. Dual-simultaneous- ignition provides an improvement of 0.8 bar on average compared to single ignition.

16

15

14 4000 RPM 4500 RPM 13 5000 RPM 12

5500 RPM IMEPn(bar) 11 5800 RPM Dual Ignition 10 Single Ignition 9 0 5 10 15 20 25 30 35 CA50 (CA ATDC)

Figure 60. Plot of knock-limited IMEPn as a function of CA50 with 87 ON at 49°C IAT and various engine speeds comparing dual-simultaneous-ignition and single ignition.

Dual-simultaneous-ignition provides knock-limited performance improvement by accelerating initial flame growth which leads to faster burning throughout the entire cycle.

Adding a second ignition point on the opposite side of the combustion chamber reduces flame travel distance, allowing load to be increased before the knock-limit is reached. Figure 61 shows that dual-simultaneous-ignition provides a FDA reduction of greater than 4 °CA compared to single ignition at the same combustion phasing. Figure 62 shows a 2-4 °CA reduction in RBA with dual-simultaneous ignition compared to single ignition. Dual-simultaneous-ignition allows combustion to occur faster, occupying a more constant volume than with single ignition, increasing thermal efficiency.

123

38 36 34 32 4000 RPM 30 4500 RPM 28 5000 RPM

FDA FDA (CA) 26 5500 RPM 24 5800 RPM 22 Dual Ignition 20 Single Ignition 18 0 5 10 15 20 25 30 35 CA50 (CA ATDC)

Figure 61. Plot of FDA as a function of CA50 with 87 ON at 49°C IAT and various engine speeds comparing dual-simultaneous-ignition and single ignition.

38 36 34 32 4000 RPM 30 4500 RPM 28 5000 RPM

RBA RBA (CA) 26 5500 RPM 24 5800 RPM 22 Dual Ignition 20 Single Ignition 18 0 5 10 15 20 25 30 35 CA50 (CA ATDC)

Figure 62. Plot of RBA as a function of CA50 with 87 ON at 49°C IAT and various engine speeds comparing dual-simultaneous-ignition and single ignition.

The thermal efficiency benefit of dual-simultaneous-ignition compared to single ignition is shown using ISFC in Figure 63. The greatest ISFC improvement is at the CA50 of MBT ignition timing with dual-simultaneous-ignition reducing ISFC decrease by around 10 g/kW-h compared

124 to single ignition. Compared to single ignition at the base timing of 26 °CA ATDC with a CA50 of around 15 °CA ATDC dual-simultaneous-ignition at MBT provides a 20 g/kW-h reduction in ISFC.

300 290 280 270 4000 RPM 260 4500 RPM 250 5000 RPM

240 5500 RPM ISFC ISFC (g/kWh) 230 5800 RPM 220 Dual Ignition 210 Single Ignition 200 0 5 10 15 20 25 30 35 CA50 (CA ATDC)

Figure 63. Plot of ISFC as a function of CA50 with 87 ON at 49°C IAT and various engine speeds comparing dual-simultaneous-ignition and single ignition.

8.8 Dual-Simultaneous-Ignition and Equivalence Ratio Study

The results from the dual-simultaneous-ignition and equivalence ratio studies have been the most promising for improving knock-limited performance of the parameters tested in this work. A test was conducted to characterize the effect of combining dual-simultaneous-ignition and varying equivalence ratio on knock-limited IMEPn with 87 ON at 49°C IAT to compare to the base 87 ON testing with the second engine. The test conditions are listed in Table 13. Intake manifold pressure was adjusted to reach the knock limit while equivalence ratio was varied and ignition timing was adjusted to maximize IMEPn at each engine speed. Knock-limited performance results are shown in Figure 64. The level of combustion phasing delay was limited by the maximum intake manifold pressure, maximum combustion variability, and maximum exhaust gas temperature as outlined previously.

125

Table 13. Test conditions for dual-simultaneous-ignition and equivalence ratio investigation of knock-limited performance with 87 ON.

TEST PARAMETER TEST CONDITION ENGINE SPEED 4000 – 5800 RPM INTAKE MANIFOLD PRESSURE 1.25 – 1.43 bar INTAKE AIR TEMPERATURE 49°C EQUIVALENCE RATIO 0.85 – 1.5 HEAD TEMPERATURE 85°C IGNITION TIMING 5.0 – 25.0 °CA BTDC END OF INJECTION ANGLE 270 °CA BTDC INJECTION PULSE-WIDTH 5.26 – 14.94 ms

16

100 ON 69°C IAT 15 Single Ignition 26° BTDC Timing 14 Engine 1 13 87 ON 49°C IAT Dual Ignition Rich 12 Retarded Timing IMEPn(bar) Engine 2 11 87 ON 49°C IAT 10 Single Ignition 26° BTDC Timing 9 Engine 2 3500 4000 4500 5000 5500 6000 Engine Speed (RPM)

Figure 64. Plot of knock-limited IMEPn with 87 ON at 49°C IAT, dual-simultaneous-ignition with retarded timing, and ϕ = 1.3-1.5, including knock-free IMEPn benchmark with 100 ON at 69°C IAT, ϕ = 1.0, and 26 °CA ATDC ignition timing with single ignition.

The combination of dual-simultaneous-ignition, retarded ignition timing, and increased equivalence ratio with 87 ON at 49°C IAT successfully enables performance greater than the base case with 100 ON at 69°C IAT as well as the 49°C IAT 100 ON base case. Knock-limited

IMEPn is raised above 15 bar for all speeds except 4000 RPM, reaching a peak of 15.41 bar at

5800 RPM. Increasing equivalence ratio and retarding ignition timing have a synergistic effect, producing an even greater improvement when employed together. The performance increase at the higher speeds was greater than expected from the single parameter studies, particularly

126 where ignition retard was limited by high exhaust gas temperatures. Increased fueling at these conditions cooled the exhaust gas as well as decreasing combustion time, allowing timing to be further retarded. Figure 65 shows the trend of IMEPn with equivalence ratio.

17

16

15 4000 RPM 14 4500 RPM 13

5000 RPM IMEPn(bar) 12 5500 RPM 5800 RPM 11

10 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 Equivalence Ratio

Figure 65. Plot of knock-limited IMEPn as a function of equivalence ratio with 87 ON at 49°C IAT and dual-simultaneous-ignition with retarded ignition timing at various engine speeds.

IMEPn at each speed increased at with equivalence ratio until reaching a maximum around φ = 1.3 - 1.4. Figure 66 shows that combustion phasing delay peaked slightly rich of stoichiometric, moving closer to MBT as equivalence ratio was increased or decreased. In this study lean operation was limited by COV of IMEP reaching the maximum limit established previously. As equivalence ratio was increased and the tendency to knock was reduced, intake manifold pressure could only be increased to the maximum allowable limit. Once the engine was operating at the desired equivalence ratio and maximum intake manifold pressure, ignition timing was advanced until knock was reached to improve IMEPn.

127

40

35

30

25 4000 RPM 20 4500 RPM

15 5000 RPM

CA50 CA50 (CA ATDC) 5500 RPM 10 5800 RPM 5

0 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 Equivalence Ratio

Figure 66. Plot of CA50 as a function of equivalence ratio with 87 ON at 49°C IAT and dual- simultaneous-ignition with retarded ignition timing at various engine speeds.

This optimization of ignition timing, equivalence ratio, and intake manifold pressure is displayed in the FDA data in Figure 67. As the effect of over-fueling begins to dominate and ignition timing is allowed to advance, FDA stays roughly constant as equivalence ratio increases.

It appears that the optimization of ignition timing, equivalence ratio, and intake manifold pressure results in a nearly constant minimum FDA at each engine speed. RBA follows a similar yet less pronounced trend, reaching a minimum value around φ = 1.3 and peaking lean of stoichiometric at most speeds. Figure 68 shows the results for RBA as a function of equivalence ratio. Like CA50, RBA decreases as equivalence ratio is increased and ignition timing is advanced.

128

40

35

30 4000 RPM 25 4500 RPM

FDA FDA (CA) 5000 RPM 20 5500 RPM

15 5800 RPM

10 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 Equivalence Ratio

Figure 67. Plot of FDA as a function of equivalence ratio with 87 ON at 49°C IAT and dual- simultaneous-ignition with retarded ignition timing at various engine speeds.

40

35

30 4000 RPM 25 4500 RPM

RBA RBA (CA) 5000 RPM 20 5500 RPM

15 5800 RPM

10 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 Equivalence Ratio

Figure 68. Plot of RBA as a function of equivalence ratio with 87 ON at 49°C IAT and dual- simultaneous-ignition with retarded ignition timing at various engine speeds.

As in the equivalence ratio study, ISFC increased with increasing equivalence ratio. The

ISFC results for the dual-simultaneous-ignition and equivalence ratio study are included in Figure

69. ISFC increased roughly 80 g/kW-h as equivalence ratio was increased from stoichiometric to

φ = 1.3 - 1.4 where maximum IMEPn was obtained. Dual-simultaneous ignition along with

129 optimizing ignition timing enable maximum IMEPn at a lower equivalence ratio, keeping the ISFC increase down to 28%, rather than the 70% increase incurred in the equivalence ratio study.

500

450

400 4000 RPM 350 4500 RPM 300

5000 RPM ISFC ISFC (g/kWh) 250 5500 RPM 5800 RPM 200

150 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 Equivalence Ratio

Figure 69. Plot of ISFC as a function of equivalence ratio with 87 ON at 49°C IAT and dual- simultaneous-ignition with retarded ignition timing at various engine speeds.

The fuel mass-flow-rate at 5800 RPM and a slightly higher IMEPn than the 100 ON benchmark was 6.9 kg/h which is 1.4 kg/h higher than the 100 ON benchmark at similar maximum power conditions for one cylinder. For a 30 minute take-off and climb-out period, 2.8 kg of additional fuel is required to use 87 ON at φ = 1.2 with retarded dual-simultaneous-ignition on all four cylinders. To offset the penalty of reduced endurance by requiring additional fuel at take-off, a cruise IFSC study was done to investigate maximizing endurance.

Engine load was maintained at the high-load cruise IMEPn of 8.72 bar established in

Section 5.2. This load corresponds to a fully-loaded aircraft sustaining cruise speeds. ISFC with

87 ON at 49°C IAT was investigated using the base single ignition configuration with 26 °CA ATDC ignition timing and φ = 1.0. Dual-simultaneous-ignition was also investigated at MBT ignition timing at two equivalence ratios, φ = 0.9 and φ = 1.0. The results are included in Figure 70.

130

300 290 280 Base Single Ignition 26° Ignition Timing 270 φ = 1.0 260 Dual Ignition 250 MBT Ignition Timing φ = 1.0 240

ISFC ISFC h) (g/kW Dual Ignition 230 MBT Ignition Timing 220 φ = 0.9 210 200 3000 3500 4000 4500 5000 Engine Speed (RPM)

Figure 70. Plot of ISFC with 87 ON at 49°C IAT for base single ignition, dual-simultaneous- ignition with MBT timing at ϕ = 1.0, and dual-simultaneous-ignition with MBT timing at ϕ = 0.9.

Dual-simultaneous-ignition at MBT ignition timing reduces ISFC by roughly 10 g/kW-h at low cruise speeds and 20 g/kW-h at high cruise speeds. Lean operation with dual-simultaneous- ignition at MBT ignition timing and φ = 0.9 does not further reduce ISFC at low cruise speeds, but causes an additional 10 g/kW-h reduction at high cruise speeds. With a typical fully-loaded flight endurance of 14 hours for an aircraft cruising at high-load and low-speed [86], the benefit from dual-simultaneous-ignition at MBT ignition timing is enough to directly offset the endurance penalty associated with a 30 minute rich and retarded takeoff condition. For an aircraft with a typical 300 kg total fuel-mass cruising at high-load and high-speed [86], an additional 3.5 hours of endurance can be added using the lean dual-simultaneous-ignition configuration at MBT ignition timing, including the additional fuel used in a 30 minute rich and retarded takeoff condition compared to the base single ignition configuration at φ = 1.0.

131

CHAPTER 9

9. SUMMARY AND CONCLUSIONS

Increased use of UAS powered by SI engines requiring high-octane fuel has increased

DoD fuel costs. An SI powered UAS that could operate on the widely used USAF JP-8 low-octane fuel would have a large impact on reducing these operating costs. To avoid destructive end-gas knock while operating on low ON fuels, the ONR of current SI engines would need to be relaxed.

A two-phase study was conducted to investigate the possibility of relaxing the octane requirement in a Rotax 914 engine. The low ON of JP-8 would limit use to low engine loads, while a reasonable octane relaxation could allow full-load operation on 87 ON which would be far less expensive and more available for use overseas than the current 100LL fuel.

The first phase of the study focused on characterizing knock-limited performance at low to medium engine loads. A dual-fuel system designed to allow in-situ octane adjustment was established and verified to perform well at cruise engine speeds, within an injection proportion of 30-70% for the two fuel systems. The limitations in injection proportion were attributed to a non-optimized fuel-injector/injector-driver circuit combination. This dual-PFI test configuration greatly increased the speed of testing multiple PRF-like fuel blends at the same test conditions without having to stop testing to change fuels.

The maximum IMEPn as a function of fuel octane rating for the AFRL Rotax 914 engine configuration with fixed 26° BTDC ignition timing was established. Maximum IMEPn for this engine was compared among dual-PFI blends from 20 to 87 ON, n-heptane, JP-8, and JP-8 blends. An estimated JP-8 octane rating of 20 ON was established and verified to within the

132 error of this test by independent testing.

Research results showed that a JP-8/isooctane dual-fuel system would allow a 40% volume-flow proportion of JP-8 at a typical high-load cruise point, and an 88% volume-flow proportion at low-load cruise. Although this work has established the volume-flow proportions of JP-8 with higher octane fuels, the added weight and complexity of injecting two separate fuels and mixing on-the-fly is not feasible for aircraft engines. However, this work revealed the

ON values necessary to sustain an aircraft at various cruise operation points. With continued relaxation of the octane requirement of the Rotax 914, neat JP-8 cruise at low loads has been shown to be a possibility. Enabling full typical cruise operation on JP-8 requires either a 50-point improvement of the JP-8 fuel octane rating or a significant reduction of the engine octane requirement in the cruise regime. Various knock-mitigation techniques including retarded ignition timing, intake air cooling, fuel-rich operation, and dual-simultaneous ignition could provide a large portion of the relaxation in octane requirement.

The second phase of this work focused on characterizing and improving knock-limited performance at high engine loads. An improved flexible ECU was created to address the variation in ignition timing and fuel pulse-width observed during initial testing. The XMOS flexible ECU was created using an XMOS SliceKit prototype development board and additional

I/O cards were designed to interface with the SliceKit. Engine testing showed that the ignition timing variation was reduced less than ± 0.1 °CA with the XMOS Flexible ECU compared to

± 3 °CA with the PIC18. The fuel pulse-width signal variation was reduced to ± 0.03 ms compared to ± 0.3 ms with the PIC18.

Maximum knock-free performance on 100 ON PRF at 49, 69, and 88 °C IAT was characterized. A full-load benchmark with 100 ON at 69 °C IAT with of maximum IMEPn of roughly 14.5 was chosen to represent the desired level of performance with 87 ON. Knock-

133 limited performance with 87 ON was characterized at 49°C IAT with standard single ignition,

26 °CA ATDC ignition timing, and stoichiometric equivalence ratio.

Knock-limited performance was characterized with 87 ON at 38, 69, and 88°C IAT to compare to the benchmark case. IMEPn increased roughly 0.6 bar by cooling IAT from 49°C to

38°C. Raising IAT to 69 and 88°C caused a 0.2 - 0.9 bar reduction in knock-limited IMEPn in each case. On average, knock-limited IMEPn fell 0.75 bar with each 20°C increase in temperature.

The effect of ignition timing on knock-limited performance was characterized and compared to the base 26 °CA ATDC ignition timing. Knock-limited IMEPn was reduced by 1 bar with MBT timing, as compared the base case. Retarding timing to approximately 18 °CA ATDC caused an IMEPn improvement of 0.75 bar at low speeds and 0.25 bar at high speeds. Retarding timing beyond the base case caused a 20 g/kW-h increase in ISFC per 10 °CA of combustion phasing delay on average. Retarding ignition timing caused FDA to decrease as RBA, COV of

IMEP, and exhaust gas temperature all increased.

An equivalence ratio study was performed with 87 ON at 49°C IAT and 26 °CA BTDC ignition timing to compare to the base 87 ON case. IMEPn was improved by 0.75 bar at 4000

RPM up to 1.7 bar at 5500 RPM under rich conditions as compared to stoichiometric. Knock- limited performance showed mild improvement with slightly lean operation at the lower engine speeds. COV of IMEP, CA50, FDA, and RBA all displayed a minimum around φ = 1.3. ISFC increased roughly 185 g/kW-h (70%) as equivalence ratio was varied from stoichiometric to that yielding maximum IMEPn (φ = 1.6).

A flush-mounted in-cylinder pressure transducer was installed to facilitate characterization of combustion phasing with dual-simultaneous-ignition to compare it to the base single ignition configuration. Dual-simultaneous-ignition with delayed combustion phasing showed a 2.2 bar improvement at 4000 RPM, 1.0 bar from 4500 – 5500 RPM, and 0.39 bar at

134

5800 RPM compared to the base case. The average 0.8 bar IMEPn improvement with dual- simultaneous-ignition nearly doubled that of the single-ignition. Dual-simultaneous-ignition caused a modest reduction in FDA, RBA, and ISFC compared to single ignition.

The combination of delayed combustion phasing with dual-simultaneous-ignition and equivalence ratio from 1.3 to 1.5 at 49°C IAT was found to enable greater maximum IMEPn than the 100 ON baseline at 49°C and 69°C. Knock-limited IMEPn was raised above 15 bar for all speeds except 4000 RPM, reaching a peak of 15.41 bar at 5800 RPM. Increasing equivalence ratio and retarding ignition timing were found to have a synergistic effect, producing an even greater improvement when employed together. ISFC increased 28% at maximum IMEPn. An additional 2.8 kg of fuel is required for takeoff under these optimized conditions with 87 ON, compared to the base 100 case.

A cruise fuel consumption study was conducted to characterize the ISFC reduction with dual-simultaneous-ignition at MBT timing compared to base case with single ignition and 26 °CA

ATDC ignition timing. Dual-simultaneous-ignition at MBT ignition timing reduced ISFC by roughly 6% at low cruise speeds and 12% at high cruise speeds. Lean operation at φ = 0.9 was characterized to investigate further cruise ISFC reduction. Lean operation with dual- simultaneous-ignition at MBT ignition timing and φ = 0.9 did not further reduce ISFC at low cruise speeds, but caused an additional 10 g/kW-h reduction at high cruise speeds. This ISFC reduction would directly offset the additional fuel used with the optimized 87 ON configuration for a 14 hour flight. With a typical 300 kg fuel mass, flight duration can be extended an additional 3.5 hours with the lean dual-simultaneous-ignition configuration at MBT ignition timing, including the additional fuel used in a 30 minute rich and retarded takeoff condition compared to the base single ignition configuration at φ = 1.0.

135

This work shows that the ONR of the Rotax 914 can be relaxed to 87 ON and retain full- load takeoff performance. The increased fuel consumption of the 87 ON optimized configuration under full load can be offset by an optimized cruise configuration, enabling greater flight endurance when required. The combination of the reduced cost of 87 ON and greater endurance could greatly reduce operating costs for SI UAS.

136

CHAPTER 10

10. RECOMMENDATIONS FOR FUTURE WORK

With an optimized 87 ON configuration established for the Rotax 914, a large portion of work remains in the application of this configuration to a field-ready system. Since provisions exist for a dual-simultaneous ignition system, and changes to ignition timing and fuel pulse- width should be limited to software changes, these should not present any great obstacle. The bulk of the remaining development efforts should be focused on adding a lightweight intercooler, and a knock-detection system. The success of this configuration requires that the intake air be cooled after turbocharging, but weight must be spared to achieve an acceptable fuel efficiency.

The knock-detection system presents the greatest hurdle in transitioning from a research laboratory to a field-ready system. In order for this optimized 87 ON configuration to achieve maximum power output the engine must be operated at near-knocking conditions during takeoff. Without a knock-detection system a richer mixture and more retarded ignition timing would be required to operate safely, reducing power output and fuel efficiency. The pressure indicating combustion analysis system used in this work is expensive and delicate. The recently developed ion sensing ignition coils [87] may provide the least intrusive path to a field- ready system optimized for 87 ON without re-designing engine hardware.

137

11. REFERENCES

[1] J. B. Heywood, Internal Combustion Engine Fundamentals, New York: McGraw-Hill, 1988.

[2] D. E. Winterbone, Advanced Thermodynamics for Engineers, New York: Wiley, 1997.

[3] S. R. Turns, An Introduction to Combustion: Concepts and Applications, Boston: McGraw-

Hill, 2000.

[4] E. R. Obert and B. H. Jennings, Internal Combustion Engines, New York: Intex Educational,

1968.

[5] H. K. Ng, Advances in Internal Combustion Engines and Fuel Technologies, Rijeka, Croatia:

InTech, 2013.

[6] W. W. Pulkrabek, Engineering Fundamentals of the Internal Combustion Engine, Upper

Saddle River, NJ.: Prentice Hall, 2004.

[7] G. P. Merker, C. Schwarz and R. Teichmann, Combustion Engines Development: Mixture

Formation, Combustion, Emissions and Simulation, New York: Springer, 20012.

[8] D. Y. Goswami and F. Kreith, Energy Conversion, Boca Raton, FL.: CRC Press, 2008.

[9] S. McAllister, J.-Y. Chen and A. C. Fernandez-Pello, Fundamentals of Combustion

Processes, New York: Springer, 2011.

[10] J. C. Fitton and R. J. Nates, "Investigation into the Relationship Between Knock Intensity

and Piston Seizure," N&O Joernaal, pp. 2-7, 1992.

138

[11] A. H. Goldingham, The in Principle and Practice, St. Joseph, MI: Gas Power

Publishing Company, 1907.

[12] H. E. Wimperis, The Internal Combustion Engine, New York: D. Van Nostrand Company,

1909.

[13] F. R. Jones, Electric Ignition for Combustion Motors, New York: John Wiley & Sons, 1912.

[14] F. W. Sterling, Internal Combustion Engine Manual, Annapolis: U. S. Naval Academy, 1911.

[15] E. W. Roberts, The Gas-Engine Handbook, Cincinnati: The Gas Engine Publishing Company,

1906.

[16] A. C. Mehrtens, Gas Engine Theory and Design, New York: John Wiley & Sons, 1909.

[17] R. D. Launius, Innovation and the Development of Flight, College Station, Texas: Texas

A&M University Press, 1999.

[18] C. D. Miller, "Relation Between Spark-Ignition Engine Knock, Detonation Waves, and

Autoignition as Shown by High-Speed Photography," Mational Advisory Committee for

Aeronautics, Cleveland, 1945.

[19] R. K. Rajput, Internal Combustion Engines, New Dehli: Laxmi, 2005.

[20] D. Bradley and G. T. Kalghatgi, "Influence of Autoignition Delay Time Characteristics of

Different Fuels on Pressure Waves and Knock in Reciprocating Engines," Combustion and

Flame, vol. 156, pp. 2307-2318, 2009.

[21] H. Zhao, Advanced Direct Injection Combustion Engine Technologies and Development,

vol. 1, New York: CRC Press, 2010.

[22] C. F. Taylor, The Internal-Combustion Engine in Theory and Practice, Cambridge, MA.: MIT

Press, 1985.

139

[23] B. Baral and R. Raine, "Knock in a Spark Ignition Engine Fuelled with Gasoline-Kerosene

Blends," SAE International, 2008-01-2417.

[24] F. Millo and C. V. Ferraro, "Knock in s.i. engines: a comparison between different

techniques for detection and control," SAE International, 1998 - 982477.

[25] E. Galloni, "Dynamic knock detection and quantification in a spark ignition engine by

means of a pressure based method," Energy Conversion and Management, vol. 64, pp.

256-262, 2012.

[26] A. K. Oppenheim, Combustion in Piston Engines: Technology, Evolution, Diagnoses, and

Control, New York: Springer, 2004.

[27] C. Arcoumanis and T. Kamimoto, Flow and Combustion in Receprocating Engines, Berlin:

Springer, 2009.

[28] J. R. Smith, R. M. Green, C. K. Westbrook and W. J. Pitz, "An Experimental and Modeling

Study of Engine Knock," in Twentieth Symposium (International) on Cumbustion/The

Combustion Insitute, 1984.

[29] W. P. Attard, H. Blaxill, E. Anderson and P. Litke, "Knock Limit Extension with a Gasoline

Fueled Pre-Chamber Jet Ingiter in a Modern Vehicle Powertrain," SAE International, 2012-

01-1143.

[30] E. K. Anderson, A. C. Brown, J. Baranski, J. L. Hoke, P. J. Litke and F. R. Schauer,

"Performance of Low-Octane Fuels in a Rotax 914 Engine with Advanced Knock Midigation

Strategies," SAE International, 2011-5725.

[31] M. Rothe, T. Heidenreich, U. Spicher and A. Schubert, "Knock Behavior of SI-Engines:

Thermodynamic Analysis of Knock Onset Locations and Knock Intensities," SAE

International, 2006-01-0225.

140

[32] MAHLE GmbH, and Engine Testing, Stuttgart: Springer, 2012.

[33] C. R. Ferguson and A. T. Kirkpatrick, Internal Combustion Engines: Applied Thermosciences,

New York: Wiley, 2001.

[34] K. Owen and T. Coley, Automotive Fuels Reference Book, Warrendale, PA: Society of

Automotive Engineers, Inc., 1995.

[35] K. J. Springer, "Energy, Efficiency, and the Environment: Three Big Es of Transportation,"

Journal of Engineering for Gas Turbines and Power, vol. 114, pp. 445-458, 1992.

[36] ASTM Standard D2699 - 12a, "Standard Test Method for Research Octane Number of

Spark-Ignition Engine Fuel," ASTM International, West Conshoshocken, PA, 2012.

[37] ASTM Standard D2700 - 12a, "Standard Test Method for Motor Octane Number of Spark-

Ignition Engine Fuel," ASTM International, West Conshoshocken, PA, 2012.

[38] V. Mittal and J. Heywood, "The Shift in Relevance of Fuel ROM and MON to Knock Onset in

Modern SI Engines Over the Last 70 Years," SAE International, 2009-01-2622.

[39] C. A. Amann, "The Automotive Spark-Ignition Engine - An Historical Perspective," in History

of the Internal Combustion Engine, New York, ASME, 1989, pp. 33-45.

[40] A. Ross and E. Rifkin, "Theory of Action," in Industrial and Engineering

Chemistry, Minneapolis, 1955.

[41] H. R. Ricardo, The High-Speed Internal-Combustion Engine, : Blackie & Son, 1934.

[42] Chevron Corporation, "Chevron Avaiation Fuels Technical Review," 2006.

[43] T. Edwards, "Liquid Fuels and Propellants for Aerospace Propulsion: 1903-2003," Journal of

Propulsion and Power, vol. 19, no. 6, pp. 1089-1107, 2003.

141

[44] W. Attard, "Small Engine Performance Limits - Turbocharging, Combustion or Design," The

University of Melbourne, 2007.

[45] B. Hamilton, "What Parameters Determine Octane Requirement?," 15 January 2004.

[Online]. Available: http://www.faqs.org/faqs/autos/gasoline-faq/part3/. [Accessed 8

December 2004].

[46] S. Russ, "A Review of the Effect of Engine Operating Conditions on Borderline Knock," SAE

Internationl, 1996-960497.

[47] M. L. Monaghan, "Future Gasoline and Diesel Engines - Review," International Journal of

Automotive Technology, vol. 1, no. 1, pp. 1-8, 2000.

[48] J. A. Topinka, M. D. Gerty, J. B. Heywood and J. C. Keck, "Knock Behavior of a Lean-Burn,

H2 and CO Enhanced, SI Gasoline Engine Concept.," SAE International, 2004-01-0975.

[49] A. Cairns, H. Blaxill and A. Irlam, "Exhaust Gas Recirculation for Improved Part and Full

Load Fuel Economy in a Turbocharged Gasoline Engine," SAE International, 2006-01-0047.

[50] A. Swarts, A. Yates, C. Viljoen and R. Coetzer, "A Further Study of Inconsistencies Between

Autoignition and Knock Intensity in the CFR Octane Rating Engine," SAE International,

2005-01-2081.

[51] A. B. Yates, A. Swarts and C. L. Viljoen, "Correlating Auto-Ignition Delays and Knock-Limited

Spark-Advance Data for Different Types of Fuel," SAE International, 2005-01-2083.

[52] K. Okamoto, T. Ichikawa, K. Saitoh, K. Oyama, K. Hiraya and T. Urushihara, "Study of

Antiknock Performance Under Various Octane Numbers and Compression Ratios in a DISI

Engine," SAE International, 2003-01-1804.

[53] W. L. Lind, Internal-Combustion Engines, Boston: Ginn and Company, 1920.

142

[54] E. Anderson, W. Attard, A. Brown, P. Litke, K. Grinstead and J. Hoke, "Experimental Study

of a Pre-Chamber Jet Igniter in a Turbocharged Rotax 914 Aircraft Engine," SAE

International, 2013-01-1629.

[55] H. Watson and M. Gledhill, "Comparison of Knock in a Jet Assisted Ignition and Normal SI

Engine," in Asia Pacific Automotive Engineering Conference, 2009.

[56] N. Watson and M. Janota, Turbocharging the Internal Combustion Engine, London:

Macmillan, 1984.

[57] L. M. Nicolai and G. Carichner, Fundamentals of Aircraft and Airship Design, Reston, VA,:

AIAA, 2010.

[58] V. M. Faires, Elementary Thermodynamics, New York: Macmillan, 1957.

[59] C. W. Wilson, F. R. Schauer, P. J. Litke, J. L. Hoke and J.-R. J. Groenewegen, "-

Based and Bio-Derived Jet Fuel Efficiency Opimization Using Fuel Injecttion in a 34cc 4-

Stroke Spark-Ignition Engine," SAE International, 2011-32-0601.

[60] J.-R. J. Groenewegen, S. S. Sidhu, J. L. Hoke, C. W. Wilson and P. J. Litke, "The Performance

and Emissions Effects of Utilizing Heavy Fuels and Algae Based Biodiesel in a Port-Fuel-

Injected Small Spark Ignition Internal Combustion Engine," AIAA, 2011-5807.

[61] R. Stone, Introduction to Internal Combustion Engines, Warrendale, PA.: SAE International,

2012.

[62] R. v. Basshuysen and F. Schafer, Internal Combustion Engine Handbook: Basics,

Componenets, Systems, and Perspectives, Warrendale, PA.: SAE International, 2004.

[63] R. Stone and J. K. Ball, Automotive Engineering Fundamentals, Warrendale, PA.: SAE

International, 2004.

143

[64] J. Wheeler, D. Polovina, S. Ramanathan, K. Roth, D. Manning and J. Stein, "Increasing EGR

Tolerance using High Tumble in a Modern GTDI Engine for Improved Low-Speed

Performance," SAE International, 2013-01-1123.

[65] S. Brussovansky, J. Heywood and J. Keck, "Predicting the Effects of Air and Coolant

Temperature, Deposits, Spark Timing and Speed on Knock in Spark Ignition Engines," SAE

International, 1992 - 922324.

[66] S. Kokjohn, R. Reitz, D. Splitter and M. Musculus, "Investigation of Fuel Reactivity

Stratification for Controlling PCI Heat-Release Rates Using High-Speed Chemiluminescence

Imaging and Fuel Tracer Fluorescence," SAE International, 2012-01-0375.

[67] S. Tanaka, F. Ayala and J. B. H. J. C. Keck, "Two-stage ignition in HCCI combustion and HCCI

control by fuels and additives," Combustion and Flame, vol. 132, pp. 219-239, 2003.

[68] D. Choi, H. Jung, Y. Chi and S. Joo, "Diesel/Gasoline Dual Fuel Powered Combustion System

based on Diesel Compression Ignition Triggered Ignition Control," SAE International, 2013-

01-1718.

[69] BOSCH, Gasoline-Engine Management: Systems and Components, Cambridge, MA: Bently,

2004.

[70] W. B. Ribbens, Understanding Automotive Control Systems, Boston: Elsevier, 2003.

[71] N. Ladommatos and H. Zhao, Engine Combustion Instrumentation and Diagnostics,

Warrendale, PA.: SAE International, 2001.

[72] G. Bansih, Engine Management: Advanced Tuning, North Branch, MN: CarTech, 2007.

[73] L. Guzzella and C. H. Onder, Introduction to Modeling and Control of Internal Combustion

Engien Systems, Berlin: Springer, 2010.

144

[74] S. Curran, V. Prikhodo, K. Cho, C. Sluder, J. Parks, R. Wagner, S. Kokjohn and R. Reitz, "In-

Cylinder Fuel Blending of Gasoline/Diesel for Improved Efficiency and Lowest Possible

Emissions on a Multi-Cylinder Light-Duty ," SAE International, 2010-10-25.

[75] C. Tumelaire, D. Gurney, T. Cains, N. Milovanovic and M. Warth, "Flexible ECU Function

Development Calibration and Engine Performance Assessment Based on Co-Simulation,"

SAE International, 2013-01-0342.

[76] BRP-Powertrain, "Operators Manual for Rotax 914 Engine," Ref. No. OM-914, OM Edition 2

/ Rev. 0, 2010.

[77] J. Schauffelle and T. Zurawka, Automotive Software Engineering, Warrendale, Pa.: SAE

International, 2005.

[78] D. R. Rogers, Engine Combustion: Pressure Measurement and Analysis, Warrendale, PA.:

SAE International, 2010.

[79] R. D. Atkins, An Introduction to Engine Testing and Development, Warrendale, PA: SAE

International, 2009.

[80] A. J. Martry and M. A. Plint, Engine Testing: Theory and Practice, New York: Elsevier, 2007.

[81] U. Kiencke and L. Nielsen, Automotive Control Systems, Heidelberg, Germany: Springer,

2005.

[82] X. Zhen, Y. Wang, S. Xu, Y. Zhu, C. Tao, T. Xu and M. Song, "The Engine Knock Analysis - An

Overview," Applied Energy, vol. 92, pp. 628-636, 2012.

[83] E. Corporan, T. Edwards, L. Shafer and M. DeWitte, "Chemical Thermanl Stability, Seal

Swell, and Emissions Studies of Alternative Jet Fuels," Energy and Fuels, no. 25, pp. 955-

966, 2011.

145

[84] Dixie Services, "Certificate of Analysis Number 134094 for JP-8 Octane Evaluation per

ASTM D2700".

[85] L. D. Jasio, Programming 32-bit Microcontrollers in C: Exploring the PIC32, New York:

Elsevier, 2008.

[86] United States Department of Defense, "Unmanned Aircraft Systems Roadmap 2005-2030,"

2005.

[87] G. Malaczynski, G. Roth and D. Johnson, "Ion-Sense-Based Real-Time Combustion Sensing

for Closed Loop Engine Control," SAE International, 2013-01-0354.

146

12. APPENDIX A – ENGINEERING DRAWING OF INTAKE PORT FLANGE

147

13. APPENDIX B – ENGINEERING DRAWING OF ADDITIONAL PFI PORT

148

14. APPENDIX C – SCHEMATIC OF DUAL-PIC18 CIRCUIT BOARD

149

15. APPENDIX D – PIC18 ECU IGNITION CONTROL PROGRAM

#include <18F452.h> #device adc=10 #fuses HS, NOBROWNOUT, STVREN, NOWDT, NOLVP #use delay(clock=40000000)

//This program implements variable spark timing for the Rotax 914 engine. It requires //an input of 35 pulses per revolution with the 36th pulse being a blank (locator) //"pulse" to calculate correct spark angle and time. It is currently set up to wait for //the 32nd pulse of the 36 pulse hall effect speed sensor before it calculates the new //time/angle. It calculates and updates the time/angle before it gets to the //min_spark_angle where it then uses the new time to fire the spark. //Timer uses a 17.5us count.

//#priority EXT1, TIMER2, EXT

#define OUTPIN_SPARK_12 PIN_D0 //pin #19 #define OUTPIN_SPARK_34 PIN_D1 //pin #20 #define OUTPIN_FREQ PIN_D2 // pin #21engine rpm pulse #define OUTPIN_VR PIN_D4 //pin #27 #define OUTPIN_ENCODER PIN_D5 //pin #28 #define SPARK_ENABLE_PIN PIN_D7 //pin #30

//CONSTANT VARIABLES #define rev_length_buffer 60000 //this MUST BE LARGER THAN rotation_length_max!!! #define rev_length_max 27429 //125 rpm; low speed limit

#define spark_angle_channel 0 #define spark_34_offset_angle 0

#define spark_angle_min -50.0 //Spark angle in degrees ATDC at 0V. So spark will be #define spark_angle_max 10.0 //Spark angle in degrees ATDC at 5V. int16 time, encoder_count, start_flag; int16 time_pulse_19, time_pulse_25, time_pulse_1, time_pulse_7; int16 stoptime_12, sparktime_12, stoptime_34, sparktime_34; int16 stoptime_12_new, sparktime_12_new, stoptime_34_new, sparktime_34_new, spark_34_offset; int8 sparktime_12_ready, rev_length12_updated, sparktime_34_ready, rev_length34_updated; float rev_length12, rev_length34; float spark_angle_slope;

150

#int_TIMER2 TIMER2_isr() { time++;

if (sparktime_12_ready == TRUE){ //recieve new spark times if they are ready sparktime_12 = sparktime_12_new; sparktime_12_ready = FALSE; }

if (sparktime_34_ready == TRUE){ //recieve new spark times if they are ready sparktime_34 = sparktime_34_new; sparktime_34_ready = FALSE; }

if ((rev_length12 <= rev_length_max) && (input(SPARK_ENABLE_PIN) == TRUE)){ if (time == sparktime_12){ output_low(OUTPIN_SPARK_12); output_high(OUTPIN_FREQ); } else{ output_high(OUTPIN_SPARK_12); output_low(OUTPIN_FREQ); } } else{ output_high(OUTPIN_SPARK_12); output_low(OUTPIN_FREQ); }

if ((rev_length34 <= rev_length_max) && (input(SPARK_ENABLE_PIN) == TRUE)){ if (time == sparktime_34) output_low(OUTPIN_SPARK_34); else output_high(OUTPIN_SPARK_34); } else output_high(OUTPIN_SPARK_34);

if (time >= rev_length_buffer){ //reset time if engine is not spinning so that buffer does not overflow. time = 0; rev_length12 = rev_length_buffer; rev_length34 = rev_length_buffer;

151

}

} //End of Timer Interrupt *****************************************************

//Pin RB0 (#33) Pulse interrupt 0 //crankshaft location pulse******************************************************* #int_EXT EXT_isr() { // locate spark pulse with speed indicator if (start_flag == 0){ start_flag = 1; encoder_count = 0; } else if ((start_flag == 1) && (encoder_count >= 35)) { encoder_count = 0; }

output_toggle(OUTPIN_VR); } //End of crankshaft position pulse interrupt**************************************

//Pin RB1 (#34) Pulse interrupt 1 //hall effect speed sensor timing pulse**************************************************** #int_EXT1 EXT1_isr() { //increment speed sensor count for each indicator encoder_count++; //measure time between 21st and 27th pulse (6 pulses) on 36 position indicator if (encoder_count == 19) { time_pulse_19 = time; } //wait until speed sensor's 27th pulse and update rev_length to calc new fire time if (encoder_count == 25) { time_pulse_25 = time; set_timer2(0); time = 0; rev_length12_updated = TRUE; }

152

if (encoder_count == 1) time_pulse_1 = time;

//wait until speed sensor's 9th pulse and update rev_length to calc new fire time if (encoder_count == 7) { time_pulse_7 = time; rev_length34_updated = TRUE; }

output_toggle(OUTPIN_ENCODER); } //End of hall effect speed sensor timing pulse interrupt*********************************** void main() { setup_adc_ports(A_ANALOG); setup_adc(ADC_CLOCK_DIV_64); setup_psp(PSP_DISABLED); setup_spi(SPI_SS_DISABLED); setup_wdt(WDT_OFF); setup_timer_0(RTCC_INTERNAL); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DIV_BY_1,174,1); //Time is in 17.5 microsecond increments ->(175*4/40000000)*1=0.0000175 setup_timer_3(T3_DISABLED|T3_DIV_BY_1); setup_ccp1(CCP_OFF); setup_ccp2(CCP_OFF); disable_interrupts(INT_TIMER2); //Block interrupts momentarily disable_interrupts(INT_EXT); disable_interrupts(INT_EXT1); disable_interrupts(GLOBAL); //Disable Global interrupt ext_int_edge(L_TO_H); //Look for positive edges on interrupt 0 ext_int_edge(1,L_TO_H); //Look for positive edges on interrupt 1

//Initialize variables******************************************************* time = 0; encoder_count = 0; start_flag = 0; time_pulse_19 = 0; time_pulse_25 = rev_length_max; time_pulse_1 = 0;

153

time_pulse_7 = rev_length_max;

rev_length12 = time_pulse_25 - time_pulse_19; //Default to a high cycle time rev_length34 = time_pulse_7 - time_pulse_1;

spark_angle_slope = 0.0009775171;

set_adc_channel(spark_angle_channel); delay_us(100);

sparktime_12 = rev_length12 + (rev_length12 * spark_angle_slope * read_adc()); sparktime_12_new = sparktime_12; output_high(OUTPIN_SPARK_12); output_low(OUTPIN_FREQ); rev_length12_updated = FALSE; sparktime_12_ready = FALSE;

sparktime_34 = rev_length34 + (rev_length34 * spark_angle_slope * read_adc()); sparktime_34_new = sparktime_34; output_high(OUTPIN_SPARK_34); rev_length34_updated = FALSE; sparktime_34_ready = FALSE;

output_low(OUTPIN_VR); output_low(OUTPIN_ENCODER);

//End initialize variables***************************************************

enable_interrupts(GLOBAL); //Enable Global interrupt enable_interrupts(INT_EXT); //Begin watching crankshaft timing pulse enable_interrupts(INT_EXT1); //Begin watching 25 tooth gear timing pulse enable_interrupts(INT_TIMER2); //Enable timing

while (1){

while ((encoder_count != 25) && (rev_length12_updated == FALSE)) {} //wait until speed sensor's 27th pulse and update rev_length to calc new fire time rev_length12 = time_pulse_25 - time_pulse_19; sparktime_12_new = rev_length12 + (rev_length12 * spark_angle_slope * read_adc()); sparktime_12_ready = TRUE;

154

rev_length12_updated = FALSE;

while ((encoder_count != 7) && (rev_length34_updated == FALSE)) {} //wait until speed sensor's 9th pulse and update rev_length to calc new fire time rev_length34 = time_pulse_7 - time_pulse_1; spark_34_offset = rev_length34 * (spark_34_offset_angle / 60.0); sparktime_34_new = time_pulse_7 + rev_length34 + (rev_length34 * spark_angle_slope * read_adc()) + spark_34_offset; sparktime_34_ready = TRUE; rev_length34_updated = FALSE;

} }

155

16. APPENDIX E – PIC18 ECU FUEL INJECTION CONTROL PROGRAM

#include <18F452.h> #device adc=10 #use delay(clock=40000000) #fuses HS, NOBROWNOUT, STVREN, NOWDT, NOLVP, CCP2B3 #include

//This program implements gasoline port fuel injection for the Rotax 914 engine. It requires // 3 signals: 1. 35 pulses per revolution with the 36th pulse being a blank (locator) "pulse". // 2. Pulse from VR box located within 10 degrees of TDC each rev. 3. Pulse from " sensor" // (cylinder 2 exhaust valve opening) at around 180 degrees after TDC on power stroke. // Timer uses a 20.0us count.

#define OUTPIN_FUEL_1 PIN_D0 //pin #19 #define OUTPIN_FUEL_2 PIN_D1 //pin #20 #define OUTPIN_FUEL_3 PIN_D2 //pin #21 #define OUTPIN_FUEL_4 PIN_D3 //pin #22 #define OUTPIN_VR PIN_D4 //pin #27 #define OUTPIN_ENCODER PIN_D5 //pin #28 #define PW_HOLD_PIN PIN_D6 //pin #29 #define FUEL_ENABLE_PIN PIN_D7 //pin #30

//CONSTANT VARIABLES #define time_buffer 60000 //this MUST BE LARGER THAN the TWICE rev_length_max!!! #define rev_length_max 3200 //750 RPM min

// Fuel_angle_channel Channel 0 Not Connected #define phi_channel 1 //desired equivalence ratio, this will be used along with MAF to calc required fuel flow. Pin #3 #define MAF_channel 2 //input from MAF sensor. Pin #4 // #define MAP_channel 3 //input from MAP sensor. Pin #5 // #define _Channel 4 //not connected #define O2_Sensor_channel 5 //input from O2 sensor. Pin #8 **O2 Sensor output: 0V = 7.35 AFR, 5V = 22.39.

#define fueltime 2 //time counts to wia to inject fuel after time is reset (must be greater than 0)

#define cylinders 4.0 //number of cylinders

#define phi_min 0.5 //phi at 0V #define phi_max 1.5 //phi at 5V

#define pw_slope 1.0 #define pw_intercept -512.0

156

#define AF_Stoich 14.90 //stoichiometric Air/Fuel ratio /* Gasoline 14.57 JP-8 14.70 Av-gas 14.90 Iso-octane 15.10 N-heptane 15.20 */

#define O2_speed_min 3750 //minimum speed for closed loop O2 control ~ 1000 rpm #define O2_closed_loop_step 0.001 //factor of enrichment given each cycle based on O2_adc #define O2_closed_loop_min 0.25 #define O2_closed_loop_max 1.75

#define O2_adc_AF_slope 0.0068359 //O2 ADC Calibration #define O2_adc_AF_int 9.0 /* ECM slope = 0.0097656 intercept = 8.0 Innovate slope = 0.0146875 intercept = 7.35 NGK AFX slope = 0.0068359 intercept = 9.0 */

#define inj_flow_hr 20.0 //injector flowrate (20 lb/hr) at rated pressure (45 psi).

#define MAF_a0 -3.5870859 //MAF = a0 + a1*ADC + a2*ADC^2 + a3*ADC^3 (lb/min) #define MAF_a1 0.02900625 //note: the curve fit is to the 10bit adc values ->0V=1 5V=1024 #define MAF_a2 -0.00006878012 #define MAF_a3 0.00000006979011 int8 cam_flag, cam_located, rev_length14_updated, rev_length23_updated, pw_hold_flag; int16 PHI_ADC_RAW, O2_ADC_RAW; int16 time_1, time_2, time_3, time_4, encoder_count, rev_length_14, cycle_length_14, cycle_length_23; int16 time_pulse_19, time_pulse_54;

157 int16 stoptime_1, stoptime_2, stoptime_3, stoptime_4; int16 MAF_adc_1, MAF_adc_2, MAF_adc_3, MAF_adc_4; float stoptime_1_new, stoptime_2_new, stoptime_3_new, stoptime_4_new; float fuel_duration_14, fuel_duration_23, fuel_duration_14_hold, fuel_duration_14_hold_pw; float PHI_desired, phi_slope, phi_intercept, MAF_adc, MAF; float inj_flow, max_fuel_recip, cylinders_recip; float O2_adc_AF, O2_adc_phi, O2_closed_loop, FA_Stoich; float pw_ctrl_intital, pw_ctrl;

#int_TIMER2 TIMER2_isr() { time_1++; time_2++; time_3++; time_4++;

if ((input(FUEL_ENABLE_PIN) == TRUE) && (rev_length_14 <= rev_length_max)) { if (time_1 == fueltime) output_high(OUTPIN_FUEL_1); else if (time_1 == stoptime_1) output_low(OUTPIN_FUEL_1);

if (time_2 == fueltime) output_high(OUTPIN_FUEL_2); else if (time_2 == stoptime_2) output_low(OUTPIN_FUEL_2);

if (time_3 == fueltime) output_high(OUTPIN_FUEL_3); else if (time_3 == stoptime_3) output_low(OUTPIN_FUEL_3);

if (time_4 == fueltime) output_high(OUTPIN_FUEL_4); else if (time_4 == stoptime_4) output_low(OUTPIN_FUEL_4); } else { output_low(OUTPIN_FUEL_1); output_low(OUTPIN_FUEL_2); output_low(OUTPIN_FUEL_3); output_low(OUTPIN_FUEL_4); }

if (time_1 >= time_buffer){ //reset time if engine is not spinning so that buffer does not overflow. time_1 = time_buffer;

158

time_2 = time_buffer; time_3 = time_buffer; time_4 = time_buffer; rev_length_14 = time_buffer; cycle_length_14 = time_buffer; cycle_length_23 = time_buffer; cam_located = FALSE; }

} //End of Timer Interrupt *****************************************************

//Pin RB0 (#33) Pulse interrupt 0 //crankshaft location pulse******************************************************* #int_EXT EXT_isr() { // locate spark pulse with VR sensor3. if ((cam_flag) || (cam_located && (encoder_count == 70))){ encoder_count = 0; cam_located = TRUE; }

output_toggle(OUTPIN_VR); } //End of crankshaft position pulse interrupt**************************************

//Pin RB1 (#34) Pulse interrupt 1 //hall effect speed sensor timing pulse**************************************************** #int_EXT1 EXT1_isr() { //increment speed sensor count for each indicator encoder_count++;

if (encoder_count == 1) { output_low(OUTPIN_FUEL_2); stoptime_2 = stoptime_2_new; //recieve new times rev_length_14 = time_1; time_2 = 0; cam_flag = FALSE;

159

}

if (encoder_count == 19) { output_low(OUTPIN_FUEL_3); stoptime_3 = stoptime_3_new; //recieve new times cycle_length_14 = time_3; time_3 = 0; }

if (encoder_count == 36) { output_low(OUTPIN_FUEL_1); stoptime_1 = stoptime_1_new; //recieve new times time_1 = 0; }

if (encoder_count == 54) { output_low(OUTPIN_FUEL_4); stoptime_4 = stoptime_4_new; //recieve new times cycle_length_23 = time_4; time_4 = 0; }

output_toggle(OUTPIN_ENCODER); } //End of hall effect speed sensor timing pulse interrupt***********************************

//Pin RB2 (#35) Cam interrupt //cam location pulse******************************************************* #int_EXT2 EXT2_isr() { if (cam_located == FALSE) cam_flag = TRUE; } //End of cam position pulse interrupt************************************** void main() { setup_adc_ports(A_ANALOG); setup_adc(ADC_CLOCK_DIV_64); setup_psp(PSP_DISABLED);

160

setup_spi(SPI_SS_DISABLED); setup_wdt(WDT_OFF); setup_timer_0(RTCC_INTERNAL); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DIV_BY_1,249,1); //Time is in 20 microsecond increments ->(200*4/40000000)*1=0.0000200. Setting timer less than 159 is unstable. setup_timer_3(T3_DISABLED|T3_DIV_BY_1); setup_ccp1(CCP_OFF); setup_ccp2(CCP_OFF); disable_interrupts(INT_TIMER2); //Block interrupts momentarily disable_interrupts(INT_EXT); disable_interrupts(INT_EXT1); disable_interrupts(INT_EXT2); disable_interrupts(GLOBAL); //Disable Global interrupt ext_int_edge(L_TO_H); //Look for positive edges on interrupt 0 ext_int_edge(1,L_TO_H); //Look for positive edges on interrupt 1 ext_int_edge(2,L_TO_H); //Look for negative edges on interrupt 2

//Initialize variables******************************************************* time_1 = time_buffer; time_2 = time_buffer; time_3 = time_buffer; time_4 = time_buffer; encoder_count = 0; cam_flag = FALSE; cam_located = FALSE; pw_hold_flag = FALSE;

MAF_adc_1 = 0; MAF_adc_2 = 0; MAF_adc_3 = 0; MAF_adc_4 = 0;

rev_length_14 = time_buffer;

cycle_length_14 = time_buffer; //Default to a high cycle time cycle_length_23 = time_buffer; //Default to a high cycle time

phi_slope = (phi_max - phi_min) / 1023.0; phi_intercept = phi_min;

161

set_adc_channel(phi_channel); delay_us(100); PHI_ADC_RAW = read_adc(); PHI_desired = PHI_ADC_RAW * phi_slope + phi_intercept; pw_ctrl = read_adc() * pw_slope + pw_intercept; inj_flow = inj_flow_hr / 60.0; //convert from lb/hr to lb/min max_fuel_recip = 1.0 / (inj_flow * cylinders); set_adc_channel(O2_Sensor_channel); delay_us(100); O2_ADC_RAW = read_adc(); O2_adc_AF = O2_ADC_RAW * O2_adc_AF_slope + O2_adc_AF_int; O2_adc_phi = AF_Stoich / O2_adc_AF; O2_closed_loop = PHI_desired;

FA_Stoich = 1.0 / AF_Stoich;

MAF_adc = (MAF_adc_1 + MAF_adc_2 + MAF_adc_3 + MAF_adc_4) * 0.25; MAF = MAF_a0 + MAF_a1*MAF_adc + MAF_a2*MAF_adc*MAF_adc + MAF_a3*MAF_adc*MAF_adc*MAF_adc; fuel_duration_14 = (cycle_length_14 * MAF * FA_Stoich * max_fuel_recip * O2_closed_loop); if (fuel_duration_14 < 2) fuel_duration_14 = 2; stoptime_1_new = fueltime + fuel_duration_14; stoptime_1 = stoptime_1_new; output_low(OUTPIN_FUEL_1); fuel_duration_23 = (cycle_length_23 * MAF * FA_Stoich * max_fuel_recip * O2_closed_loop); if (fuel_duration_23 < 2) fuel_duration_23 = 2; stoptime_2_new = fueltime + fuel_duration_23; stoptime_2 = stoptime_2_new; output_low(OUTPIN_FUEL_2); stoptime_3_new = fueltime + fuel_duration_23; stoptime_3 = stoptime_3_new; output_low(OUTPIN_FUEL_3); stoptime_4_new = fueltime + fuel_duration_14; stoptime_4 = stoptime_4_new;

162 output_low(OUTPIN_FUEL_4); fuel_duration_14_hold = fuel_duration_14_hold_pw; output_low(OUTPIN_VR); output_low(OUTPIN_ENCODER);

//End initialize variables*************************************************** enable_interrupts(GLOBAL); //Enable Global interrupt enable_interrupts(INT_EXT); //Begin watching crankshaft timing pulse enable_interrupts(INT_EXT1); //Begin watching 25 tooth gear timing pulse enable_interrupts(INT_EXT2); //Begin watching cam sensor pulse enable_interrupts(INT_TIMER2); //Enable timing while (1){

if (input(PW_HOLD_PIN) == FALSE) { set_adc_channel(phi_channel); delay_us(100); PHI_ADC_RAW = read_adc(); PHI_desired = PHI_ADC_RAW * phi_slope + phi_intercept;

if ((input(FUEL_ENABLE_PIN) == TRUE) && (rev_length_14 <= O2_speed_min)){ set_adc_channel(O2_Sensor_channel); delay_us(100); O2_ADC_RAW = read_adc(); O2_adc_AF = O2_ADC_RAW * O2_adc_AF_slope + O2_adc_AF_int; O2_adc_phi = AF_Stoich / O2_adc_AF; if (O2_adc_phi >= PHI_desired) O2_closed_loop -= O2_closed_loop_step; else if (O2_adc_phi < PHI_desired) O2_closed_loop += O2_closed_loop_step; if (O2_closed_loop <= O2_closed_loop_min) O2_closed_loop = O2_closed_loop_min; else if (O2_closed_loop >= O2_closed_loop_max) O2_closed_loop = O2_closed_loop_max; } else (O2_closed_loop = PHI_desired); }

//O2_closed_loop = 1; ////////TAKE THIS OUT FOR REAL PROGRAMMMMMMMMMMMMMMMM

set_adc_channel(MAF_channel);

163 delay_us(100); while (encoder_count != 1) {} MAF_adc_1 = read_adc(); while (encoder_count != 10) {} MAF_adc_2 = read_adc();

MAF_adc = (MAF_adc_1 + MAF_adc_2 + MAF_adc_3 + MAF_adc_4) * 0.25; MAF = MAF_a0 + MAF_a1*MAF_adc + MAF_a2*MAF_adc*MAF_adc + MAF_a3*MAF_adc*MAF_adc*MAF_adc; fuel_duration_14 = (cycle_length_14 * MAF * FA_Stoich * max_fuel_recip * O2_closed_loop); if (fuel_duration_14 < 2) fuel_duration_14 = 2; if (input(PW_HOLD_PIN) == TRUE) { if (pw_hold_flag == FALSE) { fuel_duration_14_hold_pw = fuel_duration_14; set_adc_channel(phi_channel); delay_us(100); pw_ctrl_intital = read_adc(); pw_hold_flag = TRUE; }

set_adc_channel(phi_channel); delay_us(100); pw_ctrl = read_adc() - pw_ctrl_intital;

fuel_duration_14_hold = fuel_duration_14_hold_pw + pw_ctrl;

if (fuel_duration_14_hold < 2 ) fuel_duration_14_hold = 2;

stoptime_1_new = fueltime + fuel_duration_14_hold; stoptime_4_new = fueltime + fuel_duration_14_hold; stoptime_2_new = fueltime + fuel_duration_14_hold; stoptime_3_new = fueltime + fuel_duration_14_hold; } else { pw_hold_flag = FALSE; stoptime_1_new = fueltime + fuel_duration_14; stoptime_4_new = fueltime + fuel_duration_14;

164

}

if (input(PW_HOLD_PIN) == FALSE) { if ((input(FUEL_ENABLE_PIN) == TRUE) && (rev_length_14 <= O2_speed_min)){ set_adc_channel(O2_Sensor_channel); O2_ADC_RAW = read_adc(); O2_adc_AF = O2_ADC_RAW * O2_adc_AF_slope + O2_adc_AF_int; O2_adc_phi = AF_Stoich / O2_adc_AF; if (O2_adc_phi >= PHI_desired) O2_closed_loop -= O2_closed_loop_step; else if (O2_adc_phi < PHI_desired) O2_closed_loop += O2_closed_loop_step; if (O2_closed_loop <= O2_closed_loop_min) O2_closed_loop = O2_closed_loop_min; else if (O2_closed_loop >= O2_closed_loop_max) O2_closed_loop = O2_closed_loop_max; } else (O2_closed_loop = PHI_desired);

//O2_closed_loop = 1; ////////TAKE THIS OUT FOR REAL PROGRAMMMMMMMMMMMMMMMM

set_adc_channel(MAF_channel); delay_us(100);

while (encoder_count != 36) {} MAF_adc_3 = read_adc();

while (encoder_count != 45) {} MAF_adc_4 = read_adc();

MAF_adc = (MAF_adc_1 + MAF_adc_2 + MAF_adc_3 + MAF_adc_4) * 0.25; MAF = MAF_a0 + MAF_a1*MAF_adc + MAF_a2*MAF_adc*MAF_adc + MAF_a3*MAF_adc*MAF_adc*MAF_adc;

fuel_duration_23 = (cycle_length_23 * MAF * FA_Stoich * max_fuel_recip * O2_closed_loop); if (fuel_duration_23 < 2) fuel_duration_23 = 2;

stoptime_2_new = fueltime + fuel_duration_23; stoptime_3_new = fueltime + fuel_duration_23; } } }

165

17. APPENDIX F – PIC18 DUAL-FUEL INJECTION CONTROL PROGRAM

#include <18F452.h> #device adc=10 #use delay(clock=40000000) #fuses HS, NOBROWNOUT, STVREN, NOWDT, NOLVP, CCP2B3 #include

//This program implements gasoline port fuel injection for the Rotax 914 engine. //It requires 3 signals: 1. 35 pulses per revolution with the 36th pulse being a blank //(locator) "pulse". 2. Pulse from VR box located within 10 degrees of TDC each rev. 3. //Pulse from "cam sensor" (cylinder 2 exhaust valve opening) at around 180 degrees //after TDC on power stroke. Timer uses a 16.0us count.

#define OUTPIN_FUEL_1 PIN_D0 //pin #19 #define OUTPIN_FUEL_2 PIN_D1 //pin #20 //#define OUTPIN_FUEL_3 PIN_D2 //pin #21 //#define OUTPIN_FUEL_4 PIN_D3 //pin #22 #define OUTPIN_VR PIN_D4 //pin #27 #define OUTPIN_ENCODER PIN_D5 //pin #28 #define PW_HOLD_PIN PIN_D6 //pin #29 #define FUEL_ENABLE_PIN PIN_D7 //pin #30

//CONSTANT VARIABLES #define time_buffer 60000 //this MUST BE LARGER THAN the TWICE rev_length_max!!! #define rev_length_max 3200 //750 RPM min

// Fuel_angle_channel Channel 0 Not Connected #define phi_channel 1 //desired equivalence ratio, this will be used along with MAF to calc required fuel flow. Pin #3 #define MAF_channel 2 //input from MAF sensor. Pin #4 // #define MAP_channel 3 //input from MAP sensor. Pin #5 // #define XXX_channel 4 //not connected on PIC board #define O2_Sensor_channel 5 //input from O2 sensor. Pin #8 **O2 Sensor output: 0V = 7.35 AFR, 5V = 22.39. #define octane_channel 6 //desired octane number. Pin #9

#define fueltime 2 //time counts to wia to inject fuel after time is reset (must be greater than 0)

//#define fuel_duration_min 50 //minimum injector pulse width. 1ms / 20us = 50 //#define fuel_duty_cycle_max 0.8 //80% maximum duty cycle

#define cylinders 4.0 //number of cylinders

166

#define phi_min 0.5 //phi at 0V #define phi_max 1.5 //phi at 5V

#define pw_slope 1.0 #define pw_intercept -512.0

#define AF_Stoich_Fuel_1 14.57 //stoichiometric Air/Fuel ratio (gasoline) #define AF_Stoich_Fuel_2 15.50 //stoichiometric Air/Fuel ratio (n-heptane) /* Gasoline 14.57 JP-8 14.70 Av-gas 14.90 Iso-octane 15.10 n-heptane 15.50 */

#define O2_speed_min 3750 //minimum speed for closed loop O2 control ~ 1000 rpm #define O2_closed_loop_step 0.001 //factor of enrichment given each cycle based on O2_adc #define O2_closed_loop_min 0.25 #define O2_closed_loop_max 1.75

#define O2_adc_AF_slope 0.0097656 //O2 ADC Calibration for ECM O2 Sensor/Controller #define O2_adc_AF_int 8.0 /* ECM slope = 0.0097656 intercept = 8.0 Innovate slope = 0.0146875 intercept = 7.35 NGK AFX slope = 0.0068359 intercept = 9.0 */

#define octane_min 0.0 //octane number at 0V #define octane_max 100.0 //octane number at 5V

#define inj_flow_hr 20.0 //injector flowrate (20 lb/hr) at rated pressure (45 psi).

167

#define MAF_a0 -3.5870859 //MAF = a0 + a1*ADC + a2*ADC^2 + a3*ADC^3 (lb/min) #define MAF_a1 0.02900625 //note: the curve fit is to the 10bit adc values ->0V=1 5V=1024 #define MAF_a2 -0.00006878012 #define MAF_a3 0.00000006979011 int8 cam_flag, cam_located, rev_length14_updated, rev_length23_updated, pw_hold_flag; int16 PHI_ADC_RAW, O2_ADC_RAW; int16 time_1, time_2, time_3, time_4, encoder_count, rev_length_14, cycle_length_14, cycle_length_23; int16 time_pulse_19, time_pulse_54; int16 stoptime_fuel_1, stoptime_fuel_2;//, stoptime_3, stoptime_4; int16 MAF_adc_1, MAF_adc_2, MAF_adc_3, MAF_adc_4; float stoptime_fuel_1_new, stoptime_fuel_2_new;//, stoptime_3_new, stoptime_4_new; float fuel_duration_fuel_1, fuel_duration_fuel_2, fuel_duration_23; float fuel_duration_fuel_1_hold, fuel_duration_fuel_2_hold, fuel_duration_23_hold, fuel_duration_23_hold_pw; float PHI_desired, phi_slope, phi_intercept, MAF_adc, MAF; float inj_flow, max_fuel_recip, cylinders_recip; float O2_adc_AF, O2_adc_phi, O2_closed_loop, AF_Stoich, FA_Stoich; float pw_ctrl_intital, pw_ctrl; float octane_multiplier, octane_slope, octane_intercept; //#########################################

#int_TIMER2 TIMER2_isr() { time_1++; time_2++; // time_3++; time_4++;

if ((input(FUEL_ENABLE_PIN) == TRUE) && (rev_length_14 <= rev_length_max)) { if (time_2 == fueltime) output_high(OUTPIN_FUEL_1); else if (time_2 == stoptime_fuel_1) output_low(OUTPIN_FUEL_1);

if (time_2 == fueltime) output_high(OUTPIN_FUEL_2); else if (time_2 == stoptime_fuel_2) output_low(OUTPIN_FUEL_2); } else { output_low(OUTPIN_FUEL_1);

168

output_low(OUTPIN_FUEL_2); }

if (time_1 >= time_buffer){ //reset time if engine is not spinning so that buffer does not overflow. time_1 = time_buffer; time_2 = time_buffer; time_4 = time_buffer; rev_length_14 = time_buffer; cycle_length_23 = time_buffer; cam_located = FALSE; }

} //End of Timer Interrupt *****************************************************

//Pin RB0 (#33) Pulse interrupt 0 //crankshaft location pulse******************************************************* #int_EXT EXT_isr() { // locate spark pulse with VR sensor3. if ((cam_flag) || (cam_located && (encoder_count == 70))){ encoder_count = 0; cam_located = TRUE; }

output_toggle(OUTPIN_VR); } //End of crankshaft position pulse interrupt**************************************

//Pin RB1 (#34) Pulse interrupt 1 //hall effect speed sensor timing pulse**************************************************** #int_EXT1 EXT1_isr() { //increment speed sensor count for each indicator encoder_count++;

if (encoder_count == 1) { output_low(OUTPIN_FUEL_1); output_low(OUTPIN_FUEL_2);

169

stoptime_fuel_1 = stoptime_fuel_1_new; //recieve new times stoptime_fuel_2 = stoptime_fuel_2_new; //recieve new times rev_length_14 = time_1; time_2 = 0; cam_flag = FALSE; }

if (encoder_count == 36) { time_1 = 0; }

if (encoder_count == 54) { cycle_length_23 = time_4; time_4 = 0; }

output_toggle(OUTPIN_ENCODER); } //End of hall effect speed sensor timing pulse interrupt***********************************

//Pin RB2 (#35) Cam interrupt //cam location pulse******************************************************* #int_EXT2 EXT2_isr() { if (cam_located == FALSE) cam_flag = TRUE; } //End of cam position pulse interrupt************************************** void main() { setup_adc_ports(A_ANALOG); setup_adc(ADC_CLOCK_DIV_64); setup_psp(PSP_DISABLED); setup_spi(SPI_SS_DISABLED); setup_wdt(WDT_OFF); setup_timer_0(RTCC_INTERNAL); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DIV_BY_1,249,1); //Time is in 20 microsecond increments ->(200*4/40000000)*1=0.0000200. Setting timer less than 159 is unstable.

170 setup_timer_3(T3_DISABLED|T3_DIV_BY_1); setup_ccp1(CCP_OFF); setup_ccp2(CCP_OFF); disable_interrupts(INT_TIMER2); //Block interrupts momentarily disable_interrupts(INT_EXT); disable_interrupts(INT_EXT1); disable_interrupts(INT_EXT2); disable_interrupts(GLOBAL); //Disable Global interrupt ext_int_edge(L_TO_H); //Look for positive edges on interrupt 0 ext_int_edge(1,L_TO_H); //Look for positive edges on interrupt 1 ext_int_edge(2,L_TO_H); //Look for negative edges on interrupt 2

//Initialize variables******************************************************* time_1 = time_buffer; time_2 = time_buffer; time_4 = time_buffer; encoder_count = 0; cam_flag = FALSE; cam_located = FALSE; pw_hold_flag = FALSE;

MAF_adc_1 = 0; MAF_adc_2 = 0; MAF_adc_3 = 0; MAF_adc_4 = 0; rev_length_14 = time_buffer; cycle_length_23 = time_buffer; //Default to a high cycle time phi_slope = (phi_max - phi_min) / 1023.0; phi_intercept = phi_min; set_adc_channel(phi_channel); delay_us(100); PHI_ADC_RAW = read_adc(); PHI_desired = PHI_ADC_RAW * phi_slope + phi_intercept; pw_ctrl = read_adc() * pw_slope + pw_intercept; inj_flow = inj_flow_hr / 60.0; //convert from lb/hr to lb/min

171 max_fuel_recip = 1.0 / (inj_flow * cylinders); octane_slope = (octane_max - octane_min) / 1024.0; octane_intercept = octane_min; set_adc_channel(octane_channel); delay_us(100); octane_multiplier = (octane_slope * read_adc() + octane_intercept) * 0.01;

AF_Stoich = AF_Stoich_Fuel_1 * octane_multiplier + AF_Stoich_Fuel_2 * (1.0 - octane_multiplier); set_adc_channel(O2_Sensor_channel); delay_us(100); O2_ADC_RAW = read_adc(); O2_adc_AF = O2_ADC_RAW * O2_adc_AF_slope + O2_adc_AF_int; O2_adc_phi = AF_Stoich / O2_adc_AF; O2_closed_loop = PHI_desired;

FA_Stoich = 1.0 / AF_Stoich;

MAF_adc = (MAF_adc_1 + MAF_adc_2 + MAF_adc_3 + MAF_adc_4) * 0.25; MAF = MAF_a0 + MAF_a1*MAF_adc + MAF_a2*MAF_adc*MAF_adc + MAF_a3*MAF_adc*MAF_adc*MAF_adc; fuel_duration_23 = (cycle_length_23 * MAF * FA_Stoich * max_fuel_recip * O2_closed_loop); fuel_duration_fuel_1 = fuel_duration_23 * octane_multiplier; if (fuel_duration_fuel_1 < 2) fuel_duration_fuel_1 = 2; stoptime_fuel_1_new = fueltime + fuel_duration_fuel_1; stoptime_fuel_1 = stoptime_fuel_1_new; output_low(OUTPIN_FUEL_1); fuel_duration_fuel_2 = fuel_duration_23 * (1.0 - octane_multiplier); if (fuel_duration_fuel_2 < 2) fuel_duration_fuel_2 = 2; stoptime_fuel_2_new = fueltime + fuel_duration_fuel_2; stoptime_fuel_2 = stoptime_fuel_2_new; output_low(OUTPIN_FUEL_2); output_low(OUTPIN_VR);

172 output_low(OUTPIN_ENCODER);

//End initialize variables*************************************************** enable_interrupts(GLOBAL); //Enable Global interrupt enable_interrupts(INT_EXT); //Begin watching crankshaft timing pulse enable_interrupts(INT_EXT1); //Begin watching 25 tooth gear timing pulse enable_interrupts(INT_EXT2); //Begin watching cam sensor pulse enable_interrupts(INT_TIMER2); //Enable timing while (1){

set_adc_channel(phi_channel); delay_us(100); PHI_ADC_RAW = read_adc(); PHI_desired = PHI_ADC_RAW * phi_slope + phi_intercept;

//O2_closed_loop = 1; ////////TAKE THIS OUT FOR REAL PROGRAMMMMMMMMMMMMMMMM

set_adc_channel(MAF_channel); delay_us(100);

while (encoder_count != 1) {} MAF_adc_1 = read_adc();

while (encoder_count != 10) {} MAF_adc_2 = read_adc();

if (input(PW_HOLD_PIN) == TRUE) { if (pw_hold_flag == FALSE) { fuel_duration_23_hold_pw = fuel_duration_23; set_adc_channel(phi_channel); delay_us(100); pw_ctrl_intital = read_adc(); pw_hold_flag = TRUE; }

set_adc_channel(phi_channel); delay_us(100); pw_ctrl = read_adc() - pw_ctrl_intital;

173

fuel_duration_23_hold = fuel_duration_23_hold_pw + pw_ctrl;

if (fuel_duration_23_hold < 2 ) fuel_duration_23_hold = 2;

set_adc_channel(octane_channel); delay_us(100); octane_multiplier = (octane_slope * read_adc() + octane_intercept) * 0.01;

fuel_duration_fuel_1_hold = fuel_duration_23_hold * octane_multiplier; if (fuel_duration_fuel_1_hold < 2) fuel_duration_fuel_1_hold = 2; stoptime_fuel_1_new = fueltime + fuel_duration_fuel_1_hold;

fuel_duration_fuel_2_hold = fuel_duration_23_hold * (1.0 - octane_multiplier); if (fuel_duration_fuel_2_hold < 2) fuel_duration_fuel_2_hold = 2; stoptime_fuel_2_new = fueltime + fuel_duration_fuel_2_hold;

stoptime_fuel_1_new = fueltime + fuel_duration_fuel_1_hold; stoptime_fuel_2_new = fueltime + fuel_duration_fuel_2_hold; } else { pw_hold_flag = FALSE;

if ((input(FUEL_ENABLE_PIN) == TRUE) && (rev_length_14 <= O2_speed_min)){ set_adc_channel(O2_Sensor_channel); O2_ADC_RAW = read_adc(); O2_adc_AF = O2_ADC_RAW * O2_adc_AF_slope + O2_adc_AF_int; O2_adc_phi = AF_Stoich / O2_adc_AF; if (O2_adc_phi >= PHI_desired) O2_closed_loop -= O2_closed_loop_step; else if (O2_adc_phi < PHI_desired) O2_closed_loop += O2_closed_loop_step; if (O2_closed_loop <= O2_closed_loop_min) O2_closed_loop = O2_closed_loop_min; else if (O2_closed_loop >= O2_closed_loop_max) O2_closed_loop = O2_closed_loop_max; } else (O2_closed_loop = PHI_desired);

// O2_closed_loop = 1; ////////TAKE THIS OUT FOR REAL PROGRAMMMMMMMMMMMMMMMM

set_adc_channel(MAF_channel); delay_us(100);

174

while (encoder_count != 36) {} MAF_adc_3 = read_adc();

while (encoder_count != 45) {} MAF_adc_4 = read_adc();

MAF_adc = (MAF_adc_1 + MAF_adc_2 + MAF_adc_3 + MAF_adc_4) * 0.25; MAF = MAF_a0 + MAF_a1*MAF_adc + MAF_a2*MAF_adc*MAF_adc + MAF_a3*MAF_adc*MAF_adc*MAF_adc;

fuel_duration_23 = (cycle_length_23 * MAF * FA_Stoich * max_fuel_recip * O2_closed_loop);

set_adc_channel(octane_channel); delay_us(100); octane_multiplier = (octane_slope * read_adc() + octane_intercept) * 0.01;

fuel_duration_fuel_1 = fuel_duration_23 * octane_multiplier; if (fuel_duration_fuel_1 < 2) fuel_duration_fuel_1 = 2; stoptime_fuel_1_new = fueltime + fuel_duration_fuel_1;

fuel_duration_fuel_2 = fuel_duration_23 * (1.0 - octane_multiplier); if (fuel_duration_fuel_2 < 2) fuel_duration_fuel_2 = 2; stoptime_fuel_2_new = fueltime + fuel_duration_fuel_2; } } }

175

18. APPENDIX G – PIC32 ECU IGNITION CONTROL PROGRAM

/*/////////////////////////////Change Log////////////////////////////////////////// //2012-03-07: Changed 36-1 Encoder to trigger on falling edge instead of rising./// //2012-04-12: Added Charge time parameter to control AEM coils w/ 3ms pulse./////// //2012-05-21: Added seperate spark 3,4,& tj. Doesn't exactly work well.//////////// *//////////////////////////////////////////////////////////////////////////////////

//Configuration Bit Settings #include #include

/*setup clock, starts with internal starter kit 8MHz clock and divides by two, then multiplies by 20 through PLL circuit, then post division of 1 yields 80MHz clock the input to the pll circuit must be less than of equal to 4Mhz*/ #pragma config POSCMOD = HS, FNOSC = PRIPLL #pragma config FPLLIDIV = DIV_2, FPLLMUL = MUL_20, FPLLODIV = DIV_1

/*setup peripheral bus clock with divisor to allow clock cycles between commands (divide by 2), turn off watch dog tiimer, turn off code protection, boot flash drive write protect turn off final clock speed 40MHz*/ #pragma config FPBDIV = DIV_2, FWDTEN = OFF, CP = OFF, BWP =OFF, DEBUG = OFF

////////////////////Setup variables/////////////////////////////////// #define FALSE 0 #define TRUE !FALSE

#define OUTPIN_D0 0x0001 // pin RD0 #define OUTPIN_D1 0x0002 // pin RD1 #define OUTPIN_SPARK_1 0x0004 // pin RD2 #define OUTPIN_SPARK_2 0x0008 // pin RD3 #define OUTPIN_SPARK_3 0x00010 // pin RD4 #define OUTPIN_SPARK_4 0x00020 // pin RD5 #define OUTPIN_SPARK_2_tj 0x00040 // pin RD6 #define OUTPIN_VR 0x0080 // pin RD7 #define OUTPIN_ENCODER 0x0100 // pin RD8

#define SPARK_ENABLE PORTDbits.RD9 // pin RD9

#define rev_length_buffer 500000 //This MUST BE 6X LARGER THAN rev_length_max!!! #define rev_length_max 26400 //200 rpm low speed limit 60/200=0.3 0.3/.000002 = roughly 25000 //This is the time for 60 degrees of crank angle, not a complete revolution... #define spark_angle_channel_1 0 #define spark_angle_channel_2 1 #define tj_cycles_channel 2

#define spark_angle_min -50.0 //Spark angle in degrees ATDC at 0V. So spark will be #define spark_angle_max 10.0 //Spark angle in degrees ATDC at 5V.

176

#define spark_duration 1500 //Pulsewidth for signal high to charge coil. 3ms = 0.003 /0.000015 int spark_enable, time, time2, encoder_count, start_flag, tj_spark, tj_cycles, tj_counts; int time_pulse_19, time_pulse_25, time_pulse_1, time_pulse_7; int sparktime_12, sparktime_2_tj, sparktime_34; int rev_length_12_updated, rev_length_34_updated; int chargetime_12, chargetime_2_tj, chargetime_34; float rev_length_12, rev_length_34; float spark_angle_slope;

////////////////////////READ ADC FUNCTION////////////////////////////////// int readADC(int ch) { AD1CHSbits.CH0SA = ch; // select channel AD1CON1bits.SAMP = 1; // begin sampling while (!AD1CON1bits.DONE); // wait to complete conversion return ADC1BUF0; // read the conversion result }

///////////////////TIMER 1 ISR//////////////////////////////////////// void __ISR(_TIMER_1_VECTOR,ipl7) T1_Interrupt_ISR(void) { time++;

if ((rev_length_12 <= rev_length_max) && (SPARK_ENABLE)){ if (time == chargetime_12) { PORTDSET = OUTPIN_SPARK_1; } if (time == sparktime_12) { PORTDCLR = OUTPIN_SPARK_1; } if (tj_spark) { if (time == chargetime_2_tj) { PORTDSET = OUTPIN_SPARK_2_tj; } if (time == sparktime_2_tj) { PORTDCLR = OUTPIN_SPARK_2_tj; } PORTDCLR = OUTPIN_SPARK_2;

177

} else { if (time == chargetime_12) { PORTDSET = OUTPIN_SPARK_2; } if (time == sparktime_12) { PORTDCLR = OUTPIN_SPARK_2; PORTDCLR = OUTPIN_SPARK_2_tj; } } if (time == chargetime_34) { PORTDSET = OUTPIN_SPARK_3; PORTDSET = OUTPIN_SPARK_4; } if (time == sparktime_34) { PORTDCLR = OUTPIN_SPARK_3; PORTDCLR = OUTPIN_SPARK_4; } } else{ PORTDCLR = OUTPIN_SPARK_1; PORTDCLR = OUTPIN_SPARK_2; PORTDCLR = OUTPIN_SPARK_3; PORTDCLR = OUTPIN_SPARK_4; PORTDCLR = OUTPIN_SPARK_2_tj; }

if (time >= rev_length_buffer){ //reset time if engine is not spinning so that buffer does not overflow. time = 0; start_flag = 0; rev_length_12 = rev_length_buffer; rev_length_34 = rev_length_buffer; }

mT1ClearIntFlag(); //exit TMR1 ISR } // TMR1 ISR

///////////////////TIMER 2 ISR//////////////////////////////////////// void __ISR(_TIMER_2_VECTOR,ipl1) T2_Interrupt_ISR(void) {

178

time2++; if (time2 >= 20) { time2 = 0; PORTDINV = OUTPIN_D0; PORTDINV = OUTPIN_D1; }

mT2ClearIntFlag(); //exit TMR2 ISR } // TMR2 ISR

//////////////////EXTERNAL 0 ISR/////////////////////////////////////// void __ISR(_EXTERNAL_0_VECTOR, ipl3) INT0_Interrupt_ISR(void) { PORTDINV = OUTPIN_VR;

// locate spark pulse with speed indicator if (start_flag == 0){ start_flag = 1; encoder_count = 0; } else if ((start_flag == 1) && (encoder_count >= 35)) { encoder_count = 0; } mINT0ClearIntFlag(); // exit EXT0 ISR } // Ext0 ISR

//////////////////EXTERNAL 1 ISR/////////////////////////////////////// void __ISR(_EXTERNAL_1_VECTOR, ipl6) INT1_Interrupt_ISR(void) { PORTDINV = OUTPIN_ENCODER; //increment speed sensor count for each indicator encoder_count++; //measure time between 19th and 25th pulse (6 pulses) on 36 position indicator if (encoder_count == 19) { time_pulse_19 = time; } //wait until speed sensor's 25th pulse and update rev_length to calc new fire time if (encoder_count == 25) { time_pulse_25 = time; time = 0;

179

TMR1 = 0x0; rev_length_12_updated = TRUE; } //measure time between 1st and 7th pulse (6 pulses) on 36 position indicator if (encoder_count == 1) { time_pulse_1 = time; } //wait until speed sensor's 7th pulse and update rev_length to calc new fire time if (encoder_count == 7) { time_pulse_7 = time; rev_length_34_updated = TRUE; } mINT1ClearIntFlag(); // exit EXT1 ISR } // Ext1 ISR

//////////////////EXTERNAL 2 ISR/////////////////////////////////////// void __ISR(_EXTERNAL_2_VECTOR, ipl2) INT2_Interrupt_ISR(void) { tj_spark = TRUE; tj_counts = 0;

mINT2ClearIntFlag(); // exit EXT2 ISR } // Ext1 ISR main() { SYSTEMConfigPerformance(800000000L);

/////////////////////////EXTERNNAL INT SETUP////////////////////////////// INTCON = 0x0000; // clear inturrupt control register INTCONbits.INT0EP = 1; //Interrupt 0 Edge Polarity Control bit. 1 = Rising edge. 0 = Falling edge. INTCONbits.INT1EP = 0; //Interrupt 1 Edge Polarity Control bit. 1 = Rising edge. 0 = Falling edge. INTCONbits.INT2EP = 1; //Interrupt 2 Edge Polarity Control bit. 1 = Rising edge. 0 = Falling edge. mINT0SetIntPriority(3); // set EXT0 priority mINT1SetIntPriority(6); // set EXT1 priority ////DONT DECLARE PRIORITIES OF INTERRUPTS THAT ARE NOT ACTIVE!!! mINT2SetIntPriority(2); // set EXT2 priority

////////////////////////////TIMER 1 SETUP////////////////////////////////// PR1 = 0x0025; // Set period register (16 bit). Number of cycles between interrupts (PR1*timestep=time elapsed) 120 0.025 = 3.0 microseconds (333 kHz) 60 is as fast as is stable.

180

T1CON = 0x8000; // TMR1 on, prescale 1:1, time step equals 0.025 microseconds (40 MHz) mT1SetIntPriority(7);//set T1 priority level 7 ????

////////////////////////////TIMER 2 SETUP////////////////////////////////// PR2 = 65535; // Set period register (16 bit). Number of cycles between interrup T2CON = 0x8030; // TMR2 on, prescale 1:256, time step equals 0.20 microseconds mT2SetIntPriority(1);//set T2 priority level 1

//////////////////////////////ADC SETUP//////////////////////////////////// TRISB = 0x0007; //set AN0(RB0) & AN1(RB1) as input, ohers outputs (0=output, 1=input) AD1PCFG = 0xFFF8; // set AN0(RB0) & AN1(RB1)to analog, others digital (0=analog, 1=digital) AD1CON1 = 0x00E0; // set converter to automatically begin following sampling AD1CSSL = 0; // no scanning AD1CON2 = 0; // uses MUXA references, AVdd & AVss as Vref +/- AD1CON3 = 0x0707; // use peripheral bus clock, ADCS = 7, SAMC = 7 AD1CON1bits.ADON = 1; // turn on ADC converter

//////////////////////OUTPUT SETUP///////////////////////////////////////// TRISD = 0x0200;// set PORTD RD9 as input, others as outputs (0=output, 1=input). PORTD = 0x0000;//ensure all of PORTD are off

////////////////////////Initialize variables/////////////////////////////// time = 0; time2 = 0; encoder_count = 0; start_flag = 0; time_pulse_19 = 0; time_pulse_25 = rev_length_max; time_pulse_1 = 0; time_pulse_7 = rev_length_max; tj_spark = FALSE; tj_counts = 0; rev_length_12 = time_pulse_25 - time_pulse_19; //Default to a high cycle time rev_length_34 = time_pulse_7 - time_pulse_1; spark_angle_slope = 0.0009775171; sparktime_12 = rev_length_12 + (rev_length_12 * spark_angle_slope * readADC(spark_angle_channel_1));

181

if (sparktime_12 < spark_duration) { chargetime_12 = sparktime_12 - spark_duration + time_pulse_25; } else if (sparktime_12 > spark_duration) { chargetime_12 = sparktime_12 - spark_duration; } else if (sparktime_12 == spark_duration) { chargetime_12 = 2; } sparktime_2_tj = rev_length_12 + (rev_length_12 * spark_angle_slope * readADC(spark_angle_channel_2)); if (sparktime_2_tj < spark_duration) { chargetime_2_tj = sparktime_2_tj - spark_duration + time_pulse_25; } else if (sparktime_2_tj > spark_duration) { chargetime_2_tj = sparktime_2_tj - spark_duration; } else if (sparktime_2_tj == spark_duration) { chargetime_2_tj = 2; } PORTDCLR = OUTPIN_SPARK_1; PORTDCLR = OUTPIN_SPARK_2; PORTDCLR = OUTPIN_SPARK_2_tj; rev_length_12_updated = FALSE;

sparktime_34 = rev_length_34 + time_pulse_7 + (rev_length_34 * spark_angle_slope * readADC(spark_angle_channel_1)); chargetime_34 = sparktime_34 - spark_duration; PORTDCLR = OUTPIN_SPARK_3; PORTDCLR = OUTPIN_SPARK_4; rev_length_34_updated = FALSE;

PORTDSET = OUTPIN_D0; PORTDCLR = OUTPIN_D1; PORTDCLR = OUTPIN_VR; PORTDCLR = OUTPIN_ENCODER;

///////////////////ENABLE INTERRUPTS/////////////////////////////////////// INTEnableSystemMultiVectoredInt(); // enable multiple interrupts INTEnableInterrupts(); // enable global interrupts mINT0IntEnable(1); // enable EXT0 interrupt

182

mINT1IntEnable(1); // enable EXT1 interrupt mINT2IntEnable(1); // enable EXT2 interrupt mT1IntEnable(1); // enable timer 1 interrupt mT2IntEnable(1); // enable timer 2 interrupt

PORTDCLR = OUTPIN_SPARK_1; PORTDCLR = OUTPIN_SPARK_2; PORTDCLR = OUTPIN_SPARK_2_tj; PORTDCLR = OUTPIN_SPARK_3; PORTDCLR = OUTPIN_SPARK_4;

///////////////////////////////OPERATIONAL LOOP//////////////////////////// while(TRUE) { while ((encoder_count != 25) && (rev_length_12_updated == FALSE)) {} //wait until speed sensor's 27th pulse and update rev_length to calc new fire time rev_length_12 = time_pulse_25 - time_pulse_19;

sparktime_12 = rev_length_12 + (rev_length_12 * spark_angle_slope * readADC(spark_angle_channel_1)); if (sparktime_12 < spark_duration) { chargetime_12 = sparktime_12 - spark_duration + time_pulse_25; } else if (sparktime_12 > spark_duration) { chargetime_12 = sparktime_12 - spark_duration; } else if (sparktime_12 == spark_duration) { chargetime_12 = 2; }

tj_cycles = readADC(tj_cycles_channel) * 0.1; if (tj_cycles < 1) { tj_cycles = 1; }

if (tj_spark) { tj_counts++; if (tj_counts == tj_cycles) { tj_spark = FALSE; } sparktime_2_tj = rev_length_12 + (rev_length_12 * spark_angle_slope * readADC(spark_angle_channel_2));

183

if (sparktime_2_tj < spark_duration) { chargetime_2_tj = sparktime_2_tj - spark_duration + time_pulse_25; } else if (sparktime_2_tj > spark_duration) { chargetime_2_tj = sparktime_2_tj - spark_duration; } else if (sparktime_2_tj == spark_duration) { chargetime_2_tj = 2; } } rev_length_12_updated = FALSE;

while ((encoder_count != 7) && (rev_length_34_updated == FALSE)) {} //wait until speed sensor's 9th pulse and update rev_length to calc new fire time rev_length_34 = time_pulse_7 - time_pulse_1; sparktime_34 = time_pulse_7 + rev_length_34 + (rev_length_34 * spark_angle_slope * readADC(spark_angle_channel_1)); chargetime_34 = sparktime_34 - spark_duration; rev_length_34_updated = FALSE; } // end while } //end main

184

19. APPENDIX H – XMOS XCORE IGNITION AND INJECTION CONTROL PROGRAM

//This version expands upon the single spark/injector (with specified pw) //to include 4 (or 8) spark outputs.

#include #include #include "uart_rx.h" #include "uart_tx.h" #include #include #include

#define BAUD_RATE 115200 //baud rate for RS232 connection

#define BEI_COUNTS_MAX 7200 //number of rising edges in 1 engine cycle 720 deg x 10 pulses/deg #define BEI_COUNT_PERIOD 1800 //number of encoder pulses to count before calculating speed. 180 deg x 10 pulses/deg

#define REV_PERIOD_MAX_DEFAULT 24000 //lower rev limit at 250 RPM #define REV_PERIOD_MIN_DEFAULT 920 //upper rev limit at 6500 RPM

#define COM_TIME_MULT 100 //all time inputs/variables are multiplied by 100 before calculations so that they are all in units of us

#define SPARK_DUR_DEFAULT 3000 //AEM coil charge time 3ms recommended #define SPARK_ANG_DEFAULT 260 //26 deg btc x 10 pulses/deg

#define FUEL_DUR_DEFAULT 1 //default fuel pulse width of 1us to show connectivity but not open injector #define FUEL_ANG_DEFAULT 2700 //default end of injection 270 deg btc * 10 pulses/deg (during intake stroke)

#define FUEL_CALC_ANG 600 //begin fuel calculations at 60 deg btc (x pulses/deg) for next cycle #define SPARK_CALC_ANG 1500 //begin spark calculations at 150 deg btc (x pulses/deg) for current cycle

#define spark_1_fire_pointer 1 #define spark_2_fire_pointer 2 #define spark_3_fire_pointer 3 #define spark_4_fire_pointer 4 #define spark_5_fire_pointer 5 #define spark_6_fire_pointer 6 #define spark_7_fire_pointer 7

185

#define spark_8_fire_pointer 8 #define spark_1_charge_pointer 9 #define spark_2_charge_pointer 10 #define spark_3_charge_pointer 11 #define spark_4_charge_pointer 12 #define spark_5_charge_pointer 13 #define spark_6_charge_pointer 14 #define spark_7_charge_pointer 15 #define spark_8_charge_pointer 16

#define spark_1_ang_in_pointer 1 #define spark_2_ang_in_pointer 2 #define spark_3_ang_in_pointer 3 #define spark_4_ang_in_pointer 4 #define spark_5_ang_in_pointer 5 #define spark_6_ang_in_pointer 6 #define spark_7_ang_in_pointer 7 #define spark_8_ang_in_pointer 8 #define spark_1_dur_pointer 9 #define spark_2_dur_pointer 10 #define spark_3_dur_pointer 11 #define spark_4_dur_pointer 12 #define spark_5_dur_pointer 13 #define spark_6_dur_pointer 14 #define spark_7_dur_pointer 15 #define spark_8_dur_pointer 16 #define spark_tdc_ang_in_pointer 17

#define fuel_1_start_pointer 1 #define fuel_2_start_pointer 2 #define fuel_3_start_pointer 3 #define fuel_4_start_pointer 4 #define fuel_5_start_pointer 5 #define fuel_6_start_pointer 6 #define fuel_7_start_pointer 7 #define fuel_8_start_pointer 8 #define fuel_1_stop_pointer 9 #define fuel_2_stop_pointer 10 #define fuel_3_stop_pointer 11 #define fuel_4_stop_pointer 12

186

#define fuel_5_stop_pointer 13 #define fuel_6_stop_pointer 14 #define fuel_7_stop_pointer 15 #define fuel_8_stop_pointer 16

#define spark_1_calc_trig_pointer 1 #define spark_2_calc_trig_pointer 2 #define spark_3_calc_trig_pointer 3 #define spark_4_calc_trig_pointer 4 #define spark_5_calc_trig_pointer 5 #define spark_6_calc_trig_pointer 6 #define spark_7_calc_trig_pointer 7 #define spark_8_calc_trig_pointer 8

#define fuel_1_calc_trig_pointer 1 #define fuel_2_calc_trig_pointer 2 #define fuel_3_calc_trig_pointer 3 #define fuel_4_calc_trig_pointer 4 #define fuel_5_calc_trig_pointer 5 #define fuel_6_calc_trig_pointer 6 #define fuel_7_calc_trig_pointer 7 #define fuel_8_calc_trig_pointer 8

#define fuel_1_ang_in_pointer 1 #define fuel_2_ang_in_pointer 2 #define fuel_3_ang_in_pointer 3 #define fuel_4_ang_in_pointer 4 #define fuel_5_ang_in_pointer 5 #define fuel_6_ang_in_pointer 6 #define fuel_7_ang_in_pointer 7 #define fuel_8_ang_in_pointer 8 #define fuel_1_dur_pointer 9 #define fuel_2_dur_pointer 10 #define fuel_3_dur_pointer 11 #define fuel_4_dur_pointer 12 #define fuel_5_dur_pointer 13 #define fuel_6_dur_pointer 14 #define fuel_7_dur_pointer 15 #define fuel_8_dur_pointer 16 #define fuel_tdc_ang_in_pointer 17

187

#define fuel_2_frac_pointer 18

#define spark_1_bit 0b0001 // spark 1 output #define spark_2_bit 0b0010 // spark 2 output #define spark_3_bit 0b0100 // spark 3 output #define spark_4_bit 0b1000 // spark 4 output #define spark_5_bit 0b0001 // spark 5 output #define spark_6_bit 0b0010 // spark 6 output #define spark_7_bit 0b0100 // spark 7 output #define spark_8_bit 0b1000 // spark 8 output #define fuel_1_bit 0b0001 // fuel 1 output #define fuel_2_bit 0b0010 // fuel 2 output #define fuel_3_bit 0b0100 // fuel 3 output #define fuel_4_bit 0b1000 // fuel 4 output #define fuel_5_bit 0b0001 // fuel 5 output #define fuel_6_bit 0b0010 // fuel 6 output #define fuel_7_bit 0b0100 // fuel 7 output #define fuel_8_bit 0b1000 // fuel 8 output int bei_counts_tdc_1 = BEI_COUNTS_MAX; int bei_counts_tdc_2 = BEI_COUNTS_MAX / 2; int bei_counts_tdc_3 = 3 * BEI_COUNTS_MAX / 4; int bei_counts_tdc_4 = BEI_COUNTS_MAX / 4;

//port declarations on stdcore[0] : in port adc_1_ready = XS1_PORT_1P; //ADC 1 conversion ready in on stdcore[0] : in port adc_2_ready = XS1_PORT_1O; //ADC 2 conversion ready in on stdcore[0] : buffered in port:1 p_rx = XS1_PORT_1I; //RS232 in on stdcore[0] : out port p_tx = XS1_PORT_1K; //RS232 out on stdcore[0] : struct r_i2c i2cOne = { //setup i2c clock port, data port, and frequency XS1_PORT_1L, XS1_PORT_1J, 100 //100 x 0.1 ns = 100kHz //can use 25 x 0.1 ns = 400kHz if neccesary }; on stdcore[1] : in port tdc_in = XS1_PORT_1A; //TDC signal in on stdcore[1] : in port bei_in = XS1_PORT_1E; //BEI signal in on stdcore[1] : in port cam_in = XS1_PORT_1D; //CAM signal in on stdcore[1] : in port port_1h_in = XS1_PORT_1H; //INPUT I signal 4 in on stdcore[1] : in port port_1k_in = XS1_PORT_1K; //INPUT I signal 5 in

188 on stdcore[1] : in port port_1j_in = XS1_PORT_1J; //INPUT I signal 6 in on stdcore[1] : in port port_1m_in = XS1_PORT_1M; //INPUT I signal 7 in on stdcore[1] : in port port_1n_in = XS1_PORT_1N; //INPUT I signal 8 in on stdcore[1] : in port port_1i_in = XS1_PORT_1I; //INPUT II signal 1 in on stdcore[1] : in port port_1o_in = XS1_PORT_1O; //INPUT II signal 2 in on stdcore[1] : in port port_1p_in = XS1_PORT_1P; //INPUT II signal 3 in on stdcore[1] : in port port_1l_in = XS1_PORT_1L; //INPUT II signal 4 in on stdcore[1] : out port port_4e_out = XS1_PORT_4E; //OUTPUT signal 1-4 out on stdcore[1] : out port port_4f_out = XS1_PORT_4F; //OUTPUT signal 5-8 out on stdcore[1] : out port port_4a_out = XS1_PORT_4A; //SPARK 1-4 out on stdcore[1] : out port port_4b_out = XS1_PORT_4B; //SPARK 5-8 out on stdcore[1] : out port port_4c_out = XS1_PORT_4C; //FUEL 1-4 out on stdcore[1] : out port port_4d_out = XS1_PORT_4D; //FUEL 5-8 out on stdcore[1] : out port tdc_out = XS1_PORT_1C; //ODB II TDC signal out on stdcore[1] : out port bei_out = XS1_PORT_1G; //ODB II BEI signal out on stdcore[1] : out port cam_out = XS1_PORT_1B; //ODB II CAM signal out on stdcore[1] : out port port_1f_out = XS1_PORT_1F; //ODB II signal 4 out

//global variables #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) unsigned char tx_buffer[64]; unsigned char rx_buffer[64]; #pragma unsafe arrays int atoi(char cmd_rcvbuffer[]); //funtion prototype for string to integer function

/** ======* uart transmit string * * transmits byte by byte to the UART TX thread for an input string * **/ void uart_tx_string(chanend c_uartTX,unsigned char message[100]) //transmit string on Uart TX terminal {

189

int i=0; while(message[i]!='\0') { uart_tx_send_byte(c_uartTX,message[i]); //send data to uart byte by byte i++; } }

/** ======* *respond to TDC and cam pulses * **/ void tdc_cam_thread(in port tdc_in, out port port_4e_out, out port port_4f_out, out port tdc_out, in port cam_in, out port cam_out, streaming chanend tdc_trigger_chan, streaming chanend fuel_enable_chan, streaming chanend spark_enable_chan, streaming chanend fuel_enable_master_chan, streaming chanend spark_enable_master_chan, streaming chanend cam_flag_chan){

timer t2; //timer has a period of 10ns or 0.00000001s. frequency of 100MHz. int x = 0; int y = 0; unsigned timer_2_increment; unsigned rev_period_max = REV_PERIOD_MAX_DEFAULT; //lower rev limit unsigned rev_period_min = REV_PERIOD_MIN_DEFAULT; //upper rev limit unsigned rev_period_counter_max = rev_period_max * 2; //set counter max to 2x lower rev limit unsigned rev_period_counter = rev_period_counter_max; unsigned rev_period = rev_period_counter_max; unsigned fuel_enable_flag = 0; unsigned spark_enable_flag = 0; unsigned fuel_enable_master_flag = 0; unsigned spark_enable_master_flag = 0;

#define TIMER_2_DELAY 1000 //sets timer 2 to fire @ (100MHz / 1000) = 100 kHz or 10us

t2 :> timer_2_increment; //read timer 2 into increment variable timer_2_increment += TIMER_2_DELAY; //increment timer 2 increment variable by timer 2 delay

tdc_in :> x; //read tdc_in value in order to sync tdc_out w/ tdc_in tdc_out <: x; //set tdc_out to x

190

cam_in :> y; //read cam_in value in order to sync cam_out w/ cam_in cam_out <: y; //set cam_out to y

port_4e_out <: 0b1111; port_4f_out <: 0b1111;

while (1) { select{ case tdc_in when pinsneq(x) :> x: //when tdc_in pin is no longer equal to its old value, read new value into x tdc_out <: x; //set tdc_out to x if (x == 1) { tdc_trigger_chan <: x; rev_period = rev_period_counter; rev_period_counter = 0;

if ((rev_period <= rev_period_max)&&(rev_period >= rev_period_min)&&fuel_enable_flag&&! fuel_enable_master_flag) { fuel_enable_master_flag = 1; fuel_enable_master_chan <: fuel_enable_master_flag; } else if (((rev_period >= rev_period_max)||(rev_period <= rev_period_min)||!fuel_enable_flag)&& fuel_enable_master_flag) { fuel_enable_master_flag = 0; fuel_enable_master_chan <: fuel_enable_master_flag; }

if ((rev_period <= rev_period_max)&&(rev_period >= rev_period_min)&&spark_enable_flag&&! spark_enable_master_flag) { spark_enable_master_flag = 1; spark_enable_master_chan <: spark_enable_master_flag; } else if (((rev_period >= rev_period_max)||(rev_period <= rev_period_min)||!spark_enable_flag)&& spark_enable_master_flag) { spark_enable_master_flag = 0;

191

spark_enable_master_chan <: spark_enable_master_flag; } } break;

case cam_in when pinsneq(y) :> y: //when cam_in pin is no longer equal to its old value, read new value into y cam_out <: y; //set cam_out to y if (y == 1){ cam_flag_chan <: y; //update cam flag chan if y is equal to 1 } break;

case fuel_enable_chan :> fuel_enable_flag: //if fuel enable channel changes, read it into fuel enable flag break;

case spark_enable_chan :> spark_enable_flag: //if spark enable channel changes, read it into spark enable flag break;

//when timer 2 has incremented by timer 2 delay, read in new timer 2 increment variable case t2 when timerafter (timer_2_increment + TIMER_2_DELAY) :> timer_2_increment: rev_period_counter++;

if(rev_period_counter > rev_period_counter_max) { rev_period_counter = rev_period_counter_max; rev_period = rev_period_counter_max; } break; } } }

/** ======* *respond to BEI Encoder and fire outputs * **/

192 void bei_thread(in port bei_in, out port bei_out, out port port_4a_out, out port port_4b_out, out port port_4c_out, out port port_4d_out, streaming chanend fuel_enable_master_chan, streaming chanend spark_enable_master_chan, streaming chanend tdc_trigger_chan, streaming chanend cam_flag_chan, streaming chanend spark_bei_chan, streaming chanend fuel_bei_chan, streaming chanend spark_calc_trig_chan, streaming chanend fuel_calc_trig_chan, streaming chanend bei_period_count_time_spark_chan, streaming chanend bei_period_count_time_fuel_chan){

timer t1; //the timer has a period of 10ns or 0.00000001s. Frequency of 100MHz. unsigned t1_0 = 0; unsigned t1_1 = 0; unsigned i = 0; unsigned j = 0; unsigned bei_period_count_time = 0; unsigned fuel_enable_flag = 0; unsigned spark_enable_flag = 0; int x = 0; int port_4a_bits = 0; int port_4b_bits = 0; int port_4c_bits = 0; int port_4d_bits = 0; int tdc_trigger_check = 0; int cam_flag_check = 0;

unsigned spark_1_calc_ang = bei_counts_tdc_1 - SPARK_CALC_ANG; unsigned spark_2_calc_ang = bei_counts_tdc_2 - SPARK_CALC_ANG; unsigned spark_3_calc_ang = bei_counts_tdc_3 - SPARK_CALC_ANG; unsigned spark_4_calc_ang = bei_counts_tdc_4 - SPARK_CALC_ANG;

unsigned fuel_1_calc_ang = bei_counts_tdc_1 - FUEL_CALC_ANG; unsigned fuel_2_calc_ang = bei_counts_tdc_2 - FUEL_CALC_ANG; unsigned fuel_3_calc_ang = bei_counts_tdc_3 - FUEL_CALC_ANG; unsigned fuel_4_calc_ang = bei_counts_tdc_4 - FUEL_CALC_ANG;

unsigned spark_angle_index = 0; int spark_angle_array[17] = {0};

unsigned fuel_angle_index = 0; int fuel_angle_array[17] = {0};

193 bei_in :> x; //read bei_in value in order to sync cam_out w/ cam_in bei_out <: x; //set bei_out to x t1 :> t1_1; port_4a_bits &= ~spark_1_bit; //clear spark 1 bit port_4a_out <: port_4a_bits; port_4a_bits &= ~spark_2_bit; //clear spark 2 bit port_4a_out <: port_4a_bits; port_4a_bits &= ~spark_3_bit; //clear spark 3 bit port_4a_out <: port_4a_bits; port_4a_bits &= ~spark_4_bit; //clear spark 4 bit port_4a_out <: port_4a_bits; port_4b_bits &= ~spark_5_bit; //clear spark 5 bit port_4b_out <: port_4b_bits; port_4b_bits &= ~spark_6_bit; //clear spark 6 bit port_4b_out <: port_4b_bits; port_4b_bits &= ~spark_7_bit; //clear spark 7 bit port_4b_out <: port_4b_bits; port_4b_bits &= ~spark_8_bit; //clear spark 8 bit port_4b_out <: port_4b_bits; port_4c_bits &= ~fuel_1_bit; //clear fuel 1 bit port_4c_out <: port_4c_bits; port_4c_bits &= ~fuel_2_bit; //clear fuel 2 bit port_4c_out <: port_4c_bits; port_4c_bits &= ~fuel_3_bit; //clear fuel 3 bit port_4c_out <: port_4c_bits; port_4c_bits &= ~fuel_4_bit; //clear fuel 4 bit port_4c_out <: port_4c_bits; port_4d_bits &= ~fuel_5_bit; //clear fuel 5 bit port_4d_out <: port_4d_bits; port_4d_bits &= ~fuel_6_bit; //clear fuel 6 bit port_4d_out <: port_4d_bits; port_4d_bits &= ~fuel_7_bit; //clear fuel 7 bit port_4d_out <: port_4d_bits; port_4d_bits &= ~fuel_8_bit; //clear fuel 8 bit port_4d_out <: port_4d_bits; while (1) {

194

select { case bei_in when pinsneq(x) :> x: //when bei_in pin is no longer equal to its old value, read new value into x bei_out <: x; //set bei_out to x

if(x == 1) { i++; j++;

if (j == BEI_COUNT_PERIOD) { t1_0 = t1_1; //assign previous final time to current initial time t1 :> t1_1; //assign current time to final time bei_period_count_time = t1_1 - t1_0; bei_period_count_time_spark_chan <: bei_period_count_time; //send time for bei period counts to spark loop bei_period_count_time_fuel_chan <: bei_period_count_time; //send time for bei period counts to fuel loop j = 0; //clear BEI timing index }

if (i == spark_1_calc_ang) { spark_calc_trig_chan <: spark_1_calc_trig_pointer; spark_calc_trig_chan <: 1; //set flag to calc new spark times }

else if (i == spark_2_calc_ang) { spark_calc_trig_chan <: spark_2_calc_trig_pointer; spark_calc_trig_chan <: 1; //set flag to calc new spark times }

else if (i == spark_3_calc_ang) { spark_calc_trig_chan <: spark_3_calc_trig_pointer; spark_calc_trig_chan <: 1; //set flag to calc new spark times }

195 else if (i == spark_4_calc_ang) { spark_calc_trig_chan <: spark_4_calc_trig_pointer; spark_calc_trig_chan <: 1; //set flag to calc new spark times } if (i == fuel_1_calc_ang) { fuel_calc_trig_chan <: fuel_1_calc_trig_pointer; fuel_calc_trig_chan <: 1; //set flag to calc new fuel times } else if (i == fuel_2_calc_ang) { fuel_calc_trig_chan <: fuel_2_calc_trig_pointer; fuel_calc_trig_chan <: 1; //set flag to calc new fuel times } else if (i == fuel_3_calc_ang) { fuel_calc_trig_chan <: fuel_3_calc_trig_pointer; fuel_calc_trig_chan <: 1; //set flag to calc new fuel times } else if (i == fuel_4_calc_ang) { fuel_calc_trig_chan <: fuel_4_calc_trig_pointer; fuel_calc_trig_chan <: 1; //set flag to calc new fuel times } if(fuel_enable_flag == 1) { if (i == fuel_angle_array[fuel_1_start_pointer]) { port_4c_bits |= fuel_1_bit; //set fuel 1 bit port_4c_out <: port_4c_bits; } if (i == fuel_angle_array[fuel_1_stop_pointer]) { port_4c_bits &= ~fuel_1_bit; //clear fuel 1 bit

196

port_4c_out <: port_4c_bits; } if (i == fuel_angle_array[fuel_2_start_pointer]) { port_4c_bits |= fuel_2_bit; //set fuel 2 bit port_4c_out <: port_4c_bits; } if (i == fuel_angle_array[fuel_2_stop_pointer]) { port_4c_bits &= ~fuel_2_bit; //clear fuel 2 bit port_4c_out <: port_4c_bits; } if (i == fuel_angle_array[fuel_3_start_pointer]) { port_4c_bits |= fuel_3_bit; //set fuel 3 bit port_4c_out <: port_4c_bits; } if (i == fuel_angle_array[fuel_3_stop_pointer]) { port_4c_bits &= ~fuel_3_bit; //clear fuel 3 bit port_4c_out <: port_4c_bits; } if (i == fuel_angle_array[fuel_4_start_pointer]) { port_4c_bits |= fuel_4_bit; //set fuel 4 bit port_4c_out <: port_4c_bits; } if (i == fuel_angle_array[fuel_4_stop_pointer]) { port_4c_bits &= ~fuel_4_bit; //clear fuel 4 bit port_4c_out <: port_4c_bits; } if (i == fuel_angle_array[fuel_5_start_pointer]) { port_4d_bits |= fuel_5_bit; //set fuel 5 bit port_4d_out <: port_4d_bits;

197

} if (i == fuel_angle_array[fuel_5_stop_pointer]) { port_4d_bits &= ~fuel_5_bit; //clear fuel 5 bit port_4d_out <: port_4d_bits; }

if (i == fuel_angle_array[fuel_6_start_pointer]) { port_4d_bits |= fuel_6_bit; //set fuel 6 bit port_4d_out <: port_4d_bits; } if (i == fuel_angle_array[fuel_6_stop_pointer]) { port_4d_bits &= ~fuel_6_bit; //clear fuel 6 bit port_4d_out <: port_4d_bits; }

if (i == fuel_angle_array[fuel_7_start_pointer]) { port_4d_bits |= fuel_7_bit; //set fuel 7 bit port_4d_out <: port_4d_bits; } if (i == fuel_angle_array[fuel_7_stop_pointer]) { port_4d_bits &= ~fuel_7_bit; //clear fuel 7 bit port_4d_out <: port_4d_bits; }

if (i == fuel_angle_array[fuel_8_start_pointer]) { port_4d_bits |= fuel_8_bit; //set fuel 8 bit port_4d_out <: port_4d_bits; } if (i == fuel_angle_array[fuel_8_stop_pointer]) { port_4d_bits &= ~fuel_8_bit; //clear fuel 8 bit port_4d_out <: port_4d_bits; } }

198

if(spark_enable_flag == 1) { if (i == spark_angle_array[spark_1_charge_pointer]) { port_4a_bits |= spark_1_bit; //set spark 1 bit port_4a_out <: port_4a_bits; } if (i == spark_angle_array[spark_1_fire_pointer]) { port_4a_bits &= ~spark_1_bit; //clear spark 1 bit port_4a_out <: port_4a_bits; }

if (i == spark_angle_array[spark_2_charge_pointer]) { port_4a_bits |= spark_2_bit; //set spark 2 bit port_4a_out <: port_4a_bits; } if (i == spark_angle_array[spark_2_fire_pointer]) { port_4a_bits &= ~spark_2_bit; //clear spark 2 bit port_4a_out <: port_4a_bits; }

if (i == spark_angle_array[spark_3_charge_pointer]) { port_4a_bits |= spark_3_bit; //set spark 3 bit port_4a_out <: port_4a_bits; } if (i == spark_angle_array[spark_3_fire_pointer]) { port_4a_bits &= ~spark_3_bit; //clear spark 3 bit port_4a_out <: port_4a_bits; }

if (i == spark_angle_array[spark_4_charge_pointer]) { port_4a_bits |= spark_4_bit; //set spark 4 bit port_4a_out <: port_4a_bits;

199

} if (i == spark_angle_array[spark_4_fire_pointer]) { port_4a_bits &= ~spark_4_bit; //clear spark 4 bit port_4a_out <: port_4a_bits; } if (i == spark_angle_array[spark_5_charge_pointer]) { port_4b_bits |= spark_5_bit; //set spark 5 bit port_4b_out <: port_4b_bits; } if (i == spark_angle_array[spark_5_fire_pointer]) { port_4b_bits &= ~spark_5_bit; //clear spark 5 bit port_4b_out <: port_4b_bits; } if (i == spark_angle_array[spark_6_charge_pointer]) { port_4b_bits |= spark_6_bit; //set spark 6 bit port_4b_out <: port_4b_bits; } if (i == spark_angle_array[spark_6_fire_pointer]) { port_4b_bits &= ~spark_6_bit; //clear spark 6 bit port_4b_out <: port_4b_bits; } if (i == spark_angle_array[spark_7_charge_pointer]) { port_4b_bits |= spark_7_bit; //set spark 7 bit port_4b_out <: port_4b_bits; } if (i == spark_angle_array[spark_7_fire_pointer]) { port_4b_bits &= ~spark_7_bit; //clear spark 7 bit port_4b_out <: port_4b_bits; }

200

if (i == spark_angle_array[spark_8_charge_pointer]) { port_4b_bits |= spark_8_bit; //set spark 8 bit port_4b_out <: port_4b_bits; } if (i == spark_angle_array[spark_8_fire_pointer]) { port_4b_bits &= ~spark_8_bit; //clear spark 8 bit port_4b_out <: port_4b_bits; } } } break; case tdc_trigger_chan :> tdc_trigger_check: if (cam_flag_check == 1) { i = 0; cam_flag_check = 0; } break; case cam_flag_chan :> cam_flag_check: break; case spark_bei_chan :> spark_angle_index: spark_bei_chan :> spark_angle_array[spark_angle_index]; break; case fuel_bei_chan :> fuel_angle_index: fuel_bei_chan :> fuel_angle_array[fuel_angle_index]; break; case fuel_enable_master_chan :> fuel_enable_flag: if (fuel_enable_flag != 1) { port_4c_out <: 0; //turn off injectors 1-4 port_4d_out <: 0; //turn off injectors 5-8 } break;

201

case spark_enable_master_chan :> spark_enable_flag: if (spark_enable_flag != 1) { port_4a_out <: 0; //turn off spark 1-4 port_4b_out <: 0; //turn off spark 5-8 } break; }// end select }//end while }//end main

/** ======* *spark angle calculations * **/ void spark_angle_thread(streaming chanend spark_bei_chan, streaming chanend spark_calc_trig_chan, streaming chanend bei_period_count_time_spark_chan, streaming chanend comm_spark_chan) {

unsigned bei_period_time = 1;

int spark_1_fire_ang = bei_counts_tdc_1; int spark_1_charge_ang = 0; int spark_2_fire_ang = bei_counts_tdc_2; int spark_2_charge_ang = 0; int spark_3_fire_ang = bei_counts_tdc_3; int spark_3_charge_ang = 0; int spark_4_fire_ang = bei_counts_tdc_4; int spark_4_charge_ang = 0; int spark_5_fire_ang = bei_counts_tdc_1; int spark_5_charge_ang = 0; int spark_6_fire_ang = bei_counts_tdc_2; int spark_6_charge_ang = 0; int spark_7_fire_ang = bei_counts_tdc_3; int spark_7_charge_ang = 0; int spark_8_fire_ang = bei_counts_tdc_4; int spark_8_charge_ang = 0;

202

unsigned comm_spark_index = 0; int comm_spark_array[18] = {0};

unsigned spark_calc_trig_index = 0; int spark_calc_trig_array[9] = {0};

comm_spark_array[spark_1_ang_in_pointer] = SPARK_ANG_DEFAULT; comm_spark_array[spark_2_ang_in_pointer] = SPARK_ANG_DEFAULT; comm_spark_array[spark_3_ang_in_pointer] = SPARK_ANG_DEFAULT; comm_spark_array[spark_4_ang_in_pointer] = SPARK_ANG_DEFAULT; comm_spark_array[spark_5_ang_in_pointer] = SPARK_ANG_DEFAULT; comm_spark_array[spark_6_ang_in_pointer] = SPARK_ANG_DEFAULT; comm_spark_array[spark_7_ang_in_pointer] = SPARK_ANG_DEFAULT; comm_spark_array[spark_8_ang_in_pointer] = SPARK_ANG_DEFAULT; comm_spark_array[spark_1_dur_pointer] = SPARK_DUR_DEFAULT; comm_spark_array[spark_2_dur_pointer] = SPARK_DUR_DEFAULT; comm_spark_array[spark_3_dur_pointer] = SPARK_DUR_DEFAULT; comm_spark_array[spark_4_dur_pointer] = SPARK_DUR_DEFAULT; comm_spark_array[spark_5_dur_pointer] = SPARK_DUR_DEFAULT; comm_spark_array[spark_6_dur_pointer] = SPARK_DUR_DEFAULT; comm_spark_array[spark_7_dur_pointer] = SPARK_DUR_DEFAULT; comm_spark_array[spark_8_dur_pointer] = SPARK_DUR_DEFAULT; comm_spark_array[spark_tdc_ang_in_pointer] = 0;

while (1) { select { case comm_spark_chan :> comm_spark_index: comm_spark_chan :> comm_spark_array[comm_spark_index]; break;

case bei_period_count_time_spark_chan :> bei_period_time: break;

case spark_calc_trig_chan :> spark_calc_trig_index: spark_calc_trig_chan :> spark_calc_trig_array[spark_calc_trig_index];

if (spark_calc_trig_array[spark_1_calc_trig_pointer]) { spark_1_fire_ang = bei_counts_tdc_1 - comm_spark_array[spark_1_ang_in_pointer] - comm_spark_array[spark_tdc_ang_in_pointer];

203

if (spark_1_fire_ang <= 0) spark_1_fire_ang += BEI_COUNTS_MAX; if (spark_1_fire_ang >= BEI_COUNTS_MAX) spark_1_fire_ang -= BEI_COUNTS_MAX; spark_bei_chan <: spark_1_fire_pointer; spark_bei_chan <: spark_1_fire_ang;

spark_1_charge_ang = spark_1_fire_ang - ((COM_TIME_MULT * comm_spark_array[spark_1_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (spark_1_charge_ang <= 0) spark_1_charge_ang += BEI_COUNTS_MAX; spark_bei_chan <: spark_1_charge_pointer; spark_bei_chan <: spark_1_charge_ang;

///////////////////////////////////// spark_5_fire_ang = bei_counts_tdc_1 - comm_spark_array[spark_5_ang_in_pointer] - comm_spark_array[spark_tdc_ang_in_pointer]; if (spark_5_fire_ang <= 0) spark_5_fire_ang += BEI_COUNTS_MAX; if (spark_5_fire_ang >= BEI_COUNTS_MAX) spark_5_fire_ang -= BEI_COUNTS_MAX; spark_bei_chan <: spark_5_fire_pointer; spark_bei_chan <: spark_5_fire_ang;

spark_5_charge_ang = spark_5_fire_ang - ((COM_TIME_MULT * comm_spark_array[spark_5_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (spark_5_charge_ang <= 0) spark_5_charge_ang += BEI_COUNTS_MAX; spark_bei_chan <: spark_5_charge_pointer; spark_bei_chan <: spark_5_charge_ang; }

if (spark_calc_trig_array[spark_2_calc_trig_pointer]) { spark_2_fire_ang = bei_counts_tdc_2 - comm_spark_array[spark_2_ang_in_pointer] - comm_spark_array[spark_tdc_ang_in_pointer]; if (spark_2_fire_ang <= 0) spark_2_fire_ang += BEI_COUNTS_MAX; if (spark_2_fire_ang >= BEI_COUNTS_MAX) spark_2_fire_ang -= BEI_COUNTS_MAX; spark_bei_chan <: spark_2_fire_pointer; spark_bei_chan <: spark_2_fire_ang;

spark_2_charge_ang = spark_2_fire_ang - ((COM_TIME_MULT * comm_spark_array[spark_2_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (spark_2_charge_ang <= 0) spark_2_charge_ang += BEI_COUNTS_MAX; spark_bei_chan <: spark_2_charge_pointer; spark_bei_chan <: spark_2_charge_ang;

204

///////////////////////////////////// spark_6_fire_ang = bei_counts_tdc_2 - comm_spark_array[spark_6_ang_in_pointer] - comm_spark_array[spark_tdc_ang_in_pointer]; if (spark_6_fire_ang <= 0) spark_6_fire_ang += BEI_COUNTS_MAX; if (spark_6_fire_ang >= BEI_COUNTS_MAX) spark_6_fire_ang -= BEI_COUNTS_MAX; spark_bei_chan <: spark_6_fire_pointer; spark_bei_chan <: spark_6_fire_ang;

spark_6_charge_ang = spark_6_fire_ang - ((COM_TIME_MULT * comm_spark_array[spark_6_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (spark_6_charge_ang <= 0) spark_6_charge_ang += BEI_COUNTS_MAX; spark_bei_chan <: spark_6_charge_pointer; spark_bei_chan <: spark_6_charge_ang; }

if (spark_calc_trig_array[spark_3_calc_trig_pointer]) { spark_3_fire_ang = bei_counts_tdc_3 - comm_spark_array[spark_3_ang_in_pointer] - comm_spark_array[spark_tdc_ang_in_pointer]; if (spark_3_fire_ang <= 0) spark_3_fire_ang += BEI_COUNTS_MAX; if (spark_3_fire_ang >= BEI_COUNTS_MAX) spark_3_fire_ang -= BEI_COUNTS_MAX; spark_bei_chan <: spark_3_fire_pointer; spark_bei_chan <: spark_3_fire_ang;

spark_3_charge_ang = spark_3_fire_ang - ((COM_TIME_MULT * comm_spark_array[spark_3_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (spark_3_charge_ang <= 0) spark_3_charge_ang += BEI_COUNTS_MAX; spark_bei_chan <: spark_3_charge_pointer; spark_bei_chan <: spark_3_charge_ang;

///////////////////////////////////// spark_7_fire_ang = bei_counts_tdc_3 - comm_spark_array[spark_7_ang_in_pointer] - comm_spark_array[spark_tdc_ang_in_pointer]; if (spark_7_fire_ang <= 0) spark_7_fire_ang += BEI_COUNTS_MAX; if (spark_7_fire_ang >= BEI_COUNTS_MAX) spark_7_fire_ang -= BEI_COUNTS_MAX; spark_bei_chan <: spark_7_fire_pointer; spark_bei_chan <: spark_7_fire_ang;

205

spark_7_charge_ang = spark_7_fire_ang - ((COM_TIME_MULT * comm_spark_array[spark_7_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (spark_7_charge_ang <= 0) spark_7_charge_ang += BEI_COUNTS_MAX; spark_bei_chan <: spark_7_charge_pointer; spark_bei_chan <: spark_7_charge_ang; }

if (spark_calc_trig_array[spark_4_calc_trig_pointer]) { spark_4_fire_ang = bei_counts_tdc_4 - comm_spark_array[spark_4_ang_in_pointer] - comm_spark_array[spark_tdc_ang_in_pointer]; if (spark_4_fire_ang <= 0) spark_4_fire_ang += BEI_COUNTS_MAX; if (spark_4_fire_ang >= BEI_COUNTS_MAX) spark_4_fire_ang -= BEI_COUNTS_MAX; spark_bei_chan <: spark_4_fire_pointer; spark_bei_chan <: spark_4_fire_ang;

spark_4_charge_ang = spark_4_fire_ang - ((COM_TIME_MULT * comm_spark_array[spark_4_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (spark_4_charge_ang <= 0) spark_4_charge_ang += BEI_COUNTS_MAX; spark_bei_chan <: spark_4_charge_pointer; spark_bei_chan <: spark_4_charge_ang;

///////////////////////////////////// spark_8_fire_ang = bei_counts_tdc_4 - comm_spark_array[spark_8_ang_in_pointer] - comm_spark_array[spark_tdc_ang_in_pointer]; if (spark_8_fire_ang <= 0) spark_8_fire_ang += BEI_COUNTS_MAX; if (spark_8_fire_ang >= BEI_COUNTS_MAX) spark_8_fire_ang -= BEI_COUNTS_MAX; spark_bei_chan <: spark_8_fire_pointer; spark_bei_chan <: spark_8_fire_ang;

spark_8_charge_ang = spark_8_fire_ang - ((COM_TIME_MULT * comm_spark_array[spark_8_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (spark_8_charge_ang <= 0) spark_8_charge_ang += BEI_COUNTS_MAX; spark_bei_chan <: spark_8_charge_pointer; spark_bei_chan <: spark_8_charge_ang; }

for (int inc=0;inc<9;inc++) { spark_calc_trig_array[inc] = 0;

206

} break; } } }

/** ======* *fuel angle calculations * **/ void fuel_angle_thread(streaming chanend comm_fuel_chan, streaming chanend fuel_bei_chan, streaming chanend fuel_calc_trig_chan, streaming chanend bei_period_count_time_fuel_chan) { //chanend adc_1_chan, chanend adc_2_chan,

int fuel_1_ang_start = 0; int fuel_2_ang_start = 0; int fuel_3_ang_start = 0; int fuel_4_ang_start = 0; int fuel_5_ang_start = 0; int fuel_6_ang_start = 0; int fuel_7_ang_start = 0; int fuel_8_ang_start = 0; int fuel_1_ang_stop = 0; int fuel_2_ang_stop = 0; int fuel_3_ang_stop = 0; int fuel_4_ang_stop = 0; int fuel_5_ang_stop = 0; int fuel_6_ang_stop = 0; int fuel_7_ang_stop = 0; int fuel_8_ang_stop = 0; int adc_1_value = 0; int adc_2_value = 0;

unsigned bei_period_time = 1;

unsigned fuel_calc_trig_index = 0; int fuel_calc_trig_array[9] = {0};

unsigned comm_fuel_index = 0;

207

int comm_fuel_array[20] = {0};

comm_fuel_array[fuel_1_ang_in_pointer] = FUEL_ANG_DEFAULT; comm_fuel_array[fuel_2_ang_in_pointer] = FUEL_ANG_DEFAULT; comm_fuel_array[fuel_3_ang_in_pointer] = FUEL_ANG_DEFAULT; comm_fuel_array[fuel_4_ang_in_pointer] = FUEL_ANG_DEFAULT; comm_fuel_array[fuel_5_ang_in_pointer] = FUEL_ANG_DEFAULT; comm_fuel_array[fuel_6_ang_in_pointer] = FUEL_ANG_DEFAULT; comm_fuel_array[fuel_7_ang_in_pointer] = FUEL_ANG_DEFAULT; comm_fuel_array[fuel_8_ang_in_pointer] = FUEL_ANG_DEFAULT; comm_fuel_array[fuel_1_dur_pointer] = FUEL_DUR_DEFAULT; comm_fuel_array[fuel_2_dur_pointer] = FUEL_DUR_DEFAULT; comm_fuel_array[fuel_3_dur_pointer] = FUEL_DUR_DEFAULT; comm_fuel_array[fuel_4_dur_pointer] = FUEL_DUR_DEFAULT; comm_fuel_array[fuel_5_dur_pointer] = FUEL_DUR_DEFAULT; comm_fuel_array[fuel_6_dur_pointer] = FUEL_DUR_DEFAULT; comm_fuel_array[fuel_7_dur_pointer] = FUEL_DUR_DEFAULT; comm_fuel_array[fuel_8_dur_pointer] = FUEL_DUR_DEFAULT; comm_fuel_array[fuel_tdc_ang_in_pointer] = 0; comm_fuel_array[fuel_2_frac_pointer] = 0;

while (1) { select { case bei_period_count_time_fuel_chan :> bei_period_time: break;

case fuel_calc_trig_chan :> fuel_calc_trig_index: fuel_calc_trig_chan :> fuel_calc_trig_array[fuel_calc_trig_index];

if (fuel_calc_trig_array[fuel_1_calc_trig_pointer]) { fuel_1_ang_stop = bei_counts_tdc_1 - comm_fuel_array[fuel_1_ang_in_pointer] - comm_fuel_array[fuel_tdc_ang_in_pointer]; if (fuel_1_ang_stop <= 0) fuel_1_ang_stop += BEI_COUNTS_MAX; if (fuel_1_ang_stop >= BEI_COUNTS_MAX) fuel_1_ang_stop -= BEI_COUNTS_MAX; fuel_bei_chan <: fuel_1_stop_pointer; fuel_bei_chan <: fuel_1_ang_stop;

fuel_1_ang_start = fuel_1_ang_stop - ((COM_TIME_MULT * comm_fuel_array[fuel_1_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time);

208

if (fuel_1_ang_start <= 0) fuel_1_ang_start += BEI_COUNTS_MAX; fuel_bei_chan <: fuel_1_start_pointer; fuel_bei_chan <: fuel_1_ang_start;

////////////////////////////////////////////// fuel_5_ang_stop = bei_counts_tdc_1 - comm_fuel_array[fuel_5_ang_in_pointer] - comm_fuel_array[fuel_tdc_ang_in_pointer]; if (fuel_5_ang_stop <= 0) fuel_5_ang_stop += BEI_COUNTS_MAX; if (fuel_5_ang_stop >= BEI_COUNTS_MAX) fuel_5_ang_stop -= BEI_COUNTS_MAX; fuel_bei_chan <: fuel_5_stop_pointer; fuel_bei_chan <: fuel_5_ang_stop;

fuel_5_ang_start = fuel_5_ang_stop - ((COM_TIME_MULT * comm_fuel_array[fuel_5_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (fuel_5_ang_start <= 0) fuel_5_ang_start += BEI_COUNTS_MAX; fuel_bei_chan <: fuel_5_start_pointer; fuel_bei_chan <: fuel_5_ang_start; }

if (fuel_calc_trig_array[fuel_2_calc_trig_pointer]) { fuel_2_ang_stop = bei_counts_tdc_2 - comm_fuel_array[fuel_2_ang_in_pointer] - comm_fuel_array[fuel_tdc_ang_in_pointer]; if (fuel_2_ang_stop <= 0) fuel_2_ang_stop += BEI_COUNTS_MAX; if (fuel_2_ang_stop >= BEI_COUNTS_MAX) fuel_2_ang_stop -= BEI_COUNTS_MAX; fuel_bei_chan <: fuel_2_stop_pointer; fuel_bei_chan <: fuel_2_ang_stop;

//////**************Dual Fuel Modification**************///////////////// fuel_2_ang_start = fuel_2_ang_stop - ((COM_TIME_MULT * comm_fuel_array[fuel_2_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time) * comm_fuel_array[fuel_2_frac_pointer] / 1000; if (fuel_2_ang_start <= 0) fuel_2_ang_start += BEI_COUNTS_MAX; fuel_bei_chan <: fuel_2_start_pointer; fuel_bei_chan <: fuel_2_ang_start;

////////////////////////////////////////////// fuel_6_ang_stop = bei_counts_tdc_2 - comm_fuel_array[fuel_6_ang_in_pointer] - comm_fuel_array[fuel_tdc_ang_in_pointer]; if (fuel_6_ang_stop <= 0) fuel_6_ang_stop += BEI_COUNTS_MAX; if (fuel_6_ang_stop >= BEI_COUNTS_MAX) fuel_6_ang_stop -= BEI_COUNTS_MAX;

209

fuel_bei_chan <: fuel_6_stop_pointer; fuel_bei_chan <: fuel_6_ang_stop;

//////**************Dual Fuel Modification**************///////////////// fuel_6_ang_start = fuel_6_ang_stop - ((COM_TIME_MULT * comm_fuel_array[fuel_2_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time) * (1000 - comm_fuel_array[fuel_2_frac_pointer]) / 1000; if (fuel_6_ang_start <= 0) fuel_6_ang_start += BEI_COUNTS_MAX; fuel_bei_chan <: fuel_6_start_pointer; fuel_bei_chan <: fuel_6_ang_start; }

if (fuel_calc_trig_array[fuel_3_calc_trig_pointer]) { fuel_3_ang_stop = bei_counts_tdc_3 - comm_fuel_array[fuel_3_ang_in_pointer] - comm_fuel_array[fuel_tdc_ang_in_pointer]; if (fuel_3_ang_stop <= 0) fuel_3_ang_stop += BEI_COUNTS_MAX; if (fuel_3_ang_stop >= BEI_COUNTS_MAX) fuel_3_ang_stop -= BEI_COUNTS_MAX; fuel_bei_chan <: fuel_3_stop_pointer; fuel_bei_chan <: fuel_3_ang_stop;

fuel_3_ang_start = fuel_3_ang_stop - ((COM_TIME_MULT * comm_fuel_array[fuel_3_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (fuel_3_ang_start <= 0) fuel_3_ang_start += BEI_COUNTS_MAX; fuel_bei_chan <: fuel_3_start_pointer; fuel_bei_chan <: fuel_3_ang_start;

////////////////////////////////////////////// fuel_7_ang_stop = bei_counts_tdc_3 - comm_fuel_array[fuel_7_ang_in_pointer] - comm_fuel_array[fuel_tdc_ang_in_pointer]; if (fuel_7_ang_stop <= 0) fuel_7_ang_stop += BEI_COUNTS_MAX; if (fuel_7_ang_stop >= BEI_COUNTS_MAX) fuel_7_ang_stop -= BEI_COUNTS_MAX; fuel_bei_chan <: fuel_7_stop_pointer; fuel_bei_chan <: fuel_7_ang_stop;

fuel_7_ang_start = fuel_7_ang_stop - ((COM_TIME_MULT * comm_fuel_array[fuel_7_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (fuel_7_ang_start <= 0) fuel_7_ang_start += BEI_COUNTS_MAX; fuel_bei_chan <: fuel_7_start_pointer; fuel_bei_chan <: fuel_7_ang_start; }

210

if (fuel_calc_trig_array[fuel_4_calc_trig_pointer]) { fuel_4_ang_stop = bei_counts_tdc_4 - comm_fuel_array[fuel_4_ang_in_pointer] - comm_fuel_array[fuel_tdc_ang_in_pointer]; if (fuel_4_ang_stop <= 0) fuel_4_ang_stop += BEI_COUNTS_MAX; if (fuel_4_ang_stop >= BEI_COUNTS_MAX) fuel_4_ang_stop -= BEI_COUNTS_MAX; fuel_bei_chan <: fuel_4_stop_pointer; fuel_bei_chan <: fuel_4_ang_stop;

fuel_4_ang_start = fuel_4_ang_stop - ((COM_TIME_MULT * comm_fuel_array[fuel_4_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (fuel_4_ang_start <= 0) fuel_4_ang_start += BEI_COUNTS_MAX; fuel_bei_chan <: fuel_4_start_pointer; fuel_bei_chan <: fuel_4_ang_start;

////////////////////////////////////////////// fuel_8_ang_stop = bei_counts_tdc_4 - comm_fuel_array[fuel_8_ang_in_pointer] - comm_fuel_array[fuel_tdc_ang_in_pointer]; if (fuel_8_ang_stop <= 0) fuel_8_ang_stop += BEI_COUNTS_MAX; if (fuel_8_ang_stop >= BEI_COUNTS_MAX) fuel_8_ang_stop -= BEI_COUNTS_MAX; fuel_bei_chan <: fuel_8_stop_pointer; fuel_bei_chan <: fuel_8_ang_stop;

fuel_8_ang_start = fuel_8_ang_stop - ((COM_TIME_MULT * comm_fuel_array[fuel_8_dur_pointer] * BEI_COUNT_PERIOD) / bei_period_time); if (fuel_8_ang_start <= 0) fuel_8_ang_start += BEI_COUNTS_MAX; fuel_bei_chan <: fuel_8_start_pointer; fuel_bei_chan <: fuel_8_ang_start; }

for (int inc=0;inc<9;inc++) { fuel_calc_trig_array[inc] = 0; } break;

// case adc_1_chan :> adc_1_value: // break;

211

// case adc_2_chan :> adc_2_value: // break;

case comm_fuel_chan :> comm_fuel_index: comm_fuel_chan :> comm_fuel_array[comm_fuel_index]; break; } } }

/** ======* *adc * **/ void adc_thread(in port adc_1_ready, in port adc_2_ready)//, chanend adc_1_chan, chanend adc_2_chan) { //1.2ms conversion delay. Conversion time is 1.163 ms or 860 samples/sec. int x = 0; int adc_1_value = 0; int adc_2_value = 0; //unsigned char i2c_write_register[number of bytes to write to register]={register byte to configure adc, another byte}; unsigned char i2c_write_register_1[2] = {0xC0, 0xE8}; //see ADS1115 datasheet for configuration options //{0xC0, 0xE3}; unsigned char i2c_write_register_2[2]={0x00, 0x00}; //see ADS1115 datasheet for configuration options unsigned char i2c_write_register_3[2]={0xFF, 0xFF}; //see ADS1115 datasheet for configuration options unsigned char i2c_write_register_4[1]={0x00}; //see ADS1115 datasheet for configuration options unsigned char i2c_read_register[2];//array to read ADC data to. Data is 2 bytes wide. //see ADS1115 datasheet for configuration options //0x00 is the conversion register address for the ADS1115 //0x01 is the configuration register address for the ADS1115 //0x02 is the Lo_Thresh register address for the ADS1115 //0x03 is the Hi_Thresh register address for the ADS1115 //Chan 0 = 0xC0, Chan 1 = 0xD0, Chan 2 = 0xE0, Chan 3 = 0xF0 //0x48 is the device address when ADS1115 ADR pin is connected to ground i2c_master_write_reg(0x48, 0x01, i2c_write_register_1, 2, i2cOne); //configure ADC 1 by writing the settings to configuration register i2c_master_write_reg(0x48, 0x02, i2c_write_register_2, 2, i2cOne); //configure ADC 1 by writing the settings to Lo_Thresh register i2c_master_write_reg(0x48, 0x03, i2c_write_register_3, 2, i2cOne); //configure ADC 1 by writing the settings to Hi_Tresh register

212

i2c_master_write_reg(0x48, 0x00, i2c_write_register_4, 0, i2cOne); //configure ADC 1 by writing the settings to conversion register //0x49 is the device address when ADS1115 ADR pin is connected to +Vdd i2c_master_write_reg(0x49, 0x01, i2c_write_register_1, 2, i2cOne); //configure ADC 2 by writing the settings to configuration register i2c_master_write_reg(0x49, 0x02, i2c_write_register_2, 2, i2cOne); //configure ADC 2 by writing the settings to Lo_Thresh register i2c_master_write_reg(0x49, 0x03, i2c_write_register_3, 2, i2cOne); //configure ADC 2 by writing the settings to Hi_Tresh register i2c_master_write_reg(0x49, 0x00, i2c_write_register_4, 0, i2cOne); //configure ADC 2 by writing the settings to conversion register

while(1) { select { case adc_1_ready when pinseq(1) :> void: // void was x //read from conversion register //i2c_master_rx(device address, data array, number of bytes to read, struct containing the clock and data ports); //0x48 is the default device address for the ADS1115. i2c_master_rx(0x48, i2c_read_register, 2, i2cOne); //Read value from ADC

//shift conversion result to get adc value adc_1_value = (i2c_read_register[0]<<8)|(i2c_read_register[1]);

// adc_1_chan <: adc_1_value;

//possibly add moving average code here

// printstr("adc 1 value is :"); // printint(adc_1_value); // printstrln(""); break;

case adc_2_ready when pinseq(1) :> void: //void was x //read from conversion register //i2c_master_rx(device address, data array, number of bytes to read, struct containing the clock and data ports); //0x48 is the default device address for the ADS1115.

213

i2c_master_rx(0x49, i2c_read_register, 2, i2cOne); //Read value from ADC

//shift conversion result to get adc value adc_2_value = (i2c_read_register[0]<<8)|(i2c_read_register[1]);

// adc_2_chan <: adc_2_value;

//possibly add moving average code here

// printstr("adc 2 value is :"); // printint(adc_2_value); // printstrln(""); break; } } }

/** ======* app_manager * * Polling uart RX and push button switches and send received commands to * process_data thread * **/ void comm_thread(chanend c_uartTX, chanend c_uartRX, streaming chanend fuel_enable_chan, streaming chanend spark_enable_chan, streaming chanend comm_spark_chan, streaming chanend comm_fuel_chan) { int adc_value; unsigned char buffer; unsigned char cmd_rcvbuffer[20]; unsigned char cmd_rcvbuffer_in[20]; unsigned char cmd_rcvbuffer_new[20]; unsigned char cmd_rcvbuffer_1[20]; unsigned char cmd_rcvbuffer_2[20];

unsigned char CONSOLE_MESSAGES[16][110]= { "\r\n\r\nHello Jacob!" "\r\nWelcome to JABtronic ECU\r\nPlease Type a Command",

214

"\r\n\r\nType 'help' for details\r\n\r\n>", "\r\n@#$%@!*&^ ERROR !!!\r\n DOES NOT COMPUTE", "\r\nJAB------HELP------", "\r\n\r\nenable 'spark'/'fuel'/'all'" "\r\ndisable 'spark'/'fuel'/'all'", "\r\n\r\ntdcoffset 'x' \t- Set BEI tdc offset", "\r\n\r\nfuelang 'x' \t- Set EOI angle for all injectors", "\r\nfuel'n'ang 'x' \t- Set injector 'n' EOI angle", "\r\nfuel'n'dur 'y' \t- Set injector 'n' on duration" "\r\nfuel2frac 'z' \t- Set injector 2 to 6 fraction", "\r\n\r\nsparkang 'x' \t- Set angle for all spark", "\r\nspark'n'ang 'x'\t- Set spark 'n' angle", "\r\nspark'n'dur 'y'\t- Set spark 'n' charge duration", "\r\n\r\n'x' is angle in tenths of a degree btc of combustion stroke", "\r\n'y' is time in us", "\r\n'z' is in fraction in tenths of percent" }; int j = 0, skip = 1, inc = 0, k = 0, ii = 0; uart_rx_client_state rxState; uart_rx_init(c_uartRX, rxState); uart_rx_set_baud_rate(c_uartRX, rxState, BAUD_RATE); uart_tx_set_baud_rate(c_uartTX, BAUD_RATE); uart_tx_string(c_uartTX,CONSOLE_MESSAGES[0]); //Display Welcome messages on UART TX Pin uart_tx_string(c_uartTX,CONSOLE_MESSAGES[1]); //Display help hint on UART TX Pin while(1) { j = 0; skip = 1; while(skip == 1) { select { case uart_rx_get_byte_byref(c_uartRX, rxState, buffer): cmd_rcvbuffer_in[j]=buffer; if(cmd_rcvbuffer_in[j++] == '\r') {

215

skip=0; j=0; inc = 0; k = 0; while(cmd_rcvbuffer_in[j] != '\r') { cmd_rcvbuffer[j] = cmd_rcvbuffer_in[j]; //received valid command and send the command to the process_data theread uart_tx_send_byte(c_uartTX, cmd_rcvbuffer[j]); if (cmd_rcvbuffer[j] == ' ') { inc = j + 1; } j++; } cmd_rcvbuffer[j]='\0';

if (inc > 0) { k = j - inc; ii = 0; while(ii < inc - 1) { cmd_rcvbuffer_1[ii] = cmd_rcvbuffer[ii]; ii++; } cmd_rcvbuffer_1[ii]='\0';

ii = 0; while(ii < k) { cmd_rcvbuffer_2[ii] = cmd_rcvbuffer[inc + ii]; ii++; } cmd_rcvbuffer_2[ii]='\0'; }

if(!strcmp(cmd_rcvbuffer_1,"enable")) { if(!strcmp(cmd_rcvbuffer_2,"fuel"))

216

{ fuel_enable_chan <: 1; } else if(!strcmp(cmd_rcvbuffer_2,"spark")) { spark_enable_chan <: 1; } else if(!strcmp(cmd_rcvbuffer_2,"all")) { fuel_enable_chan <: 1; spark_enable_chan <: 1; } } else if(!strcmp(cmd_rcvbuffer_1,"disable")) { if(!strcmp(cmd_rcvbuffer_2,"fuel")) { fuel_enable_chan <: 0; } else if(!strcmp(cmd_rcvbuffer_2,"spark")) { spark_enable_chan <: 0; } else if(!strcmp(cmd_rcvbuffer_2,"all")) { fuel_enable_chan <: 0; spark_enable_chan <: 0; } } else if(!strcmp(cmd_rcvbuffer_1,"fuelang")) // set angle for all injectors { comm_fuel_chan <: fuel_1_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_2_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_3_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_4_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2);

217

comm_fuel_chan <: fuel_5_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_6_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_7_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_8_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fueldur")) // set pw for all injectors { comm_fuel_chan <: fuel_1_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_2_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_3_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_4_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_5_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_6_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_7_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_8_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel1ang")) { comm_fuel_chan <: fuel_1_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel1dur")) { comm_fuel_chan <: fuel_1_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); }

218 else if(!strcmp(cmd_rcvbuffer_1,"fuel2ang")) { comm_fuel_chan <: fuel_2_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel2dur")) { comm_fuel_chan <: fuel_2_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel3ang")) { comm_fuel_chan <: fuel_3_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel3dur")) { comm_fuel_chan <: fuel_3_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel4ang")) { comm_fuel_chan <: fuel_4_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel4dur")) { comm_fuel_chan <: fuel_4_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel5ang")) { comm_fuel_chan <: fuel_5_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel5dur")) {

219

comm_fuel_chan <: fuel_5_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel6ang")) { comm_fuel_chan <: fuel_6_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel6dur")) { comm_fuel_chan <: fuel_6_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel7ang")) { comm_fuel_chan <: fuel_7_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel7dur")) { comm_fuel_chan <: fuel_7_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel8ang")) { comm_fuel_chan <: fuel_8_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel8dur")) { comm_fuel_chan <: fuel_8_dur_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"fuel2frac")) { comm_fuel_chan <: fuel_2_frac_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2);

220

} else if(!strcmp(cmd_rcvbuffer_1,"sparkang")) { comm_spark_chan <: spark_1_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_2_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_3_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_4_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_5_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_6_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_7_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_8_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"sparkdur")) { comm_spark_chan <: spark_1_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_2_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_3_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_4_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_5_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_6_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_7_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_spark_chan <: spark_8_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); }

221 else if(!strcmp(cmd_rcvbuffer_1,"spark1ang")) { comm_spark_chan <: spark_1_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark1dur")) { comm_spark_chan <: spark_1_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark2ang")) { comm_spark_chan <: spark_2_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark2dur")) { comm_spark_chan <: spark_2_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark3ang")) { comm_spark_chan <: spark_3_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark3dur")) { comm_spark_chan <: spark_3_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark4ang")) { comm_spark_chan <: spark_4_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark4dur")) {

222

comm_spark_chan <: spark_4_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark5ang")) { comm_spark_chan <: spark_5_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark5dur")) { comm_spark_chan <: spark_5_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark6ang")) { comm_spark_chan <: spark_6_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark6dur")) { comm_spark_chan <: spark_6_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark7ang")) { comm_spark_chan <: spark_7_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark7dur")) { comm_spark_chan <: spark_7_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark8ang")) { comm_spark_chan <: spark_8_ang_in_pointer;

223

comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"spark8dur")) { comm_spark_chan <: spark_8_dur_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); } else if(!strcmp(cmd_rcvbuffer_1,"tdcoffset")) { if (cmd_rcvbuffer_2[0] == '-') { ii = 0; while(ii < (k - 1)) { cmd_rcvbuffer_2[ii] = cmd_rcvbuffer_2[ii + 1]; ii++; } cmd_rcvbuffer_2[ii]='\0';

comm_spark_chan <: spark_tdc_ang_in_pointer; comm_spark_chan <: -atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_tdc_ang_in_pointer; comm_fuel_chan <: -atoi(cmd_rcvbuffer_2); } else { comm_spark_chan <: spark_tdc_ang_in_pointer; comm_spark_chan <: atoi(cmd_rcvbuffer_2); comm_fuel_chan <: fuel_tdc_ang_in_pointer; comm_fuel_chan <: atoi(cmd_rcvbuffer_2); } } else if(!strcmp(cmd_rcvbuffer,"help")) { //Displays available command list uart_tx_string(c_uartTX,CONSOLE_MESSAGES[3]); uart_tx_string(c_uartTX,CONSOLE_MESSAGES[4]); uart_tx_string(c_uartTX,CONSOLE_MESSAGES[5]); uart_tx_string(c_uartTX,CONSOLE_MESSAGES[6]);

224

uart_tx_string(c_uartTX,CONSOLE_MESSAGES[7]); uart_tx_string(c_uartTX,CONSOLE_MESSAGES[8]); uart_tx_string(c_uartTX,CONSOLE_MESSAGES[9]); uart_tx_string(c_uartTX,CONSOLE_MESSAGES[10]); uart_tx_string(c_uartTX,CONSOLE_MESSAGES[11]); uart_tx_string(c_uartTX,CONSOLE_MESSAGES[12]); uart_tx_string(c_uartTX,CONSOLE_MESSAGES[13]); uart_tx_string(c_uartTX,CONSOLE_MESSAGES[14]); // uart_tx_string(c_uartTX,CONSOLE_MESSAGES[15]); uart_tx_send_byte(c_uartTX, '\r'); uart_tx_send_byte(c_uartTX, '\n'); } else if(!strcmp(cmd_rcvbuffer,"readadc")) { // c_end<:READ_ADC; } else { //displays Invalid command message uart_tx_string(c_uartTX,CONSOLE_MESSAGES[2]); }

for(int inc=0;inc<20;inc++) { cmd_rcvbuffer[inc]='0'; //clear command reveive buffer cmd_rcvbuffer_new[inc]='0'; //clear command reveive buffer cmd_rcvbuffer_in[inc]='0'; //clear command reveive buffer cmd_rcvbuffer_1[inc]='0'; //clear command reveive buffer cmd_rcvbuffer_2[inc]='0'; //clear command reveive buffer }

uart_tx_send_byte(c_uartTX, '\r'); uart_tx_send_byte(c_uartTX, '\n'); uart_tx_send_byte(c_uartTX, '>'); } break; }//main select }//while(skip) }//while(1) }//thread

225

int main(void) { chan c_chanTX, c_chanRX; // adc_1_chan, adc_2_chan; streaming chan spark_bei_chan, fuel_bei_chan, comm_spark_chan, comm_fuel_chan, cam_flag_chan, tdc_trigger_chan, spark_calc_trig_chan, fuel_calc_trig_chan, bei_period_count_time_spark_chan, bei_period_count_time_fuel_chan, fuel_enable_chan, spark_enable_chan, fuel_enable_master_chan, spark_enable_master_chan; par { on stdcore[0] : uart_rx(p_rx, rx_buffer, ARRAY_SIZE(rx_buffer), BAUD_RATE, 8, UART_TX_PARITY_EVEN, 1, c_chanRX); on stdcore[0] : uart_tx(p_tx, tx_buffer, ARRAY_SIZE(tx_buffer), BAUD_RATE, 8, UART_TX_PARITY_EVEN, 1, c_chanTX); on stdcore[0] : comm_thread(c_chanTX, c_chanRX, fuel_enable_chan, spark_enable_chan, comm_spark_chan, comm_fuel_chan); on stdcore[0] : adc_thread(adc_1_ready, adc_2_ready);//, adc_1_chan, adc_2_chan);

on stdcore[1] : tdc_cam_thread(tdc_in, port_4e_out, port_4f_out, tdc_out, cam_in, cam_out, tdc_trigger_chan, fuel_enable_chan, spark_enable_chan, fuel_enable_master_chan, spark_enable_master_chan, cam_flag_chan); on stdcore[1] : bei_thread(bei_in, bei_out, port_4a_out, port_4b_out, port_4c_out, port_4d_out, fuel_enable_master_chan, spark_enable_master_chan, tdc_trigger_chan, cam_flag_chan, spark_bei_chan, fuel_bei_chan, spark_calc_trig_chan, fuel_calc_trig_chan, bei_period_count_time_spark_chan, bei_period_count_time_fuel_chan); on stdcore[1] : spark_angle_thread(spark_bei_chan, spark_calc_trig_chan, bei_period_count_time_spark_chan, comm_spark_chan); on stdcore[1] : fuel_angle_thread(comm_fuel_chan, fuel_bei_chan, fuel_calc_trig_chan, bei_period_count_time_fuel_chan);// adc_1_chan, adc_2_chan, } return 0; }

226

20. APPENDIX I – LAYOUT AND SCHEMATIC FOR JABTRONIC INBOARD V1.0

227

228

21. APPENDIX J – LAYOUT AND SCHEMATIC FOR JABTRONIC OUTBOARD V1.0

229

230