'||===============================================================================||
'||* Nombre Rutina: FAILSAFE_HUGO.BAS *||
'||* Entradas : GPIO.5 switch indicador de lectura de posicion de falla *||
'||* GPIO.4 potenciometro 10kohm indicador de posicion *||
'||* GPIO.3 RXin *||
'||* *||
'||* Salidas : GPIO.0 POT INDICADOR DE LECTURA POSICION DE FALLA. *||
'||* GPIO.1 LED INDICADOR DE FALLA(GLITCH). *||
'||* GPIO.2 RXout *||
'||* PIC12F675 *||
'||* . ________ *||
'||* 5v =|Vdd Vss|= GND *||
'||* switch =|gp5 gp0|= led indicador de lectura. *||
'||* POT 10Kohm. =|gp4 gp1|= led indicador de falla *||
'||* RXin =|gp3 gp2|= RXout *||
'||* . -------- *||
'||* *||
'||* Objetivo : procesar y determinar cuales señales estan fuera de los *||
'||* parametros y tomar acciones correctivas para evitar un *||
'||* fallo catastrofico. *||
'||* *||
'||* Autor : Hugo Sagardía Aguilera. *||
'||* Proyecto : FAILSAFE *||
'||* *||
'||* Micro : 12F675 *||
'||* Oscilador : IntOSC GP4 *||
'||* Velocidad : 4Mhz *||
'||* Flags : WDT OFF *||
'||* PWRT OFF *||
'||* MCLR OFF *||
'||* BODEN OFF *||
'||* CP OFF *||
'||* CPD OFF *||
'||* *||
'||* ----------- ------- ------------------------------------------------------- *||
'||* Fecha Versión Descripción Cambio *||
'||* ----------- ------- ------------------------------------------------------- *||
'||* 26/Ago/2009 1.0.0 (Version Original) *||
'||* 27/Ago/2009 1.0.1 (Manejo de interrupcion por desbordamiento *||
'||* de timer a los 20.2ms) *||
'||* 28/Ago/2009 1.0.2 1.-Se Eliminaron los pasos 1 y 2 por producir *||
'||* comportamientos erraticos al tener el stick en el *||
'||* centro y el trim no en centro, este comportamiento *||
'||* erratico es debido a que cada vez que inicia el micro, *||
'||* este calcula la posicion central del stick y sus *||
'||* maximos y minimos posibles) *||
'||* 2.- Se agrego un potenciometro para indicar la posicion *||
'||* de falla que poseera en servo *||
'||* 02/Sep/2009 1.0.3 (Lectura y Uso de la calibracion de fábrica.) *||
'||* 25/Sep/2009 1.0.4 (Ajuste del voltaje de 2.3V a 5V.) *||
'||* 28/Sep/2009 1.0.5 (Ajuste del voltaje de 2.2V a 5V. y correciones menores)*||
'||* 06/Oct/2009 1.0.6 (Se corrigio lectura del potenciometro y lectura del *||
'||* switch.) *||
'||* 07/Oct/2009 1.0.7 (se elimino la vibracion del servo al producirse la *||
'||* interrupcion que alargaba la frecuencia de 50hz.) *||
'||===============================================================================||
'CONFIGURO PUERTOS Y ADC
TRISIO = 1
Define ADC_CLOCK = 3
Define ADC_SAMPLEUS = 50
'COMPARATOR OFF
CMCON = 0x07
'VREF OFF
VRCON = 0x00
'GPIO.4 A/D
ANSEL = %00001000
Config GPIO.5 = Input
Config GPIO.4 = Input
Config GPIO.3 = Input
Config GPIO.2 = Output
Config GPIO.1 = Output
Config GPIO.0 = Output
'ACTIVA EL CONVERSOR ANALOGO DIGITAL
ADCON0 = 0
'PINES USADOS DEL MICRO
Symbol pin_debe_leer_valor = GPIO.5
Symbol pin_posicion_falla = GPIO.4
Symbol pin_entrada = GPIO.3
Symbol pin_salida = GPIO.2
Symbol pin_led_falla = GPIO.1
Symbol pin_led_lectura = GPIO.0
'CONSTANTES USADAS EN EL PROGRAMA
Const k_cero = 0
Const k_uno = 1
Const k_tres = 3
Const k_cinco = 5
Const k_nueve = 9
Const k_diez = 10
Const k_cien = 100
Const k_periodo_ms = 20000
Const k_voltaje_cero = 429
Const k_divisor = 4
'INTERVALOS MAXIMOS Y MINIMOS
Const k_pulso_min = 86 '96
Const k_pulso_max = 212 '202
Const k_pulso_mid = 149 '202
Const k_nro_max_pulsos_erroneos = 25
'PARA DETERMINAR EL PULSO PARA FAIL SAFE
Dim pulso As Byte
Dim pulso_off As Word
Dim pulso_de_falla As Byte
'PARA CONTAR EL NUMERO DE GLITCHS
Dim contador_glitch As Byte
'CONTIENE EL VALOR DEL ADC
Dim valor_pot As Word
'VARIABLE PARA CICLO USO GENERAL
Dim i As Byte
'ALMACENA EL RESULTADO DE LA CALIBRACION
Dim resultado_calibracion As Bit
'PARA 20MS DE PAUSA
'NOTA: PARA 20.1 DEBE USAR 45435
Dim v20ms_normal As Word
v20ms_normal = 44535 '-->21000 '20000-->45535 '20050-->45485 '20700-->44835
'---------------------------------
'PARA DEPURACION SOLAMENTE
'Define SIMULATION_WAITMS_VALUE = 1
'Define SEROUT_DELAYUS = 0
'---------------------------------
inicio:
resultado_calibracion = carga_calibracion()
'APAGA LOS LED
pin_led_falla = k_cero
pin_led_lectura = k_cero
If resultado_calibracion = True Then
'-----------------------------------------------------------------------
'----------------------------- P A S O 1 -----------------------------
'-----------------------------------------------------------------------
'--AQUI AL PRENDER EL RECEPTOR TIENE PRESIONADO EL SWITCH, TOMA EL --
'--VOLTAJE QUE ESTA DEJANDO PASAR EL POTENCIOMETRO DE 10Kohm Y ESTE LO--
'--INTERPRETA COMO PULSO Y LO TRADUCE EN EL SERVO COMO POSICION, --
'--SINO ESTA PRESIONADO EL SWITCH VE LA POSICION QUE TIENE EL --
'--POTENCIOMETRO Y CALCULA EL PULSO SOLAMENTE --
'-----------------------------------------------------------------------
If pin_debe_leer_valor = k_uno Then
pin_led_lectura = k_uno
While pin_debe_leer_valor = k_uno
Adcin k_tres, valor_pot
'pulso_de_falla = (valor_pot / k_diez) + k_cien
pulso_de_falla = ((valor_pot - k_voltaje_cero) / k_divisor) + k_pulso_min
If pulso_de_falla > k_pulso_max Then
pulso_de_falla = k_pulso_max
Endif
If pulso_de_falla < k_pulso_min Then
pulso_de_falla = k_pulso_min
Endif
pulso_off = k_periodo_ms - (pulso_de_falla * k_diez)
ServoOut pin_salida, pulso_de_falla
WaitUs pulso_off
Wend
'pin_led_lectura = k_cero
Else
'SI NO ESTA PRESIONADO EL BOTON SOLO LEO EL POTENCIOMETRO Y CALCULO LA POSICION DE FALLA
Adcin k_tres, valor_pot
'pulso_de_falla = (valor_pot / k_diez) + k_cien
pulso_de_falla = ((valor_pot - k_voltaje_cero) / k_divisor) + k_pulso_min
Endif
'-----------------------------------------------------------------------
'----------------------------- P A S O 2 -----------------------------
'-----------------------------------------------------------------------
'--MARCA CON EL PARPADEO DE LUCES EL FIN DE LA CONFIGURACION DE FALLO --
'--Y CENTRA EL SERVO ANTES DE PROCESAR LAS SEÑALES DE ENTRADA --
'-----------------------------------------------------------------------
For i = k_uno To k_cinco
pin_led_lectura = k_uno
WaitMs k_cien
pin_led_lectura = k_cero
WaitMs k_cien
Next i
'CENTRA EL SERVO
pulso_off = k_periodo_ms - (k_pulso_mid * k_diez)
For i = k_uno To k_cinco
ServoOut pin_salida, k_pulso_mid
WaitUs pulso_off
Next i
'-----------------------------------------------------------------------
'----------------------------- P A S O 3 -----------------------------
'-----------------------------------------------------------------------
'--CONFIGURA EL TIMER1 PARA DETECTAR LA FALTA DE PULSOS --
'--PASADO LOS 20ms --
'--hex = dec --
'--0xaf23 = 44835 --
'--DONDE 44835 ES EL RESULTADO DE 65535 - 20700, DONDE 65535 --
'--EL MAXIMO VALOR PARA EL TIMER1 DE 16 BITS, PARA QUE EJECUTE --
'--LA INTERRUPCION --
'-----------------------------------------------------------------------
T1CON.TMR1CS = k_cero
T1CON.T1CKPS0 = k_cero
T1CON.T1CKPS1 = k_cero
'CARGA EL TIMER1 CON UN VALOR TAL QUE DESBORDE A LOS 20ms
TMR1H = v20ms_normal.HB
TMR1L = v20ms_normal.LB
T1CON.TMR1ON = k_uno
PIE1.TMR1IE = k_uno
INTCON.PEIE = k_uno
'-----------------------------------------------------------------------
'----------------------------- P A S O 4 -----------------------------
'-----------------------------------------------------------------------
'--PROCESA LOS PULSOS Y DETERMINA CUAL ES ERRONEO --
'-----------------------------------------------------------------------
While pulso = pulso
pulso = k_cero
Enable
ServoIn pin_entrada, pulso
Disable
'SI EL PULSO ES VALIDO LO COPIA EN EL PIN DE SALIDA
If pulso > k_pulso_min And pulso < k_pulso_max Then
pin_led_falla = k_cero
contador_glitch = k_cero
ServoOut pin_salida, pulso
Else
pin_led_falla = k_uno
contador_glitch = contador_glitch + k_uno
If contador_glitch > k_nro_max_pulsos_erroneos Then
'ESTO ES PARA EVITAR UN DESBORDAMIENTO Y PARA QUE NO SE REINICIE contador_glitch EN 0
contador_glitch = k_nro_max_pulsos_erroneos
ServoOut pin_salida, pulso_de_falla
Endif
pin_led_falla = k_cero
Endif
Wend
Else
'SI HUBO FALLA EN LA CALIBRACION CAE ACA Y HACE PARPADEAR EL LED ROJO
For i = k_uno To k_cinco
pin_led_falla = k_uno
WaitMs k_cien
pin_led_falla = k_cero
WaitMs k_cien
Next i
Endif
End
'-----------------------------------------------------------------------
'----------------------------- P A S O 5 -----------------------------
'-----------------------------------------------------------------------
'--LEE LA CALIBRACION DEL CHIP --
'-----------------------------------------------------------------------
Function carga_calibracion() As Bit
ASM: bsf status,rp0 ;bank 1
ASM: call 3ffh ;get the cal value
'SOLAMENTE PARA DEPURACION
'ASM: movlw 0x3c
ASM: movwf osccal ;calibrate
ASM: bcf status,rp0 ;bank 0
carga_calibracion = True
WaitMs k_diez
End Function
'-----------------------------------------------------------------------
'----------------------------- P A S O 6 -----------------------------
'-----------------------------------------------------------------------
'--INTERRUPCION POR TIMER1 QUE VERIFICA QUE HAYAN PASADO MAS DE 20MS --
'--SI DESPUES DE 20MS pulso ESTA EN CERO QUIERE DECIR QUE NO HA LEIDO --
'--NADA Y EJECUTA EL PASO SIGUIENTE --
'-----------------------------------------------------------------------
On Interrupt
Save System
'CARGA EL TIMER1 CON UN VALOR TAL QUE DESBORDE A LOS 20ms
TMR1H = v20ms_normal.HB
TMR1L = v20ms_normal.LB
'LIMPIA EL FLAG QUE SEÑALA QUE SE EJECUTO LA INTERRUPCION
PIR1.TMR1IF = k_cero
'SI NO HA HABIDO UN PULSO DURANTE 20.2ms LO CONSIDERA GLITCH E INCREMENTA EL CONTADOR DE ESTOS
If pulso = k_cero And pin_entrada = k_cero And pin_salida = k_cero Then
contador_glitch = contador_glitch + k_uno
'SI EL NUMERO DE PULSOS ERRONEOS O AUSENCIAS DE ESTOS ES
'MAYOR AL NRO PERMITODO ASUME LA POSICION DE FALLA A LA SALIDA
If contador_glitch > k_nro_max_pulsos_erroneos Then
pin_led_falla = k_uno
'ESTO ES PARA EVITAR UN DESBORDAMIENTO Y PARA QUE NO SE REINICIE contador_glitch EN 0
contador_glitch = k_nro_max_pulsos_erroneos
pulso_off = v20ms_normal + (pulso_de_falla * k_diez)
ServoOut pin_salida, pulso_de_falla
TMR1H = pulso_off.HB
TMR1L = pulso_off.LB
Endif
Endif
Resume