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 4138 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…
Parents
  • jack.chaney56
    jack.chaney56 over 7 years ago

    Back again...

    The next installment is to discuss units of measure and how to look at things from the computer's point of view.  The first measurement and the one that will be used first in the example is measurement of angle. If you have taken lots of math classes and had Geometry, you would probably remember a lot of this stuff, but if you haven't had the classes, and only kind of understand how angles work, I will provide an explanation in a method that I hope will be easy to understand. The angle system is based on the points of a circle, and a line drawn from the perimeter of the circle to the center. If you draw two lines from the perimeter to the center, the two lines come together at an angle. Map makers established a measurement system for angles and declared the unit of measure to be degrees, and there were 360 degrees in a circle. Which is to say the measurement of degrees around the circle increases, until the points join. This is a measurement of 360 degrees.

     

    Math moves forward, and a need for measuring the distance around the circle was needed, so a ratio between the distance from the perimeter to the center is called the radius, and the distance around the perimeter is called the circumference. Long ago it was proven that no matter what the radius of the circle was, the ratio between radius and circumference was a constant and circumference. That constant is named pi where circumference = 2 * pi * radius. Lots of work to determine the exact value of pi has been attempted over the years, and memorization of digits of pi has been a point of contest for nearly as long. Which led to another unit of angular measure called radians where 360 degrees equated to 2pi.

     

    With that background, I can now bring in my update. A circle having 2pi radians, and pi being a constant number, and because a significant amount of derivation of geometric formulas have been performed, if pi is thought of as just a constant, it is possible to use a binary constant, and if a conversion is provided, all the math will remain. My goal was to use a numbering system that worked well for computers, which operate in binary, and to avoid using floating point to maintain processing speed. I settled on using a 16 bit integer as a base value with a sign, and a signed integer limits to +/- 215. The result then would make the value of 2pi = 32678, so pi would equate to 16384, and when necessary, a constant conversion is possible to invoke. In the meantime, much of the world, and most of the people working with engine management, work with degrees, and if 360 degrees equates to 32768, the measurement of angle is +/- 0.0109 degrees, which is a decent tolerance. There is a secondary advantage for using this method, which is, in a four cycle system, because the cam cycle is two rotations, and it is necessary to know the position in the cam cycle, by using an unsigned 16 bit value, the calculations become greatly simplified.

     

    With all that explained, I will add one more element to the process. Because in fixed point (integer) operation, you don't want your number to become too big or too small, I am introducing a PART1 and PART2 values. These numbers when multiplied equate to the total degrees in the circle (DEG_PER_REV) which from previous is 32768. PART1 and PART2 are also selected as binary constants, so multiplication or division is performed as a simple left or right bit shift, and in source code, the simple addition of:

     

    #define PART1    64L        /* part 1 of full circle for calculations */
    #define PART2    512L       /* part 2 of full circle for calculations */
    #define DEGS_PER_REV  (PART1*PART2)

     

    Since this is used in lots of places, a common include file will contain these lines.

     

    I wanted to get a realistic measurement for the existing code, so I thought RPM would be a good value to provide, and it is possible to calculate with the given values to this point. The values needed are the time difference between teeth (crkDiff, measured in tics), the number of tics per minute (TICS_PER_mS * mS_PER_SEC * SEC_PER_MIN), which is a constant, and the number of teeth in a revolution (teeth, read from calibration). The equation becomes:

     

    RPM = TICS_PER_MIN / (teeth * crkDiff);

     

    Because TICS_PER_MIN is constant, and the value of teeth, doesn't change during runtime, it is possible to calculate

     

    preRpm = TICS_PER_MIN / teeth;

     

    as a saved constant when the engine is not running and the runtime equation is a single divide

     

    RPM = preRpm / crkDiff;

     

    Tying it all together...

    In the code previously, the ignition management had a "void rtUpdateIgn(void)" function, with a comment of "not used yet, but a place holder".  It's time to implement code here. To enable the code, just add a call the function in the 1mS timer0 interrupt. The function will be divided into two parts, one part for functions while the engine is stopped, and the other part for while the engine is running.  To implement this capability, a timeout value is maintained. The value is updated at each tooth interrupt, and decremented on each pass of the loop.  When the value reads zero, the engine is stopped.  The updated section for the first update is:

     

    #define TICS_PER_mS     2000
    #define mS_PER_SEC      1000
    #define SEC_PER_MIN     60
    #define TICS_PER_MIN    (TICS_PER_mS*mS_PER_SEC*SEC_PER_MIN)
    
    SWord teeth;
    SWord getCrankToothCt(void) {
    /* Calibration value in future, but for now just provide a constant */
         return 4;
    }
    SWord rpm;
    SWord preRpm;
    
    void rtUpdateIgn(void) {
     if (tmOut > 0) {
      --tmOut;
      rpm = preRpm / crkDiff;
     } else {
      teeth = getCrankToothCt();
      preRpm = TICS_PER_MIN / teeth;
     }
    }

     

    It might be necessary for the preRpm value to be an unsigned long, because of the size, but otherwise, this should work. The other part is the update for tmOut that is performed in the crank interrupt.

     

    ...
    #define QUART_SEC     250     /* provide a 250 mS timeout 1/4 second */
    ...
    ISR(INT0_vect) {
    ...
     if (isInt0Low() ^ isCrkRising()) {
      tmOut = QUART_SEC;
    ...

     

    This is a lot for an installment, but I did sort of want to have more. I will pick up to get the next component soon.

     

    Jack

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

    Back again...

    The next installment is to discuss units of measure and how to look at things from the computer's point of view.  The first measurement and the one that will be used first in the example is measurement of angle. If you have taken lots of math classes and had Geometry, you would probably remember a lot of this stuff, but if you haven't had the classes, and only kind of understand how angles work, I will provide an explanation in a method that I hope will be easy to understand. The angle system is based on the points of a circle, and a line drawn from the perimeter of the circle to the center. If you draw two lines from the perimeter to the center, the two lines come together at an angle. Map makers established a measurement system for angles and declared the unit of measure to be degrees, and there were 360 degrees in a circle. Which is to say the measurement of degrees around the circle increases, until the points join. This is a measurement of 360 degrees.

     

    Math moves forward, and a need for measuring the distance around the circle was needed, so a ratio between the distance from the perimeter to the center is called the radius, and the distance around the perimeter is called the circumference. Long ago it was proven that no matter what the radius of the circle was, the ratio between radius and circumference was a constant and circumference. That constant is named pi where circumference = 2 * pi * radius. Lots of work to determine the exact value of pi has been attempted over the years, and memorization of digits of pi has been a point of contest for nearly as long. Which led to another unit of angular measure called radians where 360 degrees equated to 2pi.

     

    With that background, I can now bring in my update. A circle having 2pi radians, and pi being a constant number, and because a significant amount of derivation of geometric formulas have been performed, if pi is thought of as just a constant, it is possible to use a binary constant, and if a conversion is provided, all the math will remain. My goal was to use a numbering system that worked well for computers, which operate in binary, and to avoid using floating point to maintain processing speed. I settled on using a 16 bit integer as a base value with a sign, and a signed integer limits to +/- 215. The result then would make the value of 2pi = 32678, so pi would equate to 16384, and when necessary, a constant conversion is possible to invoke. In the meantime, much of the world, and most of the people working with engine management, work with degrees, and if 360 degrees equates to 32768, the measurement of angle is +/- 0.0109 degrees, which is a decent tolerance. There is a secondary advantage for using this method, which is, in a four cycle system, because the cam cycle is two rotations, and it is necessary to know the position in the cam cycle, by using an unsigned 16 bit value, the calculations become greatly simplified.

     

    With all that explained, I will add one more element to the process. Because in fixed point (integer) operation, you don't want your number to become too big or too small, I am introducing a PART1 and PART2 values. These numbers when multiplied equate to the total degrees in the circle (DEG_PER_REV) which from previous is 32768. PART1 and PART2 are also selected as binary constants, so multiplication or division is performed as a simple left or right bit shift, and in source code, the simple addition of:

     

    #define PART1    64L        /* part 1 of full circle for calculations */
    #define PART2    512L       /* part 2 of full circle for calculations */
    #define DEGS_PER_REV  (PART1*PART2)

     

    Since this is used in lots of places, a common include file will contain these lines.

     

    I wanted to get a realistic measurement for the existing code, so I thought RPM would be a good value to provide, and it is possible to calculate with the given values to this point. The values needed are the time difference between teeth (crkDiff, measured in tics), the number of tics per minute (TICS_PER_mS * mS_PER_SEC * SEC_PER_MIN), which is a constant, and the number of teeth in a revolution (teeth, read from calibration). The equation becomes:

     

    RPM = TICS_PER_MIN / (teeth * crkDiff);

     

    Because TICS_PER_MIN is constant, and the value of teeth, doesn't change during runtime, it is possible to calculate

     

    preRpm = TICS_PER_MIN / teeth;

     

    as a saved constant when the engine is not running and the runtime equation is a single divide

     

    RPM = preRpm / crkDiff;

     

    Tying it all together...

    In the code previously, the ignition management had a "void rtUpdateIgn(void)" function, with a comment of "not used yet, but a place holder".  It's time to implement code here. To enable the code, just add a call the function in the 1mS timer0 interrupt. The function will be divided into two parts, one part for functions while the engine is stopped, and the other part for while the engine is running.  To implement this capability, a timeout value is maintained. The value is updated at each tooth interrupt, and decremented on each pass of the loop.  When the value reads zero, the engine is stopped.  The updated section for the first update is:

     

    #define TICS_PER_mS     2000
    #define mS_PER_SEC      1000
    #define SEC_PER_MIN     60
    #define TICS_PER_MIN    (TICS_PER_mS*mS_PER_SEC*SEC_PER_MIN)
    
    SWord teeth;
    SWord getCrankToothCt(void) {
    /* Calibration value in future, but for now just provide a constant */
         return 4;
    }
    SWord rpm;
    SWord preRpm;
    
    void rtUpdateIgn(void) {
     if (tmOut > 0) {
      --tmOut;
      rpm = preRpm / crkDiff;
     } else {
      teeth = getCrankToothCt();
      preRpm = TICS_PER_MIN / teeth;
     }
    }

     

    It might be necessary for the preRpm value to be an unsigned long, because of the size, but otherwise, this should work. The other part is the update for tmOut that is performed in the crank interrupt.

     

    ...
    #define QUART_SEC     250     /* provide a 250 mS timeout 1/4 second */
    ...
    ISR(INT0_vect) {
    ...
     if (isInt0Low() ^ isCrkRising()) {
      tmOut = QUART_SEC;
    ...

     

    This is a lot for an installment, but I did sort of want to have more. I will pick up to get the next component soon.

     

    Jack

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

    ...good, I went through the discussion of angular measurement and what is done to preserve relevant values, then didn't use what I had presented. Instead, I went to time and RPM which doesn't use it. However, the information is important, and will be needed for the next update, where I start to discuss timing and scheduler operation.

     

    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