Serial Plotter correct, Monitor Serie with "inf" for my code to find the frequency with several pins

Hi friends,
I am writing to you because I have a question. I have made a code to find the rpm (frequency) for the wheels of my robot (I have two wheels). The libraries that I know only allow to calculate the rpm (or frequency) for one pin. Other programs compromise the rest of the code (are ok if you only want to get the rpm).

My code gives a good result in the Serial Plotter, however, in the Monitor Serie I am getting numbers followed by "inf". Please, could you help me to know what part of my code produces this error in the Serial Monitor?

I am using this motor: 210 rpm 6V DC motor with quadrature hall sensors.

In this graph you can see the fast movement for one wheel turned with my hand:

However this is the result in the Monitor Serie:

Finally, this is my code:

const byte Encoder_C1 = 2; //Green wire pin 2 digital
const byte Encoder_C2 = 3; //Yellow pin 3 digital

volatile unsigned long pulseTime, lastTime;
volatile byte changed = 0;

double Periode;
double Frequency;

volatile byte Encoder_C1Last;
volatile int pulse;
volatile boolean direction;


void setup() {
  Serial.begin(9600);
  
  pinMode(Encoder_C1, INPUT_PULLUP);
  pinMode(Encoder_C2, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(Encoder_C1), calculatePulse, CHANGE);
  attachInterrupt(digitalPinToInterrupt(Encoder_C2), calculatePulse_C2, HIGH);
}

void loop()
{
  if (changed == 1) {
    Periode = pulseTime - lastTime;
    Periode = Periode / 1000000.0; //En segundos
    Frequency = 1.0 / Periode; //En Hz

    if (!direction) {
      Frequency *= -1;
    }
    changed = 0;
  } else {
    Frequency = 0;
  }

  Serial.println(Frequency);
}

void calculatePulse()
{
  lastTime = pulseTime;
  changed = 1;
  int Lstate = digitalRead(Encoder_C1);
  if ((Encoder_C1Last == LOW) && Lstate == HIGH)
  {
    int val = digitalRead(Encoder_C2);
    if (val == LOW && direction)
    {
      direction = false; //Reverse
    }
    else if (val == HIGH && !direction)
    {
      direction = true;  //Forward
    }
  }
  Encoder_C1Last = Lstate;

  if (!direction)  pulse++;
  else  pulse--;
}

void calculatePulse_C2() {
  changed = 1;
  pulseTime = micros();
}

micros() only counts every 4 microseconds. That is 64 instruction cycles. I suspect you are getting two interrupts in the same 4 microseconds and therefore Periode == 0 and Frequency = 1.0 / 0.0 (inf?).

Hi John.
Thanks you for your fast answer. I have tried to improve in my code with a Delay of 10, 50, 50 ms. The graph has improved but the error 'inf' has not disappear...

When you fetch volatile variables, you have to turn off interrupts to keep an interrupt from changing the variable when they have been half-fetched.

  if (changed == 1)
  {
    noInterrupts();
    Periode = pulseTime - lastTime;
    interrupts();
    Periode = Periode / 1000000.0; //En segundos
    Frequency = 1.0 / Periode; //En Hz

Try that and see if it helps.

Hi John! Thanks. I have done the changes that you recommended me. But it does not work. I am getting the same results....

Hello John!
Finally, I have find a good solution. Now the code is working. It doesn't contain "inf", and the graph is ok. I would like softer graph, but I think that after all this is a good result.

const byte Encoder_C1 = 2; //Green wire pin 2 digital
const byte Encoder_C2 = 3; //Yellow pin 3 digital

volatile unsigned long pulseTime, lastTime;
volatile byte changed = 0;

volatile double Periode;
double Frequency;

volatile byte Encoder_C1Last;
volatile int pulse;
volatile boolean direction;


void setup() {
  Serial.begin(9600);

  pinMode(Encoder_C1, INPUT_PULLUP);
  pinMode(Encoder_C2, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(Encoder_C1), calculatePulse, CHANGE);
  attachInterrupt(digitalPinToInterrupt(Encoder_C2), calculatePulse_C2, HIGH);
}

void loop()
{

  if (changed == 1) {
    Frequency = 1.0 / Periode; //En Hz
    if (!direction) {
      Frequency *= -1;
    }
    changed = 0;

  } else {
    Frequency = 0;
  }

  Serial.println(Frequency);
}

void calculatePulse()
{
  lastTime = pulseTime;
  changed = 1;
  int Lstate = digitalRead(Encoder_C1);
  if ((Encoder_C1Last == LOW) && Lstate == HIGH)
  {
    int val = digitalRead(Encoder_C2);
    if (val == LOW && direction)
    {
      direction = false; //Reverse
    }
    else if (val == HIGH && !direction)
    {
      direction = true;  //Forward
    }
  }
  Encoder_C1Last = Lstate;

  if (!direction)  pulse++;
  else  pulse--;
}

void calculatePulse_C2() {
  changed = 1;
  pulseTime = micros();
  if (pulseTime > lastTime) {
    Periode = pulseTime - lastTime;
    Periode = Periode / 1000000.0; //In seconds
  }
}

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.