Deteccion de cruce por cero para controlar un triac

Si queres el encendio en el cruce por cero utilza un MOC3041, que dispara el triac directamente en el cruce por cero

Pandacba tengo el MOC3041 pero como he leido tantas cosas al final puse el MOC 3023 por que aunque es un prueba lo que quiero es que se ilumine poco a poco y luego se apague poco a poco tambien, de hay las 2 funciones que puesto en el programa.

Es que quiero quitar los interruptores que tengo en algunas zonas de la casa por que algunos me estan fallando y asi en vez de tener interruptores pondre pulsadores.

MIGLO:

:unsure: y aclara si lo que quieres es encender y apagar o dimerizar, porque creo que el MOC3041 no te sirve para dimerizar.

Eso es Papirrin las 2 cosas
 
:unsure: Le di una revizada a tu codigo por curiosidad y tampoco me gusta :LOL: (porque usas delays en la interrupcion, entre otras cosas)


mira yo los que he hecho, ya sea en basic, C o ASM, para dar el angulo de disparo utilizo un timer y la interrupcion externa, para darte una idea hice este codigo en C

Código:
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <stdbool.h>
#define _XTAL_FREQ 4000000

#pragma config FOSC = INTRCIO  
#pragma config WDTE = OFF       
#pragma config PWRTE = ON      
#pragma config MCLRE = OFF      
#pragma config CP = OFF   
#pragma config CPD = OFF       
#pragma config BOREN = OFF     
#pragma config IESO = OFF       
#pragma config FCMEN = OFF     

unsigned char BUFFER=127;

void interrupt isr(void){
 if(INTCONbits.T0IF==true){
  INTCONbits.T0IF=false; 
  PORTCbits.RC0=1;
  __delay_us(6);
  PORTCbits.RC0=0;
  INTCONbits.T0IE=false;}
 else if (PIR1bits.RCIF==true){
  PIR1bits.RCIF=false;
  BUFFER=RCREG;}
 else if (INTCONbits.INTF==true){
  INTCONbits.INTF=false; 
  TMR0=BUFFER;
  INTCONbits.T0IE=true;
  OPTION_REGbits.INTEDG=!OPTION_REGbits.INTEDG;}
}

void PIC_Init(void){
//Config
 OPTION_REGbits.INTEDG=true;
 OPTION_REGbits.T0CS=false;
 OPTION_REGbits.PS0=false;
 OPTION_REGbits.PS1=false;
 OPTION_REGbits.PS2=true;
 OPTION_REGbits.PSA=false;
 OSCCON=0x61;

//Interrupt Config
 PIE1bits.RCIE=true;
 INTCONbits.INTE=true;
 INTCONbits.PEIE=true;
 INTCONbits.GIE=true;

//Ports Config
 ANSEL=0;
 ANSELH=0;
 TRISA=0b100;
 TRISB=0b100000;
 TRISC=0b0;
 PORTA=0;
 PORTB=0;
 PORTC=0;
 
//TX_RX Config
 TXSTAbits.TXEN=true;
 TXSTAbits.TRMT=true;
 TXSTAbits.TX9=false;
 TXREG=0;
 RCSTAbits.CREN=true;
 RCSTAbits.RX9=false;

//Baud Rate Config
 RCSTAbits.SPEN=true;
 TXSTAbits.SYNC=false;
 TXSTAbits.BRGH=true;
 BAUDCTLbits.SCKP=false;
 BAUDCTLbits.BRG16=false;
 SPBRG=25;
 SPBRGH=0;
} 

void main(void)
{
 PIC_Init();
 while(true);
}

nada mas que en ese proyecto no utilice el mismo diagrama del puente rectificador que detecta el cruce por cero, en ese codigo tenia que cambiar el flanco porque fue un diagrama diferente, por eso te recominedo que definas bien que diagrama vas a utilizar.

Aclaro que en gustos se rompen generos y puede que tampoco te sirva y ese codigo lo hice en mikro C para un pic 16F690y supongo que tu estas usando PIC CCS
 
Última edición:
Asi es Papirrin yo uso Ccs, y gracias que me voy defendiendo poco a poco.

Sobre los delays de la interrupcion, pues como que se me atragantan y entonces a mi manera la hago, voy aprendiendo el tema de las interrupciones pero me cuesta mucho.

Como harias tù esa interrupcion?.
 
Mira a ver si hoy tengo un poco de tiempo y pongo un video del que tengo armado, el problema es que el codigo lo tengo en basic , vere si tambien tengo chance de migrarlo a ccs.
 
Ok, Papirrin. ¿Te importaría hacerme un ejemplo del manejo de una interrupción sin delay?
En este caso la int_ext, o la de int_rb, que son las que suelo manejar, con su explicación para que lo pueda entender.
Esto ya me lo explicó D@rbytes en su día, pero no me matizó lo de los delays.

Haber, yo de hacerlas, se hacerlas pero sencillas.
Esto es por ejemplo: Pulsar RB0 "int_ext" y que realice una función o instrucción.

Me gusta comprender las cosas, así yo me suelto haciendo mis pinitos.
Lo que pasa es que las interrupciones las tengo atragantadas, y mira que leo, pero de momento no termino de aclararme.
 
Última edición por un moderador:
Bueno aqui va el video prometido del que tengo armado y segun yo explicado del porque me gusto ese diseño que puse:

NOTA:en el video dije que era un MOC3041 pero me equivoque es un MOC3021 el que estoy utilizando XD.
 
Última edición:
Eso es lo que quiero hacer, me gusta la idea del 4N37.

El transformador que yo tengo es de 220 a 12Ac, voy a ponerme manos a la obra haber si encuentro un 4N37 y hago purebas.

Las bombillas que yo tengo son de leds, pero como no llevan regulador va bien, lo que llevan es el clasico puente con resistencia de limitacion y condensador de filtro y los leds van en serie.

Esa manera de encender la luz para la habitacion va de perlas.
 
ya hice la migracion de mi codigo de PBP a CCS....

Let's pray in C

Código:
#include <16F877A.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz
#FUSES PUT                     //Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected

#use delay(clock=4000000)

#define TRIAC  PIN_B3
#define F_MAX  PIN_B1
#define F_MED  PIN_B2

int VTO=240;


#int_RTCC
void RTCC_isr() 
{

 output_high(TRIAC);
 delay_us(10);
 output_low(TRIAC);
 disable_interrupts(INT_RTCC);
}

#int_EXT
void EXT_isr() 
{
 set_timer0(VTO);
 enable_interrupts(INT_RTCC);
}



void main()
{
   
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
   set_tris_B(0b111);
   
   while(true)
   {
    if (input(F_MAX))
          { 
       vto++;   
        delay_ms(10); // antirrebote si puedes usar otro metodo que no use delay mejor.
          }
          
    
    if (input(F_MED))
          {
          vto--;
           delay_ms(10); // antirrebote si puedes usar otro metodo que no use delay mejor.
          }   
   };

}

Obviamente es solo la parte importante. lo ajustas como quieras usando los menos delays posibles.

Video de funcionamiento:
 
Última edición:
Hola papirrin, estoy haciendo unas pruebas en proteus y se me satura el programa, te comento el transformador que yo tengo es 220 a 12, no lo tengo con toma central, lo normal es poner las conexsiones en el puente como se corresponde, pues si lo hago asi no me va ni para atras pero si le pongo como en el esquema que pusiste tu si va, esto es devido a proteus?, es mas tengo que poner el triac tambien una toma a tierra.

Otra pregunta, no tengo, de momento, ningun 4nxx ya que tu circuito me gusta mas que el mio pero si tengo un EL817 que es lo mismo que el PC817, este puede servir para hacer pruebas?.

Y por ultimo te agradezco el programa, lo entiendo todo, ya te digo que si lo hubiese tenido que hacer yo no me hubiese aclarado pero ahora me ha facilitado mas la comprension para en el futuro hacer mis pequeños pinitos, aunque se me siguen atragantando las interrupciones, yo creo que poco a poco ire cogiendo el tranquillo.

Me corrigo he probado el PC817 que aparece en proteus y en principio si que parace ser es bueno.
 
Última edición:
Hola papirrin, estoy haciendo unas pruebas en proteus y se me satura el programa, te comento el transformador que yo tengo es 220 a 12, no lo tengo con toma central, lo normal es poner las conexsiones en el puente como se corresponde, pues si lo hago asi no me va ni para atras pero si le pongo como en el esquema que pusiste tu si va, esto es devido a proteus?, es mas tengo que poner el triac tambien una toma a tierra.

bueno yo por eso no utilice el triac en el esquema que puse, porque no lo hace como en la realidad, en pocas palabras proteus a mi me sirve solo para ir probando el programa del pic sin tener que estar quemandolo en lo real a cada rato, y proteus si tiene que tener una toma a tierra como punto de referencia, pero en lo real no lo necesita, en lo real si puse una una toma a tierra pero solo para efectos de poner el osciloscopio pero no la va a llevar para que este completamente aislado el pic de la corriente alterna.

casi cualquier opto te sirve, todos son muy parecidos, o por lo menos los que yo he comparado(obviamente que sea un opto-transistor)

y de las interrupcciones no te hagas tanto lio, velo asi... un pic tiene diferentes modulos usart, timers, pwm, etc, esos modulos que son como los perifericos en una PC (mouse, teclado, impresora, etc) son independientes del CPU y casi todos tiene una interrupcion al programa principal o sea que se interrumpe el programa para ejecutar una subrutina, el cpu tiene asignada un seccion de programa en donde se coloca esa subrutina que se ejecuta al recibir esa interrupcion.

todas esos modulos modifican un registro para que sepas cual fue el que causo esa interrupcion, y esos registros de interrupcion se ven en la ficha tecnica, y cada modulo de cada pic tiene una manera particular de hacerlo por eso muchos no las comprenden y no es facil de explicarlas, se tiene que estudiar la ficha tecnica de como funciona cada una.
 
Última edición:
un pic tiene diferentes modulos usart, timers, pwm, etc, esos modulos que son como los perifericos en una PC (mouse, teclado, impresora, etc) son independientes del CPU y casi todos tiene una interrupcion al programa principal o sea que se interrumpe el programa para ejecutar una subrutina, el cpu tiene asignada un seccion de programa en donde se coloca esa subrutina que se ejecuta al recibir esa interrupcion.

todas esos modulos modifican un registro para que sepas cual fue el que causo esa interrupcion, y esos registros de interrupcion se ven en la ficha tecnica, y cada modulo de cada pic tiene una manera particular de hacerlo por eso muchos no las comprenden y no es facil de explicarlas, se tiene que estudiar la ficha tecnica de como funciona cada una.

No lo habia visto de esa manera, gracias.
 
Jeje, lo que hace el aburrimiento aveces, jeje.

Te quiero hacer unas preguntas si no te importa.

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64); esta configuracion es para 50 ciclos o para 60? es que no me aclaro con la equacion para sacar el tiempo.

Despues de haber configurado y montado el protoboard y haber resuelto 4 o 5 errores de montage tales como poner al reves el opto o conectar mal el pin Rb0 o equibocarme en el cristal ya que lo puse de 10 en vez de 4Mhz, ya me funciona el programa, pero he notado un problema que no se si es devido a la frecuencia, que es de 50ciclos, a la bombilla, esta es de leds como te comente, o a la tension que aqui es de 230Ac, el caso es que cuando conecto como esta configurado la variable VTO=240, no se me enciende pero al bajarla a 236 si, cuando llega a 107, la variable, entonces se apaga, yo lo habia modificado para que empieze en 100 y asi al ir subiendo que se valla encendiendo poco a poco, pues si empiezo en 100 no me funciona el programa pero si lo empiezo en 240, como lo tienes tu si, es mas si le pongo limitaciones al programa tales como que no baje de 100 o no supere 240 tampoco me funciona el programa y claro ya empiezo haber fantasmas por todos lados.

A que crees que puede ser devido?.

Por cierto, bonito video.



Por cierto, se me olvidaba, tengo el osciloscopio pero como lamentablemente perdi una sonda no veo como tu las señales, cosas que traen los años por no usarlo, jeje.
 
Última edición:
mira primero lo de la div de 64

la formula para eso es:
Temporización = (4 * (255-TMR0) * PreScaler)/Fosc

como tu frecuencia es de 50Hz el tiempo del ciclo es de 20mS, pero como gatillas a medio ciclo seria 10mS y despejando la formula seria:

TMR0=255-((tiempo*fosc)/4/64) o sea

TMR0=255-((.01*4000000)/4/64)=99

tu rango va de 99 a 255 , peroo como la onda de la frecuencia no es cudrada, el opto tarda unos microsegundos en saturar el transistor asi que puede fallar a los 99 y tendras que recorrerlo un poco como 100, 101... etc...

del otro lado de los 255 es mas o menos lo mismo a demas que no se puede lograr un desborde hasta los 255 porque el pic corre a una frecuencia de 4MHz y se tiene que considerar tiempos de ejecucion de cada instruccion, asi que es imposible llegar a los 255 asi que tambien tendras que bajar ese valor a doscientos cuarenta y tantos. o meter un cristal de 20Mhz o de plano usar un DSPIC si quieres que te abarque el 99.9% del rango. para mi hacer eso es excesivo pues de cualquier manera el ojo humano y el filamento ni se van a percatar.

en pocas palabras busca el rango que funcione bien y ten en cuenta que ningun metodo va a llegar al 100% del ciclo.


ahora bien si publicas tu codigo puedo decirte si existe algun otro error.
 
Última edición:
hola
bueno yo por eso no utilice el triac en el esquema que puse, porque no lo hace como en la realidad, en pocas palabras proteus a mi me sirve solo para ir probando el programa del pic sin tener que estar quemandolo en lo real a cada rato, y proteus si tiene que tener una toma a tierra como punto de referencia, pero en lo real no lo necesita, en lo real si puse una una toma a tierra pero solo para efectos de poner el osciloscopio pero no la va a llevar para que este completamente aislado el pic de la corriente alterna.

casi cualquier opto te sirve, todos son muy parecidos, o por lo menos los que yo he comparado(obviamente que sea un opto-transistor)

y de las interrupcciones no te hagas tanto lio, velo asi... un pic tiene diferentes modulos usart, timers, pwm, etc, esos modulos que son como los perifericos en una PC (mouse, teclado, impresora, etc) son independientes del CPU y casi todos tiene una interrupcion al programa principal o sea que se interrumpe el programa para ejecutar una subrutina, el cpu tiene asignada un seccion de programa en donde se coloca esa subrutina que se ejecuta al recibir esa interrupcion.

todas esos modulos modifican un registro para que sepas cual fue el que causo esa interrupcion, y esos registros de interrupcion se ven en la ficha tecnica, y cada modulo de cada pic tiene una manera particular de hacerlo por eso muchos no las comprenden y no es facil de explicarlas, se tiene que estudiar la ficha tecnica de como funciona cada una.
No vi el post antes ., sino aportaba :oops::oops::oops::oops: disculpen​
Bueno papirrin ., algo como esto., es lo que yo uso ., y me da muy buen resultado​
La señal de ZC ., la ingreso al micro por la entrada de la interupcion extena​
luego que se da el cruze por cero habilita el dimmer ., lo he probado concrgas inductivas y resistivas ., va OK​
zc_sch.gif dimmer_sch.gif dimm_best.gif last_pcb.gif
 
Última edición:
:unsure: pero asi como esta la deteccion del cruce por cero, solo detecta el ciclo completo no?

como gatillas en el ciclo negativo?
necesitas cambiar de flanco no? similar al codigo que puse de mikro C mensaje # 22

me explico?
 
Última edición:
:unsure: pero asi como esta la deteccion del cruce por cero, solo detecta el ciclo completo no?

como gatillas en el ciclo negativo?


me explico?
aver si queres te subo el ejemplo pero es en C ., para atmega​
., segun entiendo yo ., habilita el dimer cuando cruza por cero ., o sea va cambiando el PWM (aumenta o disminuye de acuerdo al comando )​
EDITO:
si papairrin es como en el mensaje numero 22​
 
Última edición:
si me gustaria verlo, segun yo tiene que cambiar de flanco... si lo he probao asi pero consume un poco de tiempo al estar cambiando el flanco de interrupcion, y por eso me gusta mas el del puente rectificador.
 
OK
si me gustaria verlo, segun yo tiene que cambiar de flanco... si lo he probao asi pero consume un poco de tiempo al estar cambiando el flanco de interrupcion, y por eso me gusta mas el del puente rectificador.
bueno aca te pongo el que uso en la maquina de humo DMX​
(uno esta para la bomba inductivo y el otro resistivo ., que es el calentador) tiene deteccion de temperatura tambien​
par que no te pierdas con el codigo la entrada de interupcion es PD3 (INT1)​
Código:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdlib.h>

typedef int8_t	s08;
typedef int16_t	s16;
typedef int32_t	s32;
typedef uint8_t	u08;
typedef uint16_t u16;
typedef uint32_t u32;

#define XTAL				8000000

#define DMX_StartCode		0 // DMX512 start code to react to (0 is for dimmers)
#define DMX_UART_Speed		250000	// standard DMX512 mode
#define DMX_UART_Div		(u16) (XTAL / 16 / DMX_UART_Speed - 1)
#define DMX_NUM_CHANNELS	3
#define DMX_INDICATOR_TIME	3

#define DIMMER_TimerStart	0xD8EF
#define DIMMER_AngleWidth	38
#define DIMMER_PORT			PORTA
#define DIMMER_PORT_DIR		DDRA

#define LED_PORT			PORTE
#define LED_PORT_DIR		DDRE
#define LED_Green			PE1
#define LED_Red				PE2

#define BLINK_Counter		25

#define PIN_Ext				PA0
#define PIN_Pump			PA1
#define PIN_Heater			PA2

#define PIN_Temp			ACO
#define PIN_ManFog			PA3

volatile u08 g_DMX_Status;		 				// current DMX status (global to be resettable)
volatile u08 g_DMX_Values[DMX_NUM_CHANNELS];
volatile u08 g_DMX_BaseAddress = 1;
volatile u08 g_DMX_IndicatorCounter = DMX_INDICATOR_TIME - 1;

volatile u08 g_DIMMER_PhaseCount;

volatile u08 g_DIMMER_PumpVal = 0;
volatile u08 g_DIMMER_PumpVal2 = 0;
volatile u08 g_DIMMER_ExtVal = 0;

volatile u08 g_TempState = 1;

volatile u16 g_CycleTime = 0;
volatile u08 g_OnTime = 0;

void DMX_ReadBaseAddress(void) {
 u08 temp;

 temp = PINC;
 g_DMX_BaseAddress=255-temp;
}

void DMX_init(void) {
 u08 i;
 // - UART mode
 UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); // 8n1
 UCSRB = (1<<RXCIE) | (1<<RXEN) | (1<<TXEN); // receive int and receiver enabled
 UBRRH = (u08) (DMX_UART_Div >> 8); // set baud rate
 UBRRL = (u08) (DMX_UART_Div);
 for (i=0; i<DMX_NUM_CHANNELS; i++) {
  g_DMX_Values[i] = 0;
 }
 g_DMX_Status = 0; // reset status to let ISR wait for next BREAK before doing anything
 DMX_ReadBaseAddress();
}

void DIMMER_init(void) {
 TCCR1B = 0b00000010; 					// set timer1 to ck/8
 // set interrupt 1 for phase zero-crossing control
 MCUCR |= (1 << ISC11);				// interrupt by falling edge
 MCUCR &= ~(1 << ISC10);				// <-^
 GICR |= (1 << INT1);					// enable interrupt0
 GIFR |= (1 << INTF1);					// clear interrupt0 flag
}

void init(void) {
 //ports
 DDRC = 192;
 PORTC = 255;
 DDRD = 4;
 PORTD = 8;
 LED_PORT_DIR = 255;
 LED_PORT = 255;

 DIMMER_PORT_DIR = 0b11110111;
 DIMMER_PORT =     0b00001111;

 ACSR = 0b01000000;								// bandgap reference (1.23V)

 TCCR0 = 0b00000101;							// set clk/1024
 TIMSK |= (1 << TOIE0);						// enable timer0 overflow interrupt
}

int main(void) {
 init();
 DMX_init();
 DIMMER_init();
 sei();										// Interrupts erlauben
 for (;;) {								// Endlosschleife
  g_DIMMER_ExtVal = g_DMX_Values[2];
  if (g_DMX_Values[0] > 7) {
   DIMMER_PORT &= ~(1 << PIN_Heater);			// LED an (Bit aus)
   if (g_TempState == 0) {
  DIMMER_PORT &= ~(1 << PIN_Heater);			// LED an (Bit aus)
    g_OnTime = 0;
    g_DIMMER_PumpVal = 0;
   } else {
    DIMMER_PORT |= 1 << PIN_Heater;				// LED aus (Bit an)
	if (bit_is_clear (PINA, PIN_ManFog)) {
     g_OnTime = 0;
     g_DIMMER_PumpVal = 255;	
	} else {
	 if (g_DMX_Values[0] < 21) {
	  g_OnTime = 0;
      g_DIMMER_PumpVal = 0;
	 } else if (g_DMX_Values[0] < 41) {
      g_CycleTime = 310;
	  g_OnTime = 10;
	 } else if (g_DMX_Values[0] < 61) {
      g_CycleTime = 370;
	  g_OnTime = 20;
	 } else if (g_DMX_Values[0] < 81) {
      g_CycleTime = 230;
	  g_OnTime = 30;
	 } else if (g_DMX_Values[0] < 101) {
      g_CycleTime = 190;
	  g_OnTime = 40;
	 } else if (g_DMX_Values[0] < 121) {
      g_CycleTime = 150;
	  g_OnTime = 50;
	 } else if (g_DMX_Values[0] < 141) {
      g_CycleTime = 135;
	  g_OnTime = 60;
	 } else if (g_DMX_Values[0] < 161) {
      g_CycleTime = 120;
	  g_OnTime = 70;
	 } else if (g_DMX_Values[0] < 181) {
      g_CycleTime = 120;
	  g_OnTime = 80;
	 } else if (g_DMX_Values[0] < 201) {
      g_CycleTime = 120;
	  g_OnTime = 90;
	 } else if (g_DMX_Values[0] < 221) {
      g_CycleTime = 120;
	  g_OnTime = 100;
	 } else if (g_DMX_Values[0] < 141) {
      g_CycleTime = 120;
	  g_OnTime = 110;
	 } else {
	  g_OnTime = 0;
      g_DIMMER_PumpVal = g_DMX_Values[1];
     }
	} 
   }	
  } else { 
   DIMMER_PORT |= 1 << PIN_Heater;				// LED aus (Bit an)
   g_DIMMER_PumpVal = 0;
  } 
 }
}

// LED-BLINKEN
SIGNAL (SIG_OVERFLOW0) {
 static u08 WaitTime = BLINK_Counter;
 static u08 SecTimer = 100;
 static u16 SecTimerPos = 0;
 static u08 TempStateCycles = 0;
 static u08 LastTempState = 0;

 if (g_OnTime > 0) {
  DIMMER_PORT |= 1 << 4;
  SecTimer--;
  if (SecTimer == 0) {
   SecTimerPos++;
   SecTimer = 100;
   if (bit_is_set (DIMMER_PORT, 7)) {
    DIMMER_PORT &= ~(1 << 7);
   } else { 
    DIMMER_PORT |= 1 << 7;
   } 
  }
  if (SecTimerPos < g_OnTime) {
   if (g_TempState == 0) {
    g_DIMMER_PumpVal = 0;
   } else {
    g_DIMMER_PumpVal = g_DMX_Values[1];
   }  
  } else {
   g_DIMMER_PumpVal = 0;
  }
  if (SecTimerPos >= g_CycleTime) {
   SecTimerPos = 0;
  }
 } else {
  DIMMER_PORT &= ~(1 << 4);
 }

 WaitTime--;
 if (WaitTime == 0) {
  // Basisadresse lesen
  DMX_ReadBaseAddress();
  if (bit_is_set (ACSR, PIN_Temp)) {
   // Heizen
   if (LastTempState == 1) {
    TempStateCycles++;
	if (TempStateCycles == 5) {
	 g_TempState = 0;
	}
   } else {
    LastTempState = 1;
    TempStateCycles = 0;
   }
  } else {
   // Temperatur erreicht
   if (LastTempState == 0) {
    TempStateCycles++;
	if (TempStateCycles == 5) {
	 g_TempState = 1;
	}
   } else {
    LastTempState = 0;
    TempStateCycles = 0;
   }
  } 
   
  // Grüne LED für Heizen / OK
  if (g_DMX_Values[0] > 7) {
   if (g_TempState == 0) {
    // Grüne LED blinken lassen = heizen
    if (bit_is_set (LED_PORT, LED_Green)) {
     LED_PORT &= ~(1 << LED_Green);			// LED an (Bit aus)
    } else { 
     LED_PORT |= 1 << LED_Green;				// LED aus (Bit an)
    } 
   } else {
    // Grüne LED an = Temperatur erreicht
    LED_PORT &= ~(1 << LED_Green);				// LED an (Bit aus)
   }   
  } else {
   // Grüne LED aus = Gerät aus
   LED_PORT |= 1 << LED_Green;				// LED aus (Bit an)
  } 
  // Rote LED für Fehler
  if (g_DMX_IndicatorCounter > 0) {
   g_DMX_IndicatorCounter--;
   LED_PORT &= ~(1 << LED_Red);				// LED an (Bit aus)
  } else {
   g_DMX_Values[0] = 255;
   g_DMX_Values[1] = 0;
   // Rote LED blinken lassen
   if (bit_is_set (LED_PORT, LED_Red)) {
    LED_PORT &= ~(1 << LED_Red);			// LED an (Bit aus)
   } else { 
    LED_PORT |= 1 << LED_Red;				// LED aus (Bit an)
   } 
  }
  WaitTime = BLINK_Counter; 
 } 
 TCNT0 = 0xb2; // 10ms
}

// DIMMER ZEROCROSSING
SIGNAL (SIG_INTERRUPT1) {
 static u08 PumpTimerPos = 255;

 TCNT1 = DIMMER_TimerStart;				// clear angle-timer
 TIFR |= (1 << OCF1A) + (1 << TOV1);		// clear compare flag; clear overflow-flag
 TIMSK |= (1 << OCIE1A) + (1 << TOIE1);	// enable timer1 compare interrupt A; enable timer1 overflow interrupt
 GICR &= ~(1 << INT1);						// disable ext-interrupt
 g_DIMMER_PhaseCount = 0xff;
 OCR1A = DIMMER_TimerStart + DIMMER_AngleWidth;
 
 PumpTimerPos=PumpTimerPos-2;
 if (PumpTimerPos < g_DIMMER_PumpVal) {
  PumpTimerPos = 255;
  DIMMER_PORT |= 1 << 5;
  g_DIMMER_PumpVal2 = 255;
 } else {
  DIMMER_PORT &= ~(1 << 5);
  g_DIMMER_PumpVal2 = 0;
 } 
}

// DIMMER ZEROCROSSING OVERFLOW
SIGNAL (SIG_OVERFLOW1) {
 TCNT1 = DIMMER_TimerStart;				// clear angle-timer
 TIMSK |= (1 << OCIE1A);					// enable timer1 compare interrupt A
 TIMSK &= ~(1 << TOIE1);					// disable timer1 overflow interrupt
 GIFR &= ~(1 << INTF1);					// clear interrupt1 flag
 g_DIMMER_PhaseCount = 0xff;
 OCR1A = DIMMER_TimerStart + DIMMER_AngleWidth;
}

// DIMMER (TIMER COMPARE)
SIGNAL (SIG_OUTPUT_COMPARE1A) {
 u16 Temp = 0;
 u16 Current;

 if (g_DIMMER_PumpVal2 > g_DIMMER_PhaseCount) {
  DIMMER_PORT &= ~(1 << PIN_Pump);			// LED an (Bit aus)
 } else {
  DIMMER_PORT |= 1 << PIN_Pump;				// LED aus (Bit an)
 }

 if (g_DIMMER_ExtVal > g_DIMMER_PhaseCount) {
  DIMMER_PORT &= ~(1 << PIN_Ext);			// LED an (Bit aus)
 } else {
  DIMMER_PORT |= 1 << PIN_Ext;				// LED aus (Bit an)
 }
 
 do {
  g_DIMMER_PhaseCount--;
  if (g_DIMMER_PhaseCount == 0) {
   break;
  }
  Temp = OCR1A;
  Temp += DIMMER_AngleWidth;
  Current = TCNT1;
 } while (Current >= Temp);	// test if next timer1-compare-value isn't already gone
 if (g_DIMMER_PhaseCount == 0) {
  TIMSK &= ~(1 << OCIE1A);					// disable timer1 compare interrupt
  DIMMER_PORT |= (1 << PIN_Ext) | (1 << PIN_Pump);				// LED aus (Bit an)
  DIMMER_PORT = 0b00001111;						// turn Dimmer port off (safe)
  if ((TIMSK & (1 << TOIE1)) == 0) {		// check for timer-overflow-interrupt; if timer1 overflow interrupt is enabled
   GIFR |= (1 << INTF1);					// clear interrupt1 flag
   GICR |= (1 << INT1);					// enable external interrupt1
  }
 } else {
  OCR1A = Temp;
 }
}

SIGNAL (SIG_UART_RECV) { // UART received one byte - highest priority
 static u16 DMX_Frame = 0;
 u08 Status = UCSRA; // status register must be read prior to UDR (because of 2 byte fifo buffer)
 u08 Byte = UDR; // immediately catch data from i/o register to enable reception of the next byte

 if ((Byte == 0) && (Status & (1<<FE))) { // BREAK detected (Framing Error)
  g_DMX_Status = 1;
  DMX_Frame = 0;
 } else if (DMX_Frame == 0) { // SC test
  if ((Byte == DMX_StartCode) && (g_DMX_Status == 1)) { // valid SC detected
   g_DMX_Status = 2;
  }
  DMX_Frame = 1;
 } else {
  if ((g_DMX_Status == 2) && (DMX_Frame >= g_DMX_BaseAddress) && (DMX_Frame < (g_DMX_BaseAddress + DMX_NUM_CHANNELS))) { // addressed to us
   u08 Channel = DMX_Frame - g_DMX_BaseAddress;
   if (Channel < DMX_NUM_CHANNELS) {
    g_DMX_Values[Channel] = Byte;
   }
   g_DMX_IndicatorCounter = DMX_INDICATOR_TIME - 1;
  }
  DMX_Frame++;
 }
}
No se como andas econ ASM ., pero siqueres tengo tambien (es lo mismo ., pero solo dimer )​
Pero tambien al igual que el anterior ., recontra probados y sin problemas​
 
Última edición:
Atrás
Arriba