Pic PWM

También podría gustarte

Está en la página 1de 10

DESCRIPCION DEL PROGRAMA MOTOR_2.

ASM

Programa que regula un PWM de 0 a 90%, variando de 1 en 1%, se puede


cambiar facil para que regule hasta 99%

Tiene 4 salidas para manejar un puente H, las dos altas RB1-3 reciben los
pulsos y las bajas
RA1-3 se quedan fijas.

Pulsadores + y - (RB4-5) para elegir la velocidad, cambia cada 500ms y luego


cada 100ms.
Pulsador Direccion (RB5) cambia la direccion del motor, 1º parado, luego
derecha, luego parado, luego izq. y vuelta a empezar, cambia cada 1 seg.
Pulsador Emergencia, para todo y muestra un mensaje que parpadea, al
soltar se quita.
Pulsador ON/OFF, arranca y para el motor.

Frecuencia PWM: 1 Khz, mas frecuencia con 4Mhz no se puede o no se


hacerlo pudiendo regular hasta 5% por ejemplo.

Muestra en un LCD 20x1 (lo cogi de un telefono fijo y funciona igual que un
16x1) el estado del motor (PARADO o MARCHA), el cicloTrabajo (0-90%) y la
direccion ( <, - , ó > )
No se usaran los mensajesDir ( <, -, > ), se escribira su codigo
correpondiente directamente

NOTA: He cambiado el programa porque al pasarlo al OpenOficce se me a


movido todo, espero no haberla cagado...

Fallos que me da el programa:

Queria poder cambiar la direccion con el motor en marcha, pero falla, solo lo
hace a veces si le doy poco a poco
En 1 y 2% sale un PWM con ciclotrabajo a 55% ma o meno
ya los mirare pero la verdad que ahora no me apetece nada de nada de nada
de nada, jejej

Tenia pensado mejorar lo siguiente:


Usar la EEPROM del pic para dejar los datos guardados, como para practicar
con el Pic y eso...
Yo e usado un motorcillo de na, pero se puede hacer alquna rampa para
arrancar poco a poco
el motor, de eso no controlo asi que es por practicar, pero nada mas..

CODIGO DEL PROGRAMA

LIST P=16F84A
INCLUDE <P16F84A.INC>
CBLOCK 0x0c
GuardaW ; para guardar W en las interrupciones
GuardaSTATUS ; para guardar W en las interrupciones
FlagEstado ; si bit0=0 motor parado, si bit0=1 en marcha
FlagDir ; bits 0,1 y 2: "000" parado, "001" izq., "010" parado, "100"
; derecha y vuelta a "000"
RegVelocidad ; guarda el valor del Ciclo de trabajo 0-90%
FlagPulsVel ; Se usa para el funcionamiento del pulsador + y -
CargaTMR0
CargaTMR0aCero ; carga un valor distinto a TMR0
FlagPWM ; bit0 (=1 PWM alto) (=1 PWM bajo), bit2=1 si se necesita cargar
ENDC ; TMR0 2 veces antes de cambiar el PWM, bit4=1 Si ya se a usado
; "CargaTMR0aCero"
#DEFINE PulsON_OFF PORTB,4
#DEFINE PulsDir PORTB,5
#DEFINE PulsMenos PORTB,6
#DEFINE PulsMas PORTB,7
#DEFINE PulsEmerg PORTB,0 ; las directivas "define" no las e usado, pero como no
; estoy seguro las dejo jejej

org 0x00
goto Inicio

org 0x04
goto AtencionInterrupcion

Mensajes
addwf PCL,F
MensajeInicial
DT "PARADO 0% DIR: -",0X00
MensajeParado
DT "PARADO",0x00
MensajeMarcha
DT "MARCHA",0x00
MensajeEmergencia
DT "CIRC. EMERG ABIERTO",0x00

Inicio
clrf PORTA
clrf PORTB ; limpia los puertos del puente H
clrf RegVelocidad ; empieza con velocidad 0
clrf FlagDir ; empieza en estado "000" PARADO
clrf FlagEstado ; Estado,bit0=0 motor parado
clrf FlagPWM
call LCD_Ini
bsf STATUS,5
movlw b'11000000' ; preescaler de 2 al TMR0, y mas cosas
movwf OPTION_REG
movlw b'00000000'
movwf TRISA
movlw b'11110001'
movwf TRISB
bcf STATUS,5
bcf PORTB,1 ; limpia la salida a la parte alta del puente H
bcf PORTB,3
nop ; retardo de seguridad contra cortos en puente H
nop ; será tiempo de sobra
nop ; ademas el IR2110 ya hará esto, pero bueno
nop
bsf PORTA,1 ; activa mosfets bajos, motor frenado a masa
bsf PORTA,3
call LCD_Borra
movlw MensajeInicial
call LCD_Mensaje
movlw b'10011000' ; habilita GIE, INT (RB0), y RBI
movwf INTCON
Principal
goto Principal

AtencionInterrupcion
btfsc INTCON,5 ; TOIE=0?? esto es porque el TMRO sigue contando y salta
TOIF
btfss INTCON,2 ; TOIF=1?? aunque no este habilitada la interrupcion
goto CompruebaTOIE
goto Interr_TMRO ; si TOIE=1 y TOIF=1 atiende interrupcion, sino salta
CompruebaTOIE ; TOIE o TOIF eran 0, asi que sigue la subrutina
bcf INTCON,3
bcf INTCON,4
bsf INTCON,7 ; activa solo TOI (si es que estaba activa, sino ninguna)
btfsc INTCON,1
goto Interr_Emergencia ; si INTF=1 atiende la interr, sino salta y activa INT
bsf INTCON,4 ; (emerg), para que pueda saltar si x ej. se mantiene
btfss INTCON,0 ; pulsado +, -, o Dir
goto FinAtencionInterrupcion ;si tampoco era RBIF=1, termina la interrupcion
btfss PulsON_OFF
goto Interr_ON_OFF
btfss PulsMas ; si RBIF=1, comprueba los pulsadores ON/OFF, +, - y Dir
goto Interr_Mas ; si dan todos 0, borra RBIF y termina la interrupcion
btfss PulsMenos
goto Interr_Menos
btfss PulsDir
goto Interr_Dir
FinAtencionInterrupcion
bcf INTCON,0 ; borra RBIF antes de habilitar RBI para que no salte
bsf INTCON,3 ; habilita RBI e INT, que se quitaron al principio
retfie

Interr_Emergencia ; --------------------------------INTERR_EMERGENCIA-------------------------
bcf INTCON,7 ;desactiva GIE
bcf PORTB,1
bcf PORTB,3 ;para la parte alta del puente H
movwf GuardaW
swapf STATUS,W
movwf GuardaSTATUS
bcf STATUS,5 ; guarda W y STATUS, y se asegura de que esta en banco 0
call Retardo_100micros
bsf PORTA,1 ; activa mosfets bajos, motor frenado a masa
bsf PORTA,3
clrf FlagEstado ; FlagEstado indica "motor parado"
call Retardo_20ms
btfss PORTB,0 ; comprueba si es un rebote
goto FinInterr_Emergencia
clrf FlagDir ; posicion "000"
call LCD_Borra
movlw MensajeEmergencia
call LCD_Mensaje ; muestra en LCD: "CIRC. EMERG ABIERTO"
Parpadeo ; parpadea el MensajeEmergencia
movlw b'00001000'
call LCD_EnviaComando
call Retardo_500ms
movlw b'00001110'
call LCD_EnviaComando
call Retardo_500ms
btfsc PORTB,0 ; comprueba si RBO=0 (emergencia acabada), si sigue a 1
goto Parpadeo ; sigue parpadeando el mensajeEmergencia
call LCD_Borra
movlw MensajeInicial
call LCD_Mensaje ; restaura el mensaje inicial
call Retardo_50micros
movlw .8
call LCD_PosicionLinea1
movf RegVelocidad,W
call BIN_a_BCD
call LCD_Byte ; escribe la ultima velocidad guardada en RegVelocidad
FinInterr_Emergencia
movlw b'00011000'
movwf INTCON
swapf GuardaSTATUS,W
movwf STATUS
swapf GuardaW,F
swapf GuardaW,W ; restaura W y STATUS
retfie

Interr_Dir ; --------------------------------INTERR_DIR-------------------------
call Retardo_20ms
btfsc PORTB,5 ; comprueba si es un rebote
goto FinInterr_RBI
EtiquetaBucleDir
btfsc FlagDir,0
goto EstabaIzq
btfsc FlagDir,1
goto EstabaParo1
btfsc FlagDir,2
goto EstabaDer
EstabaParo2
movlw b'00000001'
movwf FlagDir ;siguiente posicion de Dir
movlw .18
call LCD_PosicionLinea1
movlw b'00111100' ; pone "<" en LCD
call LCD_Caracter
goto CompruebaRB5
EstabaIzq
movlw b'00000010'
movwf FlagDir ;siguiente posicion de Dir
movlw .18
call LCD_PosicionLinea1
movlw b'00101101' ; pone "-" en LCD
call LCD_Caracter
btfsc FlagEstado,0
goto Dir_EstabaON ; si se pulsa RB5 con motor en marcha va a PARAR_MOT
goto CompruebaRB5
EstabaParo1
movlw b'00000100'
movwf FlagDir ;siguiente posicion de Dir
movlw .18
call LCD_PosicionLinea1
movlw b'00111110' ; pone ">" en LCD
call LCD_Caracter
goto CompruebaRB5
EstabaDer
movlw b'00000000'
movwf FlagDir ;siguiente posicion de Dir
movlw .18
call LCD_PosicionLinea1
movlw b'00101101' ; pone "-" en LCD
call LCD_Caracter
btfsc FlagEstado,0
goto Dir_EstabaON ; si se pulsa RB5 con mot. en marcha, va a PARAR_MOTOR
CompruebaRB5
call Retardo_1s
btfss PORTB,5 ;si se mantiene pulsado, sigue cambiando Dir cada 1 seg.
goto EtiquetaBucleDir
FinInterr_RBI
bcf INTCON,0
bsf INTCON,3 ;borra flag RBIF y habilita las RBI
retfie
Dir_EstabaON
call PARAR_MOTOR
EsperaRB5
btfss PORTB,5
goto EsperaRB5
goto FinInterr_RBI ;espera a soltar el pulsador Dir

Interr_ON_OFF ; --------------------------------INTERR_ON_OFF-------------------------
call Retardo_20ms
btfsc PORTB,4 ; comprueba si es un rebote
goto FinInterr_RBI
btfsc FlagEstado,0
goto EstabaON
btfsc FlagDir,0
goto EstabaOFF_Izq
btfsc FlagDir,2
goto EstabaOFF_Der
EsperaRB4
btfss PORTB,4
goto EsperaRB4
goto FinInterr_RBI
EstabaON
call PARAR_MOTOR
goto EsperaRB4
EstabaOFF_Izq
call ARRANCAR_IZQ
goto EsperaRB4
EstabaOFF_Der
call ARRANCAR_DER
goto EsperaRB4

Interr_Mas ; --------------------------------INTERR_MAS-------------------------
call Retardo_20ms
clrf FlagPulsVel
BucleMas
btfsc PORTB,7 ; comprueba si es un rebote, o si sigue el bucle
goto FinInterr_RBI
movlw .90
subwf RegVelocidad,W
btfsc STATUS,0
goto EsperaRB7
movlw .50
subwf RegVelocidad,W
btfsc STATUS,0
goto ModoPWM_Largo
incf RegVelocidad,F ;RegVelocidad es menor de 90, asi q incrementa 1
EtiquetaMas
movlw .8
call LCD_PosicionLinea1
movf RegVelocidad,W
call BIN_a_BCD
call LCD_Byte ; escribe RegVelocidad en LCD
btfsc FlagPulsVel,2
goto ModoRapidoMas
call Retardo_500ms
incf FlagPulsVel,F
goto BucleMas
ModoRapidoMas
call Retardo_100ms
goto BucleMas
EsperaRB7
btfss PORTB,7
goto EsperaRB7
goto FinInterr_RBI
ModoPWM_Largo
incf RegVelocidad,F
bsf FlagPWM,2
goto EtiquetaMas

Interr_Menos ; --------------------------------INTERR_MENOS-------------------------
call Retardo_20ms
clrf FlagPulsVel
BucleMenos
btfsc PORTB,6 ; comprueba si es un rebote, o si sigue el bucle
goto FinInterr_RBI
movf RegVelocidad,F
btfsc STATUS,2
goto Reg_Vel_es0
movlw .52
subwf RegVelocidad,W
btfss STATUS,0
goto ModoPWM_Corto
decf RegVelocidad,F ;RegVelocidad es mayor de 0, asi q decrementa 1
EtiquetaMenos
movlw .8
call LCD_PosicionLinea1
movf RegVelocidad,W
call BIN_a_BCD
call LCD_Byte ; escribe RegVelocidad en LCD
btfsc FlagPulsVel,2
goto ModoRapidoMenos
call Retardo_500ms
incf FlagPulsVel,F
goto BucleMenos
ModoRapidoMenos
call Retardo_100ms
goto BucleMenos
Reg_Vel_es0
call PARAR_MOTOR
EsperaRB6
btfss PORTB,6
goto EsperaRB6
goto FinInterr_RBI
ModoPWM_Corto
decf RegVelocidad,F
bcf FlagPWM,2
goto EtiquetaMenos

Interr_TMRO ; --------------------------------INTERR_TMR0-------------------------
btfss FlagPWM,0 ;estaba PWM alto o bajo?
goto PWM_estaBajo
btfsc FlagPWM,2 ;si estaba alto, es un pulso alto largo?
goto PWM_AltoLargo ;si es PWM largo, sigue manteniendolo alto o lo baja ya?
BajarPWM
bcf PORTB,3
bcf PORTB,1
movwf GuardaW
swapf STATUS,W
movwf GuardaSTATUS
bcf STATUS,5 ; guarda W y STATUS, y se asegura de que esta en banco 0
bcf FlagPWM,4
bcf FlagPWM,0 ;resetea bit4 (pulso largo), y indica bit0 que pwm esta bajo
movlw .40
subwf RegVelocidad,W
btfss STATUS,0
goto CargaPWM_BajoLargo ; PWM 1-39%
movlw .47
subwf RegVelocidad,W
btfss STATUS,0
goto PWM_BajoMedio ; PWM 40-46%
goto PWM_BajoCorto ; PWM 47-90%
CargaPWM_BajoLargo
bsf FlagPWM,2 ; ------- es PWM_BajoLargo 1-44%
movlw .12
addwf RegVelocidad,W ; suma 12
movwf CargaTMR0
addwf CargaTMR0,F
addwf CargaTMR0,F
addwf CargaTMR0,F ; multiplica por 5
addwf CargaTMR0,F
clrw ; carga un primer TMR0 con "0", luego se carga el calculado antes
goto Fin_CargarTMRO_2
PWM_BajoMedio
bsf FlagPWM,2
movlw .1
addwf RegVelocidad,W ; suma 1
movwf CargaTMR0
addwf CargaTMR0,F
addwf CargaTMR0,F
addwf CargaTMR0,F
addwf CargaTMR0,F ; multiplica por 5
movlw .56
goto Fin_CargarTMRO_2
PWM_BajoCorto
bcf FlagPWM,2 ; bit2=0 indica solo 1 TMR0
movlw .41
subwf RegVelocidad,W ; resta 41
movwf CargaTMR0
addwf CargaTMR0,F
addwf CargaTMR0,F
addwf CargaTMR0,F
addwf CargaTMR0,W ; multiplica por 5
addlw .3
movwf CargaTMR0 ;se suma 3
Fin_CargarTMRO
movf CargaTMR0,W
Fin_CargarTMRO_2
movwf TMR0
bcf INTCON,2
swapf GuardaSTATUS,W
movwf STATUS
swapf GuardaW,F
swapf GuardaW,W ; restaura W y STATUS
retfie
PWM_AltoLargo
btfsc FlagPWM,4
goto BajarPWM
bsf FlagPWM,4
goto Fin_CargarTMRO
PWM_estaBajo
btfsc FlagPWM,2 ;si estaba bajo, es un pulso bajo largo?
goto PWM_BajoLargo
SubirPWM
movwf GuardaW
swapf STATUS,W
movwf GuardaSTATUS
bcf STATUS,5 ; guarda W y STATUS, y se asegura de que esta en banco 0
bcf INTCON,2
movlw .53
subwf RegVelocidad,W
btfss STATUS,0
goto SubirPWM_corto
movlw .57
subwf RegVelocidad,W
btfss STATUS,0
goto SubirPWM_medio
bsf FlagPWM,2 ; es SubirPWM_largo 57-90%
movlw .55
subwf RegVelocidad,W ; resta 55
movwf CargaTMR0
addwf CargaTMR0,F
addwf CargaTMR0,F
addwf CargaTMR0,F
addwf CargaTMR0,W ; multiplica por 5
sublw .0
movwf CargaTMR0 ; el resultado a negativo
goto FinSubirPWM_primerTMR0
SubirPWM_corto ; PWM 1-53%
bcf FlagPWM,2
movf RegVelocidad,W
movwf CargaTMR0
addwf CargaTMR0,F
addwf CargaTMR0,F
addwf CargaTMR0,F
addwf CargaTMR0,F ; multiplica por 5
movlw .11
subwf CargaTMR0,W ; resta 11
sublw .0
movwf CargaTMR0 ; el resultado a negativo
goto FinSubirPWM
SubirPWM_medio ; PWM 54-56%
bsf FlagPWM,2
movf RegVelocidad,W
addwf RegVelocidad,W ; multiplica Reg_Vel x 2
addlw .15 ; le suma 15
sublw .0
movwf CargaTMR0 ; el resultado a negativo
goto FinSubirPWM
FinSubirPWM
swapf GuardaSTATUS,W
movwf STATUS
swapf GuardaW,F
swapf GuardaW,W ; restaura W y STATUS
swapf CargaTMR0,F
swapf CargaTMR0,W
FinSubirPWM_2
bsf FlagPWM,0 ; ahora indica PWM alto
movwf TMR0
btfss FlagDir,0
goto PWM_Derecha
bcf PORTA,3
bsf PORTB,1
retfie
FinSubirPWM_primerTMR0
clrf CargaTMR0aCero
swapf GuardaSTATUS,W
movwf STATUS
swapf GuardaW,F
swapf GuardaW,W ; restaura W y STATUS
swapf CargaTMR0aCero,F
swapf CargaTMR0aCero,W
goto FinSubirPWM_2
PWM_Derecha
bcf PORTA,1
bsf PORTB,3
retfie
PWM_BajoLargo
btfsc FlagPWM,4
goto SubirPWM
bsf FlagPWM,4
goto Fin_CargarTMRO

PARAR_MOTOR
bcf INTCON,7 ;desactiva GIE
bcf PORTB,1
bcf PORTB,3 ;para la parte alta del puente H
call Retardo_100micros ;este retardo es exagerado, con unos nop, o nada valdra..
bsf PORTA,1 ; activa mosfets bajos, motor frenado a masa
bsf PORTA,3
clrf FlagEstado ; FlagEstado indica "motor parado"
clrf FlagPWM
call LCD_Linea1
movlw MensajeParado
call LCD_Mensaje ; en LCD: motor PARADO
bcf INTCON,5 ;desactiva TOIE
bsf INTCON,7 ;activa GIE
return
ARRANCAR_IZQ
bcf INTCON,7 ;desactiva GIE
bcf PORTB,3
bcf PORTB,1
bsf FlagEstado,0 ; FlagEstado indica "motor MARCHA"
clrf FlagPWM ;activa solo un mosfet bajo, e indica que PWM esta bajo
call LCD_Linea1
movlw MensajeMarcha
call LCD_Mensaje ; en LCD: motor MARCHA
bcf PORTA,3
bsf PORTA,1
clrf TMR0
bcf INTCON,2
bsf INTCON,5 ;activa TOIE y carga TMR0 con 0
bsf INTCON,7 ;activa GIE
return
ARRANCAR_DER
bcf INTCON,7 ;desactiva GIE
bcf PORTB,1
bcf PORTB,3
bsf FlagEstado,0 ; FlagEstado indica "motor MARCHA"
clrf FlagPWM ;activa solo un mosfet bajo, e indica que PWM esta bajo
call LCD_Linea1
movlw MensajeMarcha
call LCD_Mensaje ; en LCD: motor MARCHA
bcf PORTA,1
bsf PORTA,3
clrf TMR0
bcf INTCON,2
bsf INTCON,5 ;activa TOIE y carga TMR0 con 0
bsf INTCON,7 ;activa GIE
return

INCLUDE <ALCD_MENS.INC>
INCLUDE <ALCD_4BIT.INC>
INCLUDE <ABIN_BCD.INC>
INCLUDE <ARETARDOS.INC>
END

ESQUEMA ELECTRICO

El siguiente es el esquema en el que he probado el programa,


no sera el mejor pero para practicar ya vale no?

También podría gustarte