Skip to content

Not able to make accurate Mains Frequency Counter with ESP32  #4325

@MG-Tawfeek

Description

@MG-Tawfeek

OptoCoupler_Circuit

This is the circuit I'm using to measure Frequency of mains , it's as simple as it can be
but with ESP32 , for some reason .. I'm getting inconsistent data .

This same circuit works perfectly with great accuracy with Arduino Uno , You just have to connect the OptoCoupler to arduino
instead of ESP32

The Code I'm using to test this is a simple while loops to detect high/low cycles , and again I'm getting great accuracy from
Arduino .
When using ESP32 (devKit) , :
1-If I connect the Power and GND of the PC817/EL817 from ESP32 -> lots of wrong values
2-If I power the PC817 from an External Power source and share a common ground with esp32,
it gets better , but occasionally I get Zero or half the value
This is a sample of the value I get
Screenshot from 2020-09-05 10-41-34

and those are the Zeros and Half Values I get

Screenshot from 2020-09-04 07-07-08

I use 2 sketches to debug this
-first one is to see the stability of reading per minute , just a state machine sketch

``
int count = 0;
unsigned long lastEntry;
int stat = 0;

#define INPUTPIN 34

void setup()
{

Serial.begin(115200);
pinMode(INPUTPIN, INPUT);

//Serial.printf("ESP TIMER : %jd \n", esp_timer_get_time());
}

void loop()
{

noInterrupts();
count = 0;
lastEntry = millis();
while (millis() < lastEntry + 1000)
{

bool inputSignal = (digitalRead(INPUTPIN));
switch (stat) 
{
  case 0:
    if (inputSignal) 
    {
      count++;
      stat = 1;
    }
    break;

  case 1:
    if (!inputSignal) 
      stat = 0;
    break;

  default: 
    break;
}

}
Serial.print("Frequency : ");
Serial.println(count);

interrupts();
delay(500);
}

The 2nd Sketch is to measure the Cycle length

``int FC_PIN = 34 ;
void setup()
{
Serial.begin(115200);
pinMode(FC_PIN,INPUT);
noInterrupts() ;
delay(1000);
}

void loop()
{
char buf[8] = "";
volatile int64_t start_time, end_time, cycle_duration ;
// int64_t end_time ;
// int64_t cycle_duration ;

// if(digitalRead(FC_PIN)== HIGH)
//   continue ;

//noInterrupts() ;
while(digitalRead(FC_PIN) != LOW)
// while(analogRead(FC_PIN) > 0)
  {
    // If we get here while the phase is high .. wait till the phase is LOW
  }
  

while(digitalRead(FC_PIN) == LOW)
// while(analogRead(FC_PIN) == 0)
  {
    // Wait till the LOW Phase ends so we start the timer
  }

 
start_time = esp_timer_get_time(); // timer in microSeconds

while(digitalRead(FC_PIN) == HIGH)
// while(analogRead(FC_PIN) > 0)
  {
  // another wait till the  HIGH phase ends 
  }

while(digitalRead(FC_PIN) == LOW)
// while(analogRead(FC_PIN) == 0)
{
  // another wait till we reach the high phase again
}

end_time = esp_timer_get_time() ;

cycle_duration  =  end_time - start_time ;




/////// Inaccurate .. multiple wrong readings !
// int64_t high = pulseInLong(FC_PIN, HIGH);
// int64_t low = pulseInLong(FC_PIN, LOW);
// // int64_t 
// cycle_duration = high + low ;


//sprintf(buf, "%.3f", (cycle_duration/1000.0)) ;
// dtostrf((cycle_duration/1000.0), 6, 3, buf);
//client.publish("test/dk-2", buf);

//interrupts();
Serial.printf("Start_Time : %jd \t End_Time : %jd \t", start_time, end_time);
Serial.printf("Duration for 1 Cycle is : %.3f mSec\n", cycle_duration/1000.0);

//start_time = end_time = cycle_duration = 0 ;

delay(500);

}

hopefully I'm missing something here
I've seen lots of people telling me to go for Ledc , PCNT , RMT .. and so on
All of those are fine If I'm getting a constant data but more accuracy is needed , but now it's just inconsistent data
and why I'm getting either the zero (very low value) or nearly half the reading ?

Thanks

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions