'***************************************************************************************
'NOMBRE: 16F88_MandoJEVO_01
'MICRO: PIC16f88
'Version: 2.0
'Utilización de interrupciones
''**************************************************************************************
Define CONF_WORD = 0x2f50
Define CONF_WORD_2 = 0x3ffc
Define CLOCK_FREQUENCY = 8
'Define ADC_SAMPLEUS = 10
'Define ADC_CLOCK = 5
DIM duty
(15) AS Byte
'Duty Cicle DIM curva
(15) AS Byte
'Curva grabada DIM vg
AS Byte
'Valor gatillo DIM ca
AS Byte
'Curva actual DIM cn
AS Byte
'Curva nueva DIM mca
AS Byte
'Modificacion curva actual P5 DIM mcn
AS Byte
'Modificacion curva nueva P5 DIM asa
AS Byte
'Antispin Actual P4 DIM asn
AS Byte
'Antispin nuevo P4 DIM ai
AS Byte
'Contador inicio DIM af
AS Byte
'Contador fin '---------------Variables el timer-------------------
DIM t1_ms
AS Byte
'Base de tiempos del timer 1 DIM t1_ms_t
AS Byte
'Contiene el valor de t1_ms DIM t2_ms
AS Byte
'Base de tiempos del timer 2 DIM t2_ms_t
AS Byte
'Contiene el valor de t2_ms DIM t3_ms
AS Byte
'Base de tiempos del timer 3 DIM t3_ms_t
AS Byte
'Contiene el valor de t3_ms '--------------Definición de puertos
ANSEL = %00100011 'Los pin digitales y NA5, NA1 y NA0 como analogicos
TRISB = %11110111 'Configuración input/output
TRISA = %01100011 'Configuración input/output'MODIFICADOS PARA QUE QUEDEN POLARIZADOS, ACTIVO LED1 (RA7)
CMCON = 0x07 'Comparador a off
OSCCON = 0x7e 'Set intrc To 8mhz, se usara reloj interno a 8Mhz
ADCON0 = %00100001 'Fosc/16 a 8Mhz (ADCON1.ADCS2=1) =2uSeg (minimo 1.6uSeg), channel RA4
ADCON1 = %10000000 'Volt. ref.(AVdd/AVss), selec. de escala division clock/16 ADCON1.ADCS2=1, ADC a ON
ADCON1.ADFM = 0 'Activa lectura 8bit del ADC
'--------------Configuracion Interrupciones -----------------
T1CON.TMR1CS = 0 'asigna el reloj interno al timer 1, se incrementa cada ciclo de instruccion
T1CON.T1CKPS0 = 0 'Factor de preescaler del timer 1, 0
T1CON.T1CKPS1 = 0 'Factor de preescaler del timer 1, 0
TMR1H = 0xf8 'Carga el registro del contador para que desborde cada 1 msg. byte alto 248 x 256
TMR1L = 0x30 'Carga el registro del contador para que desborde cada 1 msg. byte bajo + 48
'-------------Carga los valores iniciales del timer ------------------------
t1_ms = 0
t2_ms = 0
t3_ms = 0
t1_ms_t = 3 'Valor para el timer del P4 Arranque
t2_ms_t = 5 'Valor para el timer del P5 Curva
t3_ms_t = 200 'Valor para el timer del selector de curva
'---------------------Habilita las interrupciones --------------------------------------
T1CON.TMR1ON = 1 'Habilita el timer 1, comienza a incrementar
'PIE1.TMR1IE = 1 'Activa la interrupcion del timer
INTCON.PEIE = 1 'Bit de habilitación de interrupciones de perifericos
Enable 'INTCON.GIE habilita todas las interrupciones globales
'****************************************************************************
'Ver curva actual
'Gosub write_memoria
GOSUB vercurva
GOSUB leermemoria
GOSUB modificarcurva
GOSUB modificararranque
PIE1.TMR1IE = 1 'Activa la interrupcion del timer
'Activo el PWM
PWMon 1, 9
PWMduty 1, 0
'Rutina principal
LOOP:
'For i = 1 To 240 'Bucle solo para pruebas de tiempos
'Leo el valor del gatillo
ADCON0.CHS0 = 1 'Selecciono canal NA1 para el modulo ADC
ADCON0.CHS1 = 0
ADCON0.CHS2 = 0
'ADCON1.ADFM = 1 'Activaria lectura 10bit del ADC
'ADCON1.ADFM = 0 'Activa lectura 8bit del ADC
ADCON0.GO = 1 'Activo una lectura
WHILE ADCON0.GO = 1 'Espera hasta terminar la conversion ADC
WEND
'vg.HB = ADRESH 'ADC a 10bit
'vg.LB = ADRESL 'ADC a 10bit
vg = ADRESH 'ADC a 8 bit
SELECT CASE vg
CASE < 16
PWMduty 1, 0 'Freno
CASE < 32
PWMduty 1, duty(0)
CASE < 48
PWMduty 1, duty(1)
CASE < 64
PWMduty 1, duty(2)
CASE < 80
PWMduty 1, duty(3)
CASE < 96
PWMduty 1, duty(4)
CASE < 112
PWMduty 1, duty(5)
CASE < 128
PWMduty 1, duty(6)
CASE < 144
PWMduty 1, duty(7)
CASE < 160
PWMduty 1, duty(8)
CASE < 176
PWMduty 1, duty(9)
CASE < 192
PWMduty 1, duty(10)
CASE < 208
PWMduty 1, duty(11)
CASE < 224
PWMduty 1, duty(12)
CASE < 240
PWMduty 1, duty(13)
CASE <= 255
PWMduty 1, duty(14)
EndSelect
IF t1_ms >= t1_ms_t THEN
'Leo el valor de p4 ADC 5
ADCON0.CHS0 = 1 'Selecciono canal AN5 para el modulo ADC
ADCON0.CHS1 = 0
ADCON0.CHS2 = 1
'ADCON1.ADFM = 0 'Activa lectura 8bit del ADC
ADCON0.GO = 1 'Activo una lectura
WHILE ADCON0.GO = 1 'Espera hasta terminar la conversion ADC
WEND
asn = ADRESH 'ADC a 8bit
IF asn <> asa THEN GOSUB modificararranque
t1_ms = 0
Endif
IF t2_ms >= t2_ms_t THEN
'Leo el valor de p5 ADC 0
ADCON0.CHS0 = 0 'Selecciono canal AN0 para el modulo ADC
ADCON0.CHS1 = 0
ADCON0.CHS2 = 0
'ADCON1.ADFM = 0 'Activa lectura 8bit del ADC
ADCON0.GO = 1 'Activo una lectura
WHILE ADCON0.GO = 1 'Espera hasta terminar la conversion ADC
WEND
mcn = ADRESH 'ADC a 8bit
IF mcn <> mca THEN GOSUB modificarcurva
t2_ms = 0
t1_ms = 0 'Esto lo hago para impedir que haga las dos lecturas en la misma interrupcion
'lo que convierte t1_ms en 5 tambien pero con un desfase de 2 ms
Endif
IF t3_ms >= t3_ms_t THEN
Toggle RA7 'visualiza activacion de la rutina por el led LD1
GOSUB vercurva 'Comprueba que no se haya cambiado la curva
IF cn <> ca THEN GOSUB leermemoria
t3_ms = 0
Endif
'next i 'Bucle para pruebas
GOTO LOOP
'********************************************************
'Deteccion de la curva a leer
vercurva:
'Ver curva nueva
cn = 0
'If PORTA.4 = 1 Then cn = cn + 1
'If PORTA.3 = 1 Then cn = cn + 2
'If PORTA.2 = 1 Then cn = cn + 4
IF PORTA.5 = 1 THEN cn = cn + 8 'SOLO UTILIZO LA OPCION A.5 = 1
RETURN
leermemoria:
'Leer valores Guardados segun la curva a leer
ai = LookUp(0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240), cn 'Posicion inicial de memoria donde leer
af = LookUp(14, 30, 46, 62, 78, 94, 110, 126, 142, 158, 174, 190, 206, 222, 238, 254), cn 'Posicion final de memoria donde leer
FOR a = ai TO af
b = a - ai
curva(b) = duty(b)
NEXT a
'Genera los valores para las modificaciones de curvas
va(0) = (curva(10) - curva(4)) / 5 'Calculo maxima modificacion
va(1) = va(0) * 2 '(va(0) * 10) / 5 es el valor de correccion del 100 % multiplicado por 10
va(2) = va(0) '(va(0) * 10) / (2 * 5) es el valor de correccion del 50 % multiplicado por 10
va(3) = (va(0) * 10) / 15 '(va(0) * 10) / (3 * 5) es el valor de correccion del 30 % multiplicado por 10
ca = cn
RETURN
write_memoria: 'ESCRIBO VALORES EN LA EEPROM INTERNA DEL MICRO
FOR a = 0 TO 255
NEXT a
RETURN
'*************************************************************
'Ajuste fino de la curva grabada
'Rutina para modificar el centro de la curva
modificarcurva:
SELECT CASE mcn
CASE < 22 'P -5
mc(0) = ((va(3) * 5) / 10)
mc(1) = ((va(1) * 5) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
RETURN
CASE < 44 'P -4
mc(0) = ((va(3) * 4) / 10)
mc(1) = ((va(1) * 4) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
RETURN
CASE < 66 'P -3
mc(0) = ((va(3) * 3) / 10)
mc(1) = ((va(1) * 3) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
RETURN
CASE < 88 'P -2
mc(0) = ((va(3) * 2) / 10)
mc(1) = ((va(1) * 2) / 10)
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
RETURN
CASE < 110 'P -1
mc(0) = va(3) / 10
mc(1) = va(1) / 10
duty(5) = curva(5) - mc(0)
duty(6) = curva(6) - mc(1)
duty(7) = curva(7) - mc(1)
duty(8) = curva(8) - mc(1)
duty(9) = curva(9) - mc(0)
mca = mcn
RETURN
CASE < 145 'P 0
duty(5) = curva(5)
duty(6) = curva(6)
duty(7) = curva(7)
duty(8) = curva(8)
duty(9) = curva(9)
mca = mcn
RETURN
CASE < 165 'P +1
mc(0) = va(3) / 10
mc(1) = va(2) / 10
mc(2) = va(1) / 10
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
RETURN
CASE < 185 'P +2
mc(0) = ((va(3) * 2) / 10)
mc(1) = ((va(2) * 2) / 10)
mc(2) = ((va(1) * 2) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
RETURN
CASE < 205 'P +3
mc(0) = ((va(3) * 3) / 10)
mc(1) = ((va(2) * 3) / 10)
mc(2) = ((va(1) * 3) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
RETURN
CASE < 230 'P +4
mc(0) = ((va(3) * 4) / 10)
mc(1) = ((va(2) * 4) / 10)
mc(2) = ((va(1) * 4) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
RETURN
CASE <= 255 'P +5
mc(0) = ((va(3) * 5) / 10)
mc(1) = ((va(2) * 5) / 10)
mc(2) = ((va(1) * 5) / 10)
duty(5) = curva(5) + mc(0)
duty(6) = curva(6) + mc(1)
duty(7) = curva(7) + mc(2)
duty(8) = curva(8) + mc(1)
duty(9) = curva(9) + mc(0)
mca = mcn
RETURN
EndSelect
RETURN
'*****************************************************************
'Ajuste del control de arrancada
modificararranque:
SELECT CASE asn
CASE < 25 'P 1
duty(0) = curva(0)
duty(1) = curva(1)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
RETURN
CASE < 50 'P 2
duty(0) = curva(0) + (((curva(1) - curva(0)) * 50) / 100)
duty(1) = curva(1)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
RETURN
CASE < 75 'P 3
duty(0) = curva(1)
duty(1) = curva(1) + (((curva(2) - curva(1)) * 40) / 100)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
RETURN
CASE < 100 'P 4
duty(0) = curva(1) + (((curva(2) - curva(1)) * 40) / 100)
duty(1) = curva(1) + (((curva(2) - curva(1)) * 80) / 100)
duty(2) = curva(2)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
RETURN
CASE < 125 'P 5
duty(0) = curva(1) + (((curva(2) - curva(1)) * 80) / 100)
duty(1) = curva(2)
duty(2) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
RETURN
CASE < 150 'P 6
duty(0) = curva(2)
duty(1) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(2) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(3) = curva(3)
duty(4) = curva(4)
asa = asn
RETURN
CASE < 175 'P 7
duty(0) = curva(2) + (((curva(3) - curva(2)) * 40) / 100)
duty(1) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(2) = curva(3)
duty(3) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(4) = curva(4)
asa = asn
RETURN
CASE < 200 'p 8
duty(0) = curva(2) + (((curva(3) - curva(2)) * 80) / 100)
duty(1) = curva(3)
duty(2) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(3) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(4) = curva(4)
asa = asn
RETURN
CASE < 225 'P 9
duty(0) = curva(3)
duty(1) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(2) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(3) = curva(4)
duty(4) = curva(4) + (((curva(5) - curva(4)) * 40) / 100)
asa = asn
RETURN
CASE <= 255 'P 10
duty(0) = curva(3) + (((curva(4) - curva(3)) * 40) / 100)
duty(1) = curva(3) + (((curva(4) - curva(3)) * 80) / 100)
duty(2) = curva(4)
duty(3) = curva(4) + (((curva(5) - curva(4)) * 40) / 100)
duty(4) = curva(4) + (((curva(5) - curva(4)) * 80) / 100)
asa = asn
RETURN
EndSelect
RETURN
'----------------------- Interrupciones ------------------------------------------
'Save System
IF PIR1.TMR1IF = 1 THEN
IF t1_ms < t1_ms_t THEN t1_ms = t1_ms + 1
IF t2_ms < t2_ms_t THEN t2_ms = t2_ms + 1
IF t3_ms < t3_ms_t THEN t3_ms = t3_ms + 1
Endif
TMR1H = 0xf8 'Carga el registro del contador para que desborde cada 1 msg. byte alto 248 x 256
TMR1L = 0x30 'Carga el registro del contador para que desborde cada 1 msg. byte bajo + 48
PIR1.TMR1IF = 0 'Borra el flag del salto del tmr1
RESUME