And again with the coding…

Here’s a little Arduino code I’ve cooked up for the purposes of providing a nice crank signal to the FPGA-based ECU, for the purposes of bench testing the output. It’s a simulation of a nicely cleaned up, digital signal generated by a 36-1 toothed crank wheel on your typical Ford engine.

Essentially, a little throttle position sensor (read, potentiometer) is hooked up to adc pin 5. This is purely to give me something to twiddle to see if the FPGA is reacting quickly enough to the change in frequency (Not that I have any fear of this, really- damn thing is pretty fast- but alas, I must have something to fiddle with while testing, or it’s no fun!).

The LED flashing part is purely for visual effect; an ‘is it working’ before I had chance to hook it up to an oscilloscope for testing.

The code is simple enough, my written code is starting to look more user-friendly, and- importantly- it works. Onward with the FPGA testing, then?

Maybe after my exams; this was put together in my ‘evening off’. (Oh, ninjaedit- it only ‘works’ when debug = 1)

#include <Wire.h>
// Calibration Values for TPS
float minimumReading = 48;
float maximumReading = 919;
//Setttings for TPS
int analogPin = 5; // Throttle Position Sensor Wiper Pin
int throttleRead= 0; // variable to store the value read
int throttleCorrected= 0; // variable to store the corrected value
//LED flashy bit setup
const int ledPin = 13; // The number of the onboard LED pin
int ledState = LOW; // Used to store the LED state
//Variables for Pulse Generator
long pulseLength = 0; // Variable to store the generated pulse length
long gapLength = 0;
int toggle = 1; // Variable to act as a toggle
long lastMicros = 0; // Variable to act as timer function
int count = 1; // Variable to store the current tooth count
int calibrate = 92.59259259259; // Calibration for top speed = appx. 9k rpm
int rpm1 = 1; // Variable to store the RPM number
int debug = 1; // Debug setting- changes output from RPM & pulse length to counter & gap indicator
void setup()
Serial.begin(9600); // Setup serial
pinMode(ledPin, OUTPUT);
void loop()
tpsRead(); // Run TPS Read loop
void tpsRead()
throttleRead = analogRead(analogPin); // Read the input pin
throttleCorrected = ((throttleRead-minimumReading)/maximumReading)*100; // Subtract minimum from TPS. Calculate percentage of max
if (throttleCorrected<1)
if (debug == 0)
rpm1 = 60000000/(pulseLength*36);
Serial.print("Simulated RPM :");
Serial.print("RPM; Pulse Width :");
void pulseGenerate()
pulseLength = (throttleCorrected*calibrate); // Calculate length of 'high' pulse (in microseconds)
gapLength = pulseLength*3;
if ( (micros() > (lastMicros + pulseLength)) && (toggle==HIGH) && (count <= 35) )
lastMicros = micros();
toggle = LOW;
if ( (micros() > (lastMicros + pulseLength)) && (toggle==LOW) && (count < 35) )
lastMicros = micros();
toggle = HIGH;
count += 1;
if (debug == 1)
Serial.print (count);
Serial.print (",");
if ( (micros() > (lastMicros + gapLength)) && (toggle==LOW) && (count == 35) )
lastMicros = micros();
toggle = HIGH;
count = 1;
if (debug == 1)
Serial.println ("GAP");
Serial.print (",");

ECU Project- Entry the First

Worthy of note, is that this is -not- the first effort I’ve made in this field.

In short, the reason behind this project is that I have an MGB GT; after the second B-series engine gave up the ghost (they don’t really seem to like 20,000 motorway miles and 12,000 ‘other’ miles a year), I got fed up- and the car sat languishing in the garage for 6 months.

So, my birthday rolled around- and my mother made me a little purchase…


As it turns out, this gave me some bad ideas. As there are several people in my group of friends and acquaintances- not least of which, my father- who are very much into the Ford Capri, I’d heard of a little engine swap that can be performed relatively simply, into that vehicle- the Cosworth 24v V6.

The block length of which would just about fit. As would the gearbox- assuming I’d switch the auto ‘box that comes bolted to the engine, with an MT75 5-speed manual. Naturally, I prefer the sound of carburetors  and this is as standard a fuel-injected, ECU-controlled engine…

A solution was needed; off-the shelf solutions, as usual, too expensive… this is my first step along the route to achieving it.

The purchase of an FPGA (Field Programmable Gate Array) is my first step along the line- inspired by an interview with a gentleman who suggested that experience using them would aid my future employment prospects.

It’s a nice little device, and very clever- anyone familiar with logic circuitry will understand the basic concepts- AND, NOT and OR gates arranged in specific ways to achieve outputs that are desired.

The software we were using (Quartus II) also incorporates megafunctions- effectively, complex logic-based designs in premade ‘blocks’.

Logic Layout

Pictured above is an (admittedly, relatively complex) LED flasher. Connected to the ‘input’ on the left of the image is one of the internal clock pins on the FPGA- more on this later- and the other is connected to an included LED.

Now, to start with, I had no real idea what to expect- and other than making sure that the board was properly functional, did nothing, until I had a little backup; enter Iain, stage right, for “beer and a curry, honest”.

Further, we were not able to confirm the clock frequency of pin on the FPGA I was using. They appear to be variable, and my board turns out to have a few idiosyncrasies (including relatively poor user manuals). So, having read somewhere that it was either 12, 24, or 48 Mhz, for my trial design we set up a little counter-comparator pair- counting clock pulses, at 6000, turn LED on, at 12,000, reset the counter.

pin assignment

Pin association is given in the above image- pin 66 is one of the onboard clock sources, and pin 35 is the pin for the LED output on my board.

And… it worked! the LED flashed at a steady rate of on for half-second, off for half-second. Telling me that the frequency of the CLK source that we used was 12Mhz.

Some issues we ran into- when assigning the values for the constant values, I mistyped on no less than 3 occasions (easy to do, when you’re typing out a 32-bit binary number), omitting a digit, or duplicating another. This took a surprising length of time to rectify (when you’re not sure your design is going to work, it’s often easy to overlook something obvious). Also, we had a little fun with having to re-design the circuit at various points- the LPM_compare function required a 32 bit number to ‘compare’, up to that point everything had been working on 25 to save space… back to the drawing board!

End of Step One.