M031 ile AC Güç Kontrolü

Başlatan Kırambor, 04 Ağustos 2022, 11:52:06

Kırambor

Merhabalar herkese,

Nuvoton'un M031 işlemcisi ile AC güç kontrolü yapmak istiyorum. Bunun için bir zero crossing detector devrem bulunmakta. Zero crossing çıkışı bana şebekeden gelen sinyalin 0 geçişlerinde bir pulse veriyor. Ben bu çıkışı GPIO girişine bağladım ve o girişin interruptını aktif ettim. Interrupt içinde de timer start ediyorum.

Triac için tetikleme vermem gerekiyor. Bunun için bir GPIO portunu(PA3) output olarak tanımladım. Tetiklemeyi elde etmek için de Timer compare değeri 100 olunca PA3 1 yapıyorum. Counter limit olarak compare değeri farzediyorum 10000 olsun. Compare 10000'e ulaşınca da PA3'ü sıfıra çekip counter resetleyip timerı kapatıyorum. Timer'ı resetleme sebebim, timer'ı direkt kapatırsam counter değeri eski kaldığı yerden devam ediyor ama ben sıfırdan tekrar saymaya başlamasını istiyorum.

Referans olarak kendime bu videoyu aldım. Adam yükselen kenar algılamak için input capture vs kullanmış ama ben bunu zero crossing detector devresi ile yapıp çıkışta aldığım pulse'i GPIO interruptına veriyorum.

Burada şöyle bir şeyle karşılaştım. Timer interrupt handler fonksiyonu TMR0_IRQHandler() diye geçiyor. Fakat hem compare hem de overflow olduğunda aynı interrupt fonksiyonu içine gidiyor. Ben de interrupt handler fonksiyonuna gelen interruptlar arasında bir geçiş olabilmesi için tmr_control diye bir değer tanımladım ve o şekilde kontrol etmeye çalıştım.

Şu an denediğim kod şu şekilde:
/********************
MCU:M031SD2AE(LQFP64)
Base Clocks:
HIRC:48MHz
PLL:96MHz
HCLK:48MHz
PCLK0:48MHz
PCLK1:48MHz
Enabled-Module Frequencies:
ADC=Bus Clock(PCLK1):48MHz/Engine Clock:48MHz
ISP=Bus Clock(HCLK):48MHz/Engine Clock:48MHz
PWM0=Bus Clock(PCLK0):48MHz/Engine Clock:48MHz
SYSTICK=Bus Clock(HCLK):48MHz/Engine Clock:24MHz
TMR0=Bus Clock(PCLK0):48MHz/Engine Clock:48MHz
********************/

#include "M031Series.h"

#define pulse PA3

uint32_t tmr_control = 0;

void SYS_Init()
{
    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Enable clock source */
    CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);

    /* Waiting for clock source ready */
    CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

    /* Disable PLL first to avoid unstable when setting PLL */
    CLK_DisablePLL();

    /* Set PLL frequency */
    CLK->PLLCTL = (CLK->PLLCTL & ~(0x000FFFFFul)) | 0x0008C03Eul;

    /* Waiting for PLL ready */
    CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);

    /* If the defines do not exist in your project, please refer to the related clk.h in the Header folder appended to the tool package. */
    /* Set HCLK clock */
    CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1));

    /* Set PCLK-related clock */
    CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV1 | CLK_PCLKDIV_APB1DIV_DIV1);

    /* Enable IP clock */
    CLK_EnableModuleClock(ADC_MODULE);
    CLK_EnableModuleClock(ISP_MODULE);
    CLK_EnableModuleClock(PWM0_MODULE);
    CLK_EnableModuleClock(TMR0_MODULE);
    CLK_EnableModuleClock(UART0_MODULE);
    CLK_EnableSysTick(CLK_CLKSEL0_STCLKSEL_HIRC_DIV2, 0);

    /* Set IP clock */
    CLK_SetModuleClock(ADC_MODULE, CLK_CLKSEL2_ADCSEL_PCLK1, CLK_CLKDIV0_ADC(1));
    CLK_SetModuleClock(PWM0_MODULE, CLK_CLKSEL2_PWM0SEL_PCLK0, MODULE_NoMsk);
    CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0SEL_HIRC, MODULE_NoMsk);
    CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_PCLK0, CLK_CLKDIV0_UART0(1));

    /* Update System Core Clock */
    /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
    SystemCoreClockUpdate();
		
		//PB5 -> timer0
		SYS->GPB_MFPL = (SYS->GPB_MFPL & ~SYS_GPB_MFPL_PB5MFP_Msk) | SYS_GPB_MFPL_PB5MFP_TM0;
		
		//PB12 ve PB13 UART
		SYS->GPB_MFPH = ((SYS->GPB_MFPH & (~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk)))
                     | (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD));

    /* Lock protected registers */
    SYS_LockReg();
}

void GPIO_Init(void)
{
	//PA1-> input tanimla ve interrupt aktif et.
	GPIO_SetMode(PA,BIT1,GPIO_MODE_INPUT);
	GPIO_EnableInt(PA,1,GPIO_INT_RISING);
	NVIC_EnableIRQ(GPIO_PAPBPGPH_IRQn);
	
	//PA3-> output tanimla
	GPIO_SetMode(PA,BIT3,GPIO_MODE_OUTPUT);
}

void UART0_Init(void)
{
    /* Reset UART0 */
    SYS_ResetModule(UART0_RST);

    /* Configure UART0 and set UART0 baud rate */
    UART_Open(UART0, 115200);
}

void Timer_Init(void)
{
	TIMER_Open(TIMER0,TIMER_CONTINUOUS_MODE,1000);
	TIMER_SET_CMP_VALUE(TIMER0,100);
	
	TIMER_EnableInt(TIMER0);
	NVIC_EnableIRQ(TMR0_IRQn);
}

int main(void)
{
	SYS_Init();
	GPIO_Init();
	Timer_Init();
	UART0_Init();
	
	while(1);
}

void TMR0_IRQHandler(void)
{
	if(TIMER_GetIntFlag(TIMER0))
	{
		if(tmr_control == 0)
		{
			pulse = 1;
			tmr_control = 1;
			TIMER_SET_CMP_VALUE(TIMER0,10000);
		}
		else if(tmr_control == 1)
		{
			tmr_control = 0;
			pulse = 0;
			TIMER_ResetCounter(TIMER0);
			TIMER_Stop(TIMER0);
		}
		TIMER_ClearIntFlag(TIMER0);
	}
}

void GPABGH_IRQHandler(void)
{
	if(GPIO_GET_INT_FLAG(PA,BIT1))
	{
		TIMER_Start(TIMER0);
	}
	GPIO_CLR_INT_FLAG(PA,BIT1);
}

Referans aldığım uygulama da bu:




Zero crossing detector devrem:




Fakat çıkışta görmek istediğim tetikleme için gereken kare dalgayı göremiyorum. Nerede hata yapıyor olabilirim?

~ENES~

Hocam kare dalga gormeniz gerekmez. Şebekenin sıfır geçiş noktalarını okumaniz yeterli. Çift ledli opto kullanirsaniz her iki alternans için sıfır noktalarini yakalayabilirsiniz.

Kırambor

Alıntı yapılan: ~ENES~ - 04 Ağustos 2022, 14:00:23Hocam kare dalga gormeniz gerekmez. Şebekenin sıfır geçiş noktalarını okumaniz yeterli. Çift ledli opto kullanirsaniz her iki alternans için sıfır noktalarini yakalayabilirsiniz.
Kartta PC814 kullanıyorum. Ben ekran görüntüsündeki gibi triacı tetiklediğim sinyali görmek istiyorum. Çünkü potansiyometreye bağlayıp o sinyali hareket falan ettiricem.

mehmet

Sıfır noktasına yakın ya da daha
önce triyak tetiği kapanmalı.