THREE DIGIT COUNTER 
and 
A-to-D CONVERTER

P9

Even though the PIC LAB-1 board has only a single display, a 3-digit counter can be displayed by flashing the 3 digits then pausing before displaying again. Ws have produced up to 5 digits in this manner and the counter is fairly easy to read once you realize how the digits are displayed. 
The 3-digit counter serves to show how the limitations of a single display can be overcome. 
We have produced another project 5x7 Display, using a single display to produce a 3 and 5-digit counter. It uses a matrix of LEDs to produce a single digit and the same principle of "flashing" has been used. 
Multiple-digit counters can be called "tally counters" for recording the total production of a particular item. Some items can be weighed to get a quantity but this takes time and expense. 
The simplest is to have a detector (plus electronics) record each item as it is being produced and keep track of the total. This can be used to "back up" the values obtained from individually weighed amounts. 
A tally counter will only need to be read once a day and the single digit can be a low-cost way of showing this value. 
The program can be designed to accept a code from a set of buttons so that operators cannot access the data.  It's a security measure to avoid theft and fraud. 

THE PROGRAM
A 3-digit counter requires three files to hold the "tally." Each digit is held in the lower "nibble" (a nibble is 4 bits).
These files are initially cleared so the readout is "000."
The first digit (actually the hundreds) is displayed then the display is cleared for a short time. This is repeated for the second and third digit. 
The display is then cleared for a longer period of time to indicate the end of the number. 
The routine is then repeated. 
Throughout the program, the input must be poled at (looked at) regular intervals. The most difficult part of the program is to place the button-instruction where it can be constantly executed by the micro. 
The only place is within the display routine.
The program takes about 1 second to display the three digits and in this time the button can be pressed 10 or more times. 
By placing the button instruction (BTFSS 05,0) in the display routine it is accessed every 2mS. 
You can press the button while the display is flashing and the program will increment the tally in the background. The result is very impressive. It appear that the program is down two things at the same time.
The circuit for the counter:

Here is the complete program:
 

                     ;3digit.asm
                     ;Project: 3 Digit Counter
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC

SetUp











Table











Clear





Display

Disp1






Disp2
DelA






Inc



















Main
















ORG 0
BSF 03,5
CLRF 06
MOVLW 01
MOVWF 05
BCF 03,5
CLRF 05
CLRF 1F
CLRF 11h
CLRF 12h
CLRF 13h
GOTO Main

ADDWF 02h,1
RETLW 3Fh
RETLW 06h
RETLW 5Bh
RETLW 4Fh
RETLW 66h
RETLW 6Dh
RETLW 7Dh
RETLW 07h
RETLW 7Fh
RETLW 6Fh

MOVLW 20h
MOVWF 0D
CLRF 06
CALL Disp1
RETURN

MOVLW 80h
MOVWF 0Ch
BTFSS 05,0
GOTO Disp2
BTFSC 1F,0
GOTO DelA
BSF 1F,0
CALL Inc
GOTO DelA
BCF 1F,0
NOP
DECFSZ 1A,1
GOTO DelA
DECFSZ 0C,1
GOTO Disp1
RETURN

INCF 11h,1
MOVLW 0A
XORWF 11h,0
BTFSS 03,2
RETURN
CLRF 11h
INCF 12h,1
MOVLW 0A
XORWF 12h,0
BTFSS 03,2
RETURN
CLRF 12h
INCF 13h,1
MOVLW 0A
XORWF 13h,0
BTFSS 03,2
RETURN
CLRF 13h
RETURN

MOVF 13h,0
CALL Table
MOVWF 06
CALL Display
CALL Clear
MOVF 12h,0
CALL Table
MOVWF 06
CALL Display
CALL Clear
MOVF 11h,0
CALL Table
MOVWF 06
CALL Display
CLRF 06
CALL Clear
CALL Clear
CALL Clear
GOTO Main

END
;This is the start of memory for the program.
;Go to Bank 1
;Make all port B output
;Load W with 0000 0001
;Make RA0 input
;Go to Bank 0 - the program memory area.
;Clear portA
;Clear the button-press file
;Clear 'units' file
;Clear 'tens' file
;Clear 'hundreds' file


;Add W to the Program Counter to create a jump.
;0    format= gfedcba
;1    If any table value has a leading letter, it must be
;2    preceded with a "0."   E.g: 0A3h, 0FFh, 0CCh
;3
;4
;5
;6
;7
;8
;9



;Clear the display





;Test the input line on port A
;Button not pressed
;Button pressed first time?
;Button already pressed 
;Set button-press flag
;Button pressed. Increment count









;Increment units.
;Has count reached ten?
;Compare file 11h with ten
;Check the zero flag in Status file
;Count has not reached ten
;Zero the units file
;Increment tens.
;Has count reached ten?
;Compare file 12h with ten
;Check the zero flag in Status file
;Count has not reached ten
;Zero the tens file
;Increment hundreds.
;Has count reached ten?
;Compare file 13h with ten
;Check the zero flag in Status file
;Count has not reached ten
;Zero the hundreds


;Copy 'hundreds' into W

;Display the number


;Copy 'tens' into W

;Display the number


;Copy 'units' into W

;Display the number

;Blank the display




;Tells assembler end of program

It is very easy to change the program to create a 4 or 5 digit display. A new file (say 14h) must be added. It is cleared in SetUp and added to Inc sub-routine (by copying instructions) to produce thousands. It is then added to Main by copying a small block of instructions in Main and changing the values as needed.

ANALOGUE TO DIGITAL (A-to-D)
The analogue input on the PIC LAB-1 reads a value of resistance connected to the "pot" terminals.


Connecting a potentiometer to the PIC LAB-1

The value of resistance can be almost any value from 10 ohms to 1M (and higher).
But it's a little bit more complex than simply fitting an unknown value of resistance and  showing the value on the display. 
The program has to be "set up."
It works like this:
The first step is to decide on the maximum resistance you wish to measure. Suppose it is 1,000 ohms.  
The input line is capable of dividing this value into 256 parts (say 250 parts). This means the resolution is 1,000/250 = 4 ohms 
If the maximum value is 10,000 ohms, the resolution is 40 ohms. 
If the maximum resistance is 100,000 ohms, the resolution is 400 ohms and for 1M it is 4k. 
This is the resolution if we use a single file to hold the result. We can get a better resolution if two files are used (256 x 256 = 65,535 parts) and this will be a future experiment. 
For now, we will keep it simple and use a single file.  
In the first case, a filled count-file (containing 250) must indicate 1,000 on the display. To perform the conversion, the transfer from the count-file to the display files (files 11h, 12h and 13h) is carried out 4 times. In other words the 250 is multiplied by 4 to get 1,000. 
The pot included in the kit is 10,000 ohms. To convert 1,000 to 10,000 a zero is added to the display. 
Connect the pot to the project, burn the following program into the PIC chip and rotate the pot. You will be able to read the value on the display (from nearly zero ohms to about 10k).
The lowest digit ("0") is added to the 3-digit counter (shown above) to get 4 digits.
 

                     ;Pot1.asm
                     ;Project: Potentiometer to PIC LAB-1
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC

SetUp







Table











Clear





Delay







Inc



















Look

Look2






Main




















Main1





Main2

Main3




Main4
ORG 0
BSF 03,5
CLRF 06
MOVLW 10h
MOVWF 05
BCF 03,5
CLRF 05
GOTO Main1

ADDWF 02h,1
RETLW 3Fh
RETLW 06h
RETLW 5Bh
RETLW 4Fh
RETLW 66h
RETLW 6Dh
RETLW 7Dh
RETLW 07h
RETLW 7Fh
RETLW 6Fh  

MOVLW 80h
MOVWF 1B
CLRF 06
CALL Delay
RETURN

NOP
NOP
DECFSZ 1A,1
GOTO Delay
DECFSZ 1B,1
GOTO Delay
RETURN

INCF 11h,1
MOVLW 0A
XORWF 11h,0
BTFSS 03,2
RETURN
CLRF 11h
INCF 12h,1
MOVLW 0A
XORWF 12h,0
BTFSS 03,2
RETURN
CLRF 12h
INCF 13h,1
MOVLW 0A
XORWF 13h,0
BTFSS 03,2
RETURN
CLRF 13h
RETURN

CLRF 0C
BSF 06,7
NOP
INCF 0C,1
BTFSC 05,4
GOTO Look2
BCF 06,7
RETURN

MOVF 13h,0
CALL Table
MOVWF 06
CALL Delay
CALL Clear
MOVF 12h,0
CALL Table
MOVWF 06
CALL Delay
CALL Clear
MOVF 11h,0
CALL Table
MOVWF 06
CALL Delay
CALL Clear
MOVLW 3Fh
MOVWF 06
CALL Delay
CALL Clear
CALL Delay
CALL Delay
CLRF 11h
CLRF 12h
CLRF 13h
CALL Look
MOVLW 04
MOVWF 0F
MOVF 0C,0
MOVWF 0E
DECFSZ 0E,1
GOTO Main4
DECFSZ 0F,1
GOTO Main2
GOTO Main
CALL Inc
GOTO Main3

END
;This is the start of memory for the program.
;Go to Bank 1
;Make all Port B output
;Load W with 0001 0000
;Make RA4 input
;Go to Bank 0 - the program memory area.
;Clear PortA


;Add W to the Program Counter to create a jump.
;0    format= gfedcba
;1    If any table value has a leading letter, it must be
;2     preceded with a "0." E.g: 0A3h, 0FFh, 0CCh
;3
;4
;5
;6
;7
;8
;9



;Clear the display



;Create 300mS delay







;Increment units.
;Has count reached ten?
;Compare file 11h with ten
;Check the zero flag in Status file
;Count has not reached ten
;Zero the units file
;Increment tens.
;Has count reached ten?
;Compare file 12h with ten
;Check the zero flag in Status file
;Count has not reached ten
;Zero the tens file
;Increment hundreds.
;Has count reached ten? ;Compare file 13h with ten
;Check the zero flag in Status file
;Count has not reached ten
;Zero the hundreds



;Count-down file 
;Take cap HIGH


;Is input LOW?

;Take cap low 


;Copy 'hundreds' into W

;Display the number


;Copy 'tens' into W

;Display the number


;Copy 'units' into W

;Display the number



;Output "0"

;Blank display


;Clear 'units' file
;Clear 'tens' file
;Clear 'hundreds' file

;Four loops of "Count to display" 

;Copy 0C to W
;Move W to 0E
;Move count-down file to display-value




;Create display value


;Tells assembler end of program

You will find the readout starts at 0000 and goes as high as approx 8760. It does not show 9999.
What is the problem?
This is where the answer gets technical, but very interesting. 
The time-delay circuit made up of the 100n and 10k resistor in series, has a time-constant of approx 1,100mS to charge the 100n when the resistance is 10k. This is not the normal "time-constant" covered in a normal RC or time-delay circuit, where the capacitor charges to approx 66% of its maximum value. In our case the capacitor charges until the lower threshold of the input to the PIC detects a LOW. You can select any "cut-off point" or "trigger point" for any determination, providing the value can be repeated. 
The "Look" circuit, looks at the input for the 4 instructions between "Look2" and GOTO Look2. These instructions take 5uS. 256 loops of 5uS = 1280uS. At a time-interval of 1,100uS the loop counter is 220. The program multiplies this by 4 to get 8800. 
 
HOW CAN THE READING BE ALTERED?
This highlights two factors. 
At an execution speed of one million instructions per second, the instruction-speed is not high enough to allow the programmer to adjust the length of the loop. In other words, instructions cannot be added or deleted to make minor increments or decrements. If we remove the NOP in the loop, the counter will reach 256 when the resistance is about 8 or 9k and this will produce a false reading on the other side of the range.  
The only thing we can do is match the circuit to the program. 
If the capacitor is increased in value by about 10 times (to 1u), the charge-time will increase and this will give the programmer the ability to adjust the length of the loop. 
 
ALTERNATIVE DETECTION METHOD
There is another method of detecting the value of resistance using only a single input/output line. The circuit is shown below. It does not matter if the pot is above or below the capacitor.


Measuring resistance with a single in/out line

The program is not as fast as the method above and will result in a slower "up-date." To achieve the same resolution as above, the charging capacitor will have to be a large value (1u or higher) to allow the loop-counter to fill completely.  
The program starts with an uncharged capacitor and the "drive-line" goes high for a short period of time. The line is then changed to an input (a sense-line) and the voltage measured. The input line can only detect a change from a LOW to a HIGH. If it does not detect a HIGH, the line is changed back to an output ("drive-line") and the cycle is repeated. In this way the capacitor is gradually charged. The line reversal takes a few microseconds and a delay (a NOP) should be placed in the program to allow the line to settle from one state to the other before a reading is made. 
The program for the "look" section is as follows. To take advantage of the TRIS function, you must know the state of the other lines on Port B, if you don't want them to change state during this operation. 

LookB
LookC



CLRF 0C
MOVLW 00h
TRIS 06

BSF 06,7
INCF 0C,1
MOVLW 80h
TRIS 06
NOP
BTFSS 06,7
GOTO LookC
RETURN
;Count-down file 

;Make the top line an output. (0000 0000)
;Take cap HIGH


;Make the top line an input. (1000 0000)
;Create a delay before reading input
;Is input HIGH?
;No
;Yes.

This method takes 10uS per loop and our previous method takes 5uS. 
This is not a problem with our simple experiments. It simply means the update time is longer. 
To get the count-file to completely fill using the 10uS loop, the capacitor will have to be larger and this will also increase the update time.

To Top