viernes, 23 de septiembre de 2022

Zero Crossing con microcontrolador PIC, TRIAC doble disparo de compuerta con PIC12F675

En este proyecto se hace el uso de la tecnica de interrupcion por cruze por cero del microcontrolador PIC12F675 un programa muy simple que solo funciona cuando la onda seno crusa por sero y un retardo variable que se calcula teniendo en cuenta el periodo de la seña AC a controlar.





Asi se ve la onda de salida recortada del triac.







Como el diseño es muy antiguo tengo que actualizar las librerias y pasar el programa a C con el fin de que sea mas facil de entender.

por ahora les dejo el codigo fuente:



LIST   P=12f675

RADIX HEX

include "P12f675.inc"    ;Definiciones de registros internos

;Palabra de configuracion

__config _CPD_OFF & _BODEN_ON & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _CP_OFF & _CPD_OFF


CBLOCK  0x20
duty, ContTemp, RegDelayAng1, RegDelayAng2, RegDelayPulso
ENDC
        ORG 0
goto INICIO

ORG 4  ;inicio de la subrutina de interrupcion
        btfss   INTCON,INTF            ; Si La interrupcion corresponde al RBif sigue si no regresa
        retfie
        bcf     INTCON,GIE             ; Desabilitamos el permiso global de interrupciones
        call    pulso
;-------------------------------
        BANKSEL  option_reg
        btfss    option_reg,6
        goto     SetFl
        bcf      option_reg,6 ; sentido de disparo de la interrupcion externa 1=asendente 0 desendente.
        goto     salint
SetFl:  
        bsf      option_reg,6 ; sentido de disparo de la interrupcion externa 1=asendente 0 desendente.        
salint: 
        BANKSEL  0
;-------------------------------
        Bcf     INTCON,INTF
        bsf     INTCON,GIE
        retfie


INICIO
    BANKSEL  OSCCAL
    call 3FFh ;Get the cal value
    movwf    OSCCAL ;Calibrate
    movlw    b'11111110'
    movwf    TRISIO
    movlw    b'01100010'
    movwf    ANSEL 
    BANKSEL  option_reg
    bsf      option_reg,6 ; sentido de disparo de la interrupcion externa 1=asendente 0 desendente.
    BANKSEL  0
    bsf      gpio,0

    movlw   b'00000101'
    movwf   ADCON0
    movlw   .10
    movwf   duty

    movlw    b'00000111'
    movwf    CMCON

    bsf      INTCON,INTE
    bsf      INTCON,intf
    bsf      INTCON,GIE
;*******************************************************************************************
; Aqui comiensa el programa
KErneL
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    call     GetAdc
    movwf    duty
    movlw    .100
    movwf    ContTemp
    decfsz   ContTemp,f
    goto     $-1
    bsf      gpio,0
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;*******************************************************************************************
    goto      KErneL
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; Subrutinas de retardo independientes
;*********************************************************************
; DelayAng: retardo variable para producir un angulo de disparo variable
DelayAng
        movwf      RegDelayAng1
DelayAng1
        movlw      .8
        movwf      RegDelayAng2

        decfsz     RegDelayAng2,f
        goto       $-1

        decfsz     RegDelayAng1,f
        goto       DelayAng1
        return
;*********************************************************************
; Este retardo es para el ancho del pulso de disparo
DelayPulso
        movlw     .100
        movwf     RegDelayPulso
        decfsz    RegDelayPulso,f
        goto      $-1
        return
;*********************************************************************
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
GetAdc
   bsf     ADCON0,GO
   btfsc   ADCON0,GO
   goto    $-1
   movf    adresh,w
   return
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
pulso
        incf    duty,w
        ;movlw   .200
        call    DelayAng
        Bcf     gpio,0
        call    DelayPulso
        Bsf     gpio,0
        return



    goto      $


org 0x3ff
retlw 0x34

end


sábado, 20 de agosto de 2022

Gigantesco secuenciador de luces de 22 salidas programado en mikroc en un PIC16F876A




Esquema:



El codigo de la secuencia lo puedes ver a continuacion:

   #include <built_in.h>

   #define bts 5

//*******************************************************

// Esta rutina es la encargada de sacar a los tres puertos 22 lineeas los datos

   void Sout(unsigned long dato){

   portb=lo(dato);

   portc=hi(dato);

   porta=Higher(dato);

   }

//*******************************************************

// Esta rutina es la encargada de sacar a los tres puertos 22 lineeas los datos

   void saca(unsigned long dato){

   if(dato==0){return;}

   portb=lo(dato);

   portc=hi(dato);

   porta=Higher(dato);

   delay_ms(75);

   }

//*******************************************************

// Saca los datos con retardo segun variable

   void saca2(unsigned long dato, unsigned short t){

   unsigned short j;

   if(dato==0){return;}

   portb=lo(dato);

   portc=hi(dato);

   porta=Higher(dato);

   for(j=0;j<t;j++){delay_ms(1);}

   }

//*******************************************************

//Saca los datos invertidos al puerto leds a tierra

 void DSaca(unsigned long dato){

   dato=~dato;

   portb=lo(dato);

   portc=hi(dato);

   porta=Higher(dato);

 }

//*******************************************************

// Mueve los datos recividos secuencialmente a la derecha

  void Sec_rp(unsigned long dato, unsigned short x){

  unsigned long  dat;

  unsigned short j;

   dat=dato;

   for(j=0;j<22;j++){

   saca(dat);

   dat>>=x;

   delay_ms(100);

   }

  }

  

//*******************************************************

// Mueve los datos recividos secuencialmente a la derecha invertidos

  void Sec_rp_(unsigned long dato){

  unsigned long  dat;

  unsigned short j;

   dat=dato;

   for(j=0;j<22;j++){

   DSaca(dat);

   dat>>=1;

   delay_ms(150);

   }

  }

//*******************************************************

// Mueve los datos recividos secuencialmente a la izquierda invertidos

  void Sec_rp_2(unsigned long dato){

  unsigned long  dat;

  unsigned short j;

   dat=dato;

   for(j=0;j<22;j++){

   DSaca(dat);

   dat<<=1;

   delay_ms(150);

   }

  }

//*******************************************************

// Mueve los datos recividos secuencialmente a la derecha

  void Sec_r(unsigned long dato){

  unsigned long  dat;

  unsigned short j;

   dat=dato;

   for(j=0;j<22;j++){

   saca(dat);

   dat>>=1;

   }

  }

  

// Rutina igual que hace las salidas intermitentes

  void Sec_ri(unsigned long dato){

  unsigned long  dat;

  unsigned short j;

   dat=dato;

   for(j=0;j<22;j++){

   saca(dat);

   saca(0);

   dat>>=1;

   }

  }


// Complemento de la primera para repetirla 4 veses

     void secuenciador_r(unsigned long dato){

     unsigned short j;

     for(j=0;j<bts;j++){Sec_r(dato);}

     }

//_________________________________________________________

//*******************************************************

// Mueve los datos recividos secuencialmente a la izquierda

  void Sec_l(unsigned long dato){

  unsigned long  dat;

  unsigned short j;

   dat=dato;

   for(j=0;j<22;j++){

   saca(dat);

   dat<<=1;

   }

  }

// Rutina igual que hace las salidas intermitentes

  void Sec_li(unsigned long dato){

  unsigned long  dat;

  unsigned short j;

   dat=dato;

   for(j=0;j<22;j++){

   saca(dat);

   saca(0);

   dat<<=1;


   }

  }


// Complemento de la primera para repetirla 4 veses

     void secuenciador_l(unsigned long dato){

     unsigned short j;

     for(j=0;j<bts;j++){Sec_l(dato);}

     }

//_________________________________________________________

//*******************************************************

// COnvina dos secuencias para asi obtener la secuencia del auto fantastico

  void Sec_rl(unsigned long dato1,unsigned long dato2){

  unsigned short j;

  for(j=0;j<bts;j++){

  Sec_r(dato1);

  Sec_l(dato2);

   }

  }

  void Sec_rli(unsigned long dato1,unsigned long dato2){

  unsigned short j;

  Sec_ri(dato1);

  Sec_li(dato2);

  }

//_________________________________________________________

//*******************************************************

// Esta secuencia va encendiendo las luces una tras la otra a la izquierda

  void ll_r(){

  unsigned long dato;

  unsigned short j;

  dato=0b0000000000000000000001;

  for(j=0;j<22;j++){

  saca(dato);

  dato=dato | (dato<<1);

  }

  }

//*****************************************

  void ll_r2(unsigned long ldx,unsigned short lrx, unsigned short t, unsigned short llo){

  unsigned long dato;

  unsigned short j,i;

  dato=ldx;

  for(j=0;j<llo;j++){

  saca2(dato,t);

  for(i=0;i<lrx;i++){dato=dato | (dato<<1);}

  }

  }

// Complemento de la anterior para repetirla 4 veses

     void llenado_r(){

     unsigned short j;

     for(j=0;j<bts;j++){ll_r();delay_ms(100);}

     }


// Mescla de llenado con secuenciador

  void degradado1(){

  unsigned short j;

  for(j=0;j<bts;j++){

  Sec_r(0b1111111111111111111111);

  ll_r();

   }

  }

//_________________________________________________________

//*******************************************************

// Esta secuencia va encendiendo las luces una tras la otra a la derecha

  void ll_l(){

  unsigned long dato;

  unsigned short j;

  dato=0b1000000000000000000000;

  for(j=0;j<22;j++){

  saca(dato);

  dato=dato | (dato>>1);

  }

  }


//*******************************************************

// Esta secuencia va encendiendo las luces una tras la otra a la derecha

  void ll_l2(unsigned long ldx,unsigned short lrx, unsigned short t, unsigned short llo){

  unsigned long dato;

  unsigned short j,i;

  dato=ldx;

  for(j=0;j<llo;j++){

  saca2(dato,t);

  for(i=0;i<lrx;i++){dato=dato | (dato>>1);}

  }

  }


// Complemento de la anterior para repetirla 4 veses

     void llenado_l(){

     unsigned short j;

     for(j=0;j<bts;j++){ll_l();delay_ms(100);}

     }

// Mescla de llenado con secuenciador

  void degradado2(){

  unsigned short j;

  for(j=0;j<bts;j++){

  Sec_l(0b1111111111111111111111);

  ll_l();

   }

  }


//_________________________________________________________

//*******************************************************

// mescla secuencias a la derecha y la izquierda para ver luces que se cruzan

  void combinado(unsigned long dato1,unsigned long dato2){

  unsigned long dx,dx1,dx2 ;

  unsigned short j,i;

  for(i=0;i<2;i++){

  dx1=dato1;

  dx2=dato2;

  for(j=0;j<26;j++){

  dx=dx1 | dx2;

  saca(dx);

  dx1>>=1;

  dx2<<=1;

  }

  }

  }

//_________________________________________________________

//*******************************************************

 void conv_1(unsigned long dato1){

  unsigned long dx,dx1,dx2 ;

  unsigned short j,i;


  dx1=dato1;

  for(j=0;j<22;j++){

  dx2=dato1;

  for(i=0;i<22;i++){

  dx=dx1 | dx2;

  saca(dx);

  dx2>>=1;

  }

  dx1>>=1;

  }

 }

 //_________________________________________________________

//*******************************************************

 void conv_1inv(unsigned long dato1){

  unsigned long dx,dx1,dx2 ;

  unsigned short j,i;


  dx1=dato1;

  for(j=0;j<22;j++){

  dx2=dato1;

  for(i=0;i<22;i++){

  dx=dx1 | dx2;

  saca(dx);

  dx2<<=1;

  }

  dx1<<=1;

  }

 }

//_________________________________________________________

//*******************************************************

 void conv_2(unsigned long dato1){

  unsigned long dx,dx1,dx2 ;

  unsigned short j,i;


  dx1=dato1;

  for(j=0;j<22;j++){

  dx2=dx1;

  for(i=0;i<22;i++){

  dx=dx1 | dx2;

  saca(dx);

  dx2>>=1;

  }

  dx1>>=1;

  }

 }

//_________________________________________________________

//*******************************************************

 void conv_2inv(unsigned long dato1){

  unsigned long dx,dx1,dx2 ;

  unsigned short j,i;


  dx1=dato1;

  for(j=0;j<22;j++){

  dx2=dx1;

  for(i=0;i<22;i++){

  dx=dx1 | dx2;

  saca(dx);

  dx2<<=1;

  }

  dx1<<=1;

  }

 }

//_________________________________________________________

//*******************************************************

 void conv_3(unsigned long dato1){

  unsigned long dx,dx1,dx2 ;

  unsigned short j,i,r;


  dx1=dato1;

  dx=dato1;

  r=22;

  for(j=0;j<22;j++){

  dx2=dx;

  for(i=0;i<r;i++){

  saca(dx1 | dx2);

  dx2>>=1;

  }

  dx1= dx1 | (dx1>>1);

  dx>>=1;

  r--;

  }

 }


//_________________________________________________________

//*******************************************************

 void conv_3Inv(unsigned long dato1){

  unsigned long dx,dx1,dx2 ;

  unsigned short j,i,r;


  dx1=dato1;

  dx=dato1;

  r=22;

  for(j=0;j<22;j++){

  dx2=dx;

  for(i=0;i<r;i++){

  saca(dx1 | dx2);

  dx2<<=1;

  }

  dx1= dx1 | (dx1<<1);

  dx<<=1;

  r--;

  }

 }

//_________________________________________________________

//*******************************************************

  void conv_4(unsigned long dato){

  unsigned long  dat,dat1=0;

  unsigned short j, jf, i;


   for(i=0;i<22;i++){

   dat=dato;

   for(j=1;j<22-i;j++){

   saca(dat | dat1);

   dat>>=1;

   }

   dat1=dat1 | dat;

   }

  }


//_________________________________________________________

//*******************************************************

  void conv_4_inv(unsigned long dato){

  unsigned long  dat,dat1=0;

  unsigned short j, jf, i;


   for(i=0;i<22;i++){

   dat=dato;

   for(j=1;j<22-i;j++){

   saca(dat | dat1);

   dat<<=1;

   }

   dat1=dat1 | dat;

   }

  }


//*******************************************************

  void conv_5(unsigned long dato){

  unsigned long  dat,dat1=0;

  unsigned short j, jf, i;


   for(i=0;i<22;i++){

   dat=dato;

   for(j=1;j<i;j++){

   saca(dat | dat1);

   dat>>=1;

   }


   }

  }


//*******************************************************

  void conv_5_inv(unsigned long dato){

  unsigned long  dat,dat1=0;

  unsigned short j, jf, i;


   for(i=0;i<22;i++){

   dat=dato;

   for(j=1;j<i;j++){

   saca(dat | dat1);

   dat<<=1;

   }


   }

  }


//_________________________________________________________

//*******************************************************

  void DelVar(unsigned short t){

   unsigned short j;

   for(j=0;j<t;j++){

    delay_us(100);

   }


  }

//*******************************************************

  void brillo(){

  unsigned long dato;

  unsigned short j;

  for(j=0;j<255;j++){

  DSaca(0);

  DelVar(j);

  DSaca(~0);

  Delvar(256-j);

  }

  for(j=0;j<255;j++){

  DSaca(~0);

  DelVar(j);

  DSaca(0);

  Delvar(256-j);

  }


  }

//_________________________________________________________

//*******************************************************

//_________________________________________________________

//*******************************************************

//_________________________________________________________

//*******************************************************

  void ll_f1(){

  unsigned long dato1, dato2;

  unsigned short j;

  dato1=0b0000000000000000000001;

  dato2=0b1000000000000000000000;

  for(j=0;j<11;j++){

  saca(dato1 | dato2);

  dato1=dato1 | (dato1<<1);

  dato2=dato2 | (dato2>>1);

  }

  }

//*******************************************************

  void ll_f2(){

  unsigned long dato1, dato2;

  unsigned short j;

  dato1=0b0000000000000000000001;

  dato2=0b1000000000000000000000;

  for(j=0;j<5;j++){

  dato1=dato1 | (dato1<<1);

  dato1=dato1 | (dato1<<1);

  dato2=dato2 | (dato2>>1);

  dato2=dato2 | (dato2>>1);

  saca2(dato1 | dato2,250);

  }

  }

//*******************************************************

  void ll_f3(){

  unsigned long dato1, dato2;

  unsigned short j;

  dato1=0b0000000000000000000001;

  dato2=0b1000000000000000000000;

  for(j=0;j<4;j++){

  dato1=dato1 | (dato1<<1);

  dato1=dato1 | (dato1<<1);

  dato1=dato1 | (dato1<<1);

  dato2=dato2 | (dato2>>1);

  dato2=dato2 | (dato2>>1);

  dato2=dato2 | (dato2>>1);

  saca2(dato1 | dato2,250);

  }

  }

//*******************************************************

  void ll_f1_inv(){

  unsigned long dato1, dato2;

  unsigned short j;

  dato1=0b0000000000011111111111;

  dato2=0b1111111111100000000000;

  for(j=0;j<11;j++){

  saca(dato1 | dato2);

  dato1=dato1>>1;

  dato2=dato2<<1;

 }

 }

//*******************************************************

  void ll_f2_inv(){

  unsigned long dato1, dato2;

  unsigned short j;

  dato1=0b0000000000011111111111;

  dato2=0b1111111111100000000000;

  for(j=0;j<7;j++){

  saca2(dato1 | dato2,250);

  dato1=dato1>>1;

  dato1=dato1>>1;

  dato2=dato2<<1;

  dato2=dato2<<1;

 }

 }

//*******************************************************

  void ll_f3_inv(){

  unsigned long dato1, dato2;

  unsigned short j;

  dato1=0b0000000000011111111111;

  dato2=0b1111111111100000000000;

  for(j=0;j<5;j++){

  saca2(dato1 | dato2,250);

  dato1=dato1>>1;

  dato1=dato1>>1;

  dato1=dato1>>1;

  dato2=dato2<<1;

  dato2=dato2<<1;

  dato2=dato2<<1;

 }

 }

//*******************************************************

  void ll_f4(unsigned long dat1, unsigned long dat2, unsigned short t, unsigned short x){

  unsigned long dato1, dato2;

  unsigned short j, i;

  dato1=dat1;

  dato2=dat2;

  for(j=0;j<11;j++){

  saca2((dato1 | dato2),t);

  for(i=0;i<x;i++){

  dato1=dato1 | (dato1>>1);

  dato2=dato2 | (dato2<<1);

  }

 }

 }

//*******************************************************

void desord(){

Sout(0b0000010000000000000000); delay_ms(100);

Sout(0b0000010000001000000000); delay_ms(100);

Sout(0b0000010000001000100000); delay_ms(100);

Sout(0b0000010000001000100100); delay_ms(100);

Sout(0b0000010000001000100100); delay_ms(100);

Sout(0b0010010000001000100100); delay_ms(100);

Sout(0b0010010000101000100100); delay_ms(100);

Sout(0b0010010100101000100100); delay_ms(100);

Sout(0b0010010000101000100100); delay_ms(100);

Sout(0b0010110000101000100100); delay_ms(100);

Sout(0b0010010000101100100100); delay_ms(100);

Sout(0b0010010010101100100100); delay_ms(100);

Sout(0b0010010110101100100100); delay_ms(100);

Sout(0b1010010110101100100100); delay_ms(100);

Sout(0b1010010110111100100100); delay_ms(100);

Sout(0b1010010110111101100100); delay_ms(100);

Sout(0b1011010110111101100100); delay_ms(100);

Sout(0b1011010110111101101100); delay_ms(100);

Sout(0b1011010110111101101101); delay_ms(100);

Sout(0b1011010111111101101101); delay_ms(100);

Sout(0b1111010111111101101101); delay_ms(100);

Sout(0b1111010111111101101111); delay_ms(100);

Sout(0b1111011111111101101111); delay_ms(100);

Sout(0b1111011111111101111111); delay_ms(100);

Sout(0b1111111111111101111111); delay_ms(100);

Sout(0b1111111111111111111111); delay_ms(100);

Sout(0b1111111111011111111111); delay_ms(100);

Sout(0b1111111111011111101111); delay_ms(100);

Sout(0b1111111101011111101111); delay_ms(100);

Sout(0b1110111101011111101111); delay_ms(100);

Sout(0b1110111101011111101011); delay_ms(100);

Sout(0b1110101101011111101011); delay_ms(100);

Sout(0b1110101101011100110101); delay_ms(100);

Sout(0b1110101100011100110101); delay_ms(100);

Sout(0b1110101100010100110101); delay_ms(100);

Sout(0b1010101100010100110101); delay_ms(100);

Sout(0b1010101100010100010101); delay_ms(100);

Sout(0b1010101100010100000101); delay_ms(100);

Sout(0b1010101100010100000100); delay_ms(100);

Sout(0b1010101100010100000100); delay_ms(100);

Sout(0b1010101000010100000100); delay_ms(100);

Sout(0b1010101000010000000100); delay_ms(100);

Sout(0b1000101000010000000100); delay_ms(100);

Sout(0b1000101000000000000100); delay_ms(100);

Sout(0b0000101000000000000100); delay_ms(100);

Sout(0b0000100000000000000100); delay_ms(100);

Sout(0b0000000000000000000100); delay_ms(100);

Sout(0b0000000000000000000000); delay_ms(100);

}


//*******************************************************

void main(){

unsigned long sex, sey, dato1, dato2;

unsigned short j,i;

   adcon1=0x06;

   portb=0; porta=0; portc=0;

   trisa=0; trisb=0; trisc=0;

   

   i=eeprom_read(0x00); if(i==0){while(1);} i--; eeprom_write(0x00,i);



while(1){

for(j=0;j<10;j++){Sout(0b1111111111111111111111);delay_ms(500);Sout(0);delay_ms(500);}

for(j=0;j<45;j++){Sout(0b0101010101010101010101);delay_ms(100);Sout(0b1010101010101010101010);delay_ms(100);}

for(j=0;j<2;j++){brillo();}

for(j=0;j<10;j++){ll_f1();}

for(j=0;j<2;j++){Sec_rl(0b1111111111000000000000,0b0000000000001111111111);}

for(j=0;j<6;j++){desord();}

for(j=0;j<10;j++){Sec_rp(0b1111111111111111111111,2);}

for(j=0;j<5;j++){combinado(0b1111100000000000000000, 0b0000000000000000011111);}

llenado_l();

llenado_r();

for(j=0;j<10;j++){Sec_rp_ (0b1100000000000000000000);}

for(j=0;j<10;j++){Sec_rp_2(0b0000000000000000000011);}

}

}