Reducing the numbers of output to serial monitor

Hey Guys,

im trying to get an RPM counter using a fork light barrier working on my arduino DUE and found this code. Its the first one i found that is actually working fine and im trying to understand it to make a small change. Currently i get like 100++ RPM values printed to my serial monitor, i want the same accuarcy, just less numbers, like 4 accurate values in 1 second to be able to easily copy them. I learned that i cant use delays for that since it stops the whole code and makes the rpm values innacurate. Sadly cant figure out what i have to change to archive that :(, see the code below

byte sensor = 2;
//unsigned long startTime;
//unsigned long endTime;
//unsigned long PstartTime;
//unsigned long duration;
//byte timerRunning;
int RPM = 0;
int count = 0;
int totRPM = 0;
int avgRPM = 0;
const int relay = 4;

//unsigned long lastReading;
byte lastReading;
//unsigned long reading;
byte reading;
unsigned long stateChangeTime;
unsigned long previousStateChangeTime;
unsigned long duration;
unsigned long lastDisplay;

void setup() {
  pinMode (sensor, INPUT_PULLUP);
  pinMode (relay, OUTPUT);
  digitalWrite (relay, LOW);
  Serial.begin(115200);
}
void loop() {
  lastReading = reading;
  reading = digitalRead(sensor);
  if (reading == LOW && lastReading == HIGH)//pick up appropriate state change
  {
    stateChangeTime = millis();
    duration = stateChangeTime - previousStateChangeTime;
    previousStateChangeTime = stateChangeTime;
  }
  /*
    if (timerRunning == 0 && digitalRead(sensor) == LOW) {
      startTime = millis();
      timerRunning = 1;
      PstartTime = startTime;

    }

    if (timerRunning == 1 && digitalRead(sensor) == LOW) {
      startTime = millis();
      timerRunning = 0;
      duration = Pstartime - startTime;
  */
  RPM = 60000 / duration;
  count = count + 1;
  totRPM = RPM + totRPM;
  avgRPM = totRPM / count;
  if (count > 60) {
    totRPM = avgRPM;
    count = 1;
  }
  if (avgRPM > 181) {
    digitalWrite (relay, HIGH);
  }
  if (avgRPM <= 178) {
    digitalWrite (relay, LOW);
  }

  if (millis() - lastDisplay >= 1000)
  {
    Serial.print ("avgRPM ");
    Serial.println (RPM);
  }
}

You need to save the value of millis() to lastDisplay for each print:

if (millis() - lastDisplay >= 1000)
  {
    Serial.print ("avgRPM ");
    Serial.println (RPM);
    lastDisplay = millis(); //Add this
  }

Okay, im getting less spammed now, but its only showing 0 continuously

You are mixing data types in an unfortunate way:

RPM = 60000 / duration;

RPM (and all other RPM-values) should be declared as "unsigned int" in order to store values >32767. "60000" should be declared as a "const unsigned int" or have the "U" prefix.

Dont really see what thats changing, all i want is that i dont get like 10x the same value likes this:

21:20:55.349 -> avgRPM 372
21:20:55.349 -> avgRPM 372
21:20:55.349 -> avgRPM 372
21:20:55.349 -> avgRPM 372
21:20:55.349 -> avgRPM 372
21:20:55.349 -> avgRPM 372
21:20:55.349 -> avgRPM 372
21:20:55.382 -> avgRPM 372
21:20:55.382 -> avgRPM 372
21:20:55.382 -> avgRPM 372
21:20:55.382 -> avgRPM 372
21:20:55.382 -> avgRPM 372
21:20:55.382 -> avgRPM 372
21:20:55.382 -> avgRPM 372
21:20:55.382 -> avgRPM 372

the refreshrate is fine, i just dont want 20 values for each itteration

count is counting the iterations of the loop. That will overflow an int in a few hundredths of a second

Move the count increment and the average code inside the state change block.

MorganS:
count is counting the iterations of the loop. That will overflow an int in a few hundredths of a second

Move the count increment and the average code inside the state change block.

Sounds reasonable ty, can u please post the code with those changes? I think i did what you said but didnt change anything

Show your code.

MorganS:
Show your code.

byte sensor = 2;
//unsigned long startTime;
//unsigned long endTime;
//unsigned long PstartTime;
//unsigned long duration;
//byte timerRunning;
int RPM = 0;
int count = 0;
int totRPM = 0;
int avgRPM = 0;
const int relay = 4;

//unsigned long lastReading;
byte lastReading;
//unsigned long reading;
byte reading;
unsigned long stateChangeTime;
unsigned long previousStateChangeTime;
unsigned long duration;
unsigned long lastDisplay;

void setup() {
  pinMode (sensor, INPUT_PULLUP);
  pinMode (relay, OUTPUT);
  digitalWrite (relay, LOW);
  Serial.begin(115200);
}
void loop() {
  lastReading = reading;
  reading = digitalRead(sensor);
  if (reading == LOW && lastReading == HIGH)//pick up appropriate state change
  {
    stateChangeTime = millis();
    duration = stateChangeTime - previousStateChangeTime;
    previousStateChangeTime = stateChangeTime;
    count = count + 1;
    if (count > 60) {
    totRPM = avgRPM;
    count = 1;
  }
  if (avgRPM > 181) {
    digitalWrite (relay, HIGH);
  }
  if (avgRPM <= 178) {
    digitalWrite (relay, LOW);
  }

  }
  /*
    if (timerRunning == 0 && digitalRead(sensor) == LOW) {
      startTime = millis();
      timerRunning = 1;
      PstartTime = startTime;

    }

    if (timerRunning == 1 && digitalRead(sensor) == LOW) {
      startTime = millis();
      timerRunning = 0;
      duration = Pstartime - startTime;
  */
  RPM = 60000 / duration;
  totRPM = RPM + totRPM;
  avgRPM = totRPM / count;
  

  if (millis() - lastDisplay >= 1000)
  {
    Serial.print ("avgRPM ");
    Serial.println (RPM);
  }
}

Use control-T autoformat to make the mistake more obvious.

MorganS:
Use control-T autoformat to make the mistake more obvious.

Dont see the error, moving the count line to the statechangetime block should make it so that counts only get added when the "next" millis time is reached instead of every loop right? Don´t see any formatting error :frowning:

This stuff...

  RPM = 60000 / duration;
  totRPM = RPM + totRPM;
  avgRPM = totRPM / count;

should also be inside the same block.