desktop

Curso de programación de PIC en PICBasic Pro

holas una consulta.
Estoy haciendo un proyecto q es mensaje a celular usando un sim900 y el pic 16f873
El sim fundiona con comandos at en el cual no tengo problema alguno, el problema es en el pic cuando hago el programa en pic basic
el programa es:

CONEC VAR BYTE

TESTEO:
SEROUT PORTC.6,N9600,["AT"]
SERIN PORTC.7,N9600,CONEC ;ALMACENADO EN CONEC
IF CONEC ="OK" THEN PASO2 ; COMPARACION SI ESTA OK VA A OTRA FUNC
GOTO TESTEO

El error radica en que en el momento de comparar if CONEC ="OK" me da error
pregunta :cuando yo le envio AT al sim me responde "OK"¿como ago que CONEC me almacen esos dos caracteres?¿como puedo hacer la comparacion en if?
os agradecere en el alma si alguien me ayuda

Hola...Debes leer la ayuda(Help) del PBP en el que explica el alcance y la forma de usar del comando SERIN2 y la forma de "esperar" una cadena. De todas formas NUNCA una variable del tipo BYTE(0-255) como tienes definido a CONEC puede almacenar una cadena de caracteres pero si el valor numérico de uno solo a la vez( o la "O(79)" o "o(111)" o la "K(75)" o la "k(107)").
Saludos.

Ric.
 
Hola compañeros de nuevo por acá con mis curiosidades, estuve hace un tiempo experimentando con el modulo PWM del PIC16F877A y me fue muy bien probando lo con un led variando su intensidad. En su momento me entero que la minima frecuencia a 20MHZ es de 1.22khz y a 4mhz es de 245hz lo cual es mucho para controlar un motor dc. A mi parecer esto es por la capacidad en si del microcontrolador ya que no es practico si se quiere independizar del manejo, a esto me refiero poder mantener un motor a una velocidad a través del PWM y poder hacer otras cosas sin tener que depender del una interrupción adicional para el control del motor. Esto ya que la única forma de poder bajar esa frecuencia es con un contador a través del timer1. Entonces llego a una conclusión que es preferible manejar un pwm directo por interrupción que el físico del microcontrolador ya que seria como mas eficiente el manejo del mismo y menos complicado que usando el modulo PWM propio del micro ya que no dependería de dos pines si no que podría aplicarlo a cualquier pin I/O.
Me gustaría saber sus opiniones y análisis al respecto.
A ustedes que les parece mejor...?
 
Exacto eso es lo que venden del micro y lo que entusiasma a utilizar el modulo PWM que es independiente de las otras ejecuciones del código, pero limitado y esa limitación te obliga a utilizar una subrutina adicional para poder utilizarlo en un motor y por lo tanto ya allí ya pierdes ese aspecto de independiente. Es útil al 100% para situaciones en las cuales manejes frecuencias mayores a 245hz de lo contrario para frecuencias de 50hz por ejemplo no lo veo muy eficaz por lo de la subrutina, en ese caso creo que es preferible hacer una rutina por interrupción y ya.
 
Saludos reyvilla, leyendo tu pregunta (espero haber entendido bien) concuerdo con el amigo LaElectronicaMeodia, eso dependeria de tu proyecto, de la complejidad, o mas bien que tan grande con respecto a circuiteria quisieras hacerlo. Pero alguna vez en un proyecto utilice divisores de frecuencia, quizas podriar utilizar cualquiera de estos circuitos (existen muchos) para dividir tu frecuencia minima "245" y asi poder tener un rango mas amplio. De todas formas comenta por aqui cualquier cosa, o si lo haces de otra forma tambien podria interesarle a otros miembros del foro.
Saludos y Suerte!
 
Hola Volthor, probé el que me enviaste, pero al compilarlo me dá un error, (igual genera el archivo hex), lo simulo en proteus y se queda en el primer efecto, aún cuando vuelvo a presionar el pulsador, adjunto el .pbp y el .dsn, para que por favor lo observes (no sé si tal vez mi simulador está mal configurado), gracias, seguimos en contacto(y)

amigo, el problema que tienes es que esta mal definido el watchdog (wdt) si eliminas o colocas como corresponde la linea, compila sin problema, saludos
 
Amigos, necesito de su gran ayuda.

Tengo este código. ¿Me podrían ayudar? Está en pic basic.
¿Cómo puedo hacer una rutina de tiempo para cada pulsador?
Oséa que si presiono 5 segundos pulsador1, led1 encienda 30 minutos, si presiono 7 segundos pulsador 1,
el led1 se quede encendido 1 hora y si presiono 2 segundos pulsador1 que el led1 se apague solo al cumplirse un minuto.

Ojala me puedan ayudar. Muchas gracias por su aporte.
 

Adjuntos

  • control de relay.rar
    8 KB · Visitas: 71
Última edición por un moderador:
Amigos del foro logre implementar algo pero aun me falta anexo todo el circuito con el codigo que he podido avanzar espero me puedan ayudar lo incomodo es que no tengo internet en casa y no me dejan instalar ni el proteus ni el microcode en cabina alquilada jejeje espero su ayuda amigos

la idea es que pueda darle diferentes tiempos presionando el mismo pulsador
ejemplo;
* PRIMER TIEMPO mantengo presionado botón por un mediosegundo y activa led_1 por 10 segundos si vuelvo a presionar el boton dentro de los 10 segundos le ordenare que se apague led_1 y si no es presionado el boton se apagara después de los 10 segundos automáticamente.

* SEGUNDO TIEMPO mantengo presionado botón por 2 segundos y activa led_1 por 1 minuto si dentro del minuto se vuelve a presionar el boton led_1 se apagara y si no es presionado el boton cumple el tiempo del minuto y el led_1 se apaga automaticamente.

* TERCER TIEMPO mantengo presionado el boton por 5 segundos y se activa led_1 por un tiempo de 2 horas si dentro de este tiempo de 2 horas se vuelve a presionar el boton led_1 se apaga y si no se presiona el boton led_1 se apagara automaticamente cuando se cumpla el tiempo adecuado amigo por favor he avanzado un poco del codigo pero aun no logro dar con el codigo o con la forma adecuada de hacer por favor es`pero me puedan ayudar con sus conocimientos.
Este es el codigo
Código:
@ DEVICE PIC16F628A         
@ DEVICE INTRC_OSC_CLKOUT    
@ DEVICE WDT_OFF             
@ DEVICE PWRT_OFF            
@ DEVICE LVP_OFF               
@ DEVICE CPD_ON             
@ DEVICE PROTECT_ON 
       
DEFINE OSC 4 

CMCON = 7

TRISB = %00000000 
TRISA = %11110000 
PORTA = %00000000
PORTB = %00000000

TLED1       VAR word  
TLED2       VAR word
TLED3       VAR WORD

MinutO      var byte   
Segundo     Var Byte     
MAS_TIEMPO  VAR BYTE
INITIO      VAR BYTE
I           var byte

FLAG0       VAR BIT
FLAG1       VAR BIT
FLAG2       VAR BIT


;******POTENCIA******///////****** 
LED         var PORTB.0  
LED_1       VAR PORTB.1 
LED_2       VAR PORTB.2 
LED_3       VAR PORTB.3
Trbuz       VAR PORTB.7
;********************///////******

;******PULSADORES****///////******                   
BOTON       VAR PortA.7 
BOTON1      VAR PortA.6
BOTON2      VAR PortA.4
;********************///////******


;gosub beeps
;pause 1000

OPTION_REG = %10000101
ON INTERRUPT GOTO MI_INTERRUPCION
INTCON = %10100000

FLAG0=0
FLAG1=0
flag2=0
i=0

 INICIO:
   
     if boton then    ;como implementar los tiempos adecuadamente??????
      repeat
       pause 10
        i = i + 1      
      until not boton           
     if i =< 50 then         
       toggle led_1    
       toggle flag0    
       TLED1=0         
      else      
    if i=< 150 then 
     high led_1    
      high flag1    
       TLED2=0
     else
       toggle led_1   
       flag0=0
       flag1=0
       tled1=0
       tled2=0
      endif
     endif
    endif
   pause 10
     
GOTO INICIO

    DISABLE            
MI_INTERRUPCION: 
    MAS_TIEMPO = MAS_TIEMPO + 1
    IF MAS_TIEMPO => 61 THEN
    MAS_TIEMPO = 0
    TOGGLE LED
    if FLAG0 THEN 
    TLED1 = TLED1 + 1
    ENDIF
    IF FLAG1 THEN
    TLED2= TLED2 + 1
    ENDIF
    IF FLAG2=1 THEN
    TLED3= TLED3 + 1
    ENDIF

    IF LED_1 = 1 and TLED1 = 10 THEN  ; 10 segundos 
    flag0=0
    LED_1=0
    TLED1=0
    i=0
    ENDIF
    
    IF LED_1 = 1 and TLED2 = 60 tHEN ; 1 minuto ===> 60 segundos
    LED_1=0 
    FLAG1=0
    TLED2=0 
    i =0  
    endif
    ENDIF

    IF LED_1 = 1 and TLED3 = 7200 tHEN ; 2 horas ===> 7200 segundos
    LED_1=0 
    FLAG2=0
    TLED3=0 
    i =0  
    endif
    ENDIF
    
    INTCON = %10100000 
    Resume
    Enable
    END

Si quisiera que tenga un sonido buzzer para que me avise cuando active el tiempo de 1 minuto por decir bip bip tiempo de
for I = 0 to 1
high buzzer
pause 80
low buzzer
pause 80
next I
y cuando se cumpla el minuto vuelva a sonar bip bip afectaria esto en la rutina del conteo por interrupcion osea afectaria en algo. Ya que estuve haciendo pruebas y cuando le puse el buzzer se retrazaba un poco en contar los segundos o mejor dicho no eran exactos los segundos
 

Adjuntos

  • ckto.rar
    18.2 KB · Visitas: 60
Última edición:
mira estuve probando tu codigo agregue un par de lineas pero no trabaja no logro hallar la forma adecuada esperemos que puedan ayudar los amigos del foro o amigos moradores
lo estuve probando con segundos en cada tiempo
Código:
 INICIO:
   
     if boton then    
      repeat
       pause 10
        i = i + 1     
      until not boton           
     if i =< 30 then      
       high led_1    
       high flag0    
       TLED1=0         
      elseif 
        gosub Time1 
      ELSE   
    if i=< 150 then 
     high led_1  
      high flag1    
       TLED2=0
     else
      gosub Time1
      endif
     endif
    endif
   pause 10
     
GOTO INICIO

    DISABLE            
MI_INTERRUPCION: 
    MAS_TIEMPO = MAS_TIEMPO + 1
    IF MAS_TIEMPO => 61 THEN
    MAS_TIEMPO = 0
    TOGGLE LED
    if FLAG0 THEN 
    TLED1 = TLED1 + 1
    ENDIF
    IF FLAG1 THEN
    TLED2= TLED2 + 1
    ENDIF

    IF LED_1 = 1 and TLED1 = 8 THEN  ; 
    flag0=0
    LED_1=0
    TLED1=0
    i=0
    ENDIF
    
    IF LED_1 = 1 and TLED2 = 12 tHEN ; 
    LED_1=0 
    FLAG1=0
    TLED2=0 
    i =0  
    endif
    ENDIF
    
    INTCON = %10100000 
    Resume
    Enable
    
    Time1:
       toggle led_1  
       flag0=0
       flag1=0
       tled1=0
       tled2=0
    goto INICIO   
 END
 
mira estuve probando tu codigo agregue un par de lineas pero no trabaja no logro hallar la forma adecuada esperemos que puedan ayudar los amigos del foro o amigos moradores
lo estuve probando con segundos en cada tiempo
Código:
 INICIO:
   
     if boton then    
      repeat
       pause 10
        i = i + 1     
      until not boton           
     if i =< 30 then      
       high led_1    
       high flag0    
       TLED1=0         
      elseif 
        gosub Time1 
      ELSE   
    if i=< 150 then 
     high led_1  
      high flag1    
       TLED2=0
     else
      gosub Time1
      endif
     endif
    endif
   pause 10
     
GOTO INICIO

    DISABLE            
MI_INTERRUPCION: 
    MAS_TIEMPO = MAS_TIEMPO + 1
    IF MAS_TIEMPO => 61 THEN
    MAS_TIEMPO = 0
    TOGGLE LED
    if FLAG0 THEN 
    TLED1 = TLED1 + 1
    ENDIF
    IF FLAG1 THEN
    TLED2= TLED2 + 1
    ENDIF

    IF LED_1 = 1 and TLED1 = 8 THEN  ; 
    flag0=0
    LED_1=0
    TLED1=0
    i=0
    ENDIF
    
    IF LED_1 = 1 and TLED2 = 12 tHEN ; 
    LED_1=0 
    FLAG1=0
    TLED2=0 
    i =0  
    endif
    ENDIF
    
    INTCON = %10100000 
    Resume
    Enable
    
    Time1:
       toggle led_1  
       flag0=0
       flag1=0
       tled1=0
       tled2=0
    goto INICIO   
 END

Una pregunta en la instrucción Pause, el período es en milisegundos, según comentas quieres controlar medio segundo, por qué se pregunta por =< 50 ¿no debería ser => 500?
 
al ponerle PAUSE 10 estoy dando un tiempo de 10 ms por el tiempo de presionado del boton que es de 50 ms seria 500 msg o talvez me estoy confundiendo si podrian orientarme por favor les agradecederia inmensamente
Una pregunta en la instrucción Pause, el período es en milisegundos, según comentas quieres controlar medio segundo, por qué se pregunta por =< 50 ¿no debería ser => 500?
 
Última edición:
la idea es que pueda darle diferentes tiempos presionando el mismo pulsador
ejemplo;
* PRIMER TIEMPO mantengo presionado botón por un medio segundo y activa led_1 por 10 segundos si vuelvo a presionar el botón dentro de los 10 segundos le ordenare que se apague led_1 y si no es presionado el botón se apagara después de los 10 segundos automáticamente.

* SEGUNDO TIEMPO mantengo presionado botón por 2 segundos y activa led_1 por 1 minuto si dentro del minuto se vuelve a presionar el botón led_1 se apagara y si no es presionado el botón cumple el tiempo del minuto y el led_1 se apaga automáticamente.

* TERCER TIEMPO mantengo presionado el boton por 5 segundos y se activa led_1 por un tiempo de 2 horas si dentro de este tiempo de 2 horas se vuelve a presionar el boton led_1 se apaga y si no se presiona el boton led_1 se apagara automaticamente cuando se cumpla el tiempo adecuado amigo por favor he avanzado un poco del codigo pero aun no logro dar con el codigo o con la forma adecuada
Mira el programa que adjunto, tal vez te pueda servir como orientación para hacer lo que requieres.
No se utiliza un solo botón para determinar los periodos de retardo, pues eso puede ser muy complicado.
Se utiliza la interrupción por cambio de estado en los pines RB4 a RB7 para determinar que periodo establecer.
El programa cuenta con una rutina para periodos largos de tiempo que puedes utilizar en tu programa.

Como en todas las rutinas de retardo, una vez que el programa entra a la rutina, ya no sale hasta que se cumpla el tiempo establecido.
Por lo tanto el programa principal será retomado hasta que se cumpla la condición y retorne.

Si se puede apagar el LED presionando cualquier botón en RB4 a RB7 y volver a establecer el periodo, pero no se retomará el programa nuevamente hasta que se cumpla el conteo de la rutina.

Espero te sirva de algo este programa, o tal vez hasta lo puedas modificar para lograr tu objetivo.

Nota:
El programa lo escribí con MCS v5.0 y compilado con PBPX 3.0 porque necesitaba el archivo *.cof para realizar un debug al programa.
Sin embargo el código es compatible con versiones anteriores con solo cambiar la palabra de configuración.
La palabra de configuración para PBP 2.60 también está incluida en el programa por si se requiere.

Saludos.
 

Adjuntos

  • 16F628A Timers.rar
    43.6 KB · Visitas: 125
Última edición:
gracias amigo por tu respuesta y ayuda la idea de hacer los tiempos con un solo pulsador es porque hare activar 4 focos independientes cada uno con su pulsador y este pulsador con sus tiempos diferentes en ese caso como podria darle solucion
 
Saludos cesarim, el programa que adjunto D@rkbytes es perfectamente ajustable a lo que tienes pensado hacer.
Se utiliza la interrupción por cambio de estado en los pines RB4 a RB7 para determinar que periodo establecer.
El programa cuenta con una rutina para periodos largos de tiempo que puedes utilizar en tu programa.
Despues de eso lo que debes seleccionar es cual foco deseas encender con cada tiempo establecido.
Suerte!
 
Amigo desde ya muchas gracias por el codigo esta muy muy bueno pero lo que pretendo con esos tiempos es que sean con un mismo pulsador para activar un solo relay
Código:
Define OSC 4				; Definir que se trabajará con 4MHz.

; Declaración de variables.
Contador    Var Word
Flag        Var Bit
T1          Var Word
T2          Var Word

; Nombres para los pines.
Symbol LED_1    = PORTB.1

Inicio:
	CMCON = 7				; Comparadores analógicos OFF
	OPTION_REG.7 = 0		; Resistencias de Pull-Up en Puerto B
	TRISB = %11110000
	PORTB = TRISB
    Clear       ; Inicializar variables a 0
	
On Interrupt GoTo PORTB74_CHANGE
INTCON = $C8    ; %11001000 (Interrupción RB<7:4>)

Programa:
; Programa principal.
	Toggle PORTA.1
	Pause 80
	GoTo	Programa

Disable
PORTB74_CHANGE:
    INTCON.0 = 0    ; Limpiar flag por cambio de estado en RB<7:4>

    While PORTB.4 = 0   ; Mientras RB4 es 0...
        Pause 10
        Contador = Contador +1  ; Incrementar Contador cada 10Ms.
        If Contador = 50 Then   ; Si son 500 Ms...
        T2 = 10                 ; 10 segundos.
        LED_1 = 1               ; Enciende LED_1 por 10 segundos
        GoSub Retardo           ; Ir a Subrutina de retardo.
        EndIf
    Wend                        ; Termina el bucle.

    While PORTB.4 = 0        ; el mismo pulsador con un tiempo de 
        Pause 10
        Contador = Contador +1
        If Contador = 200 Then  ; dos segundos
        T2 = 60                 ; prende led_1 por 1 Minuto
        LED_1 = 1
        GoSub Retardo
        EndIf
    Wend

    While PORTB.4 = 0        ;el mismo pulasador con un tiempo de pulsado
        Pause 10
        Contador = Contador +1
        If Contador = 500 Then  ; de 5 segundos
        T2 = 7200               ; enciende led_1 por 2 Horas
        LED_1 = 1
        GoSub Retardo
        EndIf
    Wend
    
    While PORTB.4 = 0
        Pause 10
        Contador = Contador +1
        If Contador = 100 Then
        T2 = 1
        LED_1 = 1
        GoSub Retardo
        EndIf
    Wend

    Contador = 0
    
    If Flag Then            ; Si Flag es 1 es porque se activo el Retardo.
        Flag = 0            ; Se limpia la bandera.            
        LED_1 = 0           ; Apagar LED_1
    EndIf
    
    Resume                  ; Regresar al programa principal.
    Enable                  ; Habilitar nuevamente las interrupciones.
    
; Procedimiento para retardos largos de tiempo (Por D@rkbytes)
Retardo:
    T1 = 0                  ; Iniciar esta variable con el valor 0
    Flag = 1                ; Activar bandera de LED encendido
Aun_No:                     ; Etiqueta para realizar un bucle               
    T1 = T1 + 1             ; Incrementar T1
    Pause 1000              ; Pausar 1 segundo
    If T1 < T2 Then         ; Si la variable T1 es menor a la variable T2...
    GoTo Aun_No             ; Regresar a Aun_No
    Else                    ; Si es mayor sale del If
    LED_1 = 0               ; Apaga el LED (Fin del período)
    Flag = 0                ; Limpiar bandera de LED encendido
    EndIf                   ; Termina el If
    Return                  ; Regresa dentro de la interrupción
    
	End

y que se apague cuando se vuelva a presionar el pulsador asi no haya cumplido su tiempo programado
 
Hola compañeros estoy aún con lo del PWM, con respecto a sus limitaciones y sus ventajas, estoy realizando un ejemplo con un pic16f877A aun estoy en fases de diseño del programa para dar una idea para compararlo con respecto el PWM del pic y el PWM generado por interrupción cuando lo tenga listo lo comparto.

Por otro lado y para no saturarme con solo el PWM, con respeto a lo de el compañero cesarim estoy revisando el código algo complejo a mi parecer, creo se puede realizar con instrucciones mas simples y algoritmos menos complejos ahora estoy editando un código nuevo en base al código subido hoy mas tarde lo comparto, solo una pregunta. Por que toggle y por que no usas un simple = 1 para estar mas seguro de que sea eso lo que se cumpla. Lo digo por que colocas muchas veces IF variable THEN en ves de IF variable = 1 THEN, y toggle si es que deseas mantenerlo apagado por el mismo tiempo que encendido. Mas conveniente es si utilizas los flag como señalizadores o el mismo pin del led para saber si esta encendido o apagado y así saber como actuar en cada situación. Solo probé cambiando el toggle dentro de la interrupción por led = 0 y los IF variable = 1. Y empezó a dar mejor, de todas formas tienes muchas cosas que hiciste que hacen que sea difícil de entender y de ejecutar. Otra cosa que vi es que usas el PORTA.4 el cual debes de colocar una PULL-UP para que funciones de manera correcta. Los tiempos no se si realizaste los cálculos pero no veo configuración del TMR0 por lo que viendo tu configuración estamos hablando de 16 milisegundos con 384 useg por cada incremento de tu variable MAS_TIEMPO. Osea 16,384 x 61 = 0,999 segundos, Para el primer caso y ultimo se cumple el segundo dice 20 lo que indica que es 20seg. Al cumplirse en cualquier caso debes asegurar de volver a 0 el TMR0 y mas cuando estas desactivando el LED adicional solo activara el contador cuando se este activando alguno de los led y así hacerlo mas preciso. En conclusión voy a seguir por acá con el nuevo código y luego lo coloco saludos.

---------- Actualizado después de 2 horas ----------

Ya realicé el código esta funcionando para un solo led se modifico lo necesario para que funcionara lo mejor posible, parte del código me lo copie de un un código que realice hace unos años atrás para temporizar unas lavadoras por lo que es bien preciso. Ahora funciona de la siguiente manera.

Para iniciar se presiona el primer botón de izquierda a derecha, se mantiene presionado no mas de 200mSeg Ya que sobre pasa el valor de la variable y al pasar de 256 la variable retorna a 0.
Hay dos maneras de saber cuanto tiempo va a quedar encendido el led. Una es sonora con un beep se mantiene 10Seg con dos beep se mantiene 1 min y con 3 beep se mantiene 2 min es modificable en el código. La otra manera en revisando la memoria eeprom del pic la cual utilice como referencia para verificar el valor de la variable lo cual puede borrarse del código si no es necesario. Lo otro es duplicar las misma lineas de código para los demás botones y ya estaría listo...Cual quier cosa me avisas.

Mucho éxito :apreton: saludos.
 

Adjuntos

  • PULSADOR NUEVO COD.rar
    42 KB · Visitas: 92
Última edición por un moderador:
Atrás
Arriba