[Tutorial] y manejo de Proton IDE

D@rkbytes

Moderador
La variable VOLT debe ser del tipo Byte si es que se usa el ADC a 8 bits. (0 a 255)
Y debe ser del tipo Integer si es que el ADC va a 10 bits. (0 a 1023)
Así que no tiene sentido que sea Float.

Mejor haz esto ya con VOLT como Integer:
VOLT = ADIn 0
VOLTUP = (VOLT / 204.8) + 0.4
 
Hola. Esta vez tengo problemas en sumar números con punto flotante; y es que PROTON parece que no hace la suma o no se hacerla.

Estoy haciendo esto:

Dim VOLT As Float
Dim VOLTUP As Float

VOLT = ADIn 0
DelayUS 50
VOLT = VOLT / 204.8
VOLTUP = VOLT + 0.4

Digamos que VOLT/204 tiene como resultado 1.6 y le sumo 0.4 seria igual a VOLTUP = 2.0

Luego hago esto:

If VOLT < VOLTUP Then GoTo STAND_BY
If VOLT > VOLTUP Then GoTo POWER_ON

Como se ve VOLT (1.6) es menor que VOLTUP (2.0) y debería ir a la rutina STAND_BY, pero no lo hace y se va a POWER_ON.

Pero si lo hago así, entonces si funciona:

If VOLT < 2.0 Then GoTo STAND_BY
If VOLT > 2.0 Then GoTo POWER_ON

¿Porque?... de antemano muchas gracias por la ayuda.
Hola...Tienes que usar dos variables, una para el valor del ADC(Word) y otra para el resultado(Float).
Código:
Dim VoltP As Word
Dim VOLT As Float
Dim VOLTUP As Float

VoltP = ADIn 0
DelayUS 50
VOLT = VoltP / 204.8
VOLTUP = VOLT + 0.4
Por lo que veo siempre VOLTUP va a ser mayor de VOLT en 0.4 por que lo único que haces es sumarle 0.4 a esta(VOLTUP = VOLT + 0.4) por eso no te trabaja la comparación de "If VOLT < VOLTUP Then GoTo STAND_BY" ya que nunca se dará.

Por otro lado si solo habrá esas dos acciones pueden resumirse en

Código:
If VOLT < VOLTUP THEN
    GoTo STAND_BY
Else
    GoTo POWER_ON
ENDIF
Saludos.

Ric.
 
La variable VOLT debe ser del tipo Byte si es que se usa el ADC a 8 bits. (0 a 255)
Y debe ser del tipo Integer si es que el ADC va a 10 bits. (0 a 1023)
Así que no tiene sentido que sea Float.

Mejor haz esto ya con VOLT como Integer:
VOLT = ADIn 0
VOLTUP = (VOLT / 204.8) + 0.4
¿No se puede usar float para guardar el valor del ADC a 10 bits? pero es que necesito los decimales.

Pero probare a ver que pasa. Muchas gracias.
 

D@rkbytes

Moderador
¿No se puede usar float para guardar el valor del ADC a 10 bits?
De que se puede se puede, pero no tiene sentido y es un desperdicio de memoria.
El conversor AD entrega un valor comprendido entre 0 y 1023 (10 bits, sin decimales)
Por eso siempre se usa una variable Integer para leer el conversor y otras más para el proceso.
Incluso todo el proceso se puede realizar sin usar variables Float y aún así se pueden obtener los decimales.
Pero si se quiere usar Float por comodidad a costa del consumo de memoria, entonces debe limitarse su uso.
Mientras menos variables Float se puedan usar será mejor, y si con una sola se puede obtener el resultado, pues qué bien.

Siempre se debe tener la costumbre de ahorrar memoria aunque los programas sean pequeños o el microcontrolador muy grande.
 
Usando word para VOLT, el programa redondea la cantidad de 1.6 a 2 ...y ahora la suma no es 2.0 sino 2.4
P1.png

Usando float para VOLT, la suma es correcta. Funciona perfecto en Proteus, pero no en la realidad.
P2.png
 
Eso es porque no estás haciendo bien las cosas.

Adjunto un ejemplo.
Si, debe ser porque no he explicado lo que debe hacer el programa.

Se trata de hacer un circuito que desconecte un electrodoméstico, cuando este se encuentre en Standby,
con el fin de "ahorrar energía" y proteger el mismo.

Hago las pruebas con un televisor, el cual en standby me da un voltaje de 1.6v rectificados y 2.6v encendido, los cuales llevo
al ADC del micro (12f683).

Para ello están las 2 variables VOLT y VOLTUP. En la primera guardo el valor de 1.6v y creo un umbral sumando 0.4v para que la otra
variable sea mayor, dando como resultado = 2.0v

Cuando el TV esta en standby, el programa espera 1 minuto y a la vez revisa el ADC por si aumenta el voltaje (para saber que el tv se encendió en medio de la espera) si no enciende, el RELE se desconecta y el TV queda sin energía.

Para reactivar todo, el programa queda en una rutina donde se lee un botón del control remoto; si este se presiona
el micro energiza el tv y se repite el ciclo nuevamente.

Cuando el televisor enciende, VOLT pasa de 1.6v a 2.6v superando a VOLTUP (2.0V) y el programa mantiene el RELE conectado.

En este momento lo tengo funcionando perfectamente, pero si le pongo valores fijos. Lo de usar las variables es porque, el micro
ajustaría automáticamente el umbral al que debe trabajar, pues no es el mismo en todos los electrodomésticos.

Si dejo los valores fijos en el programa, tendría que ajustar el umbral para cada aparato ... lo cual seria muy incomodo y poco practico.

Gracias por el ejemplo, pero tampoco funciono. :cry:
 
¿No se puede usar float para guardar el valor del ADC a 10 bits? pero es que necesito los decimales.

Pero probare a ver que pasa. Muchas gracias.
Que tiene que ver que necesites decimales si siempre el ADC es de 8, 10, etc bit. No sabe nada de decimales.

Necesitas decimales al momento de la conversión a valores no antes.

Si te da mal la cuenta algo estas haciendo mal seguramente como el error de la comparación cuando tu mismo programas que incrementan el valor de una variable, jamás este ultimo puede ser menor al valor que acabas de incrementar.

Te pase el código, aplica como lo lo publique y no puede haber problema.

Si quieres ayuda global debes publicar todo(programa, esquema, lo que pretendes, etc) lo que tienes y has hecho porque si no es un juego de sacar información con tirabuzón.
Si, debe ser porque no he explicado lo que debe hacer el programa.

Se trata de hacer un circuito que desconecte un electrodoméstico, cuando este se encuentre en Standby,
con el fin de "ahorrar energía" y proteger el mismo.

Hago las pruebas con un televisor, el cual en standby me da un voltaje de 1.6v rectificados y 2.6v encendido, los cuales llevo
al ADC del micro (12f683).

Para ello están las 2 variables VOLT y VOLTUP. En la primera guardo el valor de 1.6v y creo un umbral sumando 0.4v para que la otra
variable sea mayor, dando como resultado = 2.0v

Cuando el TV esta en standby, el programa espera 1 minuto y a la vez revisa el ADC por si aumenta el voltaje (para saber que el tv se encendió en medio de la espera) si no enciende, el RELE se desconecta y el TV queda sin energía.

Para reactivar todo, el programa queda en una rutina donde se lee un botón del control remoto; si este se presiona
el micro energiza el tv y se repite el ciclo nuevamente.

Cuando el televisor enciende, VOLT pasa de 1.6v a 2.6v superando a VOLTUP (2.0V) y el programa mantiene el RELE conectado.

En este momento lo tengo funcionando perfectamente, pero si le pongo valores fijos. Lo de usar las variables es porque, el micro
ajustaría automáticamente el umbral al que debe trabajar, pues no es el mismo en todos los electrodomésticos.

Si dejo los valores fijos en el programa, tendría que ajustar el umbral para cada aparato ... lo cual seria muy incomodo y poco practico.

Gracias por el ejemplo, pero tampoco funciono. :cry:
Si sabes que quieres comparar el valor a 2V para que quieres crear una variable, sólo compara con 2 y listo por un lado y para que quieres pasar a volt el valor del ADC.

Si quieres comparar y que haga algo cuando supere los 2V de la escala de 0-5V, comparas cuando llegue al valor 409 0 410 en la lectura del ADC serán tus 2V

Código:
Dim Volt as Word
......
......
Volt= ADIn 0
If Volt <= 409 then STANBY
......
......
Sin cuentas, demoras y complicaciones de decimales, etc. por parte del microcontrolador, la cuenta la haces tú una solo vez para saber el valor de corte que corresponde al ADC, comparas y tomas la decisión que corresponde.

Si necesitas que sea variable no hay problemas, crea una con valor Word, lees el ADC con el valor de referencia y le sumas el valor correspondiente a la diferencia del ADC pero en valores redondos.
EJ: leiste 327(1.6V) le sumas 82(0.4V) y te da los 409(2V) que almacenas como límite de comparación.
Si lee 300, le sumas 82 y almacenar el resultado para ser comparado, etc, etc.

Los valores con comas solo se justifican si necesitas mostrar algo, a nivel de decisiones lógicas en este caso no son necesarios y los microcontroladores de bajos recursos no son tan buenos tratando con ellos en operaciones matemáticas.

Ric.
 
Última edición:
Hola a todos. Estoy entrenando con el PIC 16F1827 y es primer vez que lo uso. Hice un programa pequeño
con un led y un mensaje en un display lcd 2x16; el led funciona pero el mensaje no se muestra.
Quizás sea algún registro que causa problema en los puertos, pues este PIC tiene "muchas funciones" en
comparación con los PIC clásicos. Probé el programa con un 16f88 (con sus propios registros obviamente)
y funciona.¿ Alguien sabe que pasa?

El display esta bueno.

Gracias de antemano.

Código:
Device = 16F1827
Reminders 0
Config1 FOSC_HS,WDTE_OFF,PWRTE_ON,MCLRE_ON,CP_OFF,CPD_OFF,BOREN_OFF,IESO_OFF,FCMEN_OFF
Config2 WRT_OFF,PLLEN_OFF,STVREN_OFF,LVP_OFF, 'FOSC_INTOSC
Reminders 1
Xtal 10
PortB_Pullups = OFF
'****************************************************************
'All_Digital = TRUE
TRISA = %00000000
TRISB = %00000000
OSCTUNE = %00000000
'OSCCON = %01101000 '4 Mhz
CM1CON0 = %00000000
CM1CON1 = %00000000
CM2CON0 = %00000000
CM2CON1 = %00000000
APFCON0 = %00000000
APFCON1 = %00000000
'**************************************************************
'ADC
Adin_Res = 10 
Adin_Tad = FRC
Adin_Stime = 50
FVRCON = %10000001 '1.024V
ADCON0 = %00000000
ADCON1 = %11110011'Vref interno
'****************************************************************
'DISPLAY LCD
LCD_DTPin = PORTB.4
LCD_RSPin = PORTB.2
LCD_ENPin = PORTB.3
LCD_Interface = 4
LCD_Lines = 2
LCD_Type = 0
'****************************************************************
'SENSOR CAPACITIVO
CPSCON0 = %00000000
CPSCON1 = %00000000
'****************************************************************
'ALIAS
Symbol LED = PORTB.0
'****************************************************************
Cls
DelayMS 100
MAIN:
Print At 1,1,"PRUEBA DISPLAY"
Print At 2,1,"PIC 16F1827   "
High LED
DelayMS 200
Low LED
DelayMS 200
GoTo MAIN

End
 
Adivinando por que no subiste la simulación y como esta el codigo no compila por que no usaste Declare antes de algunas declaraciones como las del LCD, etc seguramente te comiste llevar el MCLR a +B y lo tienes declarado en los fusibles que lo usas.

Después de las correcciones a tu codigo a mi me funciona en Proteus 7.9
Captura.JPG
 

Adjuntos

Adivinando por que no subiste la simulación y como esta el codigo no compila por que no usaste Declare antes de algunas declaraciones como las del LCD, etc seguramente te comiste llevar el MCLR a +B y lo tienes declarado en los fusibles que lo usas.

Después de las correcciones a tu codigo a mi me funciona en Proteus 7.9
Ya incluí declare y hace lo mismo. No hice simulación pues uso un entrenador.
El MCLR esta bien. Si funciona el led es porque el micro esta funcionando.

Puede ser los fuses o el micro tiene algún puerto malo.

Gracias por la simulación ... seguiré probando. (y)
 
Si el led funciona es por que esta pasando por el sector de la impresión al LCD. Me inclino más por un error de conexión, alimentación del display, etc aunque nunca hay que descartar nada.

Los Declare son indispensables por que si no no genera el archivo hex para cargar al PIC(no compila).

erro.JPG

Yo uso la version 3.6.2.1 y si bien figuran como aceptados y en el lugar pero se niega a compilar si no los pones, puede ser esta versión.

En tu versión de los fusibles es indispensable que el pin Nº4 este a +B o directo o mediante una resistencia de Pull-Up, en la que subi yo en el mensaje anterior esta modificado para que no sea necesario.
 
Última edición:
Tengo la versión 3.5.2.7 y compila con o sin DECLARE. Las conexiones están bien, porque con
un PIC16F88 funciona utilizando los mismos pines para el LCD y el LED.
¡Encontré el problema!

Faltaba configurar los registros ANSELA y ANSELB ya que en este PIC el puerto B es
también análogo y digital.

Gracias.

Código:
Device = 16F1827
Reminders 0
Config1 FOSC_HS,WDTE_OFF,PWRTE_ON,MCLRE_ON,CP_OFF,CPD_OFF,BOREN_OFF,IESO_OFF,FCMEN_OFF
Config2 WRT_OFF,PLLEN_OFF,STVREN_OFF,LVP_OFF, 'FOSC_INTOSC
Reminders 1
Xtal 10
PortB_Pullups = OFF
'****************************************************************
'All_Digital = TRUE
TRISA = %00000000
TRISB = %00000000
OSCTUNE = %00000000
'OSCCON = %01101000 '4 Mhz
CM1CON0 = %00000000
CM1CON1 = %00000000
CM2CON0 = %00000000
CM2CON1 = %00000000
APFCON0 = %00000000
APFCON1 = %00000000
'**************************************************************
'ADC
Declare Adin_Res = 10 
Declare Adin_Tad = FRC
Declare Adin_Stime = 50
FVRCON = %10000001 '1.024V
ADCON0 = %00000000
ADCON1 = %11110011'Vref interno
ANSELA = %00000000
ANSELB = %00000000 
'****************************************************************
'DISPLAY LCD
Declare LCD_DTPin = PORTB.4
Declare LCD_RSPin = PORTB.2
Declare LCD_ENPin = PORTB.3
Declare LCD_Interface = 4
Declare LCD_Lines = 2
Declare LCD_Type = 0
Declare LCD_CommandUs = 2000
Declare LCD_DataUs = 50
'****************************************************************
'SENSOR CAPACITIVO
CPSCON0 = %00000000
CPSCON1 = %00000000
'****************************************************************
'ALIAS
Symbol LED = PORTB.0
'****************************************************************
Cls
DelayMS 100
MAIN:
Print At 1,1,"PRUEBA DISPLAY"
Print At 2,1,"PIC 16F1827   "
High LED
DelayMS 200
Low LED
DelayMS 200
GoTo MAIN

End
Asi se ve en el entrenador.

P1.png
 
Última edición:
La variable VOLT debe ser del tipo Byte si es que se usa el ADC a 8 bits. (0 a 255)
Y debe ser del tipo Integer si es que el ADC va a 10 bits. (0 a 1023)
Así que no tiene sentido que sea Float.

Mejor haz esto ya con VOLT como Integer:
VOLT = ADIn 0
VOLTUP = (VOLT / 204.8) + 0.4
Ya encontré el problema de este proyecto. Sucede que al encender el equipo a proteger (un TV en este caso) se genera un pico de corriente y después de un tiempo se estabiliza ... y como el PIC es muy rápido "captura" este valor, el cual era de unos 3 voltios y yo esperaba que fuera 1.6 (el valor del TV en stand by).

Para averiguarlo use la función MAX/MIN del multimetro ... y con esos 3v de referencia en lugar de 1.6v todas las matemáticas se alteraban y el programa no funcionaba como debería.

La solución fue entonces hacer un retardo de 12 segundos (no se si sea mucho tiempo) antes de leer el valor de stand by ... y ahora si guarda el valor correcto.

Código:
'********************************************
'Para eliminar el pico de corriente al inicio
DelayMS 300
High RELE
For CUENTAS = 0 To 11
DelayMS 1000
Next
Clear CUENTAS
'********************************************
CAPTURA:
For CUENTAS = 0 To 9
VOLT = ADIn 0
DelayUS 50
ACUMVOLT = ACUMVOLT + VOLT
Next
ACUMVOLT = ACUMVOLT / 10
ACUMVOLT = ACUMVOLT / 204.8
VOLTUP = ACUMVOLT + 0.300
Clear CUENTAS
Clear ACUMVOLT
Clear VOLT
Ahora todo funciona perfectamente; muchas gracias a todos por la ayuda. (y)
 
Hola. Ahora tengo un problema con el PIC12F1822 ... y es que configuro el PIC para hacer una conversión A/D, pero en el AN0 aparece un voltaje de 0.6v y en AN1 otro de 1.4v cuando debería ser cero. Los pines están como análogos y como entradas.

Supongo que estoy configurando mal algún registro, porque este PIC tiene varias funciones (ADC, DAC, CPS, PWM etc). Dejo la configuración de los registros. Gracias.

Código:
Device = 12F1822
Reminders = OFF
Config1 FOSC_INTOSC,WDTE_OFF,PWRTE_ON,MCLRE_OFF,CP_OFF,CPD_OFF,BOREN_OFF,CLKOUTEN_OFF,IESO_OFF,FCMEN_OFF
Config2 WRT_OFF,PLLEN_OFF,STVREN_OFF,LVP_OFF
Reminders = On
Xtal 4
'*********************************************
'DECLARACIONES
'*********************************************
Declare Adin_Res = 10 'Resolución ADC=10 bits
Declare Adin_Stime = 50
'****************************************
'CONFIGURACION DE REGISTROS
'***************************************
OSCCON = %01101010 ' 4mhz Osc interno.
OSCTUNE = %00000000                                
CM1CON0 = %00000000 'Comparador apagado
CM1CON1 = %00000000
PIE1 = %00000000
PIE2 = %00000000
PIR1 = %00000000
PIR2 = %00000000
PORTA = %00001011 '0,1,3 como entradas
ANSELA = %00000011 '0,1 entradas analogas
ADCON0 = %00000011
ADCON1 = %10110011 'FRC
FVRCON = %10000011 'VREF = 4.096V
WDTCON = %00000000 'Watchdog timer
DACCON0 = %00000000
DACCON1 = %00000000
T1CON = %00000000
CPSCON0 = %00000000
CPSCON1 = %00000000
SRCON0 = %00000000
SRCON1 = %00000000
APFCON = %00000000
BAUDCON = %00000000
LATA = %00000000
WPUA = %00000000
OPTION_REG = %10000000
INTCON = %00000000
 
Última edición:

D@rkbytes

Moderador
No entiendo para qué configuras tantos registros que no vas a utilizar.
Si únicamente quieres usar el ADC, configura nada más los registros involucrados.
Así se use o no el ADC, cuando un pin es configurado como entrada, el voltaje que aparezca en él es debido a un factor externo.
 
No entiendo para qué configuras tantos registros que no vas a utilizar.
Si únicamente quieres usar el ADC, configura nada más los registros involucrados.
Así se use o no el ADC, cuando un pin es configurado como entrada, el voltaje que aparezca en él es debido a un factor externo.
Hola. Configuro todos esos registros buscando resolver el problema. El voltaje aparece con los pines al aire sin conectar nada en ellos y el ADC lo lee. En ese programa falta TRISA que confundí con PORTA, pero al configurar todo bien el problema aun continua. Gracias.
 

D@rkbytes

Moderador
Estando un pin sin conexión cualquier carga estática lo cargará con un voltaje parásito.
Siempre es necesario que el pin tenga una conexión externa a algo.
Es una prueba absurda medir el voltaje en un pin configurado como entrada análoga.
Hasta en una que sea digital lo sería, siempre y cuando no esté configurada alguna resistencia pull-up interna.
 

Arriba