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