# PIC pulse problem

Discussion in 'Embedded Systems and Microcontrollers' started by SnydeMz, Nov 7, 2010.

1. ### SnydeMz Thread Starter New Member

Nov 7, 2010
4
0
Im a computer engineer who recently started working with PIC microchip controllers. Im currently working on a project that involves taking signals from the odometer sensor in the instrumentation panel of a car and based on those signals gives high signals on 4 different outputs of the controller. I have a complex problem involving the above. The sensor gives an output in terms of pulses...5 pulses represent a kilometer travelled. I want to measure distance travelled and based on this give output signals representing distance. For 3000km this gives 600 pulses, 5000km gives 1000 pulses, 10000km gives 2000 pulses and 15000km gives 3000 pulses. I have written code for the chip such that an input representing say 3000km(600 pulses) gives an output of a high signal on one of the output pins and so on and so forth for the rest of the distances. Now the challenge is making sure that the chip is able to distinguish between the number of pulses. How can this be achieved electronically...I have heard the term 'digital frequency divider' in some forums but have no idea what that is. please someone shed some light on this issue.

2. ### mik3 Senior Member

Feb 4, 2008
4,846
69
Use one input pin to read the pulses. According to your description, each pulse corresponds to 200m. Thus, each time the PIC receives a pulse increment a variable, which represents distance traveled, by 200.

3. ### SnydeMz Thread Starter New Member

Nov 7, 2010
4
0
i get that i can use an input pin for the pulses..if i increment a variable.. i will have to write the code such that when the variable is incremented such that it hits a certain value , say if the variable is incremented until it is equal to 15000(for case 1:3000km are repd by 15000 pulses) then output a high signal on one input pin. This would be easy if I was using C or any other language...How do I achieve this in assembly? Specifically im using the PIC16F88/PIC16F84.

Sep 7, 2009
2,796
595
5. ### thatoneguy AAC Fanatic!

Feb 19, 2009
6,349
731
Is there anything preventing you from using C?

Sourceboost C has a free compiler (for non commercial use), as well as a couple other compilers. There are limitations on them, but for your application, you wouldn't be near those limits.

6. ### mik3 Senior Member

Feb 4, 2008
4,846
69
There is a compare command, which can compare two values (registers), in assembly too.

7. ### Markd77 Senior Member

Sep 7, 2009
2,796
595
I've stripped out a lot of unnecessary code and added a little just before "loop" to preset the counter. It should go to ";TMR1 interrupt" after 15000 pulses.
I haven't tested it, it's for the wrong PIC and there is a lot of unnecessary code left, but the general idea is there.

The PIC16F88 would be fine, I wouldn't reccomend the PIC16F84 because it's old, expensive and doesen't have a timer1.

Code ( (Unknown Language)):
1.
2.         LIST P=16F628, R=DEC
3.
4.         #include "P16F628.INC"
5.
6.         __config  _INTRC_OSC_NOCLKOUT & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_ON
7.
8.         CBLOCK 0x20             ;variables
9.
10.     count
11.     count2
12.
13.     eetemp
14.     PORTAbuffer
15.     PORTBbuffer
16.     iTMR0countH
17.     iTMR0countM
18.     iTMR0countL                ;TMR0 value
19.     TMPH
20.     TMPL
21.     TMR1MSB
22.     period
23.     dutysamplecountH
24.     dutysamplecountL
25.     duty_H
26.     duty_L
27.     indutyH                    ;samples of input to get avg duty
28.     indutyM
29.     indutyL
30.     prescale
31.     usartdone
32.     freqdone
33.     usartrxcount
34.     usartrxbuf:10
35.     digitcount
36.     setstate                    ;0
37.     H_byte
38.     M_byte
39.     L_byte
40.     H_temp
41.     L_temp
42.     R0
43.     R1
44.     R2
45.     R3
46.     temp
47.         ENDC
48.
49.     CBLOCK 0x70
50.     W_TEMP
51.     STATUS_TEMP
52.     ENDC
53.
54.
55.
56.     ORG    0x000
57.     goto init
58.
59.
60.     org 0x004    ;interrupt goes here
61.     MOVWF W_TEMP ; Copy W to TEMP register,
62.     SWAPF STATUS, W ; Swap status to be saved into W
63.     MOVWF STATUS_TEMP ; Save status to STATUS_TEMP register
64.     BCF STATUS, RP0                ;bank 0
65.     btfss INTCON, T0IF                ;timer0 interrupt flag
66.     goto notTMR0
67.
68. notTMR0
69.
70.     btfss PIR1, TMR1IF
71.     goto notTMR1
72. ;TMR1 interrupt
73.
74.
75.
76.
77.     ;insert code here
78.
79.
80.
81.     bcf T1CON, TMR1ON            ;stop timer to safely write
82.     movlw 0xC5                :load with 0xC567 (=0xFFFF - decimal 15000)
83.     movwf TMR1H
84.     movlw 0x67
85.     movwf TMR1L
86.     bsf T1CON, TMR1ON            ;restart timer
87.     bcf PIR1, TMR1IF
88.
89.     goto endint
90.
91. notTMR1
92.
93.
94. endint
95.      ; should configure Bank as required
96.      ;
97.     SWAPF STATUS_TEMP,W     ; Swap nibbles in STATUS_TEMP register
98.     ; and place result into W
99.     MOVWF STATUS             ; Move W into STATUS register
100.     ; (sets bank to original state)
101.     SWAPF W_TEMP, F         ; Swap nibbles in W_TEMP and place result in W_TEMP
102.     SWAPF W_TEMP, W         ; Swap nibbles in W_TEMP and place result into W
103.
104.     retfie
105.
106.
107. init
108.
109.     CLRWDT ;Clear WDT and
110.     ;prescaler
111.     BSF STATUS, RP0
112.     MOVLW b'11011111' ;Select TMR0, and internal clock source
113.     MOVWF OPTION_REG
114.     BCF STATUS, RP0
115.
116.
117.     movlw 7
118.     movwf CMCON             ;comparators off
119.     movlw b'00000000'       ;porta outputs
120.     movwf PORTA
121.
122.     movlw b'00000100'       ; RB2(TX)=1 others are 0
123.     movwf PORTB
124.
125.     bsf STATUS,RP0          ; page 1
126.
127.     movlw B'00100001'
128.     movwf PIE1                ;USART receive and TMR1 int enabled
129.
130.     movlw 0x00
131.     movwf TRISA             ; portA all pins output
132.
133.     movlw b'11110010'       ; RB7-RB4 and RB1(RX)=input, others output
134.     movwf TRISB
135.
136.
137.
138.
139.     movlw 0x19                  ; 9600 baud, no Parity, 1 stop bit
140.     movwf SPBRG
141.     movlw b'00100100'
142.     movwf TXSTA
143.     bcf STATUS,RP0
144.     movlw b'10010000'
145.     movwf RCSTA
146.     clrf count
147. wait
148.     decfsz count,F            ;pause just in case
149.     goto wait
150.
151.
152.
153.     movlw b'11100000'        ;timer0, peripherals and global interrupts on
154.     movwf INTCON
155.
156.     clrf setstate
157.     clrf usartdone
158.     clrf period
159.     clrf duty_H
160.     clrf duty_L
161.     clrf prescale
162.     incf prescale, F            ;prescale = 1
163.     movlw 0x04
164.     movwf iTMR0countH
165.     movlw 0xD1
166.     movwf iTMR0countM
167.     movlw 0x85
168.     movwf TMR0
169.     movlw d'64'
170.     movwf dutysamplecountH
171.     clrf dutysamplecountL
172.     movlw b'00001111'
173.     movwf T1CON
174.     bsf STATUS, RP0                    ;setup PWM
175.     clrf PR2
176.     bcf STATUS, RP0
177.     clrf CCPR1L
178.     movlw b'00001100'
179.     movwf CCP1CON
180.     bsf STATUS, RP0
181.     bcf TRISB, 3
182.     bcf STATUS, RP0
183.     movlw b'00000100'
184.     movwf T2CON
185.
186.     bcf T1CON, TMR1ON            ;stop timer to safely write
187.     movlw 0xC5                :load with 0xC567 (=0xFFFF - decimal 15000)
188.     movwf TMR1H
189.     movlw 0x67
190.     movwf TMR1L
191.     bsf T1CON, TMR1ON            ;restart timer
192.
193.
194. loop
195.
196.     ;optional code here
197.
198.
199.     goto loop
200.
201.
202.
203.     END

Last edited: Nov 10, 2010
8. ### eblc1388 AAC Fanatic!

Nov 28, 2008
1,543
104
3000Km or 15000Km is a long distance for a car to travel and it will certainly takes a long time.

Make sure that the power supply is never turn off or the PIC never reset during the travel or else

This is how I will be tackling the problem.

Usually in this type of situation the value represent "total distance travel" will be saved to a non-volatile memory location inside the PIC and if the difference between the new/saved value is more than 4(1Km traveled), then the non-volatile location is updated accordingly.

The value is also updated to the non-volatile memory if it remains stable for a long time, say after 1 minutes.

On PIC power up, a check is done to see if a CLEAR key is also being pressed. If so, the memory will be cleared. Otherwise the stored value is loaded into the current memory for subsequent increment.

I would usually keep seven extra copies of the total distance traveled in the EEPROM in a circular array, each differs in value normally by 5 or less. As a result I can then discard/repair any bad data on power up if the value is out side this range. The value of these eight copies are read and the highest one is loaded as the current value. The next EEPROM write will update the next location of the circular array.

When a new pulse has come in via the odometer, the PIC memory value is immediately incremented and a one minute timer started/restarted. The timing counts would be decremented on every timer interrupt until it reaches zero where then a time_expired flag will be set.The time_expire flag will never get set if the pulses are coming in more frequent than one per minute.

Here is a flowchart of the program, created using the free Diagram Designer.

• ###### Odometer.png
File size:
17.2 KB
Views:
33
Last edited: Nov 11, 2010