AC 220V Okuma

Başlatan PICaso, 23 Kasım 2020, 15:33:29

PICaso

Alıntı yapılan: Proteus - 02 Aralık 2020, 11:07:31TrueRMS farklı RMS Farklı aralarındaki en büyük fark birinin sadece sinüsün max. noktasını bulup 0,707 ile çarpması diğerinin ise örnekler alıp ortalamasını alıp daha keskin sonuç çıkarması.

VRMS:


VTRMS:


VTRMS Kod ornegi:


Eğer keskin bir ölçüm yapacaksan VTRMS yapacaksın harmonik bindi mi sisteme sapıtır.

Hocam kod örneğinde 1024 örnek alıyor ama bunu ne kadar sürede alıyor?

Proteus

Eşit olarak bölebilirsin kaç us ise okadar illa 1024 almana da gerek yok

PICaso

Hocam zaman kavramını kafamda tam olarak oturtamadım. 1000 örnek alıyorsam 20ms/1000 kadar bir timer mı kurmam

gerekiyor. Nasıl bir şart sağlandığın da adc yaptırmalıyım? kısaca açıklar mısınız?

PICaso

Alıntı yapılan: Erol YILMAZ - 24 Kasım 2020, 11:51:25LM358 veya LM324 kullanabilirsin.
Differantial amplifier yapısı endüstriyel elektronikte sıklıkla kullanılır.

Gerilim kazancı = 3K / (2x220K) olarak hesaplanır.
Çıkışın Ofset gerilimi 2.5v'tur.

Whats-App-Image-2020-11-24-at-11-47-46" border="0

Opampın Çıkışında 2.5V ofset gerilimine bindirilmiş 3/440 oranında zayıflatılmış girişteki AC sinyali göreceksin.
Bunu da ADC yardımıyla True RMS olarak okuyabilirsin.
Hocam bu devre ile voltaj okumayı başardım. Şimdi Frekansıda okumak istiyorum. Nasıl bir yol izlemeliyim?

Erol YILMAZ

Frekans için;
ADC'ye giden sinyal ile TL431'in 2.5v luk gerilimini COMPARATOR ile karşılaştırarak oluşturduğun kare dalganın  periyoduna bakabilirsin.

PICaso

#35




Kare dalga sinyal ile picin capture fonksiyonu kullanarak şebeke frekansını ölçüyorum sorunsuz.
Sinüs ile de ADC voltajı ölçmeye çalışıyorum. Fakat lcd de ki değer 200-270 arasında geziyor. Yazılım kısmında hatalarım olduğunu düşünüyorum. Yardımlarınızı bekliyorum.

unsigned int sayici=0;
float frekans=0;
void __interrupt() kesme(void)
{
    if(CCP1IF)
    {
        CCP1IE=0;
        TMR1H=0;
        TMR1L=0;
        sayici=(CCPR1H<<8)+CCPR1L;
    }
     CCP1IE=1;
     CCP1IF=0;      
}

void ADC_Init()
{    
    TRISA = 0xff;		/*Set as input port*/
    ADCON1 = 0x07;  		/*Ref vtg is VDD & Configure pin as analog pin*/    
    ADCON2 = 0x92;  		/*Right Justified, 4Tad and Fosc/32. */
    ADRESH=0;  			/*Flush ADC output Register*/
    ADRESL=0;   
}

int ADC_Read(int channel)
{
    int digital;
    ADCON0 =(ADCON0 & 0b11000011)|((channel<<2) & 0b00111100);
    //*channel 0 is selected i.e.(CHS3CHS2CHS1CHS0=0000)& ADC is disabled
    ADCON0 |= ((1<<ADON)|(1<<GO));//*Enable ADC and start conversion
    //*wait for End of conversion i.e. Go/done'=0 conversion completed
    while(ADCON0bits.GO_nDONE == 1);
    uint8_t adc_lo = ADRESL;
    uint8_t adc_hi = ADRESH;
    digital =  (uint16_t)(adc_hi << 8) | (uint16_t)adc_lo;
    return(digital);
}

float RMS_value;
float RMS (){
    int16_t i,t;
    int32_t V1,V2;
    V1=V2=0;
    for(i=0;i<1000;i++)
    {
        t=ADC_Read(0);
        V1=V1+(int32_t)t*(int32_t)t;
        V2=V2+(int32_t)t;
    }
    RMS_value=sqrt(V1/1000.0-((V2/1000.0)*(V2/1000.0)));
    RMS_value=((float)4.31)*((float)RMS_value);   //  220V icin 
    return RMS_value;        
}

int deger1;
void main()
{    
    char s[16];
    
    TRISA = 0xff;
    TRISB = 0x00; //LCD BAGLANTILARI
    TRISD = 0x00; 
    Lcd_Init(); /*Initialize 16x2 LCD*/
    ADC_Init();			/*Initialize 10-bit ADC*/
    ///////FREKANS ICIN///////////////////////////////////////////////////////////// 
    TRISC=0XFF;
    GIE=1;
    PEIE=1;
    T1CON=0B11111001; //bit4,5;1:8 Prescale value    
    CCP1CON=0B00000101;    //Her yukselen kenarda okuma yapar   
    PIE1bits.CCP1IE=1;
    PIR1bits.CCP1IF=0;
    TMR1H=0;
    TMR1L=0;
    CCPR1H=0;
    CCPR1L=0;
//////////////////////////////////////////////////////////////////////////////// 

    while(1)    
    {      
    if(CCP1IF){
        CCP1IE=0;
        TMR1H=0;
        TMR1L=0;
        sayici=(CCPR1H<<8)+CCPR1L;     
    }
    CCP1IE=1;
    CCP1IF=0;    
    frekans=625000/(float)sayici; // 625000=20MHz/4*8 ,,,frekans floata çevrilir.           
    
    RMS();
    int toplam = 0;
        for(int j = 0; j < 100; j++) //100 farkli ADC de?erini okuruz.
    {   toplam=toplam+RMS_value; }
        deger1 = toplam / 100 ;   
        
    sprintf(s, "VOLTAJ FRQ OKUMA  " );
    Lcd_Set_Cursor(1,1);
    Lcd_Write_String(s);    
    sprintf(s, "V=%d   F=%.3f  ",deger1,frekans); 
    Lcd_Set_Cursor(2,1);
    Lcd_Write_String(s);
    }         
}

ipek

en baba counter'ler bile Sinus ölçmekte zorlanır.bir komparatör ile frekansı kare dalga formuna yaklaştırmalısınız. bu konuda terimler Comparator Slicer , Clock Shaper gibi frekans 10KHz'yi geçmiyorsa LM311 open Collector Comparator hatta LM555 bile olabilir.yinede frekans aralığınızı bilmek gerekir.

düşük frekanslar responce süresini uzatır,en kolay yöntemi Periyot ölçümüdür.

örnek ticari counterlerin çoğu düşük frekanslardaki iyileşme için Reciprocal Period dönüşümü yapar. bir mini örnek 64uS = 15625 Hz gibi.
muhakkak MCU ölçsün istiyorsanız bazı işlemcilerde Schmitt Trigger pin'i bulunmaktadır,bu pin'de bir çeşit wave shaping yapma kabiliyetine sahiptir..

PICaso

Şebeke voltajı ölçeceğim hocam. Yüksek frekanslar değil yani.

Erol YILMAZ

True RMS gerilim örneklerini 1 periyota yaymak gerekiyor...

for(i=0;i<1000;i++){
  t=ADC_Read(0);
  V1=V1+(int32_t)t*(int32_t)t;
  V2=V2+(int32_t)t;
}

kodunu tahminen güncelleyelim...

50 Hz = 20mS
64 örnek alıcaksan 20ms / 64 = 312.5uS de 1 örnek alman gerekiyor.

for(i=0;i<64;i++){
  t=ADC_Read(0);
  V1=V1+(int32_t)t*(int32_t)t;
  V2=V2+(int32_t)t;
  delay_us(280)
}

PICaso

Alıntı yapılan: Erol YILMAZ - 23 Mart 2021, 13:12:35True RMS gerilim örneklerini 1 periyota yaymak gerekiyor...

for(i=0;i<1000;i++){
  t=ADC_Read(0);
  V1=V1+(int32_t)t*(int32_t)t;
  V2=V2+(int32_t)t;
}

kodunu tahminen güncelleyelim...

50 Hz = 20mS
64 örnek alıcaksan 20ms / 64 = 312.5uS de 1 örnek alman gerekiyor.

for(i=0;i<64;i++){
  t=ADC_Read(0);
  V1=V1+(int32_t)t*(int32_t)t;
  V2=V2+(int32_t)t;
  delay_us(280)
}

Hocam bu şekilde düzenledim ama yine çalışmadı.
float RMS_value;
float RMS (){
    int16_t i,t;
    int32_t V1,V2;
    V1=V2=0;
    
    for(i=0;i<64;i++){
    t=ADC_Read(0);
    V1=V1+(int32_t)t*(int32_t)t;
    V2=V2+(int32_t)t;
    __delay_us(280);
    }
    
    RMS_value=sqrt(V1/1000.0-((V2/1000.0)*(V2/1000.0)));
    RMS_value=((float)4.31)*((float)RMS_value);   //  220V icin 
    return RMS_value;        
}

280 us nereden geldi onu da anlamadım.