Crankshaft sensor code

Folks,
I'm currently involved in an ev conversion project and wrote some code (well mostly copied!) to simulate a 60-2 crankshaft position sensor. Basically the sketch should output 58 pulses , skip two , another 58 and so on. A pot on A0 provides a reference for pulse width and hence rpm. Could someone please have a look at the sketch and let me know if I have the pulse counts correct as i don't have a dso to verify the output?

/**
crank signal simulator
*/
 
#define PULSE_PIN 10

 
void setup() {
pinMode(PULSE_PIN, OUTPUT);
}
 
/**
Simulate the high of a tooth on a
reluctor wheel
*/
void triggerHigh(int duration) {
digitalWrite(PULSE_PIN, HIGH);
delayMicroseconds(duration);
digitalWrite(PULSE_PIN, LOW);
}
 
/**
Simulate the reference marker on a
reluctor wheel
*/
void triggerReference(int duration) {
// pin should be low already
delayMicroseconds(duration);
delayMicroseconds(duration); // two delays for two missing pulses.
}
 
 
/**
Simulates a 58 tooth reluctor wheel
with a 2 tooth reference
*/
void loop(){
int val = analogRead(0);
val = map(val, 0, 1023, 100, 3500);

for(int i = 0; i <= 58; i++) {
triggerHigh(val);
delayMicroseconds(val);
}
triggerReference(val);
delayMicroseconds(val);
}

many thanks. For anyone interested in the project please see http://www.e39ev.com/

1 Like

Counting 0 through 58, inclusive, gives you 59 counts:

for(int i = 0; i <= 58; i++) {

Typically you would count to 58 by counting 0 through 57, inclusive:

for(int i = 0; i < 58; i++) {

If the two missing pulses are supposed to be the same length as the 58 other pulses you need to do FOUR delays instead of THREE (two in the triggerReference() function and one after).

I would put all the delays in the functions:

/**
crank signal simulator
*/
 
#define PULSE_PIN 10
 
void setup() {
pinMode(PULSE_PIN, OUTPUT);
}
 
/**
Simulate the high of a tooth on a
reluctor wheel
*/
void triggerHigh(int duration) {
digitalWrite(PULSE_PIN, HIGH);
delayMicroseconds(duration);
digitalWrite(PULSE_PIN, LOW);
delayMicroseconds(val);
}
 
/**
Simulate the reference marker on a
reluctor wheel
*/
void triggerReference(int duration) {
// pin should be low already
delayMicroseconds(duration);
delayMicroseconds(duration); // two delays for two missing pulses.
delayMicroseconds(duration);
delayMicroseconds(duration); // two delays for two missing pulses.
}
 
 
/**
Simulates a 58 tooth reluctor wheel
with a 2 tooth reference
*/
void loop(){
int val = analogRead(0);
val = map(val, 0, 1023, 100, 3500);

for(int i = 0; i <= 58; i++) {
    triggerHigh(val);
    }

triggerReference(val);
}

hello Jack Bauer. (and helpers)
I'm doing the same thing, now, but 36:1 for ford 1996 .
I presume you are trying to get ECU happy, so your EV, will shift an automatic tranny?, if yes, I can help you too. or a new ECU? for bench testing, like me...
I have an OBD2 test bed that i made and the CPK sensor in the FORD ECU is very fussy.. it must have to 1 pulse drop or the ECU will not gen spark.
I found this out by sending all types of wave forms and only white noise would trigger it ( the drop out must be there or ECU is a brick.) Im sure it has zero crossing detector in the ECU.;

I also found out this ECU even sparks with a dead, cam sensor... (at least cranking)
but i digress.
If you got your code running now, can you , loan it to me?

all i get compiling is . main.cpp:11: undefined reference to setup'** and **main.cpp:14: undefined reference to loop'

using code above.
im an rank rank amateur of UNO but not asm or "C"

i like your POT code for RPM, nice feature.
Good day and thanks for posting this code, it will make generating, CKP signals very easy. once i learn to make this complier happy.
running, sketch jun28a 105
my hardware is all in the mail. so was playing with the CPP.

OBD-II:
all i get compiling is . main.cpp:11: undefined reference to setup'** and **main.cpp:14: undefined reference to loop'

using code above.

That would happen if you compiled an empty sketch, or one that didn't define void setup() and void loop() functions. Did you paste the code above into a sketch (.ino) file and then build it within the Arduino IDE?

thanks!
yes, I cut and pasted it into notepad2 (64bit) the with the arduino.exe , i opened that file and built it.
i have the examples running, ok. so its me. my errors.
I then read the many posts on why java blows up. and it was me.
I had some odd illegal. comments. in the first 3 lines. switching /* xxxxx */ solved it.
// this
// that
// something.
#include "Arduino.h"
#define PULSE_PIN 10
etc..

it now compiles , no error, wish my hardware was here.
what a great product and even better docs, and support. wow.

in the old days the C compiler would error as,,, "found { with out an } end" for just about all dumb formatting. Ok I got it.
cant wait to scope this with my old tek scope.

thanks ! for helping !!

Hi,Even i am working on similar project in pic.I have to generate two pulse types on cam and crank(60-2,6+1 or 24+1) and synchronize them to get same rpm.The programming part is in C language.I have written a code for generating 60-2 pulse on pic and along with it trying to generate 6+1 simultaneously.I am able to generate 60-2 pulse but i am having trouble generating the extra pulse in 6+1 type.Can someone have a look and guide me with the modifications that i need to do to make it work.
P.S. I am using pic 18F4525.

#include<p18f4525.h>
#define mybit1 PORTCbits.RC3
#define mybit2 PORTCbits.RC2
void isr(void);
void T0_ISR(void);
void T1_ISR(void);

#pragma code int_vector=0x0008
void high_interrupt(void)
{
_asm
GOTO isr
_endasm
}
#pragma code

#pragma interrupt isr
void isr(void)
{

if(PIR1bits.TMR1IF==1)
T1_ISR();
// if(INTCONbits.TMR0IF==1)
//T0_ISR();
}
unsigned char counter1;
unsigned char counter2;
unsigned char counter3;
unsigned int i;
//unsigned int ii;
//unsigned int jj;

//unsigned int x,y;
unsigned int timer_10msec_flag;
unsigned int timer_flag;

void main()
{

OSCCON=0x77;
TRISAbits.TRISA0=1; //INPUT
TRISCbits.TRISC3=0; //OUTPUT
TRISCbits.TRISC2=0; //OUTPUT
//TRISD=0;
// TRISB=0;

ADCON0=0x03;
ADCON1=0x00;
ADCON2bits.ADFM=0;

// INTCONbits.TMR0IF=0; //CLEAR IF FLAG
PIR1bits.TMR1IF=0;

// INTCONbits.TMR0IE=1; //ENABLE INTERRUPTS
PIE1bits.TMR1IE=1;

// T0CONbits.TMR0ON=1; //START TIMERS
T1CONbits.TMR1ON=1;
INTCONbits.PEIE=1;

INTCONbits.GIE=1;

//timer_100msec_flag=0;
timer_10msec_flag=0;

counter1=0;
counter2=0;
counter3=0;
i=0;

mybit2=1;
mybit1=1;

while(1)
{
T1_ISR();

if(timer_10msec_flag==1)
{

timer_10msec_flag=0;

if(counter1<116)
{
counter1++;
counter2++;
mybit2=~mybit2;
}

else
{
mybit2=0;
if(counter1<119)
{
counter1++;
counter2++;
}

else
{
counter1=0;
//counter2=0;
}
}

if(counter2==10)
{

counter2=0;
counter3++;

mybit1=~mybit1;
//counter2=0;

}

if(counter3==12)
{
//counter3=0;

if(counter2==3)
{
mybit1=~mybit1;
counter3=0;
}

if(counter2==6)
{

mybit1=~mybit1;
counter3=0;

}

}

}

}

}

/*if(timer_10msec_flag!=0)
{
i++;
if(i==1)
{
timer_10msec_flag=1;
mybit2=~mybit2;
i=0;
timer_100msec_flag=0;
ADCON0bits.GO=1;

}

timer_10msec_flag=0;
}
}*/

//PIR1bits.TMR1IF=1;
void T1_ISR(void)
{

T1CON=0x80;

TMR1H=0xFC;
TMR1L=0x17;

T1CONbits.TMR1ON=1;
while(PIR1bits.TMR1IF==0);
T1CONbits.TMR1ON=0;
PIR1bits.TMR1IF=0;

timer_10msec_flag=1;

}

/*void T0_ISR(void)
{
T0CON=0x80;

TMR0H=0xFF;
TMR0L=0xFF;

T0CONbits.TMR0ON=1;
while(INTCONbits.PEIE==0);
T0CONbits.TMR0ON=0;

INTCONbits.TMR0IF=0;

}*/

P.S. I am using pic 18F4525.

This is NOT the PIC forum.

Hello, new to the forum and fairly new to programming but not new to general electronic work and computers. I am doing something very similar however I need the pattern on the input trigger to be changed to a signal that the ecu will be happy with.

here is the trigger wheel that the ecu needs to see:

The trigger wheel that is installed in engine appears to be a standard 60-2 wheel. I will count in a day, or two when I get a chance. My question is will I be able to modify the 60-2 input signal to a signal that matches what would be seen if I was able to use the trigger wheel above?

Thanks in advance!

The code not successful I can't