So you're a Noob? Post your questions here until you graduate! Don't be shy.

User avatar
By moose4621
#58631 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.
User avatar
By RichardS
#58691 Yes my thoughts too!

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

RichardS
User avatar
By moose4621
#58711 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();
}