Programming Guidance for RPM logger

Hello, this is my first time posting to these forums so forgive me if this is in the wrong place.

I am attempting to read the RPM of a pump and display it on a LCD, the Arduino is supposed to log the RPM based on the square wave pulsed at 5v provided by a pressure switch attached to the pump. Unfortunately when the Arduino receives no input, the LCD displays -60 and when I attach the pressure switch to the input pin (Pin 2 at the moment) the display reads a number in the hundreds of thousands that changes incredibly fast. I’ve tried changing the input pins around (making sure not to use a pin that is already used by the LCD shield) but I have the same problem every time.

This is my first time making a project with Arduino and coding C++, so I’m sure I’ve made quite a few errors, my code is mostly a Frankenstein of code I’d seen from similar projects supplemented by my very limited programming knowledge.

As you can see the first half of my code is my attempt at averaging the readings from the RPM portion of the code, as I plan to eventually have the Arduino log the average hourly RPM to an SD card.

As this is my first project and I’m having a hard time progressing from here from just using google searches I thought it’d be a good idea to ask here for some pointers and maybe a push in the right direction. I apologize in advance if this isn’t the right place to ask :confused: .

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

const int pulsePin = 2; // Input pin being pulsed is 2
unsigned long startMillis = 0;
unsigned long interval = 3600000;
int Sample_Number = 0;
int pulseHigh; // Integer var to capture high time of pulse
int pulseLow; // Integer var to capture low time of pulse
int period; // Integer var to capture total time of incoming pulse,
unsigned long frequency; // Frequency after calculations,
int RPM; //Revolutions Per Minute
unsigned long RPM_Total = 0; //Running Total of RPM
unsigned long RPM_Average = 0;
void setup() {
  // put your setup code here, to run once:
  pinMode(pulsePin, INPUT_PULLUP);

}

void loop() {
  unsigned long currentMillis = millis(); //Current millis is equal to the time elapsed since program started
  if (currentMillis - startMillis > interval) { // This line is used to compare the time elapsed to the set interval
    Sample_Number = ++Sample_Number; // This line is used to increment the number of samples by one every time this If statement is triggered
    RPM_Total = RPM + RPM_Total; // This line is used to add the RPM at the time of the interval to the running RPM_Total int
    RPM_Average = RPM_Total / Sample_Number; // This line is used to develop an average by dividing the running total by the number of samples taken
    startMillis = currentMillis; //This line is used to set the current time to the new previous time
  }
  if (Sample_Number >= 24) {
    Sample_Number = 0;
  } /*This line is used to reset the Sample_Number count when the number of counts reaches 24, AKA after one day.
  Will place code to write to the SD card in the near future.*/

  pulseHigh = pulseIn(pulsePin, HIGH, 20000); //Length of the HIGH part of square wave pulse
  pulseLow = pulseIn(pulsePin, LOW, 20000); //Length of the LOW part of the square wave pulse
  period = pulseHigh + pulseLow; // Results in time period of pulse in microseconds (PulseIn gives Micro)
  frequency = 1000000 / period; // Frequency in Hz -- 1mil Microseconds=1 Second
  RPM = frequency * 60; //Hz Multiplied by 60 seconds=Revolutions Per Minute

  lcd.setCursor(7, 1);
  lcd.print("RPM");
  lcd.setCursor(10, 1);
  lcd.print(RPM);

You realize that your interval is set at 1 hour?

Yes, I had hoped to get the RPM value and then use that interval line and an "if" to print the average value once per hour.

I don't think it's effecting my RPM code but I could definitely be wrong, I just don't know where to look to troubleshoot this.

Usually when we want to calculate a frequency (RPM) we count pulses for a finite period of time and then extrapolate. For example if we set a time interval of 1 second and count 10 pulses (revolutions) we can suggest that RPM = 10(pulses per second) * 60(seconds per minute) = 600. You can count pulses with an interrupt.

If you choose to use pulseIn, please read its use very carefully as the directions are not exactly clear (in my opinion). The timing works on a transition. If you are measuring HIGH, there must be a LOW to start, allowing the transition to HIGH to begin the timing and then transitioning to LOW to end. With your pulsePin moded to PULLUP, you may not get this.

Oh, I see, so how would I go about setting pulsein to read an interval of one second?

Ignore pulseIn. Set up a pin change interrupt for pin2 and in the ISR simply have a counter. In your loop() function, use a test to see if millis() - last_time_millis_was_reset >= 1000, if yes, multiply the count from the ISR by 60, reset last_time_millis_was_reset to millis() and your counter to 0.

I'm not sure how to use a pin change interrupt yet but now I have a direction, I really appreciate it

How would you use a pressure switch to determine RPM? Is it a diaphragm pump? Is the pressure switch able to reset before the next pulse?

This sketch at least returns a zero and seems like it is much more efficient, however I still only receive a 0 on the RPM reading. I’ve tried pulsing a second Arduino into it as well as my pressure switch, so I’m pretty sure it’s a coding issue.

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
const byte interrupt_Pin = 2; //Sets the pin used for the interrupt
volatile byte count; //Should increment when interrupt pin changes state
int last_time_millis_was_reset;
int RPM;


void setup() {
  
  pinMode(interrupt_Pin, INPUT);
  attachInterrupt(digitalPinToInterrupt(interrupt_Pin), counter, CHANGE);

}

void loop() {
  
  if (millis() - last_time_millis_was_reset >= 1000);
  {
    RPM = count * 60;
    last_time_millis_was_reset = millis();
    count = 0;
  }
  lcd.setCursor(7, 1);
  lcd.print("RPM");
  lcd.setCursor(10, 1);
  lcd.print(RPM);
}
void counter() {
  ++count;
}

Sorry to bother you again :confused:

Also Yes, it is a diaphragm pump, and there is already a tachometer wired to the pressure switch so I am fairly certain it's possible to read RPM with the Arduino, my main purpose for doing this is to log data regularly once I can get an RPM reading in the Arduino.

Also, not sure how to edit posts but by "I still only receive 0 on the RPM reading" I mean I can't get it to read out as anything other than zero, so I'm wondering if one of my = 0 statements is causing trouble?

The PinChangeInterrupt library which some may suggest has been deprecated. The library to download now is EnableInterrupt. Available through the library manager or here EnableInterrupt