Using "pulseIn" to help read a timing gear

I am trying to read a timing gear to work out RPM. Right now I am just trying to see how I can determine when the sensor passes the larger gap in the gear but I can’t seem to get consistent results.

My code is:-

int pin = 6;
unsigned long Duration = 0;

void setup() {
  Serial.begin(9600);
  pinMode(pin, INPUT_PULLUP);
}

void loop() {
  Duration = pulseIn(pin, HIGH, 10000);
  if (Duration != 0)
   {
      Serial.println(Duration);
      Duration = 0;
   }
}

A sample of the output is :-

16:34:49.176 -> 904
16:34:49.176 -> 1011
16:34:49.223 -> 946
16:34:49.223 -> 840
16:34:49.223 -> 789
16:34:49.223 -> 704
16:34:49.223 -> 752
16:34:49.223 -> 791
16:34:49.223 -> 797
16:34:49.223 -> 749
16:34:49.223 -> 708
16:34:49.270 -> 727
16:34:49.270 -> 775
16:34:49.270 -> 1332
16:34:49.270 -> 626
16:34:49.270 -> 795
16:34:49.270 -> 809
16:34:49.270 -> 776
16:34:49.270 -> 750
16:34:49.270 -> 752
16:34:49.317 -> 754
16:34:49.317 -> 723
16:34:49.317 -> 666
16:34:49.317 -> 656
16:34:49.317 -> 707
16:34:49.317 -> 767
16:34:49.317 -> 712
16:34:49.317 -> 708
16:34:49.317 -> 839
16:34:49.364 -> 814
16:34:49.364 -> 757
16:34:49.364 -> 651
16:34:49.364 -> 754
16:34:49.364 -> 1394
16:34:49.364 -> 756
16:34:49.364 -> 710
16:34:49.364 -> 677
16:34:49.411 -> 760
16:34:49.411 -> 743
16:34:49.411 -> 807
16:34:49.411 -> 781
16:34:49.411 -> 731
16:34:49.411 -> 772
16:34:49.411 -> 804
16:34:49.411 -> 884
16:34:49.411 -> 841
16:34:49.411 -> 1390
16:34:49.458 -> 783
16:34:49.458 -> 850
16:34:49.458 -> 840
16:34:49.458 -> 810
16:34:49.458 -> 861
16:34:49.458 -> 855
16:34:49.458 -> 829
16:34:49.458 -> 826
16:34:49.504 -> 830
16:34:49.504 -> 852
16:34:49.504 -> 872
16:34:49.504 -> 870
16:34:49.504 -> 871
16:34:49.504 -> 1466
16:34:49.504 -> 802
16:34:49.504 -> 857
16:34:49.504 -> 849
16:34:49.504 -> 867
16:34:49.551 -> 876
16:34:49.551 -> 869
16:34:49.551 -> 850
16:34:49.551 -> 854
16:34:49.551 -> 869
16:34:49.551 -> 872
16:34:49.551 -> 881
16:34:49.551 -> 905
16:34:49.598 -> 907
16:34:49.598 -> 889
16:34:49.598 -> 1485
16:34:49.598 -> 841
16:34:49.598 -> 898
16:34:49.598 -> 898
16:34:49.598 -> 904
16:34:49.598 -> 901
16:34:49.598 -> 894
16:34:49.645 -> 885
16:34:49.645 -> 895
16:34:49.645 -> 894
16:34:49.645 -> 907
16:34:49.645 -> 929
16:34:49.645 -> 940
16:34:49.645 -> 945
16:34:49.645 -> 935
16:34:49.645 -> 930
16:34:49.692 -> 941
16:34:49.692 -> 941
16:34:49.692 -> 949
16:34:49.692 -> 946
16:34:49.692 -> 947
16:34:49.692 -> 938
16:34:49.692 -> 927
16:34:49.692 -> 916
16:34:49.692 -> 930
16:34:49.739 -> 926
16:34:49.739 -> 941
16:34:49.739 -> 953
16:34:49.739 -> 968
16:34:49.739 -> 966
16:34:49.739 -> 972
16:34:49.739 -> 967
16:34:49.739 -> 1541
16:34:49.739 -> 918
16:34:49.786 -> 971
16:34:49.786 -> 976
16:34:49.786 -> 984
16:34:49.786 -> 980
16:34:49.786 -> 949
16:34:49.786 -> 961
16:34:49.786 -> 951
16:34:49.786 -> 930
16:34:49.786 -> 934
16:34:49.833 -> 963
16:34:49.833 -> 963
16:34:49.833 -> 981
16:34:49.833 -> 1012
16:34:49.833 -> 1012
16:34:49.833 -> 987
16:34:49.833 -> 1585
16:34:49.833 -> 950
16:34:49.879 -> 985
16:34:49.879 -> 1004
16:34:49.879 -> 1033
16:34:49.879 -> 1051
16:34:49.879 -> 1008
16:34:49.879 -> 970
16:34:49.879 -> 973
16:34:49.879 -> 985
16:34:49.926 -> 987
16:34:49.926 -> 959
16:34:49.926 -> 977
16:34:49.926 -> 1027
16:34:49.926 -> 1030
16:34:49.926 -> 1034
16:34:49.926 -> 1034
16:34:49.926 -> 1018
16:34:49.926 -> 1045
16:34:49.973 -> 1042
16:34:49.973 -> 1056
16:34:49.973 -> 1042
16:34:49.973 -> 1020
16:34:49.973 -> 1017
16:34:49.973 -> 1007
16:34:49.973 -> 1004
16:34:50.020 -> 1009
16:34:50.020 -> 958
16:34:50.020 -> 966
16:34:50.020 -> 1027
16:34:50.020 -> 1075
16:34:50.020 -> 1089
16:34:50.020 -> 1060
16:34:50.067 -> 1054
16:34:50.067 -> 1614
16:34:50.067 -> 1048
16:34:50.067 -> 1090
16:34:50.067 -> 1097
16:34:50.067 -> 1107
16:34:50.067 -> 1112
16:34:50.067 -> 1096
16:34:50.114 -> 1066
16:34:50.114 -> 1035
16:34:50.114 -> 1007
16:34:50.114 -> 986
16:34:50.114 -> 978
16:34:50.114 -> 977
16:34:50.114 -> 984
16:34:50.114 -> 995
16:34:50.161 -> 1035
16:34:50.161 -> 1078
16:34:50.161 -> 1076
16:34:50.161 -> 1082
16:34:50.161 -> 1055
16:34:50.161 -> 1095
16:34:50.161 -> 1112
16:34:50.161 -> 1106
16:34:50.208 -> 1105
16:34:50.208 -> 1102
16:34:50.208 -> 1078
16:34:50.208 -> 1068
16:34:50.208 -> 1038
16:34:50.208 -> 991
16:34:50.208 -> 971
16:34:50.208 -> 964
16:34:50.254 -> 963
16:34:50.254 -> 984
16:34:50.254 -> 986
16:34:50.254 -> 996
16:34:50.254 -> 1031
16:34:50.254 -> 1068
16:34:50.254 -> 1073
16:34:50.254 -> 1069
16:34:50.254 -> 1066
16:34:50.301 -> 1036
16:34:50.301 -> 1643
16:34:50.301 -> 1086
16:34:50.301 -> 1076
16:34:50.301 -> 1077
16:34:50.301 -> 1108
16:34:50.301 -> 1125
16:34:50.348 -> 1047
16:34:50.348 -> 1009
16:34:50.348 -> 966
16:34:50.348 -> 890
16:34:50.348 -> 866
16:34:50.348 -> 854
16:34:50.348 -> 853
16:34:50.348 -> 839
16:34:50.395 -> 865
16:34:50.395 -> 848
16:34:50.395 -> 872
16:34:50.395 -> 908
16:34:50.395 -> 948
16:34:50.395 -> 959
16:34:50.395 -> 940
16:34:50.395 -> 842
16:34:50.395 -> 1571
16:34:50.442 -> 804
16:34:50.442 -> 852
16:34:50.442 -> 915
16:34:50.442 -> 870
16:34:50.442 -> 670

Now there are 22 gaps on the wheel and one gap is 3x larger than the others. I can see that the duration to the next high is periodically a lot larger than the other gap readings but they do not always come at 22 reading intervals.

I have a pulse read of 0.01 second as the timing gear wheel will be spinning at various speeds.

Please see the attached for a picture of the timing wheel.

Thanks, Daniel.

Do you know what the signal output from the sensor looks like?
Should you be looking at low or high duration?
What RPM range are you expecting?

You may find it better to use interrupts instead of pulseIn() to detect the gap. You can time between similar edges. Once you detect the gap, then keep count.

Thanks for the reply.

As for the sensor output if you mean on an oscilloscope, I don't know that and don't have one available to me.

I'm looking for a HIGH duration because this is where I need to take the timing marker from.

I am expecting RPM to be around 12,000 at a maximum. This is why I chose to use intervals of 0.01 of a second.

I do have another routine using interrupts but I found I got a better reading from the pulseIn function. I can see that it does show me the large gap time but it's not consistent and I wonder if it's my coding that is the problem.

Daniel.

I'm looking for a HIGH duration because this is where I need to take the timing marker from.

I'm unclear if the gaps read high or low? Can you please clarify. What is the sensor output when a gap is in front, and when a tooth is in front?

I do have another routine using interrupts but I found I got a better reading from the pulseIn function. I can see that it does show me the large gap time but it's not consistent and I wonder if it's my coding that is the problem.

Let's think through the timing. The wheel is equivalent to 23 teeth (22 + missing tooth). 12000RPM = 200RPS. 4600 "pulses" per second if all the teeth were there. So, for a normal tooth and gap, the tooth is approximately in front of the sensor for 110 microseconds and the gaps are 110 microseconds.

So, you are looking for a gap of 300us compared to the normal gap of 100 us. I don't understand why your pulseIn() data is showing a factor of two instead of three.

I do believe that your task is better done with interrupts.

Are you going to need position information around the cycle, or are you only looking for RPM?

If you don't really need the timing in relation to the gap, then just counting 22 edge transitions from HIGH to LOW or the other way around can give RPM. The gap is only relevant if you need to time other events through the cycle.

As the high point on the gear wheel passes to the low point or gap an electrical pulse is created. This pulse is what I am reading. I need to not only count the smaller gaps as they pass over the sensor but the large gap will give me one full rotation since it was last seen so I can calculate RPM.

Do you mean factor of 2 but the timing duration? I would hope that seeing as the large gap is 3x the size of the small gaps that it would be 3x but actually after we pass the large gap we come across a solid of 3x the normal solid. By solid I mean a part of the gear that is not classed as a gap. This may be the cause of the confusion in the readings I am getting but I am not sure.

I am not going to suggest I am the greatest coder but I would greatly appreciate someone with better knowledge critisise my code if I have made a poor error.

Thanks, Daniel.

DanielHowden:
I am trying to read a timing gear to work out RPM. Right now I am just trying to see how I can determine when the sensor passes the larger gap in the gear but I can’t seem to get consistent results.

What sort of sensor are you using?

It would not occur to me to use pulseIn() for this task. I would just create a short Interrupt Service Routine to measure the time time between pulses. Have a look at the code in this link.

Do you really need to detect Top Dead Centre or are you only interested in measuring the speed?

…R

Thanks for the input on this topic. I'll go back and revisit the interrupt solution.

R - I do need to detect the timing marks on the wheel as well as revolutions.

Thanks, D.

DanielHowden:
I need to not only count the smaller gaps as they pass over the sensor but the large gap will give me one full rotation since it was last seen so I can calculate RPM.

It’s slightly off the beaten path but, it seems like the Input Capture feature of Timer1 would get you most of the way there with less fuss. Either sensor edge, your choice, can generate an interrupt, for counting, and will *capture *TCNT1 for comparison with previous readings. A reading of approximately two times the last one could indicate the timing gap.

pulseIn() is a very crude instrument which is useful for reading isolated pulses. It is not appropriate for this task.

Remember the chip inside your Arduino was obsolete and about to be discontinued before it was selected to be the core of the Arduino. Those chip designers many years ago knew that you would want to do this project so they designed dedicated hardware inside the chip to help you in this task.

Strangely the Arduino people did not anticipate your needs so there is very little software to support you. But you have the hardware.

Interrupts can be brain-bending but this is the clue you need to use your hardware effectively.