We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF or read online on Scribd
You are on page 1/ 6
Generating the CPS signal
To operate an ECM while not installed, besides all simulated sensors and actuators (replaced by resistors and
LED) the camshaft position sensor's (CPS) signal is required too. The CPS signal synchronizes everything
inside the ECM. Originally this signal is generated by detecting slots in a rotating cup utilizing a Hail sensor.
At the start of each slot the sensor voltage will drop from 5 to 0 volts, at the end it will jump up from 0 to 5
volts again.
Depending on the Buell model, two versions of rotor cups are available: for EFI equipped bikes a 6-slot cup
is used, for carburettor Buells it's a cup with only 2 slots. Later models (DDF-3 and up) do not have a
camshaft sensor at all, but a crankshaft sensor instead, This sensor signal can not be simulated that easily,
therefore it is not taken into account here.
To set up a signal generator, a small micro controller can be used, like a AVR or PIC (to name just two of the
many available). A very common platform is the Arduino UNO, exemplary shown below. This board will be
connected to a PC with a USB cable, which will provide power and also will be used to transfer new
programs ("sketches" in Arduino speak) to the board.
az: onboard LED
12 Coster)
1 crank, 1 deg resol
10 CeS{carbed)
B02
‘The sketch made available below will provide 5 signals, as listed:
1, Pin 13 - Activity signal, also shown by the built-in LED, toggles very 2nd revolution of the crankshaft
2. Pin 12 - CPS signal for DDFI and DDFI-2 (6 slots in CPS cup)
3. Pin 11 - Crankshaft signal, toggles with each degree of cranshaft rotation
4, Pin 10 - CPS signal for Buells with carburetors (2 slots in CPS cup)
5. Pin 8 - 2 sensor trigger signal, toggles each 16th revolution, Before feeding this signal to the ECM, a
voltage divider is required, to adjust it’s voltage to the usual 0 ... 1 volts range.
Al signals combined will look similar to the image below (the crankshaft signal has been suppress for better
visibility):epee Acpen- Newey
SUAS BES|> Pe TMS bRAAR
(oii az) Lege Thinteld : 1
‘= ee
a
ena Sande 5K O28
Click image for unscaled view
The source code for this sketch can also be downloaded here.
/f Arduine XB/S1 CPS signal generator
“
// To set engine speed: open serial monitor, send "+" to increase and "-" to decrease «
“uw
// Pins used:
// 13 = onboard LED (toggles once per ignition cycle)
// 12 = CPS signal XB (6 slots in cup)
// 11 = crank signal (toggles once pez crankd degree)
// 10 = CPS signal $1 (2 slots in cup)
{J @ = 02 signal (toggles once per @ cycles} - voltage divider required for ECM input!
uy
// ave-libe Library includes
#include
#include
¥define 02 PINEO
fdefine CPSs: PINB2
foefine CRANK PINES
fcefine CPSXB PINS
define LED PINES:
static volatile unsigned int degCount; // count timeticks
static volatile byte revCount; // count revolutions
static volatile byte countl, count2, count3, count4, counts; // GP counters
static volatile byte blipxBIndex, blips1index; // rotor cup description
// 6 slot retor cup for fuel injected engines, degrees crankshaft where CPSXB signal toc
static unsigned int blipsxB[12] = (45, 90, 135, 180, 225, 405, 450, 495, 540, 585, 630,
// 2 slot rotor cup for carbed engines, degrees crankshaft where CPSS1 signal toggles
static unsigned int blipssi(4} = (270, 315, 675, 720);// overflow compare register values @ 8 Miz for specific engine speeds
/JOCRIA = 168; Wa RPM
/JOCRIA = 178; 11-75 RPM.
/JOCRIA = 192; W7% RPM
/JOCRIA = 199; W/ 6750 RPM,
/JOCRIA = 207; 11 65 RPM
/JOCRIA = 225; 1) 6% RPM,
/JOCRIA = 244; U/ 3k5 RPM
/JOCRIA = 269; U/ 3k REM
/JOCRIA = 289; 11 4k5 RPM
/JOCRIA = 338; 1 oe RPM
/JOCRIA = 386; U/ 3k5 RPM
/JOCRIA = 448; U/ 3k RPM
/JOCRIA = 537; 11 2kS RPM,
/JOCRIA = 673; 1 2% RPM,
//OCRIA = 897; / 15 RPM
/JOcR1A = 1224; // Lkl RPM
/JOCRIA = 1346; // ik RPM
/JOCRIA = 1682; // 800 RPM
/fstatic unsigned int compares(18] = {168, 178, 192, 199, 207, 225, 244, 269, 299, 338,
static unsigned int compares(18] = (332, 395, 380, 394, 409, 443, 484, 932, 592
static unsigned int rpms(18] (8000, 7500, 7000, 6750, 6500, 6000, 5800, 5000, 4500
// index to compares/rpm arrays
static volatile char speedindex
15; // start @ 1100 rpm
// main loop
void loop()
‘
Ant input = 0
if (Serial.available(}) {
input = Serial.read();
//Serial.printin(input, HEX); // mirror input, for testing only
// parse input
Af (input == (int) 1+")
speedindex ~
else if (input
speedIndex 167
(iat)
Vf index rotation
(speedindex < 0)
speedIndex = 17;
else if (speedindex > 17)
speedIndex = 0;
// update compare match registerOCRIA = compares (speedindex];
Serial.printin (rpms [speedindex]) ;
Serial.print ("2 "
// timeri/counterl compare A interrupt signal handler
ISR (TIMER1_COMPA_vect)
// called, when a timerl/counter! matches compare value
// voggle crankPin @ every degree of crankshaft
PORTB “= (2 << CRANK);
// increase degress crankshaft
degcount ++;
Af (degcount
bLipsxs[bLipxetndex)) (
// toggle CPSKS signal @ every blip of CPSxB
PORTE “= (1 << CPSXB);
// increase blip index
blipxBindex ++;
Hf reset index
Af (bLipxBIndex >= 12)
bLipXBindex = 0;
if (degcount >= blipsSi[blipsiindex}) (
Jf toggle CPSSt signal @ every blip of cPSs1
PORTS “= (1 << CPSS1);
// increase blip index
blipSlindex ++;
// reset index
Af (blipSLindex >= 4)
blipSlindex = 0;
// reset crankshaft degrees counter after 2 revolutions
4 (degcount == 720) {
// toggle LED @ every ignition cycle
PORTB “= (1 << LED);
degcount = 0;
sevCount +47
Af (revcount// toggle 02 signal @ & ignition cycles
PORTE “= (1 << 02)7
evCount = 0;
// setup and initialization
void setup)
(
// set pins of port B te output mode
DDRB = OxFF;
// set CPS signa? to high on start,
// otherwise output will be inverted
PORTB “= (1 << CPSXB);
PORTE “= (2 << CPSS1)+
// initialize counter and indexes
degCount
revCount = 0;
blipxBindex = 0;
blipst index
/Jspeedindex = 15; // start @ 1100
//epeedindex = 17;
// initialize serial connection
Serial begin (9600);
Serial.print ("2");
Serial.printin (rpms [speedindex]) ¢
Serial.print ("2");
// initialize Timerl
elie / disable global interrupts
TCCRIA = 0; Jf set entire TCCRIA register to 0
NCCRIB = 0; // same for TCCRIB
// turn on CTC mode
TOCRIB |= (1 << WGMI2);
// Set CS10 and CS12 bits for 1024 prescaler (test only)
//ICCRIB |= (1 << C810);
//ICCRIB |= (1 << CS12)¢
// Set CS10 for no prescaler
NCCRIB |= (1 << C810);
// set compare match register to desired timer count
OCRIA = compares {speedindex];
// enable timer compare interrupt:
TIMSKL |= (1 << OCTEIA);
// enable global interrupts:sei;