@@ -1890,6 +1890,10 @@ static float readTankSensor(uint8_t idx) {
18901890 // Analog sensors would typically use analog input, but we support digital threshold mode here
18911891 pinMode (pin, INPUT_PULLUP);
18921892
1893+ // Validate pulses per revolution (common validation for both methods)
1894+ uint8_t pulsesPerRev = (cfg.pulsesPerRevolution > 0 ) ? cfg.pulsesPerRevolution : 1 ;
1895+ const float MS_PER_MINUTE = 60000 .0f ;
1896+
18931897 float rpm = 0 .0f ;
18941898
18951899 // Choose detection method: pulse counting or time-based
@@ -1906,8 +1910,10 @@ static float readTankSensor(uint8_t idx) {
19061910 const uint32_t MAX_ITERATIONS = RPM_SAMPLE_DURATION_MS * 2 ;
19071911 unsigned long firstPulseTime = 0 ;
19081912 unsigned long secondPulseTime = 0 ;
1913+ unsigned long localLastPulseTime = 0 ; // Local tracking for proper debounce
19091914 uint32_t iterationCount = 0 ;
19101915 bool firstPulseDetected = false ;
1916+ bool secondPulseDetected = false ;
19111917
19121918 // Detect edge transitions based on sensor type
19131919 while ((millis () - sampleStart) < (unsigned long )RPM_SAMPLE_DURATION_MS && iterationCount < MAX_ITERATIONS) {
@@ -1936,14 +1942,17 @@ static float readTankSensor(uint8_t idx) {
19361942
19371943 if (edgeDetected) {
19381944 unsigned long now = millis ();
1939- if (now - gRpmLastPulseTime [idx] >= DEBOUNCE_MS) {
1945+ // Debounce using local tracking within this measurement cycle
1946+ if (now - localLastPulseTime >= DEBOUNCE_MS) {
1947+ localLastPulseTime = now;
19401948 if (!firstPulseDetected) {
19411949 firstPulseTime = now;
19421950 firstPulseDetected = true ;
1943- } else {
1951+ } else if (!secondPulseDetected) {
19441952 secondPulseTime = now;
19451953 gRpmPulsePeriodMs [idx] = secondPulseTime - firstPulseTime;
19461954 gRpmLastPulseTime [idx] = secondPulseTime;
1955+ secondPulseDetected = true ;
19471956 break ; // Got our measurement, exit early
19481957 }
19491958 }
@@ -1965,13 +1974,17 @@ static float readTankSensor(uint8_t idx) {
19651974 gRpmLastSampleMillis [idx] = millis ();
19661975
19671976 // Calculate RPM from pulse period
1968- if (gRpmPulsePeriodMs [idx] > 0 ) {
1969- const float MS_PER_MINUTE = 60000 .0f ;
1970- uint8_t pulsesPerRev = (cfg.pulsesPerRevolution > 0 ) ? cfg.pulsesPerRevolution : 1 ;
1977+ if (secondPulseDetected && gRpmPulsePeriodMs [idx] > 0 ) {
1978+ // Got a valid measurement this cycle
19711979 // RPM = (60000 ms/min) / (period_ms * pulses_per_rev)
19721980 rpm = MS_PER_MINUTE / ((float )gRpmPulsePeriodMs [idx] * (float )pulsesPerRev);
1981+ } else if (firstPulseDetected && !secondPulseDetected) {
1982+ // Only one pulse detected - RPM is very low or stopped
1983+ // Use a conservative estimate based on the sample duration
1984+ // If we didn't get a second pulse in 3 seconds, RPM is < 20 (assuming 1 pulse/rev)
1985+ rpm = 0 .0f ;
19731986 } else {
1974- // No valid period , keep last reading
1987+ // No pulses detected , keep last reading
19751988 rpm = gRpmLastReading [idx];
19761989 }
19771990
@@ -2039,9 +2052,7 @@ static float readTankSensor(uint8_t idx) {
20392052 gRpmLastPinState [idx] = lastState;
20402053 gRpmLastSampleMillis [idx] = millis ();
20412054
2042- // Calculate RPM from pulse count
2043- const float MS_PER_MINUTE = 60000 .0f ;
2044- uint8_t pulsesPerRev = (cfg.pulsesPerRevolution > 0 ) ? cfg.pulsesPerRevolution : 1 ;
2055+ // Calculate RPM from pulse count (using pre-validated pulsesPerRev)
20452056 rpm = ((float )pulseCount * MS_PER_MINUTE) / ((float )RPM_SAMPLE_DURATION_MS * (float )pulsesPerRev);
20462057 }
20472058
0 commit comments