TODOPIC
Microcontroladores PIC => Lenguaje Basic para microcontroladores PIC => Mensaje iniciado por: fco1306 en 02 de Enero de 2012, 19:18:07
-
¿Alguien me puede decir que misterio tienen RB3 y RB4 de este pic?
Tengo el siguiente programa en pic simulator
Define CONF_WORD = 0x3f01
'Pic 16f628A opcion servos con relé
Define CLOCK_FREQUENCY = 4
'Define SIMULATION_WAITMS_VALUE = 1
AllDigital 'todos los pines digitales
Define SEROUT_DELAYUS = 0
'Definición de puertos
Symbol servo1 = PORTA.2
Symbol servo2 = PORTA.3
Symbol servo3 = PORTA.1
Symbol servo4 = PORTA.0
'Symbol bot_desv1 = PORTA.1
'Symbol bot_desv2 = PORTA.3
'Symbol bot_desv3 = PORTA.7
'Symbol bot_desv4 = PORTA.5
Symbol control1 = PORTB.7
Symbol control2 = PORTB.6
Symbol control3 = PORTB.4
Symbol control4 = PORTB.3
Symbol tx_485_enable = PORTB.5
'Definicion entradas-salidas
TRISA = %11100000
TRISB = %11011010
Dim fin_transmision As Byte
Dim bytes_bufer As Byte
Dim usart_imagen(20) As Byte
Dim usart_bufer(20) As Byte
Dim n As Byte
Dim n_usart As Byte
Dim nombre As Byte
fin_transmision = "!"
bytes_bufer = 0
n_usart = 0
Gosub usart_activa_rx
WaitMs 500 'pausa para estabilizar la entrada
'------------------------------------INICIO DEL PUERTO SERIE, TIMER E INTERRUPCONES------------------
Hseropen 9600 'Velocidad del puerto serie e inicializa los comandos de bajo nivel que controlan la USART
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos(USART), para que funcione la implementación P. SERIE
PIE1.RCIE = 1 'Activa la interrupcion de la USART en modo rx
Enable
INTCON.GIE = 1 'habilita todas las interrupciones globales
'--------------------------------------Inicio Programa--------------------------------------------------
Gosub clear_bufer 'Borra el BUFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
WaitMs 500
main:
If control1 = 1 Then
WaitMs 100
While control1 = 1
Wend
servo1 = 1
WaitMs 1000
servo1 = 0
WaitMs 1000
Endif
If control2 = 1 Then
WaitMs 100
While control2 = 1
Wend
servo2 = 1
WaitMs 1000
servo2 = 0
WaitMs 1000
Endif
If control3 = 1 Then
WaitMs 100
While control3 = 1
Wend
servo3 = 1
WaitMs 1000
servo3 = 0
WaitMs 1000
Endif
If control4 = 1 Then
WaitMs 100
While control4 = 1
Wend
servo4 = 1
WaitMs 1000
servo4 = 0
WaitMs 1000
Endif
Goto main
End
On Interrupt 'Comienzan las rutinas de las interrupciones
Save System 'Guarda los valores del sistema
PIE1.RCIE = 0 'desactiva la interrupcion de la USART en modo rx
Hserget usart_bufer(n_usart)
If usart_bufer(n_usart) > 0 Then
nombre = usart_bufer(n_usart)
n_usart = n_usart + 1
Endif
PIR1.TMR1IF = 0 'borra el flag de salto del tmr1
PIR1.RCIF = 0 'borra el flag de salto de la usart
PIE1.RCIE = 1 'activa la interrupcion de la USART en modo rx
Resume
usart_activa_rx:
WaitMs 100
tx_485_enable = 0
WaitMs 50
Return
usart_activa_tx:
WaitMs 100
tx_485_enable = 1
WaitMs 50
Return
clear_bufer:
For n = 0 To 1 'desbloquea el puerto serie fisico en caso de bloqueo por exceso de entrada de datos
PIE1.RCIE = 0 'deshabilita la interrupcion del modulo serie
RCSTA.CREN = 0 'protocolo de desbloqueo puerto serie
RCSTA.CREN = 1 'protocolo de desbloqueo puerto serie
RCSTA.OERR = 0 'protocolo de desbloqueo puerto serie
Next n
Gosub clearbufer 'borra el bufer por soft de los datos recibidos por el puerto serie
PIR1.RCIF = 0 'borra el flag de salto de la usart
PIE1.RCIE = 1 'activa la interrupcion de la USART en modo rx
Return
clearbufer: 'BORRA E INICIALIZA EL BUFER IMAGEN DEL PUERTO SERIE
Dim c_serial As Byte
For c_serial = 0 To 20 'pasa por cada uno de los bytes del bufer
usart_bufer(c_serial) = 0 'borra bytes del bufer apuntador,
'que nos indica si esa posición del bufer tiene datos
Next c_serial 'repite hasta el total del bufer
c_serial = 0
Return
en el que estoy trabajando.
Tengo los pines rb3 rb4 rb6 y rb7 conectados a una resistencia de 10K y de ésta a masa. En teoría están a cero.
Esta parte de código funciona
If control1 = 1 Then
WaitMs 100
While control1 = 1
Wend
servo1 = 1
WaitMs 1000
servo1 = 0
WaitMs 1000
Endif
Control1 que es b7 permanece a cero y servo1=0.El problema me aparece en la parte de si control 3 y control4 son igual a uno.
El programa se comporta de manera extraña.Servo3 y servo4 que son leds permanecen encendidos. Si conecto un led a las salidas servo1 y servo2 permanecen apagados,tal como indica el programa ya que control1 y control2 son cero.En la simulación funciona bien.
Si desconecto las resistencias de control3 y control4,los leds se encienden,pero si hago masa en alguna de ellas el led correspondiente se apaga.No sé ¿alguna explicación?
-
Pues después de darle vueltas no encontré el problema .
Monté el circuito de nuevo en una placa de prototipos, cambiando los pines y funciona.Por más vueltas que le dí no fuí capaz de encontrar el error en la electrónica.
-
Hola;
He estado revisando el programa y no veo porqué no funciona.
Si hay un error grave en usart_bufer() y, es que la defines con veinte elementos que son nombrados del 0 al 19, y tu escribes en el 20, este ultimo elemento no pertenece al vector y al escribir en el estas sobre escribiendo posiblemente una variable del sistema o tuya misma, normalmente esto produce cuelgues y cosas raras.
Lo mismo te pasa en la lectura de la variable en la rutina de interrupciones, en este caso como es lectura no afecta, pero también te sales del vector.
Otro tema es que se recomienda poner la rutina de interrupciones después de todas las demás rutinas.
He simplificado la rutina de interrupciones ya que haces operaciones redundantes.
El uso de Hserget ya borra la bandera de interrupciones de la usart cuando el bufer del módulo queda vacío.
Aunque Gosub/Return ya quedaron obsoletos en este lenguaje, la estructura del programa está correcta.
Por otro lado el uso de Gosub/Return ahorra memoria de stack que en esta familia de microcontroladores es de solo 8 niveles.
Para el bucle For:
Cada vez que se ejecuta un bucle For de nuevo, su variable asociada se hace 0 de forma automática.
Define CONF_WORD = 0x3f01
'Pic 16f628A opcion servos con relé
Define CLOCK_FREQUENCY = 4
'Define SIMULATION_WAITMS_VALUE = 1
Define SEROUT_DELAYUS = 0
'Definición de puertos
Symbol servo1 = PORTA.2
Symbol servo2 = PORTA.3
Symbol servo3 = PORTA.1
Symbol servo4 = PORTA.0
'Symbol bot_desv1 = PORTA.1
'Symbol bot_desv2 = PORTA.3
'Symbol bot_desv3 = PORTA.7
'Symbol bot_desv4 = PORTA.5
Symbol control1 = PORTB.7
Symbol control2 = PORTB.6
Symbol control3 = PORTB.4
Symbol control4 = PORTB.3
Symbol tx_485_enable = PORTB.5
'Definicion entradas-salidas
AllDigital 'todos los pines digitales
TRISA = %11100000
TRISB = %11011010
Dim fin_transmision As Byte
Dim bytes_bufer As Byte
Dim usart_imagen(20) As Byte
Dim usart_bufer(20) As Byte
Dim n As Byte
Dim n_usart As Byte
Dim nombre As Byte
fin_transmision = "!"
bytes_bufer = 0
n_usart = 0
Gosub usart_activa_rx
WaitMs 500 'pausa para estabilizar la entrada
'------------------------------------INICIO DEL PUERTO SERIE, TIMER E INTERRUPCONES------------------
Hseropen 9600 'Velocidad del puerto serie e inicializa los comandos de bajo nivel que controlan la USART
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos(USART), para que funcione la implementación P. SERIE
PIE1.RCIE = 1 'Activa la interrupcion de la USART en modo rx
Enable
INTCON.GIE = 1 'habilita todas las interrupciones globales
'--------------------------------------Inicio Programa--------------------------------------------------
Gosub clear_bufer 'Borra el BUFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
WaitMs 500
main:
If control1 = 1 Then
WaitMs 100
While control1 = 1
Wend
servo1 = 1
WaitMs 1000
servo1 = 0
WaitMs 1000
Endif
If control2 = 1 Then
WaitMs 100
While control2 = 1
Wend
servo2 = 1
WaitMs 1000
servo2 = 0
WaitMs 1000
Endif
If control3 = 1 Then
WaitMs 100
While control3 = 1
Wend
servo3 = 1
WaitMs 1000
servo3 = 0
WaitMs 1000
Endif
If control4 = 1 Then
WaitMs 100
While control4 = 1
Wend
servo4 = 1
WaitMs 1000
servo4 = 0
WaitMs 1000
Endif
Goto main
End
'Subrutinas -----------------------------------------------
usart_activa_rx:
WaitMs 100
tx_485_enable = 0
WaitMs 50
Return
usart_activa_tx:
WaitMs 100
tx_485_enable = 1
WaitMs 50
Return
clear_bufer:
For n = 0 To 1 'desbloquea el puerto serie fisico en caso de bloqueo por exceso de entrada de datos
PIE1.RCIE = 0 'deshabilita la interrupcion del modulo serie
RCSTA.CREN = 0 'protocolo de desbloqueo puerto serie
RCSTA.CREN = 1 'protocolo de desbloqueo puerto serie
RCSTA.OERR = 0 'protocolo de desbloqueo puerto serie
Next n
Gosub clearbufer 'borra el bufer por soft de los datos recibidos por el puerto serie
PIR1.RCIF = 0 'borra el flag de salto de la usart
PIE1.RCIE = 1 'activa la interrupcion de la USART en modo rx
Return
clearbufer: 'BORRA E INICIALIZA EL BUFER IMAGEN DEL PUERTO SERIE
Dim c_serial As Byte
For c_serial = 0 To 19 'pasa por cada uno de los bytes del bufer (de 0 a 19 = 20 elementos)
usart_bufer(c_serial) = 0 'borra bytes del bufer apuntador,
'que nos indica si esa posición del bufer tiene datos
Next c_serial 'repite hasta el total del bufer
c_serial = 0 '(Cada vez que se ejecuta el For, c_serial se hace 0 de forma automática)
Return
On Interrupt 'Comienzan las rutinas de las interrupciones (desactiva todas las interrupciones).
Save System 'Guarda los valores del sistema
Hserget usart_bufer(n_usart)
If usart_bufer(n_usart) > 0 and n_usart < 20 Then ' (para n_usart de 0 a 19 = 20 elementos)
nombre = usart_bufer(n_usart)
n_usart = n_usart + 1
Endif
Resume '(Activa las interrupciones de nuevo)
-
Pues yo he tenido el mismo problema al cambiar por el pic16f628, pongamos que le intento mandar un pulso entre los 0,5 y 1,5ms y nnai de la china es como si la patilla de pulso del servo tuviera mayor impedancia y pusiera a cero cualquier patilla del puerto A, (que menuda cabronada). Habría que reforzar la corriente del puerto A con un pequeño transistor.
La verdad que fue una cabronada.. había comprado ese pic entre otras razones para tener mas código y cuando fui a hacer una practica con los servos me lleve ese chascazo.. jejeje. Habría que prepararlos para el puerto B. y de paso quedarían las patillas del puerto al que van a los comparadores analógicos libres para poder hacer comparaciones de caídas de tensión.
Un saludo
-
Y bueno el programa no lo entendí muy bien.. Pero me imagino que WaitMs 1000 es = un pause 1000 (vamos una parada de 1000 milisegundos = a un segundo).
No se, me imagino que lo sabrás pero el pulso que se introduce en un servo es de 0.5 milisegundos un lado y 1,5 milisegundos el lado contrario según varíes ese intervalo de tiempo el servo se coloca en una posición y otra. Y has de dejar un intervalo de 3minimo a 20maximo milisegundos entre pulso y pulso, algo óptimo seria entre 5 y 10 milisegundos entre pulsos.
Un saludo.