desktop

Curso de programación de PIC en PICBasic Pro

Edit:
Mejoras para eliminar rebotes del pulsador...
Hola.

Quiero recordar que el método Button ya tiene un procedimiento antirebote.

De la documentación:

BUTTON
BUTTON Pin,Down,Delay,Rate,BVar,Action,Label
Lee un Pin y, opcionalmente, realiza un antirebote y una autorepetición. Pin se ajusta automáticamente como entrada. Pin puede ser una constante (0-15), o una variable que contenga un número de 0 a 15 (p.e. B0) o el nombre de un patilla (p.e. PORTA.0).

Down Estado de la patilla cuando se pulsa el botón (0,1).
Delay Ciclo de cuenta antes de que comience la autorepetición (0-255). Si es 0, no se realiza ningún antirebote o autorepetición. Si es 255, se realiza un antirebote, y no una autorepetición.
Rate Velocidad de autorepetición (0-255).
BVar Variable de tamaño byte usada internamente para el contador de rebote o repetición. Se debe inicializar a 0 antes de usarla, y no usarla en el resto del programa.
Action Estado del botón para actuar (0 si no debe estar pulsado, 1 si sí debe estar).
Label La ejecución sigue en esta etiqueta si Action es verdadera.

Se puede definir la longitud del antirebote con un DEFINE:

DEFINE BUTTON_PAUSE 50

Más información: http://melabs.com/resources/pbpmanual/5_4-5_6.htm#56
 
Quiero recordar que el método Button ya tiene un procedimiento antirebote.

De la documentación:

BUTTON
BUTTON Pin,Down,Delay,Rate,BVar,Action,Label
Si, así es, y sobre este tema ya se ha hablado anteriormente unas páginas atrás.

En pruebas físicas no ha resultado suficiente y es por eso que agregué otras rutinas más.
Otro problema es que al interactuar Button con la interrupción por RB0, Delay debe ser menor a 255 para no afectar la interrupción.

Edit:
Simplificación del código anterior sin usar la instrucción Button:
PHP:
; Declaración de variables.
Flag    Var Bit

; Nombres para los pines.
Symbol LED      = PORTB.4

Inicio:
    OPTION_REG = 0          ; Pull-Ups (PORTB) y Falling edge (INT-RB0)
    INTCON = %11010000      ; Habilitar interrupción por RB0
    
    ; Activar el servicio de interrupciones.
    On Interrupt GoTo SDI_RB0
    
    Low LED: Flag = 0       ; "LED" y "Flag" en 0 al iniciar.

Programa:
    While Flag = 1          ; Mientras "Flag" sea 1...
        Toggle LED          ; Cambiar de estado "LED"
        Pause 50            ; Cambiar el tiempo del destello aquí
    Wend                    ; Salir del bucle cuando "Flag" sea 0
        
    Low LED                 ; Apagar el LED
        
    GoTo Programa
    
; Servicio de interrupción por RB0
SDI_RB0:
    Disable                 ; Desactivar interrupciones.
    
    If INTCON.1 = 1 Then    ; Si es interrupción por RB0, entonces...        
        If Flag = 0 Then    ; Si "Flag" está en 0, entonces...
            Flag = 1        ; Establecer "Flag" en 1
        Else                ; Caso contrario...
            Flag = 0        ; Establecer "Flag" en 0    
        EndIf
        INTCON.1 = 0        ; Limpiar flag INTF
    EndIf
    
    Resume                  ; Retornar al programa (RETFIE)
    Enable                  ; Volver a activar interrupciones.
    
    End
 
Última edición:
en la ayuda dice:


si un signo # antecede a un elemento, la representacion ASCII para cada digito se envia al LCD

asi que prueba asi:
Lcdout $fe,$C0,"Dato: ",#Dato

Hola , Muchas gracias por tu respuesta. lo que quiero es poder controlar con 2 pulsadores la aparición de letra por letra del abecedario en un LCD. Con el primer pulsador empiece de la letra "A" .....hasta la letra "Z", por cada pulso que haga y me pueda detener en culaquier letra y luego con el segundo pulsador empiece a devolver por cada pulso que haga y me pueda detener en culaquier letra o llegar hasta la letra "A" nuevamnete.

Quiero saber como darle un valor a cada letra, para que al pulsar el pulsador1 una vez, aparezca la letra "A" y quede en pantalla, luego al pulsar el pulsador1 otra vez, aparezca la letra "B", luego al pulsar el pulsador1 otra vez, aparezca la letra "C" y asi sucesivamente llegar a cualquier letra o al final con la letra "Z", luego con el pulsador2 devolverme letra por letra por cada pulsada que haga, desde la letra en que quedé a cualquier letra o al final que para el pulsador2 seria la letra "A".

Gracias.
 
:unsure:¿quieres saber como se hace o quieres que te lo hagan? es diferente...

al codigo que pusiste en donde dice

Lcdout $fe,$C0,"Dato: ",DEC Dato

le pruebas poniendo:

Lcdout $fe,$C0,"Dato: ",#Dato

que es lo que indique en el mensaje anterior.. y delimitas con la condicion "if" el rango de la A a la Z.
 
Última edición:
:unsure:¿Quieres saber como se hace o quieres que te lo hagan? es diferente...
jesusmolo ya puso el código que hizo, pero ha comentado que no le funciona.
Al código que pusiste en donde dice:

Lcdout $fe,$C0,"Dato: ",DEC Dato

Le pruebas poniendo:

Lcdout $fe,$C0,"Dato: ",#Dato

Que es lo que indiqué en el mensaje anterior y delimitas con la condición "if" el rango de la A a la Z.
Al usar los operadores que propones, lo que se obtendrá será un número y no una letra.

Lo que jesusmolo quiere hacer es algo muy sencillo.
Si tomamos como base la Tabla ASCII, veremos que la letra A mayúscula equivale al número 65 y así sucesivamente hasta la Z que equivale al código ASCII 90.

Entonces mostrar cada letra en orden de abajo hacia arriba y viceversa, sería muy sencillo:
PHP:
Letra       Var Byte

    LCDOut $FE,1,"   Abecedario"
    
    Letra = 65

Programa:
    If PORTB.2 = 0 Then
        Letra = Letra + 1
        If Letra >90 Then Letra = 90
    EndIf
    
    If PORTB.3 = 0 Then
        Letra = Letra - 1
        If Letra <65 Then Letra = 65
    EndIf
        
    LCDOut $FE,$C0,"Letra: ",Letra
    Pause 250
    
    GoTo    Programa


    End
Así de fácil. :cool:
 
Última edición:
jesusmolo ya puso el código que hizo, pero ha comentado que no le funciona.

yo entendi diferente, entendi que agarro un codigo que alguien hizo y queria que alguien se lo ajustara a sus necesidades, pero bueno...

Al usar los operadores que propones, lo que se obtendrá será un número y no una letra
la verdad no me acuerdo, pero ahora que mencionas y seguramente lo tienes mas fresco si, con solo mandar el codigo ascii es suficiente..pero por ahi iba XD (y)
 
Última edición:
Pues si, es por eso que se han hecho preguntas acerca de por qué no se muestra el valor en la pantalla, o por qué se ven letras en vez de números.
Si se manda un 49 se verá un 1, pero si se manda como #49 o Dec 49, se verá el número 49

En el programa anterior se manda a la pantalla desde el 65 hasta el 90, letras <A:Z> en ASCII
Y para la minúsculas sería desde el 97 hasta el 122, letras <a:z> en ASCII

Si recorriéramos toda la tabla, desde el 0 hasta el 127, en los primeros 32 números no se vería nada, o se verían cuadros negros.

También se podría hacer con una tabla LookUp y así se podría poner la ñ o Ñ, pero no todas las pantallas la tienen en su CGROM.
 
si, si te creo dark segun yo si es correcto tu codigo...

para serte honesto me queda la duda del #, o sea que sea lo mismo el # que el DEC, el dec si estoy seguro que no funcionaria.

cuando tenga un poco de tiempo lo checo para ver si es lo mismo o que diferencia hay, si la hay entre esos.

saludos...
 
Para serte honesto me queda la duda del #, o sea, que sea lo mismo el # que el DEC, el dec si estoy seguro que no funcionaría.
Para mostrar letras ninguno funcionaría, ambos convierten un número a cadena para poder ser visualizado.

# Se usa más que nada para enviar un número como cadena por RS-232 y terminando el envío con 13,10 (Cr/Lf)
Al terminar de esta forma el envío para pasar a la siguiente línea, ya no existe problema de que la siguiente cadena se sobreponga a la anterior.

Dec también convierte un número a cadena pero con la ventaja de que se puede definir la cantidad de dígitos a mostrar.
Por ejemplo: Dec5 123 nos mostrará, 00123
Cuando tenga un poco de tiempo lo checo para ver si es lo mismo o que diferencia hay, si la hay entre esos.
La principal diferencia se notará cuando se escriba en la pantalla LCDOut $FE,$80,#123 y después se escriba LCDOut $FE,$80, #5
Entonces el 5 quedará en el lugar del 1 y la lectura se confundirá.
En cambio con Dec3 1 se enviará el número 1 con dos ceros a la izquierda: 001

De esta forma ya no se mezclarán los números enviados y se mostrará un resultado coherente.
 
Última edición:
jesusmolo ya puso el código que hizo, pero ha comentado que no le funciona.

Al usar los operadores que propones, lo que se obtendrá será un número y no una letra.

Lo que jesusmolo quiere hacer es algo muy sencillo.
Si tomamos como base la Tabla ASCII, veremos que la letra A mayúscula equivale al número 65 y así sucesivamente hasta la Z que equivale al código ASCII 90.

Entonces mostrar cada letra en orden de abajo hacia arriba y viceversa, sería muy sencillo:
PHP:
Letra       Var Byte

    LCDOut $FE,1,"   Abecedario"
    
    Letra = 65

Programa:
    If PORTB.2 = 0 Then
        Letra = Letra + 1
        If Letra >90 Then Letra = 90
    EndIf
    
    If PORTB.3 = 0 Then
        Letra = Letra - 1
        If Letra <65 Then Letra = 65
    EndIf
        
    LCDOut $FE,$C0,"Letra: ",Letra
    Pause 250
    
    GoTo    Programa


    End
Así de fácil. :cool:




Muy buenos dias. muchas gracias D@rkbytes, era exactamente lo que buscaba, gracias por aclarar esta duda y recordar lo referente al codigo ASCII. :aplauso: :apreton:
 
¡Hola a todos!
Ya que están con los LCD, quiero hacer una consulta.
Hace un par de meses, construí un pequeño módulo para un LCD 16x2 usando un PIC16F628 que tenía un par de puertos dañados, y pensé que sería útil controlarlo con un solo pin.

Me explico: por ejemplo, usar un 12F629 para alguna aplicación y enviar por medio de un solo pin las instrucciones a otro PIC que se encarga exclusivamente de manejar el LCD.

Adjunto el diagrama de mi circuito.
Lo programé (puse pines para ICSP), y solito tal cual está funciona a las mil maravillas.
Mi problema es que cuando envío una palabra (por ejemplo "hola" ) solo muestra un caracter.
Uso la instrucción SerIn/SerOut de PICBASIC PRO.

Este es el código que uso. Sólo módulo.
Código:
cmcon=7

TRISA=%00000100
TRISB=%00000000

DEFINE LCD_DREG PORTB                             ' Set LCD Data port
DEFINE LCD_DBIT 0                                     ' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_RSREG PORTA                           ' Set LCD Register Select port
DEFINE LCD_RSBIT 4                                   ' Set LCD Register Select bit
DEFINE LCD_EREG PORTA                             ' Set LCD Enable port
DEFINE LCD_EBIT 3                                     ' Set LCD Enable bit
DEFINE LCD_BITS 8                                     ' Set LCD bus size (4 or 8 bits)
'DEFINE LCD_LINES 2                                   ' Set number of lines on LCD
'DEFINE LCD_COMMANDUS 1500                    ' Set command delay time in us
'DEFINE LCD_DATAUS 44                              ' Set data delay time in us

pause 200                                                  'LCD intializing pause

inicio:

lcdout $FE, 1, "Hola"      
lcdout $FE, $C0, "YO SOY GROOT"    
pause 1000

goto inicio
end
Módulo con otro PIC:
Código:
INCLUDE "modedefs.bas"

cmcon=7

TRISA=%00000100
TRISB=%00000000

DEFINE LCD_DREG PORTB                             ' Set LCD Data port
DEFINE LCD_DBIT 0                                     ' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_RSREG PORTA                           ' Set LCD Register Select port
DEFINE LCD_RSBIT 4                                   ' Set LCD Register Select bit
DEFINE LCD_EREG PORTA                             ' Set LCD Enable port
DEFINE LCD_EBIT 3                                     ' Set LCD Enable bit
DEFINE LCD_BITS 8                                     ' Set LCD bus size (4 or 8 bits)
'DEFINE LCD_LINES 2                                   ' Set number of lines on LCD
'DEFINE LCD_COMMANDUS 1500                    ' Set command delay time in us
'DEFINE LCD_DATAUS 44                              ' Set data delay time in us

datos var word

pause 200                                                  'LCD intializing pause

inicio:

serin porta.2, N2400, datos

lcdout $FE, 1, "Hola"      
lcdout $FE, $C0, "YO SOY GROOT"   
pause 1000

lcdout $FE, 1, "palabra"
lcdout $FE, $C0, datos
pause 1000

goto inicio
end
 

Adjuntos

  • Modulo LCD by EOTH.jpg
    Modulo LCD by EOTH.jpg
    77.5 KB · Visitas: 28
Última edición por un moderador:
Hace un par de meses, construí un pequeño módulo para un LCD 16x2 usando un PIC16F628 que tenía un par de puertos dañados, y pensé que sería útil controlarlo con un solo pin.

Me explico: por ejemplo, usar un 12F629 para alguna aplicación y enviar por medio de un solo pin las instrucciones a otro PIC que se encarga exclusivamente de manejar el LCD.
Mira por aquí: 16F628A LCD One Wire con 74HC595
Esto viene del tema: Temporizador para insoladora con 16F628A

Ese programa lo podrás migrar sin ningún problema para que funcione con un PIC12F629.
 
Que tal Darkbytes! saludos a ti y a todo el foro.
Bueno pues,les escribo por que tengo un par de dudas en una linea de codigo
es sobre el tema de decodificacion del protocolo Sony,les cuento este codigo lo encontre en la red esta escrito en pic basic
pro lo estuve analizando y creo que si le entiendo la mayor parte y algo que he leido de teoria sobre la decodificacion del
protocolo Sony,este codigo no trae "comentarios" asi que lo yo le entiendo es lo siguiente:

define variable tipo word
define los tris
despues va a main donde detecta la cabecera si es menor a ese valor se regresa si no avanza
despues con los pulsin lee los 7 bits que corresponden a comando y salta a la etiqueta detectair y dependiendo el valor
si es <80 pongo la variable en cero(0) sino en uno(1) y asi con los siete bits(b0...b6)
*Nota: El bit7=0 se le agrega un octavo bit puesto a cero para completar un byte y así poder trabajar mejor a nivel del software

***Bueno hasta aqui todo bien,creo que le he entendido***


Mi duda es esta linea donde aparece la variable b9 definida como word:

b9=(128*b7)+(64*b6)+(32*b5)+(16*b4)+(8*b3)+(4*b2)+(2*b1)+(1*b0)

bueno supongo que es aqui donde se unen o se juntan los resultados de todos los pulsin individuales de los 7 bits para dar
digamos un resultado total,si alguien haya hecho algo semejante con la decodificacion Sony que me pudiera explicar esta Linea
de codigo osea como saca esos valores que por lo que veo van en orden decreciente(b7...b0) y luego los multiplica por valores
como 128,64,32,16,8,4,2,1 aqui es donde no le entiendo o habra otra forma de explicarlo?
lo que esta en la parte de abajo es bastante entendible eso ya es el resultado de b9.
Anexo imagenes y codigo en PBP...Gracias
 

Adjuntos

  • imagen_SONY.jpg
    imagen_SONY.jpg
    28.7 KB · Visitas: 34
  • Control_Remoto_Infrarrojo_SONY.rar
    102.9 KB · Visitas: 44
Lo que hace ese programa, es leer el ancho de los pulsos ingresados e irlos guardando en variables.
Luego se compara cada nivel y dependiendo del tamaño, se le asigna un nuevo valor a cada variable.

Entonces si realizamos una operación con los valores máximos, tendríamos el siguiente resultado:
b0 = 1
b1 = 1
b2 = 1
b3 = 1
b4 = 1
b5 = 1
b6 = 1
b7 = 0

128 * b7 = 0
64 * b6 = 64
32 * b5 = 32
16 * b4 = 16
8 * b3 = 8
4 * b2 = 4
2 * b1 = 2
1 * b0 = 1

Entonces: b9 = (0 + 64 + 32 + 16 + 8 + 4 + 2 + 1) = 127

Como b9 nunca sobrepasará de 127, debería ser del tipo Byte.
Igualmente las otras variables, ya que en las comparaciones tampoco se excede de 255

Obviamente 127 sería el valor máximo de la suma, en el caso de que todos los pulsos fueran superiores a 80.
O sea, el caso "Else" de las comparaciones, donde se le reasigna el valor 1 a cada variable.
Por lo tanto b9 podrá ser de un valor inferior a 127 que posteriormente se usa para realizar otras comparaciones.

Nota sobre PulsIn:
Cuando se usa una variable del tipo Byte (8 bits) para almacenar el resultado de PulsIn, sólo se toma el LSB
O sea, los 8 bits menos significativos de los 16 bits que retornan como resultado.
 
la instruccion PULSIN sera la adecuada?

Que tal Darkbytes y a todos en el foro!

Encontre este proyecto en la red es sobre un Detector de Proximidad.Esta diseñado con un solo microcontrolador y esta escrito en ASM cosa que no manejo y bueno ya que estamos en pic basic pro,la pregunta es ¿puedo utilizar la funcion PULSIN por aquello de PulsIn PORTA.0,0,pulsos ,(lectura de pulsos en estado bajo) para capturar la señal de rebote,como ves en el texto de mas abajo remarque en negrita lo que considere relevante es decir:
emitir pulsos a 38khz--->rebotar en el objeto--->capturar la señal(frecuencia)--->comparar la señal enviada con la recibida y en base a eso ejecutar acciones.

En resumen mi duda es:¿puedo utilizar la funcion PULSIN para capturar la señal de rebote y luego comparar? por que no se me ocurre otra idea.

Anexo un par de imagenes y un programa PWM con Hardware con el pic 16f628A con un ciclo util del 50% y frecuencia de 38 KHZ aproximadamente
Por su aportacion Gracias...


*****Extracto del texto original*****

Principio de funcionamiento:

Por medio del microcontrolador, se activa el LED infrarrojo mediante trenes de pulsos. Cuando algún objeto se aproxima al LED (a una distancia que puede regularse entre 5 y 20 cms, dependiendo de la corriente que se suministre al LED), refleja la energía hacia el detector, el cual envía la señal al microcontrolador. El microcontrolador compara la señal enviada con la señal recibida y, si son similares, entonces activa el relevador.

El envío de pulsos, y la comparación entre la frecuencia de envío y la recibida, hace posible evitar el disparo en falso del relevador por efecto de sombras o cambios en la luminosidad del ambiente, ya que el dispositivo puede funcionar de día y de noche.

Descripción:

El principio de funcionamiento es generar, por medio del firmware en el microcontrolador, un tren de 30 pulsos modulando a una portadora de 36 kHz, cada uno con una duración de de 835 us, y seguido por un espacio de la misma duración, como se muestra en la imagen de abajo. Para generar tal señal, se utiliza la función PWM (Modulación por ancho de pulso) integrada en el hardware del microcontrolador 18F2550.

Esta señal se emitida por el diodo infrarrojo TN153B, reflejada por el objeto y detectada por el receptor de infrarrojo TMF5360. La señal de 36 khz demodulada es analizada por un algoritmo en el firmware del microcontrolador 18F2550, que posteriormente activa el relevador cuando se detecta una señal válida.
 

Adjuntos

  • Detector de Proximidad_01.jpg
    Detector de Proximidad_01.jpg
    49.6 KB · Visitas: 52
  • Detector de Proximidad_02.jpg
    Detector de Proximidad_02.jpg
    36.4 KB · Visitas: 42
  • PWM_hardware.jpg
    PWM_hardware.jpg
    104.1 KB · Visitas: 41
  • PWMhardware.rar
    73.3 KB · Visitas: 53
Buenas Arturo vie el dribe de tu video en interne , y me he apuntado al foro , yo no controlo mucho de pic , pero bueno intentare ponerme al dia , el proyecto de este motor con encoder es de lo mejorcito que he visto por la red , lo he intentado simular en Proteus , pero no lo he conseguido asi que lo intentare hacer en fisico , pero me parece tam bueno que creo que se merece un pos independiente , para ver si se sigue desarrollando porque creo que podria dar mas de si , yo algo intentare y si lo consigo lo pondre por aqui anque dudo que lo consiga , pero creo que le hace falta el empujon de un dato mas ( la velocidad ) , porque creo que los desplazamintos los hace todos a la maxima velocidad y estaria bien poder elegir no solo el punto de destino si no a que velocidad lo hace .
 
Hola compañeros, buenas noches.

He practicado y realizado proyectos pequeños con el PIC16f84A.
Ahora quise cambiarme al PIC16F88, que según lo que he leído es compatible pin a pin y en la gran parte de la programación.
Quise adaptar este simple programa para encender un LED añadiendo la instrucción CMCON = 7 para habilitar el puerto A como digital, como también la instrucción OSCCON = %01100110 para hablitar el oscilador interno, pero aun así no me funcionó.
¿Ustedes que sugieren?

Código:
cmcon=7                ; Desactiva los comparadores analogicos de todos los pines del puerto A y
                       ; convierte las salidas y entradas en digital del puerto A.
                       

OSCCON=%01100110     ; Configura oscilador interno en 4MGH de frecuencia estable  
                                          
Define Osc 4 ' Define el Oscilador para un Cristal  ' de 4 Mhz.

TRISA = %11110111            ' Configura el puerto A como entrada.
TRISB = $00            ' Configura puerto B como salida.

PORTB = $00 ' Inicializa el puerto B

Inicio:

If PORTA.4 = 1 Then PORTB.7 = 1 ' Pregunta si RA0 = 1, si se cumple
                                ' la condición entonces enciende el Led.
                                
Pause 1000 ' Hace una pausa de 1 segundo (1000 ms)

Low PORTB.7 ' Apaga el Led

Pause 1000 ' Hace una pausa de 1 segundo (1000 ms)

GoTo inicio ' Salta a la etiqueta "Inicio"

End
 
Última edición por un moderador:
Quise adaptar este simple programa para encender un LED añadiendo la instrucción CMCON = 7 para habilitar el puerto A como digital, como también la instrucción OSCCON = %01100110 para hablitar el oscilador interno, pero aun así no me funcionó.
CMCON no es el registro que hace los pines analógicos como digitales.
Y el oscilador interno no se activa con el registro OSCCON, ahí se configura.
¿Ustedes que sugieren?
Que le des una buena leída a la hoja de datos. :cool:
Ahí encontrarás las configuraciones y entenderás el por qué no funciona tu programa.

Suerte.
 
Hola buenas noches D@rkbytes.

Tenias toda la razón, investigando en la hoja de datos del pic 16f88 encontré que colocando en 0 el registro ANSEL todos los puertos se colocaban en digital o si le coloco en binario puedo determinar que bit puedo establecer como analogo o digital. Muchas gracias.

Tengo una duda porqué al precionar el pulsador me toca esperar hasta 2 segundos para que encienda el led.

Muchas gracias.
 
Porque tienes 2 retardos de 1000 ms después de la sentencia IF.
Por lo tanto, siempre habrá 2 segundos para que se regrese a la etiqueta "Inicio"

Podrías envolver las instrucciones dentro de un solo bloque IF, pero de todos modos siempre existirá el retardo.
Haciendo eso, al menos cuando se salga del bloque IF no tendrás que dejar el pulsador presionado esperando el retorno.
 
Atrás
Arriba