-->
Page 1 of 2

rpm tacho using interrupts

PostPosted: Thu Nov 24, 2016 3:54 pm
by moose4621
I am trying to get a tacho working for feedback into a PID loop but the code I used for a Uno doesn't seem to work for ESP8266 Wemos D1 mini.
I get erratic results and I also get an output even when the motor is powered down.
I am guessing there is a difference in the way interrupts are handled????
I cannot seem to find any examples of tacho code for ESP8266 so here I am.

The code
Code: Select allvolatile float time = 0;
volatile float time_last = 0;
volatile int long rpm_array[5] = {0, 0, 0, 0, 0};
int pot;

void setup()
{
  pinMode(14, INPUT_PULLUP);
  //IO14 (D5) Set As An Interrupt
  attachInterrupt(14, fan_interrupt, FALLING);



  Serial.begin(115200);
  digitalWrite(13, HIGH);
  analogWrite(12, 500);
}

//Main Loop To Calculate RPM and Update LCD Display
void loop()
{
  while (1) {


    int long rpm = 0;

    //Slow Down The Display Updates
    delay(400);

    //Update The RPM

    noInterrupts();
    unsigned long copyTime = time;
    interrupts();


    if (time > 0)
    {

      //5 Sample Moving Average To Smooth Out The Data
      rpm_array[0] = rpm_array[1];
      rpm_array[1] = rpm_array[2];
      rpm_array[2] = rpm_array[3];
      rpm_array[3] = rpm_array[4];
      rpm_array[4] = 60 * (1000000 / (time * 36));
      //Last 5 Average RPM Counts Eqauls....
      rpm = (rpm_array[0] + rpm_array[1] + rpm_array[2] + rpm_array[3] + rpm_array[4]) / 5;

      // rpm = 60*(1000000/(time * 36));
      Serial.print(rpm);
      Serial.println(" rpm");
      //Serial.println(pot);
    }

  }
}


//Capture The IR Break-Beam Interrupt
void fan_interrupt()
{
  time = (micros() - time_last);
  time_last = micros();
}


The output.
Code: Select all54 rpm
83387 rpm
83391 rpm
83347 rpm
83349 rpm
83349 rpm
19 rpm
20 rpm
20 rpm
19 rpm
19 rpm
20 rpm
19 rpm
19 rpm
19 rpm
19 rpm
19 rpm
19 rpm
53 rpm
53 rpm
52 rpm
52 rpm
52 rpm
20 rpm
20 rpm


Any help would be appreciated.

Re: rpm tacho using interrupts

PostPosted: Fri Nov 25, 2016 2:14 pm
by martinayotte
Did you tried to use strong external pullup instead of weak internal one ?

Re: rpm tacho using interrupts

PostPosted: Fri Nov 25, 2016 10:04 pm
by RichardS
Yes my thoughts too!

And you need to set time = 0; after the if (time>0) is done... :-)

RichardS

Re: rpm tacho using interrupts

PostPosted: Sat Nov 26, 2016 9:38 am
by moose4621
Latest code. Still erratic.
Code: Select allint RPWM = 12;
int LPWM = 16;
int L_EN = 13;
int R_EN = 15;


//void setPWMfrequency(int freq){
//   TCCR2B = TCCR2B & 0b11111000 | freq ;
//  }


volatile float time = 0;
volatile float time_last = 0;
volatile float rpm_array[5] = {0, 0, 0, 0, 0};
int pot;

void setup()
{
  //   setPWMfrequency(0x02);// timer 0 , 3.92KHz
  pinMode(14, INPUT_PULLUP);
  pinMode(L_EN, OUTPUT);
  pinMode(R_EN, OUTPUT);
  analogWriteFreq(3920);//set pwm freq for ESP8266

  //Digital Pin 2 Set As An Interrupt
  attachInterrupt(14, fan_interrupt, FALLING);

  Serial.begin(115200);
  digitalWrite(R_EN, HIGH);
  digitalWrite(L_EN, HIGH);
  analogWrite(RPWM, 100);// default is 0 - 1023
  analogWrite(LPWM, 0);

}

//Main Loop To Calculate RPM and Update LCD Display
void loop()
{
  while (1) {

      float  rpm = 0;

    //Slow Down The Display Updates
    delay(400);

    if (time > 50000)
    {

      //5 Sample Moving Average To Smooth Out The Data
      rpm_array[0] = rpm_array[1];
      rpm_array[1] = rpm_array[2];
      rpm_array[2] = rpm_array[3];
      rpm_array[3] = rpm_array[4];
      rpm_array[4] = 60 * (1000000 / (time * 36));
      //Last 5 Average RPM Counts Eqauls....
      rpm = (rpm_array[0] + rpm_array[1] + rpm_array[2] + rpm_array[3] + rpm_array[4]) / 5;

      // rpm = 60*(1000000/(time * 36));
      Serial.print(" time "); Serial.print(time);
      Serial.print("  ");
      Serial.print(rpm_array[4]);
      Serial.println(" rpm");
      //Serial.println(pot);
     
    }
time = 0;
  }
 
}


//Capture The IR Break-Beam Interrupt
void fan_interrupt()
{
  time = (micros() - time_last);
  time_last = micros();
}