Curso de programación de PIC en PICBasic Pro

Veo que usas el canal 1, pero en el código sólo estás estableciendo como entrada RA0.
Por lo tanto, RA1 quedará funcionando como salida.
Elimina la instrucción TRISA = 1 para dejar el puerto A como entradas. (Por defecto)

Si el sensor mide hasta 30 amperes y se obtiene 1 ampere por cada 0.066 V, entonces...
0.066 * 30 = 1.98 V.
30 Amperes será tu valor de lectura máximo y 1.98 V será el voltaje de entrada máximo al conversor AD.

Aquí conviene usar el voltaje de referencia VRef+ para establecer un limite y poder realizar un ajuste.

Mira este código de ejemplo para que lo entiendas:
PHP:
;*******************************************************************************
@ Device PIC16F877A    ; Microcontrolador utilizado
; Palabra de configuración:
@ Device XT_OSC,WDT_OFF,PWRT_ON,LVP_OFF
;*******************************************************************************
; Definición de pines para la pantalla.
Define LCD_DREG PORTD        ; Puerto de datos.
Define LCD_DBIT     4        ; Bit de inicio de datos.
Define LCD_RSREG PORTD        ; Puerto de RS (Register Select)
Define LCD_RSBIT    3        ; Pin para RS
Define LCD_EREG PORTD        ; Puerto de E (Enable)
Define LCD_EBIT     2        ; Pin para E

; Declaración de variables:
Valor_ADC   Var Word
Amperes     Var Byte

Inicio:
    Define ADC_BITS 10      ; 10 bits de resolución
    ADCON1 = %10000101      ; Just. Der. Canales 0,1, VRef+ AN3

Inicia_LCD:
    LCDOut $FE,$83,"AMPERIMETRO"

Programa:
    ADCIn 0,Valor_ADC
    Amperes = ((30 * Valor_ADC) / 1024)
    LCDOut $FE,$C4,Dec2 Amperes," Amps."
    GoTo    Programa


    End
El voltaje de referencia que debe ser de 1.98 V, lo puedes obtener con un CI TL431 y un potenciómetro como divisor de tensión.
 
:unsure: no me cierra algo y debe de ser por eso que estoy trabado como puerta con cerrojo o burro empacado :LOL:
por que implementas 0.066 (uV o mV?) ... yo implemente0.66 ... por ahí veo que arranca parte de mi problema... y el otro gran problema que tengo, es que yo me encerre con lo que dice la hoja de dato, que la salida es de 0-5Vcc, o sea, 5Vcc para 30Amp y 2,3Vcc para 0Amp y 0Vcc para -30Amp
Voy a quedarme un buen rato interpretando tu ejemplo y ver si puedo abrir un poco la mente... que brona cuando me trabo :(
Millon de gracias :aplauso: (y) ... termino y subo resultados ;)

EDIT: me parecia que no me cerraba algo, mirá, esta es la grafica que muestra la curva de la salida segun la corriente que pasa por el hall

In_Out_ASC712.JPG
Voy a jugar con tu ejemplo para ver si puedo hacer magia :) En este caso, podria usar referencia 5Vcc, verdad?
 
Última edición:
¿Por qué implementas 0.066 (uV o mV)?
Yo implementé 0.66. Por ahí veo que arranca parte de mi problema.
Yo sólo tomé como referencia los 66 mV que mencionaste.
La tensión de salida proporcional en el sensor de 30Amp, es de 66mV por cada Ampere.
0.66 V, son 660 mV. y 0.066 V, son 66 mV.

Basándome en eso fue que realicé la fórmula.
Si el voltaje de salida es lineal, no hay problema, pero si no lo es, será necesario realizar una tabla para ir tomando valores.
 
me paree que la slaida no es lineal... o por lo menos eso estoy viendo en proteus... Creo que me voy a inclinar por invertir las siguientes horas en una tabla con lookup como bien vos decis... me voy a quedar pelado, eso ponele la firma jajajajaja Gracias amigazo, ahora veo como arrancar de cero...tendria que borrar todo lo que hice para no perderme, equivocarme y arrancare de cero
 
:unsure: sigo dando vueltas como una calesita por que me di cuenta que yo estoy dividiendo por 1024 (supuestamente 5Vcc), siendo que el sensor la señal es de 2.5 a 5Vcc para corrientes positivas de 0 a 30Amp... si yo lo sigo interpretando de la misma manera que antes, si no mal interpreto, estaria metiendo todos los valores enteros dentro del 1024, cuando justamente los valores mas bajos corresponderian a 0-2.4Vcc, o sea, corriente negativa (ejemplo -30Amp)... Como yo necesito solo la parte positiva, tengo que ver como separar las lecturas mayores a 2.5Vcc y de ahi buscarle la vuelta para la transformacion... :unsure: Toy muy errado? :rolleyes: acepto un cachetazo :LOL:
 
Al ver la siguiente gráfica, me parece que existen más de los 1.98 V que supuestamente se obtendrían al sensar 30 amperes.
Gráfica Sensed Current.jpg
Sensar 0 Amperes está por los 2.5 V, mientras que 30 amperes está casi por los 4.5 V.

¿Ya realizaste pruebas en físico con el sensor para ver que valores arroja?
 
Al ver la siguiente gráfica, me parece que existen más de los 1.98 V que supuestamente se obtendrían al sensar 30 amperes.
Sensar 0 Amperes está por los 2.5 V, mientras que 30 amperes está casi por los 4.5 V.

¿Ya realizaste pruebas en físico con el sensor para ver que valores arroja?

Lo estoy por encargar porque me pareció un muy buen precio (99$, o sea, 10 dolares aproximadamente) en cuanto a funcionalidad, tamaño y para la infinidad de proyectos que lo podría meter (si es que puedo llegar a entender como usarlo :LOL:)

Igualmente, por lo que vi, hay algo de desinformación al respecto.
La hoja de datos dice una cosa, en varios foros y google otras tantas y más o menos, sólo concuerda con la hoja de datos de los valores del sensor si le coloco una corriente variable.

Estaba justamente perdiendo el tiempo en una tabla que pensé que era la solución.
Suena gracioso, pero estaba en el arenero escribiendo una desparramada y de repente me pasó algo por la cabeza y arranqué a escribir unas lineas, pero después me di cuenta que seguía co la misma idea del principio y tendría el mismo problema. :rolleyes:

---------- Actualizado después de 3 horas ----------

No entiendo dónde estoy aplicando mal mis matemáticas. :LOL:
El primer error que noté, es que si entran 5V (4,98Vcc), en el micro se lee ValorADC=1003 como máximo y en 0V=511
Ahí seguro le estoy errando en la configuración del puerto.

El tema está en que estoy viendo de hacerlo trabajar de esta manera y no me cierra.
Como tengo que trabajar entre 512 y 1024, lo que hago es restar ambos y lo divido por la cantidad de pasos (30Amp=30pasos), dándome como resultado la supuesta sensibilidad, o dicho en otra forma, la tensión que varía entre paso y paso (1,71v)

(1024 - 512)=513 / 30 =17.1 = 1,71v por Amp

Hasta acá en una hoja con lápiz cuaja la idea:

(ValorADC - Offset)/ sensibilidad * pasos

Pero llevarlo al plano real está siendo todo un fastidio. No me da para nada el valor que tendría que darme. :((n)


Código:
DEFINE OSC 4
@ DEVICE pic16F877A
@ DEVICE pic16F877A, WDT_OFF
@ DEVICE pic16F877A, PWRT_On
@ DEVICE pic16F877A, PROTECT_OFF

DEFINE LCD_DREG      PORTD    
DEFINE LCD_DBIT      4        
DEFINE LCD_RSREG  PORTD    
DEFINE LCD_RSBIT  2    
DEFINE LCD_EREG      PORTD    
DEFINE LCD_EBIT   3        
DEFINE LCD_BITS      4    
DEFINE LCD_LINES  2

Define    ADC_BITS    10             ' Establece el número de bits en el resultado
Define    ADC_CLOCK    3             ' Ajuste el reloj de origen (rc=3)
Define    ADC_SAMPLEUS    50          ' Establezca el tiempo de muestreo en uS 

INTCON=%10100001           
TMR0=0 
T2CON = %00000110
PR2=124     

CMCON=7

ADCON1=%10000010
TRISA=%000001
TRISB=%11111111
TRISC=%01111011
TRISD=%00000000     


AUX var word 
AMP var word
ValorADC var word
Offset con 512               

;ON INTERRUPT GoTo ATENCION
;********************************************************************
;Configuro como valor offset 511 que representa supuestamente el valor 2.49V-0A
;para sacar la escala, resto la lecura maxima con la lectura minima y la divido
;por los pasos
; (1024 - 512)=513 / 30 =17.1 = 1,71v por Amp  
;Supuestamente entonces, para hacer la lectura tendria que:
;(ValorADC - Offset)/ sensibilidad * pasos 
; y no me da para nada... #@¬€<*n¨*^[]&¬¬!!!!!! 
;********************************************************************
LCDOUT $fe,1
Inicio:

pause 200
aDCIN 0, ValorADC
AMP = (ValorADC - offset) * 17 /513
AUX = (ValorADC - Offset) /513         ;una prueba alternativa que tampoco me dá


LCDOUT $FE,$80,"A=",dec AMP,".",dec1 amp," ADC=",dec ValorADC
LCDOUT $FE,$C0,"A=",dec Aux,".",dec1 aux
goto inicio


End

;----------------------------------------------------------------
;----------------------------------------------------------------

;*****************************************************************
;++++++++++++++++++++++++ INTERRUPCION +++++++++++++++++++++++++++
;*****************************************************************

DISABLE
ATENCION:
        

INTCON.2=0    
RESUME
ENABLE

END
;*****************************************************************
;*****************************************************************
:unsure:
La salida es lineal, al parecer.
 
Última edición por un moderador:
Cada paso del ADC a 10 bits con VRef+ en 5 V y VRef- en 0V, es cada 0.00488 V (4.88 mV.)

Pero si el ACS712 con 0 Amperes tiene 2.5 V como salida, entonces la lectura del ADC será de 512. (La mitad)
Eso se tendrá que descontar para que con 2.5 V, la lectura en 0 Amperes muestre 0.

Prueba así, pero recuerda que el valor mínimo de entrada al ADC son 2.5 V y el máximo 4.5 V.
PHP:
; Declaración de variables:
Valor_ADC   Var Word
Amperes     Var Byte

Inicio:
    Define ADC_BITS 10      ; 10 bits de resolución
    ADCON1 = %10000101      ; Just. Der. Canales 0,1, VRef+ AN3

Inicia_LCD:
    LCDOut $FE,$83,"AMPERIMETRO"

Programa:
    ADCIn 0,Valor_ADC
    Amperes = (30 * (Valor_ADC - 512) / 439) ; 439 = Valor por paso en 4.5 V. (0.00439 V.)
    LCDOut $FE,$C4,Dec2 Amperes," Amps."
    GoTo    Programa


    End
Este programa usa el pin RA3 (AN3/VRef+) en donde deberás establecer la tensión de referencia.
Coloca un potenciómetro y fija un valor alrededor de 4.88 V para realizar la prueba.

Algo así: ACS712-30A Test.jpg
 
Última edición:
Con la referencia mejoro mucho, tenes razon; Ahí logre hacer algo que se aproxima un poquito mas, pero estoy viendo que lo voy a tener que hacer fisicamente si o si para ver si no es la libreria de proteus lo que no me cierra con exactitud (estoy dudando de los pasos)...

Código:
DEFINE OSC 4
@ DEVICE pic16F877A
@ DEVICE pic16F877A, WDT_OFF
@ DEVICE pic16F877A, PWRT_On
@ DEVICE pic16F877A, PROTECT_OFF

DEFINE LCD_DREG      PORTD    
DEFINE LCD_DBIT      4        
DEFINE LCD_RSREG  PORTD    
DEFINE LCD_RSBIT  2    
DEFINE LCD_EREG      PORTD    
DEFINE LCD_EBIT   3        
DEFINE LCD_BITS      4    
DEFINE LCD_LINES  2


INTCON=%10100001           
TMR0=0 
T2CON = %00000110
PR2=124     

CMCON=7
TRISB=%11111111
TRISC=%01111011
TRISD=%00000000     
PARAR         VAR PORTB.3
BOTON_MAS     VAR PORTB.4
BOTON_MENOS   VAR PORTB.5
BOTON_ENTER    VAR PORTB.6
BOTON_MENU     VAR PORTB.7

Valor_ADC   Var Word
Amperes     Var Byte 
AMP var word              
Mamp var word
;ON INTERRUPT GoTo ATENCION

Inicio:
Define ADC_BITS 10      ; 10 bits de resolución
ADCON1 = %10000101      ; Just. Der. Canales 0,1, VRef+ AN3
    
Programa1:
    LCDOut $FE,1
    ADCIn 0,Valor_ADC
    Amp = (30 * (Valor_ADC - 512) / 439) 
    gosub limites       
    LCDOut $FE,$80,Dec Amp,".",dec1 mamp," Amps"
    LCDOut $FE,$C0, dec valor_adc 
    pause 100
    GoTo Programa1      

Limites:
    if amp > 0 and amp < 1023 then   ; anti desborde
    amp = Amp-1
    mamp = amp>> 1 +1 
    if Valor_ADC < 512 then
    mAmp = 0
    endif
    endif
    if Valor_ADC < 512 then         ;para ignorar valores negativos
    Amp = 0
    endif
    if Valor_ADC > 1022 then        ;para limitar el maximo
    Amp = 30
    endif
     
    return

End

;----------------------------------------------------------------
;----------------------------------------------------------------

;*****************************************************************
;++++++++++++++++++++++++ INTERRUPCION +++++++++++++++++++++++++++
;*****************************************************************

DISABLE
ATENCION:
        

INTCON.2=0    
RESUME
ENABLE

END
;*****************************************************************
;*****************************************************************
:unsure: si no puedo sacarle un mejor margen a los mA... tendre que hacer una tabla al parecer :rolleyes:
 
acá logre mejorarlo un poco sin la referencia de tension ...

Código:
DEFINE OSC 4
@ DEVICE pic16F877A
@ DEVICE pic16F877A, WDT_OFF
@ DEVICE pic16F877A, PWRT_On
@ DEVICE pic16F877A, PROTECT_OFF

DEFINE LCD_DREG      PORTD    
DEFINE LCD_DBIT      4        
DEFINE LCD_RSREG  PORTD    
DEFINE LCD_RSBIT  2    
DEFINE LCD_EREG      PORTD    
DEFINE LCD_EBIT   3        
DEFINE LCD_BITS      4    
DEFINE LCD_LINES  2
;INTCON=%10100001           
;TMR0=0 
;T2CON = %00000110
;PR2=124     
;CMCON=7
DEFINE    ADC_BITS    10        
DEFINE    ADC_CLOCK    3        
DEFINE    ADC_SAMPLEUS    50
ADCON1=%10001110 
TRISB=%11111111
TRISC=%01111011
TRISD=%00000000     

PARAR         VAR PORTB.3
BOTON_MAS     VAR PORTB.4
BOTON_MENOS   VAR PORTB.5
BOTON_ENTER    VAR PORTB.6
BOTON_MENU     VAR PORTB.7

Valor_ADC   Var Word
AMP         var word              
mA          var byte
;ON INTERRUPT GoTo ATENCION

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

Inicio:
   LCDOut $FE,1
   ADCIN 0,valor_adc  
   LCDOut $FE,$80,"ADC =",dec valor_adc
   amp=((valor_adc-511)*100)/139   ;511 es el punto minimo y 139 el valor del paso en mA
   mA=amp//10
   amp=amp/10
   LCDOUT $FE,$C0,"Amp=",dec amp,",",dec mA
   pause 100
   goto inicio 

End

;----------------------------------------------------------------
;----------------------------------------------------------------

;*****************************************************************
;++++++++++++++++++++++++ INTERRUPCION +++++++++++++++++++++++++++
;*****************************************************************

DISABLE
ATENCION:
        

INTCON.2=0    
RESUME
ENABLE

END
;*****************************************************************
;*****************************************************************

ASC712_16F877A.JPG

lo que no me cierra, es que para que el programa me de un valor aproximado con esa libreria, eh tenido que colocar en el valor del paso el 139 (el doble y un poco mas de los 66mV que dice la hoja de datos)... asi que tendre que esperar a tener el sensor en mis manos para ver realmente de cuanto es el salto.
 
No cuando inicia asigna el codigo ascii a eprom1 como lo tienes, el que parece ser 48 necesitas quitar las comillas asi:
Código:
n1 var byte
eprom1 var byte

eprom1=0
[COLOR="red"]'aqui siiii... eprom1 vale 0[/COLOR]
PAUSE 100
[COLOR="blue"]'no tiene sentido que antes declares a eprom1=0 si haces la lectura de la eeprom[/COLOR]
READ 0, eprom1
[COLOR="red"]'aqui si no se ha grabado la eeprom con n1 , eprom1 vale 255[/COLOR]
IF eprom1=255 THEN grabar_clave
GOTO Bienvenida

grabar_clave:
[COLOR="Red"]??? aqui a n1 nunca le dices cuanto vale?[/COLOR]
Write 0, n1
pause 10

' debes poner una pausa de 10ms para que complete la grabacion

siempre entra al iniciar porque la memoria por defecto esta en 255 (FF)

Hola amigo. muchas gracias por esta aclaración. Si yo hubiese sabido que la eprom por defecto al inicarse vale 255 (FF) no hubiera preguntado. Ahora todo está claro. Es más. teniendo la teoría que me dijiste, veo (e hice pruebas) que no importa que valor tiene eprom1, por que siempre al iniciarse se escribirá 255 y por lo tanto se ejecutara´"grabar_clave". Luego ya no valdrá 255 y se ejecutará "Bienvenido". Tambien gracias por el dato de darle una pausa de 10ms después del WRITE. Saludos.
 
como es el codigo de interrupcion por timer en el pic 18f4550 ya vengo buscando horas en internet pero no hay mucho material del tema sino que hay mucho info de interrupcion externa
 
¿De cuál timer? El PIC18F4550 tiene 4 timers, 1 de 8 bits y 3 de 16 bits.
El código también depende de lo que quieras hacer.

:unsure: Interesante. Cómo se nota que no toqué la hoja de datos.
Ahora implemento el buscador de la página para ver si encuentro más información del 18F4550.
Estoy dejando de lado los 16F876 y 16F877 para adentrarme a esta nueva familia con USB, ya que me di cuenta que varios fuses que usaba anteriormente, no me funcionan con el 18F2550/4550 :cry:
 
Última edición por un moderador:
Estoy dejando de lado los 16F876 y 16F877 para adentrarme a esta nueva familia con USB, ya que me di cuenta que varios fuses que usaba anteriormente, no me funcionan con el 18F2550/4550
Así es. Los fuses de la palabra de configuración para los PIC18F2550/4550, son diferentes a los PIC16.
Sobre todo por la configuración del prescaler, aunque algunos PIC de nueva generación como los PIC12F18XX y PIC16F18XX, también lo tienen.
No para el uso del módulo USB con oscilador a cristal, sino para elevar la frecuencia del oscilador interno.

Otra cosa a tener en cuenta, es que usan dos líneas o más para la palabra de configuración.
 
si, tenes razon... practicamente estoy re-arrancando de cero por que son similares, pero :no: iguales....
lo poco que hice, me base en fuses de ejemplo y no preste atencion... vamos a ver si me pongo al dia relativamente rapido, por que tengo varias cositas para hacer y me esta gustando bastante este micro. Saludos y veremos con que dolor de cabezo me vuelvo :LOL:
 
Hola, saludos
hace unos meses atras D@rkbytes me ayudo con un contador ascendente, descendente,de 1 a 6 y viceversa, a partir de ahi logre hacerle unas pequeñas modificaciones a mi gusto, lo que no he podido lograr es hacer que muestre un 0 si le pongo un 0 en el pin RA2 del pic 16f84A independientemente del numero en que este la cuenta, no logro dar la instruccion correcta, pido el favor alguien me ayude con esto y disculpen por haber solicitado ayuda en este tema ya que asm desde cero hace 6 meses nadie escribe, adjunto archivos el .bas que he manipulado y el original sin modificacion, Gracias.
 

Adjuntos

  • Archivos.rar
    25.1 KB · Visitas: 47
Última edición:
Lo que no he podido lograr, es hacer que muestre un 0 si le pongo un 0 en el pin RA2 del PIC16F84A independientemente del número en que esté la cuenta, no logro dar la instrucción correcta.
No funciona porque la sentencia la estás colocando al inicio y no dentro del bucle.
Eso hará que sólo sea leída cuando se inicia el programa y no constantemente.

Un cambio para eso, sería así:
PHP:
Digito Var Byte

Inicio:
    TRISB = $80
    PORTB = 6
    Clear
        
MainLoop:

    IF PORTA.2 = 0 then
        PORTB = $3F
    EndIf 
      
    If PORTA.1 = 1 Then
        Digito = Digito + 1
        If Digito > 6 Then
            Digito = 6
        Endif
        GoSub BCD7Segs
        While PORTA.1 = 1: Wend
    EndIf

    If PORTA.0 = 1 Then
        If Digito = 0 Then
            Digito = 0
        Endif
        Digito = Digito - 1
        GoSub BCD7Segs
        While PORTA.0 = 1: Wend
    EndIf
    
    Goto MainLoop
    
BCD7Segs:
    LookUp Digito,[6,$5B,$4F,$66,$6D,$7D], PORTB
    Return

     End
Disculpen por haber solicitado ayuda en este tema ya que asm desde cero hace 6 meses nadie escribe.
Este es el tema correcto porque los archivos que adjuntas están escritos en PIC Basic Pro.
No están escritos en ensamblador y tampoco con Proton IDE como mencionas, por el archivo "asm proton ide.txt"

Ahora hay que aclarar algo importante.
El código que expuse hace lo que quieres, pero retiene el conteo.
Si se presionan los botones para incrementar o decrementar, el conteo continuará desde donde se quedó.

Si al mostrar un 0 en el display deseas que el conteo también sea 0 nuevamente, el código deberá ser diferente.

Con respecto a los temas sin actividad:
Si puedes preguntar en temas que tengan más de 6 meses sin actividad.
Lo que no debes hacer, es responder a consultas que ya fueron tratadas en su tiempo o escribir mensajes con contenido irrelevante que no aporten al tema.
 
Última edición:
Gracias, D@rkbytes, me guie con el codigo que envio, logre acomodarlo con un poco de trabajo, y ya hace lo que quiero que haga, contar del 1 al 6 y viceversa y al recibir un pulso negativo en RA2 colocar un cero sin tener en cuenta el numero mostrado y vuelve a empezar, de todas maneras se puede aumentar del 0 al 9, aqui lo pongo de pronto a alguien le interese y le sirva para aplicarlo en algun proyecto, Saludos.
 

Adjuntos

  • Archivos.rar
    16.4 KB · Visitas: 43
Atrás
Arriba