Guri: Ignition Controller for Air Cooled Engines

Ignition controller for VW air cooled engines.

Similar projects worth following
Volkswagen air cooled engines have been produced over 70 years and millions of them still in use today pushing beetles, buses and even small aircraft. Such engines cheap and easy to maintain yet their outdated design provides space for a lot of hacking. The present project addresses a small but important improvement in the engine by the control of ignition system timing.


In a typical ignition system the high voltages necessary to burn the fuel are generated by a coil which is driven by a switching mechanism linked to the crankshaft. The switching is mechanically synchronized in order to provide the spark at the right moment, so the fuel has time to burn and push the piston with the power of the explosion.

Such process involves three important time related parameters: Coil charging time, Fuel burning time and Engine speed. The burning time also depends upon the load on the engine which is perceived by the vacuum in the admission chamber (manifold).

One of the problems of the ignition system is that both the charging time and the fuel burning speed are nearly constant allover the engine speed rate, which required some compromise solutions even in the systems with electronic ignition:

  • The coil charging time was set about 50% of the time (Dwell time) and the current is limited by the coil internal resistance (a series resistor is also used in some systems). The current limitation implies in a spark with low energy, specially during startup where the battery voltage can drop down to 8 Volts.
  • The burning time is changed according to the engine speed by the use of mass and spring mechanism (centrifugal advance) and with a vaccum capsule (vaccum advance). Both mechanisms provide an angular displacement that is tuned to match with the timing required by the engine, but the dispersion of parameters specially on the springs used in both mechanisms is high and you can't find spare/alternative springs to buy, only assembled parts which in turn are physically alike but have different part numbers and no information available.

The present project tries to address both of problems by providing precise timing of both coil charging time and spark release with the minimum addition of parts and adds some safety features.


The circuit was designed to stand between the original sensor and the coil. It consists of a Micro controller, a MAP sensor and and a Power Transistor.

The diagram below depicts the timing for a typical system with HALL sensor:

At the TDC the microcontroller measures the time taken in the previous cycle (90° of the distributor shaft). Then the software assumes that the timing of the next cycle will be close enough from the previous cycle, i.e. it assumes that the timing between two cycles is nearly constant (the rate of change can be considered in the calculation using a filter or a PID calculation, tough). Then it adds the base timing with the vaccum timing to calculate the moment of the spark. From the Spark time it subtracts the coil charging time and calculates the moment of the starting of the charge. Both times (Start of Charge and Spark) are programmed in two timers which in turn will generate an interrupt that will turn the coil on and another that will turn the coil off, thus generating the spark that will generate and explosion which will peak a bit after the TDC.

One important thing to notice about the picture above is that the timing reference is being taken at the TDC instead of 10°-15° before TDC, usually used in conventional system.

Software Architecture

The basic software architecture consists of a main loop and several interrupts.

The main loop is where the ADCs are read. One of the ADC channels reads the car battery voltage and use the value to calculate the coil charging time. Another channel is used to read the vacuum signal coming from the MAP sensor and provides an additional time for burning the mixture.

The external interrupt is used to measure the time it take for the engine to turn 180° which is sensed every 90° on the distributor shaft (which runs at half speed of the engine). From this time it is subtracted the base time (around 2ms) added to the contribution from the vacuum sensor and resulting in the time Tspark which is the moment where the spark must be generated. Then, from Tspark is subtracted the coil charging time and the result...

Read more »

  • 1 × ATMEGA8 Microprocessors, Microcontrollers, DSPs / ARM, RISC-Based Microcontrollers
  • 1 × 74HC74 Electronic Components / Misc. Electronic Components
  • 1 × 7805 Connectors and Accessories / Miscellaneous Connectors
  • 1 × IRGB14C40 Ignition IGBT with on-chip Gate-Emitter and Gate-Collector clamps
  • 1 × PRT03/04 (Magnetti Marelli) 100KPa Manifold Air Pressure sensor

View all 14 components

  • ​Map Sensor Constraints

    danjovic05/25/2016 at 19:16 0 comments

    The easiest way to measure the Manifold Air Pressure is using an off the shelf automotive MAP sensor which integrates all signal conditioning circuitry and provides a linear response to a vacuum signal.

    The MAP sensors are specified in kPa (kilo Pascal), so before choosing a sensor we must convert the original vacuum capsule response range to kPa. Talking in numbers the engine vacuum capsule provides advance from 60mmHg to 270mmHg which corresponds from 8kPa up to 36Kpa.

    Unfortunately the MAP sensor with the range most close to this that I could find was the PRT 03/04 which covers from 17 to 105Kpa. The problem with this sensor is that the measurement starts at 17kPa which will make us loose the measurement down to 8kPA (60mmHg).

    However, a closer look at the vacuum x advance table shows us that the vacuum contribution to overall advance can be zero up to 110mmHg. Then if we add 0° of advance for vacuum signals below 127mmHg in practice we have only lost a small range of measurement (110mmHg to 127mmHg). Good enough.

  • Testing Interrupt chain

    danjovic04/30/2016 at 21:52 0 comments

    The firmware for Guri deeply relies on interruptions to work. Today I've started to test this mechanism. Basically an input generated by the RPM sensor (points/hall sensor) is used to trigger the external interrupt which clears the Timer 1 and program two output compare values being one to turn on a power transistor and charge the coil and another for turning off the transistor thus interrupting the coil current and generating a spark.

    There are at least two conditions that should be cared of:

    1. The engine speed is decreasing so fast that we reach the next revolution pulse before the time to the coil to turn off. As a failsafe for this condition the ext int code turns the coil off.

    2. The engine stops but timer 1 is running and both compare outputs are programmed to generate interrupts. To deal with that situation the timer 1 overflow shuts the coil off, then stops the timer from counting and disable the compare interrupts. Both Timer1 and compare interrupts will be turned on again only in the next pulse from engine revolution sensor.

    It is worth to mention that the when the first pulse from engine revolution sensor, either after powerup or after an overflow of timer 1 will be dismissed as with timer 1 stopped its value will be zero which is out of the valid RPM range for enabling the charging of the coil.

    The capture below depicts the simulated engine revolution sensor in blue and the coil charging pulse in yellow. Assuming (for instance) that the coil needs 3ms to charge and the spark must occur 2ms before the TDC, the firmware measures the time taken from the previous turn and subtracts the amount of timer1 counts equivalent to 2ms and program compare output B. From this time it subtracts the amount of time equivalent to 3ms and program the compare output A.

    Such timings can be seen in more detail on the capture below

    The rising edge of the blue trace represent the moment that the engine reaches the TDC.

    2ms before that is where the yellow trace drops down to disable the power transistor and generate the spark.

    3ms before the spark time (5ms before TDC) the yellow trace goes up to enable the power transitor to charge the coil.

    The events have been described bacwards because this is how the firmware calculate the times: Bacwards from the estimated time of the next TDC.

  • Calculation of the voltage divider for measuring the battery voltage.

    danjovic04/29/2016 at 14:58 0 comments

    The expected operation range of the car battery is something from 8.0Volts during startup up to 14,2 Volts for the generator/alternator providing full charge at high engine speeds. Since the maximum voltage at ADC is +5V from the microcontroller Vcc the ratio between the resistors should be around the voltage ratio. Assuming a small margin on the upper voltage limit, lets say 15 Volts we expect a ratio of around 15:5 or 3:1. As for the voltage divider composed of two resistors, R17 on the upper side and R18 on the lower side the division ratio is (1+R17/R18). Playing with some E12 series values we pick the values 33 and 15 which gives a ratio of 3,2:1 which is close enough.

    Knowing that the output impedance of the source for the AVR ADCs shall be less than 10KOhms we choose the resistors so the Thevenin equivalent resistance is about one degree of magnitude below or something around 1KOhm. Then by selection 3300 Ohms and 1500 Ohms for R17 and R18 we have an equivalent resistance of around 1031 Ohms which is again good enough.

    With such values we have the following Counts on the ADC for the expected operation range.

  • Signal Generator

    danjovic04/27/2016 at 04:06 0 comments

    I've implemented a simple signal generator using my AVR-Fun experimental board in order to help me in the tests. The RPM can be increased/ decreased in steps of 50 or 100 RPM within the 150..7000RPM range using the 5 buttons on the board. The third (central) button sets RPM to Idle value (RPM).

    The prototype has advanced a bit with the incorporation of the frontend circuitry for sensing RPM and manifold vacuum.

  • New layout for preliminary board

    danjovic04/22/2016 at 20:27 0 comments

    Created a new layout for the boards. Two trim-pots were added to allow tuning of the coil charging time as well as the advance time. Both will come in handy whe debugging the firmware.

  • Working on the prototype

    danjovic04/21/2016 at 17:36 0 comments

    I've started to work on the prototype. It is being gradually assembled and tested beginning with the microcontroller and components necessary to clock it and read the ADCs. So far, the components have been placed on the veroboard in a position very similar to the preliminary PCB

    The basic program structure is ready and the ADC code is ready too.

  • Preliminary PCB

    danjovic04/18/2016 at 21:41 0 comments

    I've designed the printed circuit board for the prototype. It is a single faced design to make ease to build at home. It took me two jumpers to accomplish the task but they are hidden under the microcontroller.

    The board dimensions are 71 x 58.5 mm (2.8 by 2.3 inches) in order to fit into a CP-013 box manufactured by Patola.

    The circuit was some corrections proposed by @K.C. Lee (thanks). From the preliminary design I've added the series resistor in the base of the current sensing transistor (Q5) as well as the pulldown on the base of the IGBT (Q3). I've also picked standard value resistors of the voltage divider that will sense the battery voltage and added a clamp to Vcc to protect against voltage peaks above 19Volts on the high side of R17.

  • Preliminary schematics

    danjovic04/18/2016 at 16:44 3 comments

    First schematics, fresh out of the oven. Used only one voltage regulator, though.

  • Pressure Sensor

    danjovic04/15/2016 at 22:00 0 comments

    According to the engine data I have found (distibutor 040 905 205.32) the vaccum advance starts to add up to the base+centrifugal advance at manifold pressures above 60mmHG. After that an additional advance is added to the distributor up to 11~15° at 270mmHg. This is performed mechanically by a capsule with a flexible membrane attached to the distributor.

    In new vehicles the manifold pressure is measured by using a sensor, usually a piezoresistive sensor, powered by 5Volts and providing a linear output voltage within a givem pressure range. Such sensors are specified in KPa therefore to find a sensor that fits the VW air cooled carburetor system it is necessary to convert the MAP values to KPA.

    60mmHG = 8KPa

    270mmHG = 36KPa

    Unfortunately most of the MAP sensors available in the market are in the range of 200-400Kpa. The most suitable sensor I was able to find was one of the models used in the early fuel injection systems.

    Such sensor, modelPRT 03/04 is manufactured by Magnetti Marelli has a ful with a full scale of 100KPa. The bad is that the measuring range for this sensor begins at 17KPa (127.5 mmHg) and this will will cause some loss in the beginning of the pressure scale we need to cover.

    Another issue to consider is the voltage range for the expected pressure range the sensor will work on. It will vary from 250mV to 722mV. Initially the AVR ADC will be measuring this value directly and this will result in ADC output values in the range of 51 to 148 counts which is less than 100 values. That may be a good size for a lookup table but it might be necessary to add an amplifier. This will be addressed in the test results.

  • ​Prescaler value selection​

    danjovic04/14/2016 at 22:16 0 comments

    In the VW air cooled engine the distributor shaft turns at a half of the speed of the crankshaft. Then for a given RPM the distributor turns at RPM/2. In terms of time the engine takes T to perform a full turn while the distributor takes 2*T.

    Since the distributor generates 4 impulses at each turn, the time interval between two impulses is a quarter of the time for a full turn of 2*T/4 which equals T/2. We must use this ratio to choose a prescale factor for the Timer1 that will provide good timing resolution for higher RPMs and yet don't overflow at lower RPMs.

    Assuming the AVR will operate at 16MHz, we have 62,5ns per cycle. The prescaler values availabe are 1:1, 1:8, 1:64, 1:256 and 1:1024

    The engine idle speed is around 900RPM and the maximum speed is around 6000RPM, but during startup the engine RPM is low so let's check consider a range from 300RPM up

    In that range we have an interval between impulses (T/2) from 100ms to 5ms. Within these times we can have the following amount of impulses for different prescalers.

    The smaller prescale value that fits to our need is 64. With this value we and time engine speeds as low as 150 RPM yet we still have resolution of 10 RPM around 6000 RPM.

View all 15 project logs

Enjoy this project?



ogdento wrote 02/02/2017 at 07:27 point

this is awesome work.  a system like this would be perfect on my 1965 VW Notchback!

  Are you sure? yes | no

danjovic wrote 02/02/2017 at 15:32 point

Thanks! I haven't finalized the project yet but stay tuned! In the meantime you can check another project, that uses a modified TSZ-i module and has dwell control:

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates