RPM Sketch Help needed

Hardware:
Arduino Mega 2560
Hall effect sensor: Honeywell 103SR13A-1, 3 wires, ground, power and signal (unipolar)
One magnet: one revolution is one signal, South side facing sensor
Small LED on breadboard to blink with Hall Effect signal (so I can tell signal is being sent)
Adafruit DS1307 RTC
Adafruit standard 4X20 LCD with Adafruit i2c backpack

Problem:
LCD displays the following;

Time: displayed correctly

RPM: first displays 62 briefly, then 132 briefly, then 662…after ±10 seconds of 662, keeping the magnet rotating on drill the display shows 662 ±80% of time and 132 ±20% of time. 132 is the correct RPM. When drill removed the display reads 062 if 662 was last reading or 052 if 132 was last reading.

Here is my sketch:

  // include the library code:
  #include <Wire.h>
  #include "RTClib.h"
  #include <LiquidCrystal.h>
  LiquidCrystal lcd(0);
  RTC_DS1307 rtc;

  volatile byte half_revolutions;
  unsigned int rpm;
  unsigned long timeold;
  float lastmillis;
 //pinmode(5, INPUT, PULLUP);Fishing
  void setup() 
   {
    
   lcd.begin(20, 4);
   delay(10);
   lcd.setBacklight(HIGH);
   Serial.begin(57600);
   attachInterrupt(5,rpm_fun, RISING);//Initialize the intterrupt pin (Arduino Mega pin 18)
   half_revolutions = 0;
   rpm = 0;
   timeold = 0;
  
 }

  void loop() 
  {
  DateTime now = rtc.now();
  lcd.setCursor(15, 0);
  delay(100);
  lcd.print(now.hour(), DEC);
  lcd.print(':');
  lcd.print(now.minute(), DEC);
  delay(100);

   //if (half_revolutions >= 20)//this is the problem
     //rpm = (float(30*1000/(millis() - timeold)*half_revolutions)); //fishing
     rpm = 30*1000/(millis() - timeold)*half_revolutions;
     //rpm = ((millis() - timeold)*1000); // Fishing
     timeold = millis();
     half_revolutions = 0;
     //Serial.println(rpm,DEC);
     lcd.setCursor(10, 2);
     delay(100);
     lcd.print("RPM ");
     lcd.print(rpm,DEC);
     delay(100);
   }
 
   void rpm_fun()
   {
   half_revolutions++;
   
   Serial.println("detect");

  
  }

Attached is a representation of physical layout, schematic and Fritzing pictorial.

Of course I am very very inexperienced in both C++ and electronics, so sorry if my error(s) are super obvious.

I’ve tried dozens of resistor combinations to no avail and tried many variations on the sketch also to no avail.

Thanks in advance for any and all suggestions.

Jan 14 Fritzing.pdf (332 KB)

  1. Don’t put a Serial.println() in the ISR.
  2. Draw " " over the display area before displaying a new number.
  3. Update the display less often. If you update frequently then half_revolutions and millis()-timeold will both be small integers and produce imprecise results. Update only when millis()-timeold > 500.

johnwasser,

Thanks for the prompt reply, but I'm afraid your response is a case of "pearls before swine"...I am a farmer and you need to type a little slower, please...lol...

I don't understand what is meant by display area nor where/how to put " " over it.

Likewise I don't understand how to change the time between display updates.

Do to my near total lack of programming ability, if you could post examples of the corrected code you referenced I would be very grateful.

Thanks

johnwasser is referencing a few examples which are found in the arduino IDE itself. If you open a sketch, at the top you will see the "file" tab, in the drop down menu you will see examples, click digital, then click blinkwithoutdelay. It shows you how to use "time" in milliseconds to perform tasks depending on the amount of millis(time) that has passed. If you search the forum you will find a plethora of examples using millis(). It is quite useful and doesn't block other functions/actions from happening as delay() does.

When printing to an lcd or serial monitor, as johnwasser mentioned, repeatedly updating can cause erroneous data to be displayed. What he suggests is something like this...

int displayRPM()
{

int displayinterval = 500;
startmillis = millis();

if(endmillis - startmillis >= 500)
serial.println(rpm);
else 
serial.println("    ");

endmillis = millis()

}

when you print (" "), it basically prints empty space, instead of possibly wrong data. Using millis(), you determine what the startmillis(start time) is, subtract it from endmillis(stop time) and compare the result to displayinterval.

Bill

Billdefish

Thanks for the info and help....will check it out in the morning.

This lack of knowledge sure makes this arduino business frustrating!

Good thing I have "stick-to-it-tivness"

Thanks again