Autor Tema: Dimmer digital - Error en lectura de pulsadores - XC8  (Leído 2675 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Nano_T

  • PIC10
  • *
  • Mensajes: 36
Dimmer digital - Error en lectura de pulsadores - XC8
« en: 13 de Febrero de 2017, 01:27:38 »
Muy buenas gente! He estado muy alejado del foro por cuestiones de estudio, mil perdones!

El cuento va mas o menos así.. Estoy haciendo una placa de reemplazo para una campana extractor de humos que instalé en casa http://articulo.mercadolibre.com.ar/MLA-621970152-campana-de-cocina-tst-lacar-60-embalaje-extra-gratis-cc-_JM.. Cuestión que el control original se quemó a los primeros 5 minutos, así que como tocan vacaciones, 16f628a y a jugar!

El esquema en cuestión del reemplazo es el siguiente.


Consta de una entrada de CA de 15v, regulación a 5v, detector de cruce por cero con un PC817, una salida amplificada para unas tiras led. El control de potencia se realiza con un BT139 con la respectiva red snubber original del motor, y se maneja el disparo con un optotriac MOC3021, el micro es un 16F628A.

El micro corre con su oscilador interno puesto a 4Mhz y por un error de diseño, olvidé la resistencia a vcc, el MCLR está configurado como entrada y puesto a 5v.

El error que se produce es el siguiente.
Como se ve, se produce un cambio automático de estados. Es como si siempre recibiese un estado alto en las entradas. A excepción del botón de apagado que parece responder.
La etapa de control del ángulo de disparo se realiza perfecto, no hay disparos erróneos, etc, etc..
Error en la placa también creo que está descartado. Sin el microcontrolador puesto recibo 0v y 5v correctamente en cada pata de entrada correspondiente. Con el micro colocado la medición típica es de 2v (¿problema de impedancia de las entradas?, ¿error en los registros?, ¿está oscilando?, ni remota idea..)

El código que ahora tiene cargado es el siguiente. Compilado en XC8.
Código: [Seleccionar]
/*
 * Author: Leonardo Barreiro
 * Created on 20 de enero de 2017, 12:14
*/

#include <pic16f628a.h>
#include <xc.h>

//  #pragma config statements should precede project file includes.
    #pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
    #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
    #pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
    #pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
    #pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
    #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
    #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
    #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
    #define _XTAL_FREQ 4000000

// Pines
    #define Boton_apagado PORTAbits.RA1
    #define Boton_velocidades PORTBbits.RB7
    #define Boton_LUZ PORTBbits.RB6
    #define Vel_1_led PORTAbits.RA0
    #define Vel_2_led PORTAbits.RA7
    #define Vel_3_led PORTAbits.RA6
    #define TRIAC_out PORTBbits.RB1
    #define TIRA_LED_out PORTBbits.RB2
    #define ZERO_CROSS_in PORTBbits.RB0
// Source statements
    #define TMR0_Carga_MAX 255
    #define TMR0_Carga_MED 203   //0b11001011 // 203  = 3.392ms -> Triac 66.08%
    #define TMR0_Carga_LOW 152   //0b10011000 // 152  = 6.656ms -> Triac 33.44%
    #define TMR0_Carga_OFF 0   //0b00000000 //   0 = 16.384ms -> Triac 0%
    unsigned char dimmer_time;
    unsigned char Velocidad = 0;
    bit LUZ;
   
void interrupt ISR(void){
    if(INTF){
        TMR0 = dimmer_time; /*   TOIF = 1 -> Triac 100%
                                       *  Carga 203 = 3.392ms -> Triac 66.08%
                                       *   Carga 152 = 6.656ms -> Triac 33.44%
                                       *   Carga  0 = 16.384ms -> Triac
                                       */
        INTF = 0; // Clear interruption flag
    }
   
    if(T0IF){
        TRIAC_out = 1;
        __delay_us(1500); //Triac fire propagation delay
        TRIAC_out = 0;
        T0IF = 0;
    }
}

void main(void){
    OPTION_REG = 0b01000101; /*   Pull-ups are enabled by individual port latch values,
               * interrupt on rising edge of INT,
               * TMR0 clock source on internal instruction,
               * nothing to do,
               * Prescaler is assigned to the TMR0,
               * Prescaler rate 1:64
               */
    CCP1CON = 0b00000000;
    CMCON = 0b00000111;
    INTCON = 0b10110000; /* Global interrupt enable,
           * Peripheral interrupt disable,
           * TMR0 overflow interrupt enable,
           * RB0/INT external interrupt enable,
           * RB Port change interrupt disable,
           * All flags bit did not overlow.
           */
    PCONbits.OSCF = 1; //Oscilador en 4MHZ
    TRISA = 0b00111110;
    TRISB = 0b11111001; /* 1 = IN ; 0 = OUT
          * RA_IN RA1      -   RA_OUT  RA0 RA6 RA7
          * RB_IN RB0 RB6 RB7   -   RB_OUT  RB1 RB2
          */
    PORTA = 0;
    PORTB = 0;
       
while(1){
   if(Boton_velocidades == 1){
       __delay_ms(500);
       switch (Velocidad) {
      case 3:
          Velocidad = 0;
          dimmer_time = TMR0_Carga_OFF;
          Vel_3_led = 0;
          break;
      case 2:
          Velocidad = 3;
          dimmer_time = TMR0_Carga_MAX;
          Vel_2_led = 0;
          Vel_3_led = 1;
          break;
      case 1:
          Velocidad = 2;
          dimmer_time = TMR0_Carga_MED;
          Vel_1_led = 0;
          Vel_2_led = 1;
          break;
      case 0:
          Velocidad = 1;
          dimmer_time = TMR0_Carga_LOW;
          Vel_1_led = 1;
          break;   
      default:
          break;
       }
   }
   if(Boton_apagado == 1){
       Velocidad = 0;
       dimmer_time = TMR0_Carga_OFF;
       Vel_1_led = 0;
       Vel_2_led = 0;
       Vel_3_led = 0;
       __delay_ms(500);
   }
   if(Boton_LUZ == 1){
       TIRA_LED_out = LUZ;
       LUZ = !LUZ;
       __delay_ms(500);
   }
  }
}

He probado cambiar el Switch del algoritmo del pulling por cascadas de If y tampoco nada.. He revisado los registros TRIS y nada tampoco.. ¿Por dónde queda mirar?

Salutes y muchas gracias de antemano!

Algunos extras..
« Última modificación: 13 de Febrero de 2017, 11:54:50 por Nano_T »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Dimmer digital - Error en lectura de pulsadores - XC8
« Respuesta #1 en: 23 de Febrero de 2017, 16:08:01 »
Lo que veo es que te garantiza que la onda que obtengas del secundario del transformador este en fase con la de los 220V.

Los pines de entrada estan bien. ( El hardware )
El software estas activando los Pull-ups (segun tus comentarios), lo cual es absurdo ya que al presionar tu boton estarias llevandolo a VDD, es decir estarian como presionados.

Nunca pongas un delay en la interrupcion.

Te das cuenta que TMR0_CARGA_MAX es 255, es decir solo tiene que contar 1 para que salte la interrupcion?. lo cual es MUY poco tiempo y tus 1500us de delay serian un desastre combinado.

Por ultimo como consejo de programacion, si usas Velocidad = 0 para decir que esta apagado, no lo uses luego como LOW en la seleccion de velocidades, o es OFF o es LOW. Nunca ambos.

Desconectado Nano_T

  • PIC10
  • *
  • Mensajes: 36
Re:Dimmer digital - Error en lectura de pulsadores - XC8
« Respuesta #2 en: 23 de Febrero de 2017, 19:28:52 »
Killer! Un honor como siempre leerte y antes que nada te agradezco mucho tu tiempo!

Creo que tenes razón con las pull-up, no me di cuenta! Esta noche lo pruebo!
I'm apologize!  :oops:

Sé que es mala costumbre poner un delay en una interrupción, aunque no veo contraposición en este caso.
El timer precargado con 255 busca tener un disparo en el triac apenas exista una interrupción en RB0. A pesar del delay, la próxima interrupción no ocurre sino aproximadamente 10ms después y próximo desborde del timer ocurre 16.384ms después.
De la misma manera que utilicé un timer sin precarga para no tener disparos en el triac. No es muy elegante, pero fué lo más rápido que se me ocurrió  :roll:

En la programación expresé LOW como indicador de una baja velocidad del motor. Creo que logré expresarlo de esa manera en el switch. No entendí muy bien a que te referís.

Muchísimas gracias de nuevo! Postearé resultados!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Dimmer digital - Error en lectura de pulsadores - XC8
« Respuesta #3 en: 23 de Febrero de 2017, 22:52:19 »
Citar
Sé que es mala costumbre poner un delay en una interrupción, aunque no veo contraposición en este caso.

El problema es si llega una interrupcion externa mientras esta el delay, ya que al salir volveria a re entrar a la interrupcion por culpa de lo anterior, pero esta ves ya no sabes a ciencia cierta donde. Aunque 1.5ms no es mucho y si no pasas el delay ese + timer del medio ciclo entonces no hay problema.

Citar
En la programación expresé LOW como indicador de una baja velocidad del motor. Creo que logré expresarlo de esa manera en el switch. No entendí muy bien a que te referís.

Es que en el boton de OFF pones a velocidad en 0.. Mientras que luego en el boton de de cambiar de velocidad toma al 0 como velocidad baja. Solo es una apreciacion, si funciona correctamente no hay ningun problema. E incluso podrias resumir el programa a:

Código: C
  1. char ArrayVelocidad[] = {TMR0_Carga_OFF,TMR0_Carga_LOW,TMR0_Carga_MED,TMR0_Carga_MAX};
  2. char SalidaLeds[] = {0b00000000,0b00000001,0b10000000,0b01000000};
  3.  
  4. void main(void){
  5.  
  6.     while(1){
  7.                 __delay_ms(500);
  8.                 if(Boton_velocidades == 1){
  9.                         Velocidad++;
  10.                         if( (sizeof ArrayVelocidad - 1) == Velocidad) Velocidad = 1;
  11.                 } else if(Boton_apagado == 1){
  12.                         Velocidad = 0;
  13.                 } else if(Boton_LUZ == 1){
  14.                         TIRA_LED_out ^= 1;
  15.                 }
  16.  
  17.                 dimmer_time = ArrayVelocidad[Velocidad];
  18.                 PORTA =  (PORTA & 0b00111110) | SalidaLeds[Velocidad];
  19.     }
  20. }