element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Ben Heck Featured Content
  • Challenges & Projects
  • element14 presents
  • element14's The Ben Heck Show
  • Ben Heck Featured Content
  • More
  • Cancel
Ben Heck Featured Content
Forum Engine Management
  • Blog
  • Forum
  • Documents
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Ben Heck Featured Content to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 63 replies
  • Subscribers 46 subscribers
  • Views 4156 views
  • Users 0 members are here
Related

Engine Management

jack.chaney56
jack.chaney56 over 9 years ago

Hi Ben,

I am a programmer with a very small amount of skill with circuits, and am looking to create a platform for an engine management system, using an Arduino Mega 2560. I had done a bit of the coding, when I ran into some timing issues with the built in Arduino manager, so I switched over and started using AVR Studio and a programmer to go directly to the chip itself.  The code looks like it should work ok, but now I need some additional circuits to handle the energy levels of coils and injectors (Something like IGBTs). Sensors are being run through simple dividers (no protection yet), and cam and crank inputs are through a simple comparitor

 

Let me know what you think,

Jack

  • Sign in to reply
  • Cancel

Top Replies

  • jack.chaney56
    jack.chaney56 over 7 years ago +2
    Back again... After a bit of time away seeking enlightenment (and a steady paycheck), I am ready to get back to work on my project. I have continued to play around with the code and a number of components…
  • jack.chaney56
    jack.chaney56 over 7 years ago +2
    I want to start this thing right, so the shopping list for people that want to play along at home: Raspberry Pi - version is not significant if you don't mind a slow response when using Eclipse, but 3B…
  • jack.chaney56
    jack.chaney56 over 7 years ago +2
    Start off with two things. First, I forgot (neglected) to provide instruction on how to get the compiled code onto the Nano. Fault of familiarity; having done the process so many times, I had shifted to…
  • jack.chaney56
    jack.chaney56 over 7 years ago

    clean up is done... time for fun.

     

    Sharp eyed folks out there might recognize, that most all the parts are in place for performing ignition management. The tach event array tkEv[] holds the TDC for each cylinder. By subtracting a value for total advance from each of the TDCs a coil event (coEv[]) angle is obtained. This is done simply in a short loop in the 1mS ignition process while the engine is running, similar to the loop to set the tkEv[] values during engine off. The value of total advance is calculated once, then applied to the tkEv in the loop. The other part of the operation is the start of dwell for each event, the dwell is a value that provides sufficient time to charge the coil, but not too much beyond fully charging the coil. This value is also captured as an angle, and the start of event (cost[]) is calculated by subtracting the dwell angle from the coil event angle. This is also done in the loop. The calculation of dwell angle is also a one time operation, and then applied in the loop.

     

    That wordy explanation, works out to just a few lines of code.

    UWord coEv[8];
    UWord coSt[8];
    
    void rtUpdateIgn(void) {
    ...
        updateTotAdv();
        updateDwlAng();
    ...
        if (tmOut > 0) {
    ...
            for (c = 0; c < cylCt; c++) {
                coEv[c] = tkEv[c] - getTotAdv();
                coSt[c] = coEv[c] - getDwlAng();
            }
    ...

     

    The two functions getTotAdv() and getDwlAng() return the angle of advance, and the angle of dwell calculated the one time.

     

    The last part is to include the operation in the scheduler, in the same way as the tach. The difference being, coil operation passes the cylinder number for cases where the operation is coil on plug, so the call to setCoil() has the coil number as well as the state.

     

                if ((min < coSt[c]) && (coSt[c] <= max)) { ft = (SLong)(coSt[c] - pa) * bs / PART2; ignCoHi(c, ft, tm); }
                if ((min < coEv[c]) && (coEv[c] <= max)) { ft = (SLong)(coEv[c] - pa) * bs / PART2; ignCoLo(c, ft, tm); }

     

    and the same for the other range of min/max

                if ((min < coSt[c]) || (coSt[c] <= max)) { ft = (SLong)(coSt[c] - pa) * bs / PART2; ignCoHi(c, ft, tm); }
                if ((min < coEv[c]) || (coEv[c] <= max)) { ft = (SLong)(coEv[c] - pa) * bs / PART2; ignCoLo(c, ft, tm); }

     

    The coil process takes over the fast timer operation, and the tach is moved to the slow operation.

     

    You might ask what values should go in total advance and dwell angle, and you are right to ask. For now, something like 20 degrees (1820) for dwell and 8 degrees (728) for dwell should be fine. To run some preliminary testing, the routines updateTotAdv() and updateDwlAng() can be stubbed out, and the getTotAdv() and getDwlAng() just return the constant values.

     

    Now it's getting fun.

     

    Jack

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • jack.chaney56
    jack.chaney56 over 7 years ago

    Coming to the end of phase 1 of the project. I am attaching a zip file with the source to this stage. The next stuff starts getting into engine theory and why timing of certain events is more critical than others.... Oh dear, I have a nice zip file, and can't find how to attach it here. I will do some searching, then attach it as soon as I figure it out.  On to engine theory stuff...

     

    When the ignition event occurs (piston ignition), there is a downward force on the piston which is converted into a rotational force by the piston rod and crankshaft. When this happens, there is a similar force in the opposite direction which produces a wobble of the motor. Because things are generally bolted down, the motor doesn't jump out of the compartment, however the force still is there. The goal is to reduce the effect caused by this rocking motion. The solution implemented is to have the pistons fire in a sequence to balance out the forces. This is why engines implement a firing sequence Chevy uses 18436572 for an 8 cylinder motor. It is possible to keep this sequence stored someplace in an array, and just read the array value based on the sequence number in the coil firing sequence, and for many, many operations, this is the method used.  But I looked at the problem, and said, how do I make this easier for the controller. The solution became simple, just save the angle in the array properly.  For the Chevy 8 cylinder example; cylinder 1 is zero degrees, cylinder 8 is at the first position past 0, or 90 degrees. cylinder 4 is in the second positon, or 180 degrees, cylinder 3 is next at 270, etc.  When the exercise is over, the array of positions is (using our radians and the tkEv array).

    tkEv[0] = 0;

    tkEv[1] = 57344;

    tkEv[2] = 24576;

    tkEv[3] = 16384;

    tkEv[4] = 40960;

    tkEv[5] = 32768;

    tkEv[6] = 49152;

    tkEv[7] = 8192;

     

    Which is how it gets stored in the calibration section, along with the cylinder count (8). The calisthenics can be performed in the user interface for the calibration program. Returning to the program, the window is compared to each cell of the array and when the value is within the window, the event is scheduled. it can be seen that the counter for doing the comparison, now holds the proper cylinder number.

     

    Next thing to look at is the issue of "advance". For those that don't know already, in a cylinder, fuel and air are mixed to produce a flammable mixture, then under pressure, the mixture is ignited by a spark. The ignition of the fuel mixture is not instantaneous. In super slow motion, it is interesting to see the burning of the mixture occurs in a traveling wave. The goal is to maximize the impact of the wave at the point of TDC, so the greatest amount of energy is transferred to the down stroke of the power cycle. Because the rate of burn changes based on pressure and does not happen instantaneously, the command to ignite fuel happens before the cylinder reaches TDC. This is called the advance, and is measured as an angle. As the speed of the motor increases, the angle of advance also increases to compensate for the burn rate remaining generally the same. However, the rate of burn is somewhat dependent on pressure as well, so there is also a pressure compensation that needs to be factored in. Earlier in the compression cycle means the pressure value is lower, also, if the intake volume, measured by manifold air pressure (MAP), is lower or higher, the compression value changes as well. The good news is, the change in compression based on cylinder position sort of balances out because it generally increases to a stable amount and the RMS value (this is sort of based on a sinusoidal curve), stays pretty static, the MAP is the governing factor and the lower the MAP the more time is needed, so the advance increases. We have identified two components that influence the value of advance, the RPM and the MAP. The ignition is actually a chemical reaction called oxidation. Because it is a chemical reaction, the ambient temperature of the container (cylinder) also factors into rate of reaction. This means that temperature will also need to be factored into the value of total advance.

     

    Sounds a little like this is getting into some complex math during runtime. The rule in embedded systems is a table is always faster. So, how to use a table in this case. Quite simply, if the table is a two dimensional array, with one axis as the RPM and the other as MAP, the table can be constructed so the value of advance resides at the array cell based on the RPM and MAP coordinates. However, for a reasonable range of MAP values and RPM speeds, the array would tend to become very large. In order to keep the table size reasonable, some math is necessary. The technique is called planar interpolation. You may be familiar with linear interpolation where one value X0 and another value X1 and the f(x) values Y0 and Y1 that equate. Any point Yn along the line segment, can be calculated based on the Xn point. The equation is:

                      Xn x (Y1 - Y0)

    Yn = X0 + ---------------------

                          (X1 - X0)

     

    Similarly this operation can be done in two dimensions. The difference is, instead of using two end points, the operation uses the four corner points of a plane. The corner points are Z0, Z1, Z2, and Z3 and relate to X0, X1, Y0, and Y1 where Z0 is the value at (X0,Y0), Z1 is at (X1,Y0), Z2 at (X0,Y1), and Z3 at (X1,Y1). The formula resolves to:

     

    Z0(X1-Xn)(Y1-Yn) + Z1(Xn-X0)(Y1-Yn) + Z2(X1-Xn)(Yn-Y0) + Z3(Xn-X0)(Yn-Y0)

    ----------------------------------------------------------------------------------------------

                                           (X1-X0)(Y1-Y0)

     

    Thats the formula, I'll add it to code in a little while. I want to save this so it isn't lost (lots of editing)

     

    Jack

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • jack.chaney56
    jack.chaney56 over 7 years ago

    I found out how to attach a zip file... I had to go over to the advanced editor

     

    So here is the zip with the source so far.

    Attachments:
    ECM_E14_20180901.zip
    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • jack.chaney56
    jack.chaney56 over 7 years ago in reply to jack.chaney56

    ...as expected, I checked my work after my panic of loosing all my work and noticed the linear interpolation was a little wrong. The X0 + should be a Y0 +

     

    sorry again

    Jack

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • mp2100
    mp2100 over 7 years ago in reply to jack.chaney56

    Jack.

    Yes, please. Pay attention to what your wife says. It will make the results better for you, everyone. :-)

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • jack.chaney56
    jack.chaney56 over 7 years ago in reply to jack.chaney56

    Checking back to make sure I am covering things the way I said, and so far I haven't strayed too far. The only thing I skipped was the part about injectors. This is was because the only thing different about injectors is the schedule. There are different strategies with injectors, they are; throttle body injection (TBI), batch, staggered batch, sequential, and staged.

     

    TBI is the simplest, and is quite similar to normal aspiration. Normal aspiration is when the fuel is drawn into the carburettor by the intake vacuum, and controlled by a needle valve. With throttle body injection, the injector shoots the fuel into the intake chamber.  With normal aspiration, the flow is continuous, with TBI, it is pulsed to control the volume of fuel, and with TBI it is pulsed four times per cam cycle. Batch is when the injectors are mounted along the intake manifold, closer to the cylinder intake, and usually an injector for each cylinder. Batch means all the injectors open at the same time, twice per cam cycle. Staggered fire, is the same as batch, except the injectors are divided into two groups, and each group fires together, twice per cam cycle, but out of phase so half then the other half then the first again, etc.

     

    The last two are for performance systems, again with injectors close to the cylinder intake (or inside the cylinder). Sequential means the fuel is supplied during the intake fueling stroke of the cylinder and needs to be timed accordingly. Since it is sequential, each injector operates independently, and only fires once per cam cycle. Staged fueling is again, for high performance systems when the demand for fuel exceeds what can be supplied by a single injector. In these cases, a second bank of injectors is used to increase the volume. The timing follows the pattern of sequential injection.

     

    Without getting into volume of fuel (yet), it is possible to see the scheduling of fuel injections becomes just another event pair to open and close the injectors, either individually or as a group. The timing can be associated again with an angle of event.  There is lots more to fueling, which will be covered, but I hope this provides how much of the work is already in place from the ignition timing operation.

     

    Jack

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • mp2100
    mp2100 over 7 years ago in reply to jack.chaney56

    Still trying to catch up with all the details but I'm enjoying reading thru it all.  I  want to encourage your postings.  I'm not in the automotive industry but chemical industry. It's all kind of the same and all a bit different.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • fayobambam@gmail.com
    fayobambam@gmail.com over 7 years ago in reply to jack.chaney56

    I don't know if it has been said but there is an open source project called speeduino. Its been running engines for a while now, actually my daily runs on it. It started on the ATMEGA 2560 but its been ported to the teensy 3.6? ARM32. You could use the well developed hardware for testing purposes with your code.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • jack.chaney56
    jack.chaney56 over 7 years ago in reply to rsc

    Hi again,

     

    Back to your first statement, about volume of work for a single programmer.  I guess it might be... but I am an old, retired, programmer. This is a good exercise to see if it really can be done.

     

    My problem is, I do need help with the hardware stuff (circuit design and layout). My stuff is all using breadboard, LEDs, and some Rube Goldberg mechanical devices.  I think I have the software working, but would really appreciate some partnership assistance from time to time

     

    Jack

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • jack.chaney56
    jack.chaney56 over 7 years ago in reply to fayobambam@gmail.com

    Hi,

    No I had not seen that (yet), if you could post the link here, I can chase things down and see if it will give me some help with the hardware aspects of this project. My source is primarily for 328, but I also have a version that runs on 2560 that uses all shared code with the exception of 4 files.

     

    Thank you for the shout out,

    Jack

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
<>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube