@@ -247,9 +247,15 @@ static unsigned long gLastRelayCheckMillis = 0;
247247
248248// RPM sensor state for Hall effect pulse counting
249249// We track pulses per tank that uses an RPM sensor
250- static volatile uint32_t gRpmPulseCount [MAX_TANKS] = {0 };
250+ static uint32_t gRpmPulseCount [MAX_TANKS] = {0 };
251251static unsigned long gRpmLastSampleMillis [MAX_TANKS] = {0 };
252252static float gRpmLastReading [MAX_TANKS] = {0 .0f };
253+ static int gRpmLastPinState [MAX_TANKS] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
254+
255+ // RPM sampling duration in milliseconds (sample for a few seconds each period)
256+ #ifndef RPM_SAMPLE_DURATION_MS
257+ #define RPM_SAMPLE_DURATION_MS 3000
258+ #endif
253259
254260// Forward declarations
255261static void initializeStorage ();
@@ -1107,59 +1113,49 @@ static float readTankSensor(uint8_t idx) {
11071113 return linearMap (milliamps, 4 .0f , 20 .0f , 0 .0f , cfg.heightInches );
11081114 }
11091115 case SENSOR_HALL_EFFECT_RPM: {
1110- // Hall effect RPM sensor - non-blocking pulse counting
1116+ // Hall effect RPM sensor - sample pulses for a few seconds each measurement period
11111117 // Use rpmPin if available, otherwise use primaryPin
11121118 int pin = (cfg.rpmPin >= 0 && cfg.rpmPin < 255 ) ? cfg.rpmPin :
11131119 ((cfg.primaryPin >= 0 && cfg.primaryPin < 255 ) ? cfg.primaryPin : (2 + idx));
11141120
11151121 // Configure pin as input with pullup for Hall effect sensor
11161122 pinMode (pin, INPUT_PULLUP);
11171123
1118- unsigned long now = millis ();
1119- unsigned long lastSample = gRpmLastSampleMillis [idx];
1124+ // Sample pulses for RPM_SAMPLE_DURATION_MS (default 3 seconds)
1125+ // This provides accurate RPM measurement by counting multiple pulses
1126+ unsigned long sampleStart = millis ();
1127+ uint32_t pulseCount = 0 ;
1128+ int lastState = gRpmLastPinState [idx];
11201129
1121- // First reading - initialize and return 0
1122- if (lastSample == 0 ) {
1123- gRpmLastSampleMillis [idx] = now;
1124- gRpmPulseCount [idx] = 0 ;
1125- return 0 .0f ;
1130+ // Initialize lastState from current pin on first reading
1131+ if (gRpmLastSampleMillis [idx] == 0 ) {
1132+ lastState = digitalRead (pin);
1133+ gRpmLastPinState [idx] = lastState;
11261134 }
11271135
1128- // Count pulses since last reading (non-blocking quick scan)
1129- // This reads the current state and counts any transition
1130- // Note: Static array initialized to HIGH (pullup default state)
1131- static int lastPinState[MAX_TANKS];
1132- static bool lastPinStateInit = false ;
1133- if (!lastPinStateInit) {
1134- for (uint8_t j = 0 ; j < MAX_TANKS; ++j) {
1135- lastPinState[j] = HIGH;
1136+ // Count pulses over the sampling duration
1137+ while (millis () - sampleStart < RPM_SAMPLE_DURATION_MS) {
1138+ int currentState = digitalRead (pin);
1139+ // Count falling edges (HIGH to LOW transitions)
1140+ if (lastState == HIGH && currentState == LOW) {
1141+ pulseCount++;
11361142 }
1137- lastPinStateInit = true ;
1143+ lastState = currentState;
1144+ // Small delay to allow other processing and avoid excessive polling
1145+ delay (1 );
11381146 }
1139- int currentState = digitalRead (pin);
11401147
1141- // Count falling edges (HIGH to LOW transitions)
1142- if (lastPinState[idx] == HIGH && currentState == LOW) {
1143- gRpmPulseCount [idx]++;
1144- }
1145- lastPinState[idx] = currentState;
1146-
1147- // Calculate RPM only when sufficient time has passed (1 second minimum)
1148- unsigned long elapsed = now - lastSample;
1149- if (elapsed < 1000 ) {
1150- // Not enough time elapsed, return last calculated RPM
1151- return gRpmLastReading [idx];
1152- }
1148+ // Save last pin state for next sample
1149+ gRpmLastPinState [idx] = lastState;
1150+ gRpmLastSampleMillis [idx] = millis ();
11531151
1154- // Calculate RPM from accumulated pulse count
1155- // Note: Assumes 1 pulse per revolution (modify divisor for multi-pole magnets)
1156- // For multi-pole magnets, divide pulse count by number of poles
1157- uint32_t pulses = gRpmPulseCount [idx];
1158- float rpm = ((float )pulses * 60000 .0f ) / (float )elapsed;
1152+ // Calculate RPM from pulse count
1153+ // Formula: RPM = (pulses / sample_duration_seconds) * 60 seconds/minute
1154+ // Simplified: RPM = pulses * 60000 / sample_duration_ms
1155+ // Note: Assumes 1 pulse per revolution (adjust calculation for multi-pole magnets)
1156+ const float MS_PER_MINUTE = 60000 .0f ;
1157+ float rpm = ((float )pulseCount * MS_PER_MINUTE) / (float )RPM_SAMPLE_DURATION_MS;
11591158
1160- // Reset for next measurement period
1161- gRpmLastSampleMillis [idx] = now;
1162- gRpmPulseCount [idx] = 0 ;
11631159 gRpmLastReading [idx] = rpm;
11641160
11651161 // Return RPM value (heightInches field is used as max RPM for scaling/alarms)
0 commit comments