INICIO_ISR
movwf W_Temp ; Copiamos W a un registro Temporal
swapf STATUS, W ; Invertimos los nibles del registro STATUS
movwf STATUS_Temp
ISR
btfsc INTCON,T0IF ; miramos si la interrupcion es por TIMER0
goto ACTIVAR_R ; es por TIMER0 vamos a activar TRIAC_R
btfsc PIR1,TMR1IF ; Consultamos si es por TMR1
goto ACTIVAR_S ; es por TIMER1 vamos a activar TRIAC_S
btfsc PIR1,TMR2IF ; consultamos si es por TIMER2
goto ACTIVAR_T ; es por TIMER2 vamos a activar TRIAC_T
goto FIN_ISR ; si no fue ninguna, va a salir de la interrupcion
INICIO_ISR
movwf W_Temp ; Copiamos W a un registro Temporal
swapf STATUS, W ; Invertimos los nibles del registro STATUS
movwf STATUS_Temp
ISR
btfsc PIR1,TMR1IF ; Consultamos si es por TMR1
goto ACTIVAR_S ; es por TIMER1 vamos a activar TRIAC_S
btfsc PIR1,TMR2IF ; consultamos si es por TIMER2
goto ACTIVAR_T ; es por TIMER2 vamos a activar TRIAC_T
btfsc INTCON,T0IF ; miramos si la interrupcion es por TIMER0
goto ACTIVAR_R ; es por TIMER0 vamos a activar TRIAC_R
goto FIN_ISR ; si no fue ninguna, va a salir de la interrupcion
Para hacer mas exacto la temporización del tmr0, puedes utilizar algunos NOP en la interrupción antes de re-ajustar al tmr0
En cuanto a mi sugerencia, sino me equivoco, puedes utilizarlo aún pero con banderas que la iras activando según su orden.
Otra idea, es que puedes configurar al tmr0 como contador y utilizar un reloj de precisión exterior. Sería mejor utilizar el bit RB0/int pero seguro lo tienes ocupado para detectar el cruce por cero.
Que FOSC estas usando y podrías subirla a 20Mhz de ser necesario?
Podrian ser valores del 0 al 255 en lugar del 0 al 100? Digo para aprovechar todo el rango de un byte y mejorar la resolución.
En tu comentario anterior mencionas muchas veces mS cuando deberian ser, me parece, uS. El tiempo para el valor que mencionas del 1% me parece incorrecto, o he entendido mal como funciona...
CitarQue FOSC estas usando y podrías subirla a 20Mhz de ser necesario?
De momento estoy trabajando con 4Mz, pense en subirlo a 8Mz para darle mejor definicion, pero entonces en TMR0 tenia que subir de 1/64 a 1/128, por lo que creo que casi estoy en el mismo caso. Se podria subir a 20Mz de ser necesario con clock externo, con los internos las opciones son 4 o 8Mz. De no ser por este problema 4Mz sobrarian.
CitarPodrian ser valores del 0 al 255 en lugar del 0 al 100? Digo para aprovechar todo el rango de un byte y mejorar la resolución.
Las potencias van en porcentajes 1% en 1% o 0.5% en 0.5% por eso lo divido en 100 partes 200 etc. no entiendo bien porque al dividirlo en 255 voy a tener mas precision, aqui me perdi. :lol:
Bueno, veo que seguís insistiendo en potencias de 1% en 1%, cuando en realidad lo que varias de a 1% es el tiempo de trabajo(duty time), no la potencia. Sí correspondería la mísma variación en potencia, si la curva de voltaje fuese horizontal(V constante) pero en tu caso son senoidales, por ende la potencia varía en cada momento distinto de tiempo y deja de ser proporcional. He aqui uno de los problemas a mi parecer. Estás particionando la potencia de manera desproporcional. Seguramente un arranque suave tendría mejor resultado respondiendo a una curva de potencia exponencial si tu problema es en los valores bajos de potencia aplicada.
El programa recibe el duty time a aplicar por USART, 9600 baudios. Te recomiendo que lo pruebes.
El algorítmo lo que hace básicamente es llevar 3 contadores. Cada contador está asociado a una fase distinta. Cuando se detecta un cambio de flanco en una de las 3 entradas que sensan los cruces por cero, el algoritmo setea la salida para activar la fase asociada y carga el valor de su contador.
En cada iteración, se calcula la diferencia de tiempo entre el valor actual del TIMER2 y el de la iteración anterior. De esta manera obtenemos la diferencia de tiempo(medida en ciclos de ejecución). Este valor se le resta a cada contador, hasta que el contador llega al mínimo, momento en el cual se pone a bajo la salida asociada.
bcf PHASE1OUT
bcf PHASE2OUT
bcf PHASE3OUTBueno Bruno ante todo gracias por el trabajo que te estas tomando.
Le he estado vueltas al programa y decir que es bastante complejo, lo de hacerlo con contadores independientes fue la primera opcion que baraje, pero si bien en variaciones de W de 10% e incluso de 5% iba bastante bien cuando me meti a la del 1% era mucho tiempo metido en interrupciones y por eso la desheche, no quiero decir que no sea buena solucion, pero me parecio mejor la de los tres TMRs.CitarEl algorítmo lo que hace básicamente es llevar 3 contadores. Cada contador está asociado a una fase distinta. Cuando se detecta un cambio de flanco en una de las 3 entradas que sensan los cruces por cero, el algoritmo setea la salida para activar la fase asociada y carga el valor de su contador.
Aqui no entiendo muy bien, cuando se detecta cruce por 0 se activa la cuenta correspondiente a esa fase y transcurrido ese tiempo se setea ese triac, o lo estoy entendiendo mal?
CitarEn cada iteración, se calcula la diferencia de tiempo entre el valor actual del TIMER2 y el de la iteración anterior. De esta manera obtenemos la diferencia de tiempo(medida en ciclos de ejecución). Este valor se le resta a cada contador, hasta que el contador llega al mínimo, momento en el cual se pone a bajo la salida asociada.
Y aqui es cuando se pondra a 1, decir que en los optos se puede activar por 0 y desactivar por 1, te refieres a esto?. Pero entonces al principio cuando haces.Código: [Seleccionar]bcf PHASE1OUT
bcf PHASE2OUT
bcf PHASE3OUT
habria que ponerlos a 1 no? para que los triacs estuvieran a 0.
Saludos.
Es justo al reves. Cuando se detecta el cruce por cero, se levanta la salida correspondiente del triac. Una vez que la cuenta pasa el minimo admitido, se pone a cero la salida. Obviamente es muy sencillo dar vuelta la logica si es lo que necesitas.
Fijate que eso está hecho trabajando en el banco 1. Es sólamente otra manera de configurar los TRIS de los pines independientemente en lugar de todo el puerto. Alli lo que hago entonces, es solo declarar esos pines como salidas.