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.
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
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
MOVLW 01 ;Load W with 0000 0001
MOVWF 05 ;Make RA0 input
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 05 ;Clear portA
CLRF 1F ;Clear the button-press file
CLRF 11h ;Clear 'units' file
CLRF 12h ;Clear 'tens' file
CLRF 13h ;Clear 'hundreds' file
GOTO Main
Table ADDWF 02h,1 ;Add W to the Program Counter to create a jump.
RETLW 3Fh ;0 format= gfedcba
RETLW 06h ;1 If any table value has a leading letter, it must be
RETLW 5Bh ;2 preceded with a "0." E.g: 0A3h, 0FFh, 0CCh
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6
RETLW 07h ;7
RETLW 7Fh ;8
RETLW 6Fh ;9
Clear MOVLW 20h
MOVWF 0D
CLRF 06 ;Clear the display
CALL Disp1
RETURN
Display MOVLW 80h
MOVWF 0Ch
Disp1 BTFSS 05,0 ;Test the input line on port A
GOTO Disp2 ;Button not pressed
BTFSC 1F,0 ;Button pressed first time?
GOTO DelA ;Button already pressed
BSF 1F,0 ;Set button-press flag
CALL Inc ;Button pressed. Increment count
GOTO DelA
Disp2 BCF 1F,0
DelA NOP
DECFSZ 1A,1
GOTO DelA
DECFSZ 0C,1
GOTO Disp1
RETURN
Inc INCF 11h,1 ;Increment units.
MOVLW 0A ;Has count reached ten?
XORWF 11h,0 ;Compare file 11h with ten
BTFSS 03,2 ;Check the zero flag in Status file
RETURN ;Count has not reached ten
CLRF 11h ;Zero the units file
INCF 12h,1 ;Increment tens.
MOVLW 0A ;Has count reached ten?
XORWF 12h,0 ;Compare file 12h with ten
BTFSS 03,2 ;Check the zero flag in Status file
RETURN ;Count has not reached ten
CLRF 12h ;Zero the tens file
INCF 13h,1 ;Increment hundreds.
MOVLW 0A ;Has count reached ten?
XORWF 13h,0 ;Compare file 13h with ten
BTFSS 03,2 ;Check the zero flag in Status file
RETURN ;Count has not reached ten
CLRF 13h ;Zero the hundreds
RETURN
Main MOVF 13h,0 ;Copy 'hundreds' into W
CALL Table
MOVWF 06 ;Display the number
CALL Display
CALL Clear
MOVF 12h,0 ;Copy 'tens' into W
CALL Table
MOVWF 06 ;Display the number
CALL Display
CALL Clear
MOVF 11h,0 ;Copy 'units' into W
CALL Table
MOVWF 06 ;Display the number
CALL Display
CLRF 06 ;Blank the display
CALL Clear
CALL Clear
CALL Clear
GOTO Main
END ;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.
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
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all Port B output
MOVLW 10h ;Load W with 0001 0000
MOVWF 05 ;Make RA4 input
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 05 ;Clear PortA
GOTO Main1
Table ADDWF 02h,1 ;Add W to the Program Counter to create a jump.
RETLW 3Fh ;0 format= gfedcba
RETLW 06h ;1 If any table value has a leading letter, it must be
RETLW 5Bh ;2 preceded with a "0." E.g: 0A3h, 0FFh, 0CCh
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6
RETLW 07h ;7
RETLW 7Fh ;8
RETLW 6Fh ;9
Clear MOVLW 80h
MOVWF 1B
CLRF 06 ;Clear the display
CALL Delay
RETURN
Delay NOP ;Create 300mS delay
NOP
DECFSZ 1A,1
GOTO Delay
DECFSZ 1B,1
GOTO Delay
RETURN
Inc INCF 11h,1 ;Increment units.
MOVLW 0A ;Has count reached ten?
XORWF 11h,0 ;Compare file 11h with ten
BTFSS 03,2 ;Check the zero flag in Status file
RETURN ;Count has not reached ten
CLRF 11h ;Zero the units file
INCF 12h,1 ;Increment tens.
MOVLW 0A ;Has count reached ten?
XORWF 12h,0 ;Compare file 12h with ten
BTFSS 03,2 ;Check the zero flag in Status file
RETURN ;Count has not reached ten
CLRF 12h ;Zero the tens file
INCF 13h,1 ;Increment hundreds.
MOVLW 0A ;Has count reached ten? ;Compare file 13h with ten
XORWF 13h,0 ;Check the zero flag in Status file
BTFSS 03,2 ;Count has not reached ten
RETURN ;Zero the hundreds
CLRF 13h
RETURN
Look CLRF 0C ;Count-down file
BSF 06,7 ;Take cap HIGH
Look2 NOP
INCF 0C,1
BTFSC 05,4 ;Is input LOW?
GOTO Look2
BCF 06,7 ;Take cap low
RETURN
Main MOVF 13h,0 ;Copy 'hundreds' into W
CALL Table
MOVWF 06 ;Display the number
CALL Delay
CALL Clear
MOVF 12h,0 ;Copy 'tens' into W
CALL Table
MOVWF 06 ;Display the number
CALL Delay
CALL Clear
MOVF 11h,0 ;Copy 'units' into W
CALL Table
MOVWF 06 ;Display the number
CALL Delay
CALL Clear
MOVLW 3Fh
MOVWF 06 ;Output "0"
CALL Delay
CALL Clear ;Blank display
CALL Delay
CALL Delay
Main1 CLRF 11h ;Clear 'units' file
CLRF 12h ;Clear 'tens' file
CLRF 13h ;Clear 'hundreds' file
CALL Look
MOVLW 04 ;Four loops of "Count to display"
MOVWF 0F
Main2 MOVF 0C,0 ;Copy 0C to W
MOVWF 0E ;Move W to 0E
Main3 DECFSZ 0E,1 ;Move count-down file to display-value
GOTO Main4
DECFSZ 0F,1
GOTO Main2
GOTO Main
Main4 CALL Inc ;Create display value
GOTO Main3
END ;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.
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.
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 CLRF 0C ;Count-down file
LookC MOVLW 00h
TRIS 06 ;Make the top line an output. (0000 0000)
BSF 06,7 ;Take cap HIGH
INCF 0C,1
MOVLW 80h
TRIS 06 ;Make the top line an input. (1000 0000)
NOP ;Create a delay before reading input
BTFSS 06,7 ;Is input HIGH?
GOTO LookC ;No
RETURN ;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.
Quick Links
Legal Stuff
Social Media