Adhiriendo un ADC virtual (multitasking) a un PIC16F628A
Posted by nelsonlombardo on May 29, 2011
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!




Fernando_León Medina said
Lo voy a practicar, ello solucionaría un problemita, un desafío.
Muchas gracias
ferlemega
nelsonlombardo said
Éxitos entonces!
Saludos
Fabián said
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!
nelsonlombardo said
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.