Concurrent measuring of high and low states of two pins

Hello all

After a hiatus from my project (illness and work), I am looking back into it.

I have a sketch I am writing, and after a good deal of help from here, I managed to streamline it to something manageable.

I am measuring the time two pins are high and low and using that data to calculate frequency.

One function is acting as a rev counter, one as a speedometer. The arduino will be driving a nixie dash.

However, when the frequency of pulses is very low (or stalled completely - either the car is not moving or the engine is off) the sketch will grind to a halt while it waits to read a change in the state of the pins.

Can the "Demonstration code for several things at the same time"
Demonstration code for several things at the same time - Project Guidance - Arduino Forum help me here? I am struggling with how to program in such a way that the high and low time on the pins is monitored while the sketch goes off and does the other things required of it (there is a lot more to the sketch than just speed and revolutions) . I'm really trying but my little brain is struggling with how I might manage this.

Failing that, is there a way to write a time out into the functions?

I know I could get around this by having two different boards but that would be a shame.

Could I have two timers running at the same time? So, perhaps record the time at which the RPM pin changed state, then the time at which the MPH pin changed state. and then perform the other functions while the board waits for the pins to change state?

Code below.

void Revs()  {

    Htime=pulseIn(18,HIGH);      //read time pin is high
    Ltime=pulseIn(18,LOW);        //read time pin is low
    
    Ttime = Htime+Ltime;

    RPM=1000000/Ttime/2*60;    //getting frequency with Ttime is in Micro seconds, then divide frequency by two, as there are 2 pulses per crank revolution to give revs per second, multiplied by 60 to get revs per minute

//Writing RPM value to nixie tubes

    writeToPort = (RPM / 1000 % 10) << 4;
    writeToPort = writeToPort + (RPM / 100 % 10);
    PORTE = writeToPort + (RPM / 100 % 10);
    writeToPort = (RPM / 10 % 10) << 4;
    writeToPort = writeToPort + (RPM % 10);
    PORTD = writeToPort;
}
void Speed()  {

    Htime=pulseIn(19,HIGH);      //read high time
    Ltime=pulseIn(19,LOW);        //read low time
    
    Ttime = Htime+Ltime;

    MPH=1000000/Ttime*3600*0.0011122571986   //getting frequency with Ttime is in Micro seconds, then multiply by 3600 to get revs per hour, multiplied by wheel circumference in miles to get miles per hour 
    
//Writing MPH value to nixie tubes

    writeToPort = (MPH / 10 % 10) << 4;
    writeToPort = writeToPort + (MPH % 10);
    PORTF = writeToPort;   
}

Full sketch below for reference:

//Analogue Pins
int RPMAnalogueOutputPin = 1;
int OilTempSensePin = 2;
int OilTempOutputPin = 3;
int OilPressureSensePin = 4;
int OilPressureOutputPin = 5;
int BoostSensePin = 6;
int BoostOutputPin = 7;
int FuelLevelSensePin = 8;
int FuelLevelOutputPin = 9;
int FuelPressureSensePin = 10;
int FuelPressureOutputPin = 11;
int LambdaSensePin = 12;
int LambdaOutputPin = 13;
int BatteryVoltageSensePin = 14;
int BatteryVoltageOutputPin = 15;

//Digital Pins
const int ChargeWarningSensePin = 16;
const int OilWarningSensePin = 17;
const int RPMInterruptPin = 18;
const int SpeedInterruptPin = 19;
const int NixieRev1A = 20;
const int NixieRev1B = 21;
const int NixieRev1C = 22;
const int NixieRev1D = 23;
const int NixieRev2A = 24;
const int NixieRev2B = 25;
const int NixieRev2C = 26;
const int NixieRev2D = 27;
const int NixieRev3A = 28;
const int NixieRev3B = 29;
const int NixieRev3C = 30;
const int NixieRev3D = 31;
const int NixieRev4A = 32;
const int NixieRev4B = 33;
const int NixieRev4C = 34;
const int NixieRev4D = 35;
const int NixieSpeed1A = 36;
const int NixieSpeed1B = 37;
const int NixieSpeed1C = 38;
const int NixieSpeed1D = 39;
const int NixieSpeed2A = 40;
const int NixieSpeed2B = 41;
const int NixieSpeed2C = 42;
const int NixieSpeed2D = 43;
const int AntiPoisonButton = 44;
int Htime;              //integer for storing high time
int Ltime;                //integer for storing low time
float Ttime;            // integer for storing total time of a cycle
int RPM;                //RPM calculated from pulses on coil earth, 2 per crank revolution
int MPH;                //MPH calculated from  pulses from speedo magnet, 1 per revolution, and one mile divided by tyre circumference
byte writeToPort; // this is for displaying the result in binary, but not in the way you normally would (I need each digit displayed as a 4 bit binary, rather than all four digits displayed as one binary string)

void setup()
{
  pinMode(RPMAnalogueOutputPin, INPUT);
  pinMode(OilTempSensePin, INPUT);
  pinMode(OilTempOutputPin, OUTPUT);
  pinMode(OilPressureSensePin, INPUT);
  pinMode(OilPressureOutputPin, OUTPUT);
  pinMode(BoostSensePin, INPUT);
  pinMode(BoostOutputPin, OUTPUT);
  pinMode(FuelLevelSensePin, INPUT);
  pinMode(FuelLevelOutputPin, OUTPUT);
  pinMode(FuelPressureSensePin, INPUT);
  pinMode(FuelPressureOutputPin, OUTPUT);
  pinMode(LambdaSensePin, INPUT);
  pinMode(LambdaOutputPin, OUTPUT);
  pinMode(BatteryVoltageSensePin, INPUT);
  pinMode(BatteryVoltageOutputPin, OUTPUT);
  pinMode(ChargeWarningSensePin, INPUT);
  pinMode(OilWarningSensePin, INPUT);
  pinMode(RPMInterruptPin, INPUT);
  pinMode(SpeedInterruptPin, INPUT);
  pinMode(20, OUTPUT);
  pinMode(21, OUTPUT);
  pinMode(22, OUTPUT);
  pinMode(23, OUTPUT);
  pinMode(24, OUTPUT);
  pinMode(25, OUTPUT);
  pinMode(26, OUTPUT);
  pinMode(27, OUTPUT);
  pinMode(28, OUTPUT);
  pinMode(29, OUTPUT);
  pinMode(30, OUTPUT);
  pinMode(31, OUTPUT);
  pinMode(32, OUTPUT);
  pinMode(33, OUTPUT);
  pinMode(34, OUTPUT);
  pinMode(35, OUTPUT);
  pinMode(36, OUTPUT);
  pinMode(37, OUTPUT);
  pinMode(38, OUTPUT);
  pinMode(39, OUTPUT);
  pinMode(40, OUTPUT);
  pinMode(41, OUTPUT);
  pinMode(42, OUTPUT);
  pinMode(43, OUTPUT);
  pinMode(AntiPoisonButton, OUTPUT); 

  typedef void (*num_func) ();
  num_func functions [] = { OilTemperature, OilPressure, OilPressureWarning, BoostPressure, FuelLevel, FuelLevelWarning, FuelPressure, FuelPressureWarning, Lambda, LambdaWarning, BatteryLevel, ChargeWarning, Revs, Speed};

}
void loop()
{

    static int index = 1;

  if (index > 14);
  index = 1;

}  

void Revs()  {

    Htime=pulseIn(18,HIGH);      //read high time
    Ltime=pulseIn(18,LOW);        //read low time
    
    Ttime = Htime+Ltime;

    RPM=1000000/Ttime/2*60;    //getting frequency with Ttime is in Micro seconds, then divide frequency by two, as there are 2 pulses per crank revolution to give revs per second, multiplied by 60 to get revs per minute

//Writing RPM value to nixie tubes

    writeToPort = (RPM / 1000 % 10) << 4;
    writeToPort = writeToPort + (RPM / 100 % 10);
    PORTE = writeToPort + (RPM / 100 % 10);
    writeToPort = (RPM / 10 % 10) << 4;
    writeToPort = writeToPort + (RPM % 10);
    PORTD = writeToPort;
}
void Speed()  {

    Htime=pulseIn(19,HIGH);      //read high time
    Ltime=pulseIn(19,LOW);        //read low time
    
    Ttime = Htime+Ltime;

    MPH=1000000/Ttime*3600*0.0011122571986   //getting frequency with Ttime is in Micro seconds, then multiply by 3600 to get revs per hour, multpilied by wheel circumference in miles to get miles travelled per hour 
    
//Writing MPH value to nixie tubes

    writeToPort = (MPH / 10 % 10) << 4;
    writeToPort = writeToPort + (MPH % 10);
    PORTF = writeToPort;   
}
    
void OilTemperature() {

  int val = analogRead(OilTempSensePin); // read the value from the oil temp sender

  val = constrain(val, 500, 900); // reset the value to within these parameters CHANGE ME

  int OilTempLevel = map (val, 500, 900, 0, 255); // CHANGE ME

  analogWrite(OilTempOutputPin, OilTempLevel); // write OilTemperature to OilTemperatureOutputPin
}

void OilPressure() {

  int val = analogRead(OilPressureSensePin); // read the value from the oil pressure sender

  val = constrain(val, 500, 900); // reset the value to within these parameters CHANGE ME

  int OilPressureLevel = map (val, 500, 900, 0, 255); // CHANGE ME

  analogWrite(OilPressureOutputPin, OilPressureLevel); // OilTemperature to OilTemperatureOutputPin

}

void OilPressureWarning() {

}

void BoostPressure() {
  int val = analogRead(BoostSensePin); // read the value from the boost pressure sender

  val = constrain(val, 500, 900); // reset the value to within these parameters CHANGE ME

  int BoostPressureLevel = map (val, 500, 900, 0, 255); // CHANGE ME

  analogWrite(BoostOutputPin, BoostPressureLevel); // write BoostPressureLevel to BoostOutputPin

}

void FuelLevel() {
  int val = analogRead(FuelLevelSensePin); // read the value from the fuel level sender

  val = constrain(val, 500, 900); // reset the value to within these parameters CHANGE ME

  int FuelLevel = map (val, 500, 900, 0, 255); // CHANGE ME

  analogWrite(FuelLevelOutputPin, FuelLevel); // write FuelLevel translates to FuelLevelOutputPin

}

void FuelLevelWarning() {

}

void FuelPressure() {
  int val = analogRead(FuelPressureSensePin); // read the value from the fuel pressure sender

  val = constrain(val, 500, 900); // reset the value to within these parameters CHANGE ME

  int FuelPressureLevel = map (val, 500, 900, 0, 255); // CHANGE ME

  analogWrite(FuelPressureOutputPin, FuelPressureLevel); // write FuelPressure to FuelLevelOutputPin

}

void FuelPressureWarning() {

}

void Lambda() {
  int val = analogRead(LambdaSensePin); // read the value from the lambda sender

  val = constrain(val, 500, 900); // reset the value to within these parameters CHANGE ME

  int LambdaLevel = map (val, 500, 900, 0, 255); // CHANGE ME

  analogWrite(LambdaOutputPin, LambdaLevel); // write LambdaLevel to LambdaLevelOutputPin
}

void LambdaWarning() {

}

void BatteryLevel() {
  int val = analogRead(BatteryVoltageSensePin); // read the value from the fuel level sender

  val = constrain(val, 500, 900); // reset the value to within these parameters CHANGE ME

  int BatteryLevel = map (val, 500, 900, 0, 255); // CHANGE ME

  analogWrite(BatteryVoltageOutputPin, BatteryLevel); // write BatteryVoltage to FuelLevelOutputPin

}

void ChargeWarning() {

}

With only this code in loop(), what makes your program work?

void loop()
{

    static int index = 1;

  if (index > 14);
  index = 1;

}

None of the functions seems to be called.

...R

Robin2:
With only this code in loop(), what makes your program work?

void loop()

{

static int index = 1;

if (index > 14);
  index = 1;

}



None of the functions seems to be called.

...R

Hi Robin

The complete code is a work in progress. I am just working on the individual functions at the moment, and want to get the two concurrent frequency counters working first. I only included the main body of the work in progress for context, to indicate why either one of the frequency counter functions hanging up would be a problem.

With the main body of the code, I am working on having a variable rate at which the functions are called - this is because I will be using nixie bars and nixie tubes, and particularly with the bars I want to be able to fine tune the rate at which they are moved to control the floating of the bar (common problem with nixie bars, especially when using PWM output and having too high fluctiations on their inputs).
I'm going to do this by introducing a potentiometer to an analogue pin. The value on the pot will be given a number, and a counter started in the loop. The value of the pot will be the value at which the counter increments, calling each function in turn at each increment. Does that make sense? I am working on a little sketch to do that, and am fairly confident that it will work.

void loop() {

  UpdateRate = analogRead(UpdateRatePin); //assign value to the update rate

  //looks to see if time equal to the value of the reading on UpdateRate pin. If no, skip, if yes, call next function

  currentMillis = millis();
  if (currentMillis - startMillis >= UpdateRate);
  {
    //throw something in here to call functions in turn, and then:
    startMillis = currentMillis; //:reset the clock ready for the next refresh. 
  }

Something like this... But that's not what I am thinking about at the moment, I may bin that idea entirely and just run the whole lot in a loop. For now, I just want to get the frequency counters working.

fall-apart-dave:
The complete code is a work in progress. I am just working on the individual functions at the moment,

Please post a short complete program that works and illustrates the problem. Without that we are only guessing.

...R

Robin2:
Please post a short complete program that works and illustrates the problem. Without that we are only guessing.

...R

const int RPMInterruptPin = 18;
const int SpeedInterruptPin = 19;
const int NixieRev1A = 20;
const int NixieRev1B = 21;
const int NixieRev1C = 22;
const int NixieRev1D = 23;
const int NixieRev2A = 24;
const int NixieRev2B = 25;
const int NixieRev2C = 26;
const int NixieRev2D = 27;
const int NixieRev3A = 28;
const int NixieRev3B = 29;
const int NixieRev3C = 30;
const int NixieRev3D = 31;
const int NixieRev4A = 32;
const int NixieRev4B = 33;
const int NixieRev4C = 34;
const int NixieRev4D = 35;
const int NixieSpeed1A = 36;
const int NixieSpeed1B = 37;
const int NixieSpeed1C = 38;
const int NixieSpeed1D = 39;
const int NixieSpeed2A = 40;
const int NixieSpeed2B = 41;
const int NixieSpeed2C = 42;
const int NixieSpeed2D = 43;
int Htime;              //integer for storing high time
int Ltime;                //integer for storing low time
float Ttime;            // integer for storing total time of a cycle
int RPM;                //RPM calculated from pulses on coil earth, 2 per crank revolution
int MPH;                //MPH calculated from  pulses from speedo magnet, 1 per revolution, and one mile divided by tyre circumference
byte writeToPort; // this is for displaying the result in binary, but not in the way you normally would (I need each digit displayed as a 4 bit binary, rather than all four digits displayed as one binary string)


void setup()

{

  pinMode(RPMInterruptPin, INPUT);
  pinMode(SpeedInterruptPin, INPUT);
 


}


void loop()

{

    Htime=pulseIn(18,HIGH);      //read high time
    Ltime=pulseIn(18,LOW);        //read low time
    
    Ttime = Htime+Ltime;

    RPM=1000000/Ttime/2*60;    //getting frequency with Ttime is in Micro seconds, then divide frequency by two, as there are 2 pulses per crank revolution to give revs per second, multiplied by 60 to get revs per minute

//Writing RPM value to nixie tubes

    writeToPort = (RPM / 1000 % 10) << 4;
    writeToPort = writeToPort + (RPM / 100 % 10);
    PORTE = writeToPort + (RPM / 100 % 10);
    writeToPort = (RPM / 10 % 10) << 4;
    writeToPort = writeToPort + (RPM % 10);
    PORTD = writeToPort;


    Htime=pulseIn(19,HIGH);      //read high time
    Ltime=pulseIn(19,LOW);        //read low time
    
    Ttime = Htime+Ltime;

    MPH=1000000/Ttime*3600*0.0011122571986;   //getting frequency with Ttime is in Micro seconds, then multiply by 3600 to get revs per hour, multpilied by wheel circumference in miles to get miles travelled per hour 
    
//Writing MPH value to nixie tubes

    writeToPort = (MPH / 10 % 10) << 4;
    writeToPort = writeToPort + (MPH % 10);
    PORTF = writeToPort;   


}

So. If there is no change on pin 18 for RPM (engine not running), it will just hang and wait.
If there is no change on pin 19 for MPH (car not moving or moving very slowly), it will just hang and wait.

My question, how is it best approached to make these functions run concurrently, or at worst to add a time out of, say, 250mS where it will just skip?

Thanks

Are you saying that the program hangs on the line

Htime=pulseIn(18,HIGH);      //read high time

I have never used that function but my understanding is that it has a default timeout of 1 second and you can change that.

Maybe the problem is that if it times out it almost immediately gets stuck in another pulseIn() for another timeout.

What happens if you check if the timeout has occurred before doing anything else?

Separately, I don't understand why you have this code twice in loop()

   Htime=pulseIn(19,HIGH);      //read high time
    Ltime=pulseIn(19,LOW);        //read low time
    
    Ttime = Htime+Ltime;

And, I suspect this line

PORTE = writeToPort + (RPM / 100 % 10);

should be

PORTE = writeToPort;

Another issue IMHO is that pulseIn() is a blocking function and if you want to check the pulse width on two I/O pins a non-blocking approach would be better. Have a look at how the interval between pulses is measured in the code in this link. It is an extract from a program I wrote to manage the speed of a small DC motor.

...R

 Htime = pulseIn(19, HIGH);   //read high time
  Ltime = pulseIn(19, LOW);     //read low time

That code is going to have the (probably) undesirable effect of delaying your code for a complete cycle of the input. Not too bad at high rpm/speed, but still an eternity in terms of how many other things you could be doing during that time.

General method for measuring rpm would be to keep a count of the number of pulses on the input pin during a sampling period, then calculate the rpm from the number of pulses and the length of the sampling period. You could do this by checking for a change in state of the input pin each time through the loop, if the remainder of the code is fast enough to guarantee you will not miss a pulse, but at higher rpm it would be better to use interrupts.

Which arduino are you using? The number of analog/digital pins in your code imply something as large as a mega, but the direct port instructions for the display indicate something else.

Hi Robin

Robin2:
Are you saying that the program hangs on the line

Htime=pulseIn(18,HIGH);      //read high time

I have never used that function but my understanding is that it has a default timeout of 1 second and you can change that.

Maybe the problem is that if it times out it almost immediately gets stuck in another pulseIn() for another timeout.

What happens if you check if the timeout has occurred before doing anything else?

Separately, I don't understand why you have this code twice in loop()

   Htime=pulseIn(19,HIGH);      //read high time

Ltime=pulseIn(19,LOW);        //read low time
   
    Ttime = Htime+Ltime;




And, I suspect this line


PORTE = writeToPort + (RPM / 100 % 10);



should be


PORTE = writeToPort;





Another issue IMHO is that pulseIn() is a blocking function and if you want to check the pulse width on two I/O pins a non-blocking approach would be better. Have a look at how the interval between pulses is measured in the [code in this link](https://forum.arduino.cc/index.php?topic=564223.msg3844595#msg3844595). It is an extract from a program I wrote to manage the speed of a small DC motor.

...R

So to answer your questions...

I need to have the high and low period of the pulse to get total pulse time to then calculate frequency.

PORTE = writeToPort + (RPM / 100 % 10); is deliberate. I need to write to the port in a very specific way in order for the decoder chips to correctly decode for using the nixie tubes. I need it to write each digit separately (so, for example, 1234 needs to be written as four individual binary numbers, so 0001 - 0020 - 0011 - 0100, rather than expressed as one binary number i.e. 10011010010). So I need to send each single digit of the number in turn, not the whole number. Does that make sense?

I shall have a look at the link, thank you.

david_2018:

 Htime = pulseIn(19, HIGH);   //read high time

Ltime = pulseIn(19, LOW);    //read low time




That code is going to have the (probably) undesirable effect of delaying your code for a complete cycle of the input. Not too bad at high rpm/speed, but still an eternity in terms of how many other things you could be doing during that time. 

General method for measuring rpm would be to keep a count of the number of pulses on the input pin during a sampling period, then calculate the rpm from the number of pulses and the length of the sampling period. You could do this by checking for a change in state of the input pin each time through the loop, if the remainder of the code is fast enough to guarantee you will not miss a pulse, but at higher rpm it would be better to use interrupts.

Which arduino are you using? The number of analog/digital pins in your code imply something as large as a mega, but the direct port instructions for the display indicate something else.

I don't mind the code delaying slightly but yes agreed, at low speeds with a frequency of just 2 hertz at the wheel, it would be a pain.

I did originally try that but could never get it to work, and then found that I could do it very simply. Though at the time I was toying with the idea of using just one tiny board to do the speed and another to do revs and not run the analogue stuff on arduino at all.

It is an arduino mega, yes. the port instructions work on a Mega, do they not?

Thanks

Dave

fall-apart-dave:
It is an arduino mega, yes. the port instructions work on a Mega, do they not?

Yes, the port instructions work, but you are using PORTD, PORTE, and PORTF, which do not match the defines at the top of your code.

Hard to find a good port reference for the mega, this is the list I made from the pins_arduino.h file and the mega reference page:

A0  PF0
A1  PF1
A2  PF2
A3  PF3
A4  PF4
A5  PF5
A6  PF6
A7  PF7
A8  PK0
A9  PK1
A10 PK2
A11 PK3
A12 PK4
A13 PK5
A14 PK6
A15 PK7
D0  PE0
D1  PE1
D2  PE4
D3  PE5
D4  PG5
D5  PE3
D6  PH3
D7  PH4
D8  PH5
D9  PH6
D10 PB4
D11 PB5
D12 PB6
D13 PB7
D14 PJ1
D15 PJ0
D16 PH1
D17 PH0
D18 PD3
D19 PD2
D20 PD1
D21 PD0
D22 PA0
D23 PA1
D24 PA2
D25 PA3
D26 PA4
D27 PA5
D28 PA6
D29 PA7
D30 PC7
D31 PC6
D32 PC5
D33 PC4
D34 PC3
D35 PC2
D36 PC1
D37 PC0
D38 PD7
D39 PG2
D40 PG1
D41 PG0
D42 PL7
D43 PL6
D44 PL5
D45 PL4
D46 PL3
D47 PL2
D48 PL1
D49 PL0
D50 PB3
D51 PB2
D52 PB1
D53 PB0

fall-apart-dave:
Hi Robin

So to answer your questions...

I need to have the high and low period of the pulse to get total pulse time to then calculate frequency.

That does not answer my first question in Reply #6 which was What happens if you check if the timeout has occurred before doing anything else?

You say you are measuring RPM and speed. What is producing the signals that you are trying to interpret?

...R

Robin2:
That does not answer my first question in Reply #6 which was What happens if you check if the timeout has occurred before doing anything else?

You say you are measuring RPM and speed. What is producing the signals that you are trying to interpret?

...R

I didn't answer the first question because I don't quite understand the question, and I'm at work so don't have my kit with me.

RPM is pulses from the negative side of the ignition coil via a pulse conditioning circuit to convert the messy noisy ground pulse to a clean 5v square wave.

MPH is from a hall sensor in close proximity to the original spinning magnet on the speedometer cable which would normally produce an eddy current to move the speedometer needle which again produces a nice uniform 5v square wave.

david_2018:
Yes, the port instructions work, but you are using PORTD, PORTE, and PORTF, which do not match the defines at the top of your code.

Hard to find a good port reference for the mega, this is the list I made from the pins_arduino.h file and the mega reference page:

A0  PF0

A1  PF1
A2  PF2
A3  PF3
A4  PF4
A5  PF5
A6  PF6
A7  PF7
A8  PK0
A9  PK1
A10 PK2
A11 PK3
A12 PK4
A13 PK5
A14 PK6
A15 PK7
D0  PE0
D1  PE1
D2  PE4
D3  PE5
D4  PG5
D5  PE3
D6  PH3
D7  PH4
D8  PH5
D9  PH6
D10 PB4
D11 PB5
D12 PB6
D13 PB7
D14 PJ1
D15 PJ0
D16 PH1
D17 PH0
D18 PD3
D19 PD2
D20 PD1
D21 PD0
D22 PA0
D23 PA1
D24 PA2
D25 PA3
D26 PA4
D27 PA5
D28 PA6
D29 PA7
D30 PC7
D31 PC6
D32 PC5
D33 PC4
D34 PC3
D35 PC2
D36 PC1
D37 PC0
D38 PD7
D39 PG2
D40 PG1
D41 PG0
D42 PL7
D43 PL6
D44 PL5
D45 PL4
D46 PL3
D47 PL2
D48 PL1
D49 PL0
D50 PB3
D51 PB2
D52 PB1
D53 PB0

I see. I've not looked into the ports much, will address this once I get the rpm and mph measurements working as I want.

fall-apart-dave:
I didn't answer the first question because I don't quite understand the question,

When you don't understand a question, please don't ignore it. If you explain what you don't understand I will try to help.

RPM is pulses from the negative side of the ignition coil via a pulse conditioning circuit to convert the messy noisy ground pulse to a clean 5v square wave.

MPH is from a hall sensor in close proximity to the original spinning magnet on the speedometer cable which would normally produce an eddy current to move the speedometer needle which again produces a nice uniform 5v square wave.

I would expect that the sort of code in the link I gave you in Reply #6 would be ideal for measuring the time of those pulses. All you need is to measure the time intervals between rising (or falling, but not both) edges of the pulses.

...R

Robin2:
When you don't understand a question, please don't ignore it. If you explain what you don't understand I will try to help.

I would expect that the sort of code in the link I gave you in Reply #6 would be ideal for measuring the time of those pulses. All you need is to measure the time intervals between rising (or falling, but not both) edges of the pulses.

...R

You mean this part specifically?

void getIsrData() {
    if (newIsrMicros == true) {
        prevRevMicros = revMicros; // save the previous value
        noInterrupts();
            revMicros = isrMicros;
            revCount = isrCount;
            newIsrMicros = false;
        interrupts();
        revDuration = revMicros - prevRevMicros;

in tandem with this

void revDetectorISR() {
    isrMicros = micros();
    isrCount ++;
    newIsrMicros = true;

i'm trying to understand how it works.

My understanding, if you would humour me, is:

  1. Within the "reDetectorISR" function, if "revDeectorISR" on pin 0 sees a rising edge, IsrMicros is set to the current time.

  2. "isrCount" is counting total revolutions

  3. A flag is put up to show that the "newIsrMicros" time has been updated

  4. The "getIsrData" function then picks up this flag

  5. The last value held "prevRevMicros" is saved

  6. Interrupts are stopped

  7. "revCount" is updated with the current number

  8. "newIsrMicros" is set back to "false" to indicate it has been read

  9. "revDuration" is calculated by subtracting current time from previous time, to give a remainder

Would I be right in thinking that:

From the calculation in 9, RPM is possible to calculate by simply multiplying by 100000 to get Hz and then by 60 to get RPM.

is that a fair assessment of what the code is doing? I ask so that I have the best understanding possible of what you have written there.

fall-apart-dave:
My understanding, if you would humour me, is:

  1. Within the "reDetectorISR" function, if "revDeectorISR" on pin 0 sees a rising edge, IsrMicros is set to the current time.
  2. "isrCount" is counting total revolutions
  3. A flag is put up to show that the "newIsrMicros" time has been updated
  4. The "getIsrData" function then picks up this flag
  5. The last value held "prevRevMicros" is saved
  6. Interrupts are stopped
  7. "revCount" is updated with the current number
  8. "newIsrMicros" is set back to "false" to indicate it has been read
  9. "revDuration" is calculated by subtracting current time from previous time, to give a remainder

Would I be right in thinking that:

From the calculation in 9, RPM is possible to calculate by simply multiplying by 100000 to get Hz and then by 60 to get RPM.

Your description of the process seems correct.

If the number of microseconds representing a single revolution is (for example) 4756µs then the number of revs per second will be 1,000,000 / 4756 = 210.26 and the number of revs per minute will be RPS * 60 = 12,615 if my maths is correct.

...R

Excellent, thanks for that. I'll have a tinker.

I'll be looking at a maximum of 25Hz for mph and 250Hz for rpm. I think.