Projects Research & Design Hub

Open-Source Engine Control

Via KICAD, GCC, Eclipse and OpenOCD

Jared and Andrey developed an open-source engine management system. In this article, Jared explains how he designed an engine control circuit board to control a large variety of internal combustion gas engines.

  • How to build an open-source engine management system and engine control circuit board

  • How to use rusEFI firmware 

  • How to use an RTOS to decode the pulses

  • How to detect the crank shaft angle

  • How to interpret the engine control output signals

  • How to develop the event scheduler

  • More about the build server and development environment

  • rusEFI firmware

  • STMicroelectronics (ST) STM32F4 Arm processor

  • ST’s Discovery development board

  • EFI Analytics’ Tuner Studio

  • Maxim Integrated MAX9926

  • ChibiOS real-time OS

  • QUCS simulation software

  • KiCAD free multiplatform PCB layout tool.

Have you ever been frustrated by a snow blower with worn springs or corroded governor linkages? Or, have you ever thought that you could adjust your vehicle’s engine to make it run better? You’re not alone. I felt the same way, which is why I developed a circuit board—dubbed Frankenso—for controlling a wide variety of engines.

Prior to starting the engine control project, I searched the Internet and found a few low-cost options. However, most had a variety of issues. For some projects out there, I couldn’t access the hardware because of licensing issues. I also found several edgy gearheads who did not react well to professional criticism. It was a frustrating mess. Fortunately, I eventually came across a software developer I could work with, Andrey Belomutskiy, and rusEFI (, a GPL open-source engine control unit (ECU) project run by a community of like-minded people interested in electronic engine control. That started a chain of events that resulted in Frankenso (see Photo 1).

Photo 1
Frankenso uses a MAX9926 which is configured in a way that allows the use of either a VR signal or a digital signal from a Hall sensor or optical sensor.

Frankenso is an engine control circuit board which can control a large variety of internal combustion petrol (gasoline) engines. At the time of writing this article, the rusEFI firmware with the Frank boards has controlled a high-revving, 10,000-RPM single cylinder two-stroke moped engine, as well as a V8 sequential injection and a variety of variations between those two setups.

An engine requires the controller to know its crankshaft angle. Then the controller has to deliver injector pulses for fuel and spark pulses for ignition, and it has to provide those pulses at the proper crank angle to enable the engine to operate. There are a variety of circuits required to get information to and from the controller such that the controller can know when the spark and fuel events need to happen. Frankenso does this with the help of the rusEFI software.


The rusEFI software includes the firmware for the STMicroelectronics STM32F4, which is a 168-MHz ARM processor that you’ll find on the $15 Discovery development board. This brain board can connect via USB/serial communications to the JAVA-based dev console, which allows for development tasks. The dev console is a JAVA multi-platform GUI that enables you to set up which injector is injector 1 or which circuit is the fan driver. The rusEFI software also has a communications channel to a popular tuning software package put out by EFI Analytics called Tuner Studio (TS). The rusEFI firmware is also documented with Doxygen, which allows anyone with a web browser to study the code. Doxygen offers some interesting call graphs and includes many color schemes and URL links to make it easier to study the code. The Doxygen documents are available at

Once you finish the initial setup with the dev console, the general process is to plug in a USB cable to a laptop, open TS, and adjust the engine parameters. Frankenso includes an LCD and joystick for tuning without an external PC. This can be really handy if you forget your laptop on race day and you need to change your upper coolant temperature limit from, say, 230°F to 250°F. I once saw that happen to a hill climb racer. His used a re-flashed OEM ECU, which had the upper factory limit set at 230°F, and then it shut the engine off. He didn’t care if it blew some water out the radiator cap as it crossed the finish line so he wanted to change the limit to 250°F or more. He really wished he had a flexible solution that would allow him to make small adjustment like this, which is what Frankenso strives to offer.

Let’s review how the basic signals flow into, through, and out of the Frankenso board. We’ll start with the crank angle decoding.


There are several ways the crank shaft angle is detected. This crank angle is required such that the controller will know the proper times to deliver fuel and the proper times to create spark events. The three most common sensors are the variable reluctor (VR), Hall sensor, and optical crank angle detector. Frankenso uses a Maxim Integrated MAX9926 that is configured in a way that allows the use of either a VR signal or a digital signal from a Hall or optical sensor. The MAX9926 is basically an op-amp with high gain that will toggle its output based on a slight variation in input voltage. If you connect a coil to the op-amp’s positive and negative terminals (see Figure 1), then you wave a magnet across the front of the coil, and the coil will make a voltage across the op-amp.

This will result in the op-amp’s output going to its positive rail and negative rail. The op-amp output is then connected to the microcontroller. For an engine, the magnet is embedded in the center of the coil, and the crank shaft has a toothed wheel. When the metal of the toothed wheel is moving across the front of the magnet, it will change the flux that flows through the coil, which changes the op-amp input voltage and then changes the pulses to the microcontroller. These digital pulses enable the microcontroller to decode the crankshaft’s angle.

Figure 1 
This is a VR crank angle diagram. The crank decoder OS task will analyze these pulses and will update the software with information like RPM and crank angle. (Source: Maxim Integrated)

So why use the MAX9926 instead of an op-amp? There are several reasons. One is that it comes with some internal resistors, which are really nice as well it has many features that make it rugged. Those resistors will allow a floating input to float to VCC/2. This is really handy for hall or optical setups. You can let one of the inputs float and then connect the other input to your digital input (see Figure 2). Whenever your digital input crosses VCC/2, the output changes state. Also, the MAX9926 has some nice clamping diodes that are handy if a VR is too hot, which can generate more energy and result in excessive voltage that the op-amp input cannot handle. The clamping diodes will offer significant protection, typically preventing damage to the sensitive op-amp input. This excess energy can be from a VR sensor, or simply coupled in via spark plug RF or other sources.

The input protection is handy for protecting digital signals as well as the analog VR signal. The MAX9926 is also really handy because it includes a design guide that helps you get all the parts balanced correctly. The design guide helps ensure you have properly chosen parts preventing things like overpowering the clamping diodes which ensures the input can handle the ripple from these inductive spikes as it runs to the protection diodes on the rails. The flexibility, as well as the design guide, is worth the couple dollars for the chip. The result from this chip is either a protected conversion of an analog signal into a series of digital pulses, or it’s a protected buffered digital input. Buffering the digital signal is handy as it allows protection of the upstream devices and keeps noise off the PCB.

Figure 2 
This figure is similar to Figure1, but it is modified to show how the Hall sensor or optical sensor is connected.

Once the input is captured physically, the software will have to decode the pulses. The software uses a real-time OS known as ChibiOS, which allows for several tasks to be executed at the same time. One of these tasks is the crank angle decoder. There are many different crank wheel patterns out there. Some are called skipped tooth; others have some really odd patterns. The crank decoder OS task analyzes these pulses and updates the software with information like RPM and crank angle. One of the great things about Frankenso using rusEFI software is that the crank decoder is very flexible and it’s possible to decode pretty much any pattern. Different decoders can be configured for different applications, and they can be changed with some software called the “dev console.” If a pattern isn’t currently decoded, there are several examples and a new pattern decoder can be developed. Typically, it takes a day or so to get a new decoder created.

Now that the crank decoder task is updating the RPM and crank angle, another OS task known as the scheduler looks at this information and update information for fuel events, spark events, and other such events. For example, when set to use the speed density fuel algorithm, it will look at the Manifold Absolute Pressure (MAP) sensor and RPM then it will use a tuning table to determine a fuel pulse’s length. After this initial prediction, there are manipulations for things like cold engine enrichment to increase fuel when the engine is cold and acceleration enrichment for when you tromp on the long pedal. Things like that will cause variations beyond the initial prediction. Let’s say this algorithm determines the fuel pulse should be 4 ms to deliver the proper amount of fuel for that rotation. The scheduler also has been preconfigured to inject at a specific crank angle. Let’s say that’s been set to 10°. Refer to Listing 1 for a snippet of speed density algorithm, which is one of the options for predicting fuel.

Listing 1 – Speed density fuel prediction algorithm[1]

Part of the scheduler relies on a 1-MHz, 32-bit event timer. This timer allows the scheduler to schedule events for up 4,000 s, which is about 1 h from the current time. There is a piece of memory that contains a list of events and the time when that event should happen. For every processed event, it looks at this memory and finds the time for the next event. It then sets the timer to trigger for the next event. While processing that event, it again resets itself. This allows scheduled events to be processed and update the outputs for fuel and spark (see Listing 2).

Listing 2 – Scheduler snippet[2]

OK, now back to the scheduler. It knows the fuel pulse needs to start at 10°, so it first schedules an event to happen at an earlier time—let’s say, 0°. This event refreshes the fuel pulse based on the most recent engine data. As noted above, this rotation should start at 10° and should be 4 ms. The scheduler knows the current position, RPM, and current time, so it can schedule an event that turns on the injector at time x and turn it off at time x + 4 ms. Refer to the snippet in Listing 3 to see how events are scheduled.

Listing 3 – Event scheduled snippet[3]

Injector 8 can be set to open at angle 700°, so at 690° it schedules an event to calculate the fuel pulse, which we’ll assume is also 4 ms. Then it again calculates the event times that turn the injector on and off. The scheduler continuously updates this way for the fuel and spark events. Other events can be scheduled as required, and they can be scheduled for 0.1° of rotation at 10,000 RPM.


Now that we have briefly gone over how the signals are captured and flow through the software, let’s go over the outputs. For example, the injectors are nothing more than solenoids. The inductive kicks are something that is commonly seen by embedded applications. An injector is nothing more than a normal solenoid, but with precision timing requirements. While the snubber or flyback diode topology was common once upon a time (see QUCS simulation in Figure 3a), for precision applications, it has gone the way of the dodo. Modern tech uses an over-voltage protected (OVP) MOSFET (see QUCS simulation in Figure 3b). These will clamp the voltage to a fixed voltage and decay the energy linearly.

The linear decay means you will have more accurate control over when the pintle drops and closes off fuel. A snubber diode topology will recirculate the current through the coil and decay exponentially. Not only does this take longer, the tolerance for when the pintle closes is larger, which adds a tolerance on your delivered fuel. So you have less knowledge of how much fuel you actually delivered for the combustion charge. There is also some consideration about the thermal constraints. The snubber diode relies on the coils internal resistance to dissipate the energy as heat, which is then absorbed by the fuel. Generally, you want cold fuel and cold intake air. Some people consider this to be a big deal, but in reality, this fuel heating is very small compared to the rest of the energy being involved.

However, it does raise a slight benefit of the OVP topology, as OVP keeps that small amount of heat out of the fuel. A down side of the OVP topology is that you need to consider the heat in the electrical enclosure. This decay energy is absorbed largely by the OVP, which needs to be removed from the low-side driver chips or they will hit the thermal limits and shut down. Refer to Figure 4 to how that was taken into consideration with the Frankenso board. At the time of writing this, I do not know the exact Rth, but we expect the worst case to be the red line and the best case to be the blue line. Based on a gut feeling and other experiences, I expect an Rth of 50C/W can be obtained for reasonably low cost.

Figure 4
This might or might not need a heatsink. The 100°C is the UL suggested limit for FR4. The driver chip is limited to 150°C. 

For Frankenso, the goal was flexibility so it uses the OVP MOSFET and if you need the diode snubber topology for some reason, it includes a place to install a snubber diode. We have seen the need for the diode when the low-side drive is being used for something other than injectors. Commonly, alternators will use a low-side field control. This can be connected to the injector low-side driver and you want a slow response. So a diode can be installed that will allow that channel to function as an alternator control instead of an injector controller. Yes, these low-side drivers can be configured for more than injectors. They are generic low-side drivers that can be configured for other tasks like fan control, alternator control, fuel pump relay control, and so on.

The ignition driver is done with a high/low driver chip (see Figure 5). This chip can drive an external igniter like the J701. The coil’s secondary side will generate around 40 kV, which results in around a 400-to-500-V pulse on the primary side of the coil. Often the igniter is integrated into the coil, which is then driven by 12 or 5 V or is a low-side drive. The high/low driver allows a configurable high-side drive for either 5 or 12 V, and it changes state from this high to the low GND state. This allows it to drive pretty much any igniter out there.

Figure 5
This is a wiring diagram that was done on at least one engine. There are many options for how this can be wired. 

That’s a very basic overview of how the Frankenso board with the rusEFI software work. There are many layers to this project. We are looking to interest people who like a friendly environment and are results driven. There are many areas we know could be better optimized, but we tend to focus on features and optimize only if that would enhances a feature. If you would like to get involved, we would we very happy to have you along. If you simply want to learn more, that’s also OK. Feel free to contact us and chat it up in the forums. Even better, feel free to post some suggested firmware feature changes.


Other items of potential interest include the build server, which includes automatic testing with live hardware that creates protective layers for development and prevents unintentional bugs. As well, there is PC simulation which allows development without hardware, and there are several features like SD card for datalogging and Bluetooth wireless. The firmware is compiled on a build server. It’s possible for developers to get access to this server such that they can compile with the same setup as the official releases.

The development environment is an Eclipse Windows-based setup; however, it uses a GPL compiler. If someone were to attempt getting everything configured, it could be a Linux-friendly development environment. Frankenso was developed with KiCAD, a GPL free multiplatform PCB layout tool. The bare boards and solder-it-yourself kits are available. We occasionally get boards populated to help minimize the labor before people can get involved. We are trying to make this more friendly to software developers. There are two primary developers right now who have made many great contributions. It would be great if we can get more people to contribute.


To-do items include baro corrections for applications with active boost via turbochargers or superchargers, error checking via temperature sensors, and event logging. We also want to develop fuel stratified injection (FSI) drivers. There is an endless supply of items that can be developed. A list is posted at:

[1] RUS Electronic Fuel Injection,

Maxim Integrated, “MAX9924–MAX9927: Variable Reluctance Sensor Interfaces with Differential Input and Adaptive Peak Threshold,” 19-4283, Rev 4, 2012,
rusEFI Source, also mirrored here
rusEFI Wiki,

ChibiOS Free embedded RTOS
ChibiOS |
Tuner Studio (TS)
EFI Analytics |
KiCAD PCB Layout tool
MAX9926 VR Sensor interface
Maxim Integrated |
rusEfi GPL Open-source ECU
rusEfi |
STM32F4 Discovery
STMicroelectronics |


Keep up-to-date with our FREE Weekly Newsletter!

Don't miss out on upcoming issues of Circuit Cellar.

Note: We’ve made the Dec 2022 issue of Circuit Cellar available as a free sample issue. In it, you’ll find a rich variety of the kinds of articles and information that exemplify a typical issue of the current magazine.

Would you like to write for Circuit Cellar? We are always accepting articles/posts from the technical community. Get in touch with us and let's discuss your ideas.

Sponsor this Article
+ posts

Jared Harvey ( is a Maine-based project engineer with a BS in Electromechanical Engineering.

Andrey Belomutskiy (, MS, is a New Jersey-based software developer and low-budget car racer.

Supporting Companies

Upcoming Events

Copyright © KCK Media Corp.
All Rights Reserved

Copyright © 2024 KCK Media Corp.

Open-Source Engine Control

by Jared Harvey and Andrey Belomutskiy time to read: 13 min