-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Description
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
and those are the Zeros and Half Values I get
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