Curso de programación de PIC en PICBasic Pro

hola amigos recurro a ustedes por una ayudita quiero desarrollar un seguidor de linea podria usar la sentencia select case y leer el puerto del micro para que me vaya haciendo los case o estoy en lo correcto o que deberia hacer
 
No espera y le hecho un vistazo

Amigo Arturoc recuerda:


MODO CAPTURE

CARACTERÍSTICAS

• EL REGISTRO CCPR1H:CCPR1L CAPTURA EL VALOR DE TMR1 (16 BITS) CUANDO OCURRE UN EVENTO EN EL PIN RC2/CCP1. CUANDO SE REALIZA LA CAPTURA CCP1IF=1 (REG PIR1). ESTE FLAG DEBE SER BORRADO POR SOFTWARE. EL PIN RC2/CCP1 DEBE SER CONFIGURADO COMO ENTRADA EN TRISC.
• EL TIMER1 DEBE ESTAR EN MODO TEMPORIZADOR O EN MODO CONTADOR SINCRÓNICO
• SI CCP1IE=1 SE GENERA INTERRUPCIÓN EN MODO CAPTURE
• CUANDO EL MODO CAPTURE ES CAMBIADO PUEDE GENERARSE UNA INTERRUPCIÓN FALSA, DEBE EVITARSE HACIENDO CCP1IE=0 Y CCP1IF=0

Comprueba con la configuraciones mencionadas y me comentas

por lo que en tu programa debes configurar el modo de captura dependiendo del REGISTRO CCP1CON:

• CCP1X:CCP1Y: BITS MENOS SIGNIFICATIVOS DE PWM

• CCP1M3:CCP1M0: SELECCIONA MODO DE CCP1
• 0000: CCP1 DESHABILITADO
• 0100: CAPTURE, CADA FLANCO DE BAJADA EN RC2/CCP1
• 0101: CAPTURE, CADA FLANCO DE SUBIDA EN RC2/CCP1
• 0110: CAPTURE, CADA 4º FLANCO DE SUBIDA EN RC2/CCP1
• 0111: CAPTURE, CADA 16º FLANCO DE SUBIDA EN RC2/CCP1

• 1000: COMPARE, SALIDA =1 (CCPIF =1)
• 1001: COMPARE, SALIDA =0 (CCPIF =1)
• 1010: COMPARE, SE GENERA INTERRUPCIÓN (CCPIF =1)
• 1011: COMPARE, DISPARO ESPECIAL, DIFERENTE A CCP2
• 11XX: PWM
 
Última edición:
gracias mi amigo autotronico he revisado el codigo de ese robot pero no entiendo muy bien lo que hace con el loop puedo entender que con el loop revisa siempres el pueto a pero lo que no entiendo segun miro es como ir activando los case deberia entender que con el case 0 todo el puerto A esta en 0 y asi desde el bit mas bajo o me equivoco
 
Aqui hay algo :

Para ayudarte te explicare todo el código y la utilización de los comandos empezando con la función SELECT CASE que es una estructura de control que proporciona PBP para utilizarse se debe empezar con select case y terminar la operación con end select.
Su propósito es el simplificar las estructuras anidadas if, Then, else que utilizamos cuando se da una condición, en los casos en que sea siempre la mima variable y se necesiten varias decisiones en función de los valores posibles, y su estructura es la siguiente:
SELECT CASE variable
CASE valor1: instruccion1

END SELECT
En el ejemplo que posteaste se utiliza de la siguiente manera me tome la liberta de utilizar con el pic 16f877A:
@ DEVICE xt_osc ; definimos Oscilador externo
define osc 4
TRISA=1 ; puerto A como entradas digitales
ADCON1=7
Pause 2000
Loop: ;Bucle principal
Select case PORTA ; condición determinada por el Puerto A del pic 16F877A
; Los casos utilizados se desarrollan bajo las posibles variables obtenidas del puerto A del pic 16F877A, defeneciendo cuatro por las entradas que son dos RA0 y RA1 respectivamente.
Case 0
Gosub izquierda
; En esta condición (PRIMERA) RA1 y RA 0 están a cero lógico con lo que se pretende ir a la rutina de izquierda con el comando GOSUB.
Case 1
Gosub adelante
; En esta condición (segunda) RA1 y RA0 están a cero lógico y a uno lógico respectivamente con lo que se pretende ir a la rutina de adelante con el comando GOSUB.

Case 2
Gosub atras
; En esta condición (tercera) RA1 y RA0 están a uno lógico y a uno lógico respectivamente con lo que se pretende ir a la rutina de adelante con el comando GOSUB.
Case 3
Gosub derecha
; En esta condición (Cuarta) RA1 y RA0 están a uno lógico con lo que se pretende ir a la rutina de derecha con el comando GOSUB.
End select ; fin Del condicional
Goto loop ; crea un bucle cerrado ir a Loop
; En estas rutinas se utiliza el puerto b del pic como complemento siendo cero (0) a cinco (5) RB0 a RB5 respectivamente si te fijas siempre cero (RB0) y tres (RB3) estén a uno lógico ya que habitan los driver para los motores que deben ser servos ya que si fueran dc normales se embalan y no hay control en el giro, la única posibilidad es la utilización de los comandos PWM y HPWM, cuando se ha ejecutado se retorna a la función que fue precedida con el comando RETURN. Los otro pines son los habilitadores de polaridad del motor para que giro en sentido horario y antihorario los cuales son (1, 2, 4,5) o (RB1, RB2, RB4, RB5).
adelante:
high 0:high 1: low 2
high 3:high 4: low 5
return
atras:
high 0:low 1: high 2
high 3:low 4: high 5
return
izquierda:
high 0:low 1: high 2
high 3:high 4: low 5
return
derecha:
high 0:high 1: low 2
high 3:low 4: high 5
return
end
Espero te sea de ayuda para tu proyecto amigo.


amigo atricio me equivoque en condicion tres caso dos es a uno logico en RA1 y cero logico en RA0.

Case 2
Gosub atras
; En esta condición (tercera) RA1 y RA0 están a uno lógico y a uno lógico respectivamente con lo que se pretende ir a la rutina de adelante con el comando GOSUB.

En esta condición (tercera) RA1 y RA0 están a uno lógico y a cero lógico respectivamente con lo que se pretende ir a la rutina de adelante con el comando GOSUB.
 
que bobo ya habia preguntado esto y estaba muy bien explicado no habia visto esta explicacion del amigo mecatrodatos...Mil disculpas amigos por no buscar bien la informacion y hacerles pasar el tiempo quero hacerlo con un micro 16F873A usando sensores CNY70 espero salga bien seguire molestando cualquier pregunta muchas gracias de nuevo
 
• 0101: CAPTURE, CADA FLANCO DE SUBIDA EN RC2/CCP1

cuando se produce un flanco de subida en RC2 se genera una interrupcion "habilito las interrupciones" y voy y la atiendo y le digo que incremente o decremente en 1 el contador segun sea el caso

ASI ESTA CONFIGURADO

ON INTERRUPT GOTO Interrupcion
INTCON.7 =1 'HABILITAR INTERRUPCIONES GLOBALES
PIR1.2=0
PIE1.2=1 YA PROBE CON PIE1.2=0
CCP1CON = %00000101
T1CON = %00000011 YA PROBE CON %00000001

Interrupcion:
disable
'incrementa o decrementa en 1
enable
resume

pero no me funciona
no se esta generando la interrupcion......

Autotronico
como es que funciona el modulo ccp1 en captura. cuando se produce un flanco de subida captura el valpr del timer1 y genera una interrupcion y aqui es donde yo debo de incrementar o decrementar un contador?

este es un video que me encontre de lo que quiero hacer
es con un dspic30f2010 y yo estoy utilizando un 16f877a
 
Última edición:
mira este enlace especifica como utilizar el CCP como modulo de captura:
http://iesmachado.org/web insti/dep...royectos/pic_f_877/TEMA_21_modulo_ccp_pwm.pdf
:D

Gracias autotronico
dice que en modo captura: cuando se produce un flanco de subida captura el valor que posee el TMR1.....creo que es mejor utilizar el TMR1 como contador.....ya estoy utilizando el TMR0 como contador y en proteus si me funciona....falta ver la velocidad a la que puede leer los pulsos del encoder...la desventaja es que es un contador de 8 bit el TMR0.......el primer codigo que publique utilice el TMR1 como contador pero perdia pulsos.....

has implementado PID en un micro para un motor?
 
TMR1H = 0; Timer1 alta de 8 bits
TMR1L = 0; Timer1 baja de 8 bits
T1CON.0 = 1; iniciar el temporizador de 16 bits
PAUSE 100; captura de 100 m de la entrada
; Frecuencia de reloj
T1CON.0 = 0; parada de 16 bits del temporizador
TMR1.BYTE0 = TMR1L; lectura baja de 8 bits
TMR1.BYTE1 = TMR1H; lectura de alta de 8 bits
TMR1 = TMR1 - 11; Corrección de captura
SI = TMR1 = 65.525 THEN NOSIGNAL; ver el libro de PBP
; explicación

Esta es la rutina que debes emplear para leer una señal en modo de captura poniendo a 1 el T1CON.0 y en 0 para comparar con valor de variable creada es este caso TMR1 VAR WORD en tu programa activas el Timer1 antes de la condicional (IF B1=1 THEN GOTO CAM_POS) y das un tiempo de captura muy corto ( PAUSE 1 ) en vez de activar y desactivar el TMR1 antes de la condicional con un Pause de 100 ( por el oscilador de 4 MHz que creo estas utilizando), por lo que el modulo de comparación no tiene el tiempo para ejecutarse y realizar la condicional del programa. Por otro lado si he realizado control PID para motores y sistemas de temperatura.
 
Última edición por un moderador:
Ya entendi el funcionamiento en modo captura y no me sirve por que cuando se da el tiempo para hacer la captura (los 100 mS que dices) lo que esta capturando son los valores del timer y no los pulsos de el encoder, ahora que paso con todo el tiempo (lineas de programa) que el micro esta trabajando, esta perdiendo pulsos del encoder, si los pulsos llegan en otro tiempo que no sea esos 100 mS ya los perdi.

estoy haciendo pruebas con el TMR0 como contador y en el proteus si me esta funcionando....deja lo pruebo con el servo y subo el codigo...
 
el código anterior sirve para el pic 18f4431 porque todos los registros aplican, por otro lado para el pic 16f877A se debe modificar :unsure:

Otra cosa deseo saber como es el encoder que utilizas

bien aquí hay un código para el pic 16f877A con al utilzacion del TMrR1 y TMR2
HTML:
@ Device XT_OSC         ' 
@ Device WDT_ON         ' 
@ Device PWRT_ON        ' 
@ Device BOD_ON         ' 
@ Device LVP_OFF        ' 
@ Device CPD_OFF        '

define __16F877A    1
define OSC 20

DEFINE INTHAND  DO_ISR

DEFINE DEBUG_REG    PortC
DEFINE DEBUG_BIT    6
DEFINE DEBUG_BAUD   9600
DEFINE DEBUG_MODE   0

' ------------- Direcciones de hardware---------------------------

GIE     VAR     INTCON.7    'habilitación de interrupción Global
PEIE    VAR     INTCON.6    ' Perif. Eq. Habilitación de interrupción
ADIE    VAR     PIE1.6      ' A-2-D convertidor de habilitación de interrupción

TMR1IE	VAR		PIE1.0		' PIE direccion 10h
TMR2IE  VAR     PIE1.1

TMR1ON  VAR     T1CON.0		' Registros en PIC.inc
TMR2ON  VAR     T2CON.2		


EnaPin  VAR PORTC.2     ' PWM pin
FwdPin  VAR PORTB.5
RevPin  VAR PORTB.4
QuadPin1 Var PORTC.0

LED     var PORTC.3

' ------------- Espacio para Asignar la interrupción de almacenamiento --------

wSave   VAR     BYTE    $20     SYSTEM  ; Guardar registro W en bank0
wSave1  VAR     BYTE    $A0     SYSTEM  ;  Guardar reg W en bank1
; wSave2  VAR     BYTE    $120    SYSTEM  ; 
; wSave3  VAR     BYTE    $1A0    SYSTEM  ;
sSave   VAR     BYTE    Bank0   SYSTEM  ; Guardar localizacion en registro STATUS 
pSave   VAR     BYTE    Bank0   SYSTEM  ; Guardar localizacion en reg PCLATH 

StatFlag        VAR BYTE Bank0
GyroTaskFlag	VAR	StatFlag.0
OddCycleFlag	VAR	StatFlag.1
QuadStateFlag   var Statflag.2

QuadCount   VAR Byte    Bank0   ; Contar  [-127..0..127] encoder 
QuadPins    Var Byte    Bank0   ; estado actual de los pines 
QuadPrev    VAR Byte    Bank0   ; estado del pin del encoder 
QuadByte    Var Byte    Bank0

' -------------- Asignar variables---------------------------

ADVal       Var Word
DutyCycle   Var Byte
nLoops      VAR Byte
    
'============================================================================


CodeStart:

    Goto    InitSeq        ' Pasar a subrutinas

'============================================================================

'Do_ISR
'Servicio de rutina de interrupción
'Manejar todad las interupciones
Asm

DO_ISR

    IF (CODE_SIZE <= 2)
        movwf   wsave          ; guardar registro W
        swapf   STATUS,W       ; guardar registro Status
        clrf    STATUS         ; cambiar al banco 0
        movwf   ssave          ; guardar estado de área en el banco 0
        movf    PCLATH,W       ; guardar conteo de programa 
        movwf   psave          ; guardar en el Banco 0 la localizacion
    EndIF
    
; ==========================================================================
; ver quinen causó la interrupción.
; vector a las rutinas correctas

    clrf    STATUS          ; cambio en el banco 0
    BTFSC   PIR1,TMR1IF     ; Timer1 desbordamiento?
    GOTO    T1_INT          ; Sí - Pase a la rutina de Timer1

    BTFSC   PIR1,TMR2IF     ; Desbordamiento Timer2?

    GOTO    T2_INT          ;Sí - Pase a la rutina Timer2
    CLRF    PIR1
    GOTO    ISR_Done        ; Error - no maneja la interrupción
    
; ==========================================================================
; Volver -1,0,1 en W reg
; Lo que debe ser de rutina en pzge 0

QUAD1_JUMP
    CLRF    PCLATH      ; PÁGINA CERO
    ADDWF   PCL,F       ; salto Indirectos 

    RETLW   0           ; 00 -> 00
    RETLW   1           ; 00 -> 01
    RETLW   1           ; 00 -> 10
    RETLW   1           ; 00 -> 11

    RETLW   1           ; 01 -> 00
    RETLW   0           ; 01 -> 01
    RETLW   1           ; 01 -> 10
    RETLW   1           ; 01 -> 11

    RETLW   1           ; 10 -> 00
    RETLW   1           ; 10 -> 01
    RETLW   0           ; 10 -> 10
    RETLW   1           ; 10 -> 11

    RETLW   1           ; 11 -> 00
    RETLW   1           ; 11 -> 01
    RETLW   1           ; 11 -> 10
    RETLW   0           ; 11 -> 11
    
; ==========================================================================

T1_INT                      ; Timer1 desbordamiento
    BCF     T1CON,TMR1ON    ; Apague el timer1
    BCF     PIR1, TMR1IF    ; Desactive la bandera de interrupción
;    BCF 	PORTB,5			; Apagar Pin pulso - a su veztodos los pines
;    BCF 	PORTB,4         ;
    GOTO    ISR_Done        

; ============================================================================
; Obtener los datos del codificador de cuadratura
; Inc / Dec durante interupcion ,@1.25 kHz frecuencia de muestreo
; limpiar QuadCount durante el ciclo de dirección
                           
T2_INT                      ; Timer2 / PWM de interrupción
    BCF     PIR1, TMR2IF    ; Desactive la bandera de interrupción

    MOVF    PORTC,W         ; Leer cuádruple sensor Pins - esto tiene que cambiar
    ANDLW   1               ; AND con 0001
    MOVWF   _QuadPins

    MOVF    _QuadPrev,W
    ADDWF   _QuadPins,W
    MOVWF   _QuadByte
    
    BTFSC   _QuadByte.0         ; Chequear Bit 0
    INCF    _QuadCount,F

     MOVF    _QuadPins,W
     MOVWF    _QuadPrev
    
    GOTO ISR_Done
    
    
;    BCF 	PORTB,4
    
    ;    INCF    _QuadCount,F

; ------

    BCF STATUS,C            ; Borrar bit
    MOVF    PORTC,W         ; Leer cuádruple sensor Pins - esto tiene que cambiar
    ANDLW   1               ; AND con 0001
;    ANDLW   6               ; AND con 0110

    MOVWF   _QuadPins
;    RRF     _QuadPins,F     ; Roll derecho -> 0011
    
    RLF     _QuadPrev,F     ; Roll pines anterior en bits superior
    RLF     _QuadPrev,W     ; Roll en W Reg: 1100
    IORWF   _QuadPins,W     ; O anterior y los estados CRNT: PPCC
    MOVWF   _QuadPrev       ; guardar  para la próxima vez
    
;    Movlw   1
    MOVF    _QuadPrev,W     ; parece innecesario
    CALL    QUAD1_JUMP
    ADDWF    _QuadCount,F
    
; ===============================

ISR_Done
    Movf    psave,w         ; Restaurar el registro PCLATH
    Movwf   PCLATH
    swapf   ssave,w         ; Restaurar el registro STATUS r
                            ;(banco establece a su estado original)
    Movwf   STATUS          ; mover W al reg Status 
    swapf   wsave,f         ; Swap w_guardar
    swapf   wsave,w         ; Swap w_guardar en W
    
    RETFIE
    
EndASM

'============================================================================
'============================================================================


' Subrutinas para leer voltajes A/D convertidor

Read_Pot1:
    ADCON0 = %10000001  ' 

Read_AD:
        nLoops = 0
        Pauseus 10              '
        ADCON0.2 = 1            ' iniciar conversion 
wLoop:
        nLoops = nLoops + 1
        Pauseus 5              ' tiempo para  conversion
        IF ADCON0.2 = 1 then wLoop
        
        adval.HIGHBYTE = ADRESH
        adval.LowBYTE = ADRESL
        Return

'-----------------------------------------------------------------------
'-----------------------------------------------------------------------

InitSeq:

    TRISA = %00000001	'configuracion  PORTA
    TRISB = %00000000	' PORTB
    TRISC = %10000001   ' PORTC 

    ADCON1 = %10000000	'
    CCP1CON = 0         ' MOdulo CCP en OFF

    HIGH FwdPin
    LOW RevPin

    QuadCount = 0
    QuadPrev = 0
    StatFlag = 0
    
    T2CON = %00000011   ' Timer2 Pre-Scaler = 1:16, Timer OFF
    TMR2 = 0            ' limpiar Timer2
    PR2 = 255           ' SPWM  = 1.25 kHz
    CCPR1L = 63         ' Duty Cycle a 25%
    CCP1CON = %00101100 ' modo PWM ,ciclo util= 10
    TMR2ON = 1
    
    Pause 500
    HIGH  LED
    DEBUG 13,10,"Velocidad", 13
    Pause 500

    GIE = 1     ' Habilitst interrpcion clobal
    PEIE = 1    ' Periférico de habilitación de interrupción
    TMR2IE = 1  ' habilitar bit de interrupcion del Timer2 
    
    Low    LED
    debug "Hecho que el bucle principal!", 13
    pause 1000

'-----------------------------------------------------------------------

mainloop:
    Toggle LED
    
    Gosub Read_Pot1             ; devuelve el valor 0 .. 1023
    adval = adval / 2           ; Ahora  0 .. 511
'    Debug "Pot: ", DEC ADval, 13
 
    if adval > 255 then
        adval = adval - 256
        fwdpin = 0
        revpin = 1
    else
        adval = 255 - adval
        fwdpin = 1
        revpin = 0
    Endif
    
    Adval = 255 - Adval         ; 0 = velocidad completa
                                
                                
    Debug "Ciclo Util: ", DEC ADval, "qCount: ", dec QuadCount, "qPrev:  ", dec QuadPrev, 13
    QuadCount = 0
    
    CCPR1L = ADval MIN 255      ; Establecer Ciclo 0 .. 255
                                
    Pause 400
    Goto mainloop
        
'    debug 13, "All Done.", 13
    End
        
End

saludos espero te sirva
 
Última edición:
que tal Autotronico
el encoder que estoy utilizando en el servomotor es similar al video del post #1091, son dos canales A y B , de 500 pulsos por canal, 3000 rpm, 24 Volts el motor y 2.7 Amp....todavia estoy probando lo del TMR0 como contador, tiene detalles espero maniana poder sacarlos y publicar el codigo...
muchas gracias por todos tus ejemplos...voy a ver que puedo utilizar de este ultimo ejemplo que publicaste

mira este video es de un robot que hice junto con dos alumnos TSU
http://www.uts.edu.mx/archivoselectronicos/Video/ArchivosElectronicos\3VideoRobot_UTS\RP5E_UTS1.rar
esta hecho con Motore Paso a Paso, este proyecto es para hacero con servomotores
 
Última edición:
hola electronicos, tengan un buen dia, tengo un problema con un servo "parallax futaba"
al desarrollar el programa con MPLAB 8.02 con un compilador pic basic pro 2.45
en un pic16f84a funciona perfecto, pero al desarrollarlo en un pic16f877a no consigo que me haga la rutina,obviamente le configuro el "device", espero que alguien ayude gracias de antemano
les dejo el programa:

********************************************
define osc 4
trisb=0
portb=0
i var byte
inicio:
for i=0 to 40
portb.0=1
pauseus 550
portb.0=0
pause 25
next i
pause 900
for i=0 to 35
portb.0=1
pauseus 1300
portb.0=0
pause 25
next i
pause 900
for i=0 to 35
portb.0=1
pauseus 2200
portb.0=0
pause 25
next i
goto inicio
End
**********************************
 
hola gente del foro.
otra vez yo por aca, desviando el tema de los demas :LOL: ...
bueno, mi pregunta es la siguiente: puedo o no puedo generar una señal de 38khz con un pic16f628 con clock interno mediante la instruccion freqout???
:cabezon:ya me he sacado las patillas de tanto renegar para que funcione un bumper inffrarrojo para un microbot que estoy haciendo y no he logrado nada :cry:
aca les dejo el codigo por si me pueden dar una manito :D
saludosss

Código:
@ DEVICE MCLR_OFF, INTRC_OSC, WDT_OFF, LVP_OFF, BOD_OFF, PWRT_ON, PROTECT_OFF
 
CMCON = 7                     ' desactivo el convertidor AD del puerto A
TrisA=%11111111               'todo el port A como entrada
TrisB=%00000000               'todo el port B como salida
PORTA = %11111111             'todo el port A en 1
PORTB = %00000000             'todo el port B en 0
ojoder var bit
ojoizq var bit

inicio:
FREQOUT portb.4,50,38500
ojoder = porta.0
ojoizq = porta.1
if ojoder = 0 then giroder
if ojoizq = 0 then giroizq
goto inicio

giroder:
portb = %00000101            'port B 0 y port B 2 a nivel 1 giro a la derecha
goto inicio

giroizq:
portb = %00001010              'port B 1 y port B 3 a 1 giro hacia la izquierda
goto inicio
 
que tal amigos, espero q esten bien todos por ahiiii

una pregunta....

como puedo hacer por medio de PIC16f877a o componentes hacer que leds...enciendan gradualmente y a pagen gradualmente??? cual seria el programita....diagrama....para realizar esto???
 
Atrás
Arriba