Adhiriendo un ADC virtual (multitasking) a un PIC16F628A

Para los que se quejan que no tienen un conversor analógico digital en este pic, acá les dejo un algoritmo que hace uso de los módulos comparadores y de tensión de referencia para lograr hacer la conversión de una señal lenta a una longitud de 4bits. No es mucho, pero para ciertas aplicaciones sobra.

Utilizando la teoría de aproximación de registros sucesivos que hacen uso algunos conversor ADC comerciales (antes), diseñe este algoritmo escrito en forma multitasking (máquinas de estado cooperativo). El algoritmo:

;------------------------------------------------------------------------------
; The ADC procedure is a pseudo-ADC. The basic idea is use two modules: vref.
; and comparator. Now using multitasking...
Prc_Adc1                          ; Procedure to work on ADC pseudo-function.-
    btfss    Sts_Analog1,0        ; Status = 0 ?
    goto     Lbl_Sts_Ana1_1       ; Move to next state...
    return                        ; Idle task.-
Lbl_Sts_Ana1_1                    ; 
    btfss    Sts_Analog1,1        ; Status = 1 ?
    goto     Lbl_Sts_Ana1_2       ; Move next state...
    clrf     Flg_Ana1             ; Clear flag.- 
    movlw    0x08                 ; Is like make Steps equal to zero.-
    movwf    Steps_Ana1           ; Clear steps.-
    bcf      STATUS,C             ; Clean up carry.-
    rlf      Sts_Analog1,F        ; Assign next state.-
    return                        ; Return to scheduler.-
Lbl_Sts_Ana1_2                    ; 
    btfss    Sts_Analog1,2        ; Status = 2 ?
    goto     Lbl_Sts_Ana1_3       ; Move next state...
    movlw    0x08                 ; Put the correct value of resolution.-
    movwf    Ref_Ana1             ; Voltage reference.-
    movwf    Dref_Ana1            ; Voltage "resolution".-
    bcf      STATUS,C             ; Clean up carry.-
    rlf      Sts_Analog1,F        ; Assign next state.-
    return                        ; Return to scheduler.-
Lbl_Sts_Ana1_3                    ;
    btfss    Sts_Analog1,3        ; Status = 3 ?
    goto     Lbl_Sts_Ana1_4       ; Move next state...
    bcf      CMCON,CIS            ; Bit 3, select the comparator (analog 1).- 
    call     Delay_10             ; Delay of 10 micro-seconds.-
    movlw    0xA0                 ; Enable vref and low range.-
    iorwf    Ref_Ana1,W           ; Charge the voltage reference.-
    bsf      STATUS,RP0           ; Bank 1.-
    movwf    VRCON                ; Effective.-
    call     Delay_10             ; Delay of 10 micro-seconds.-
    bcf      STATUS,RP0           ; Bank 0.-
    btfss    CMCON,6              ; Check comparator.-
    goto     Lbl_Set_Ana1_1       ; Non subtraction.-
    movf     Steps_Ana1,W         ; Decrement mask.-
    subwf    Ref_Ana1,F           ; If Ref_Ana1 < then clear bit.-
Lbl_Set_Ana1_1                    ;
    bcf      STATUS,C             ; Clean up carry.-
    rrf      Steps_Ana1,F         ; Like Steps++.-
    bcf      STATUS,C             ; Clean up carry.-
    rlf      Sts_Analog1,F        ;
    return                        ; Return to scheduler.-
Lbl_Sts_Ana1_4                    ; 
    btfss    Sts_Analog1,4        ; Status = 4 ? 
    goto     Lbl_Sts_Ana1_5       ; Move next state...
    bcf      STATUS,C             ; Clean up carry.-
    rrf      Dref_Ana1,F          ; Dref / 2.-
    movf     Dref_Ana1,W          ; Inc. ref..-
    iorwf    Ref_Ana1,F           ; Ref = Ref + Dref.-
    bcf      STATUS,C             ; Clean up carry.-
    rlf      Sts_Analog1,F        ; Next state.-
    return                        ; Return to scheduler.-
Lbl_Sts_Ana1_5                    ;
    btfss    Sts_Analog1,5        ; Status = 5 ?
    goto     Lbl_Sts_Ana1_6       ; Move next state...
    movf     Steps_Ana1,W         ;
    xorlw    0x00                 ; Steps is finish?
    btfss    STATUS,Z             ;
    goto     Lbl_Set_Ana1_2       ; Steps < 5
    bcf      STATUS,C             ; Clean up carry.-
    rlf      Sts_Analog1,F        ;
    return                        ; Steps == 5
Lbl_Set_Ana1_2                    ;
    clrf    Sts_Analog1           ;
    bsf     Sts_Analog1,3         ; Pseudo-loop.-
    return                        ; Return to sheduler.-
Lbl_Sts_Ana1_6                    ;
    bsf     Flg_Ana1,0            ; Flag = UP.-
    clrf    Sts_Analog1           ;
    bsf     Sts_Analog1,1         ; Status = BEGIN.- 
    return                       ; End of Proc_Adc1.-
;------------------------------------------------------------------------------ 

Para poder utilizar el algoritmo es necesario declarar:

Sts_Analog1   equ 0x..
Flg_Ana1      equ 0x..
Steps_Ana1    equ 0x..
Dref_Ana1     equ 0x..
Ref_Ana1      equ 0x.. 

El algoritmo fue escrito para usarse en un proyecto que pronto voy a subir. Fue configurado suponiendo el uso de los cuatros comparadores multiplexados usando -V como Vref:

Conf_Comp                       ; Procedure to comparator configuration.-
    movlw   b'00000010'         ; Clear tmp.-
    movwf   CMCON               ;
    bsf     STATUS,RP0          ;
    bsf     VRCON,7             ; Enable voltage reference.-
    bsf     VRCON,5             ; Enable high range.-
    bcf     STATUS,RP0        ;
    return                      ; End of conf_comp

Bueno, algunos comentarios:

  • El procedimiento Delay10 es un retardo de 10 micro-segundos, deben construir según la velocidad de clock que esten utilizando.
  • Obviamente el no posee un método de hold&sample.
  • La velocidad cuando el código es denso es muy lento, deberán estudiar la cantidad de tiempo que le lleva la ejecución.
  • Es muy útil (a mi parecer) para situaciones dónde ser requiere sólo algunos niveles de discriminación. Por ejemplo, la bomba de presurización luego de una sisterna.
  • Es una atractiva forma de agregar un ADC, divertido de escribir, divertido de ver funcionar.

Espero que les sirva, en lo personal me ayudo y fue una buena solución al momento de implementar un ADC sencillo.

Happy hacking!

4 thoughts on “Adhiriendo un ADC virtual (multitasking) a un PIC16F628A

  1. Fernando_León Medina says:

    Lo voy a practicar, ello solucionaría un problemita, un desafío.
    Muchas gracias

    ferlemega

  2. Fabián says:

    Hola, es genial el trabajo que te tomaste. Me gustaría poder utilizarlo en un proyecto, pero no termino de entenderlo. Podrías darme un ejemplo de como adquirir un valor desde lo que vendría a ser el programa principal? desde ya, muchas gracias!

    • Hola Fabián, que bueno que te agrade. Entiendo que está complicado entenderlo, aparte está escrito el código con una técnica de multitasking llamada “máquinas de estado cooperativas”. Ahora estoy complicado con varios proyectos, pero pienso subir el proyecto original dónde se usa este código. De ahí tendrías un ejemplo bastante claro de cómo usarlo, eso espero. Prometo subirlo.
      Saludos,
      Nelson.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s