PIC pulse problem

Thread Starter

SnydeMz

Joined Nov 7, 2010
5
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.
 

mik3

Joined Feb 4, 2008
4,843
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.
 

Thread Starter

SnydeMz

Joined Nov 7, 2010
5
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.
 

thatoneguy

Joined Feb 19, 2009
6,359
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.
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.
 

Markd77

Joined Sep 7, 2009
2,806
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.

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

Rich (BB code):
        LIST P=16F628, R=DEC  

        #include "P16F628.INC"  

        __config  _INTRC_OSC_NOCLKOUT & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_ON

        CBLOCK 0x20             ;variables
    
    count
    count2

    eetemp
    PORTAbuffer
    PORTBbuffer
    iTMR0countH
    iTMR0countM
    iTMR0countL                ;TMR0 value
    TMPH
    TMPL
    TMR1MSB
    period
    dutysamplecountH
    dutysamplecountL
    duty_H
    duty_L
    indutyH                    ;samples of input to get avg duty
    indutyM
    indutyL
    prescale
    usartdone
    freqdone
    usartrxcount
    usartrxbuf:10
    digitcount
    setstate                    ;0 
    H_byte
    M_byte
    L_byte
    H_temp
    L_temp
    R0
    R1
    R2
    R3
    temp
        ENDC

    CBLOCK 0x70
    W_TEMP
    STATUS_TEMP
    ENDC



    ORG    0x000           
    goto init


    org 0x004    ;interrupt goes here
    MOVWF W_TEMP ; Copy W to TEMP register,
    SWAPF STATUS, W ; Swap status to be saved into W
    MOVWF STATUS_TEMP ; Save status to STATUS_TEMP register
    BCF STATUS, RP0                ;bank 0
    btfss INTCON, T0IF                ;timer0 interrupt flag
    goto notTMR0

notTMR0

    btfss PIR1, TMR1IF
    goto notTMR1
;TMR1 interrupt




    ;insert code here 



    bcf T1CON, TMR1ON            ;stop timer to safely write
    movlw 0xC5                :load with 0xC567 (=0xFFFF - decimal 15000)
    movwf TMR1H
    movlw 0x67
    movwf TMR1L
    bsf T1CON, TMR1ON            ;restart timer
    bcf PIR1, TMR1IF

    goto endint

notTMR1

    
endint
     ; should configure Bank as required
     ;
    SWAPF STATUS_TEMP,W     ; Swap nibbles in STATUS_TEMP register
    ; and place result into W
    MOVWF STATUS             ; Move W into STATUS register
    ; (sets bank to original state)
    SWAPF W_TEMP, F         ; Swap nibbles in W_TEMP and place result in W_TEMP
    SWAPF W_TEMP, W         ; Swap nibbles in W_TEMP and place result into W

    retfie


init

    CLRWDT ;Clear WDT and
    ;prescaler
    BSF STATUS, RP0
    MOVLW b'11011111' ;Select TMR0, and internal clock source
    MOVWF OPTION_REG
    BCF STATUS, RP0


    movlw 7
    movwf CMCON             ;comparators off
    movlw b'00000000'       ;porta outputs
    movwf PORTA

    movlw b'00000100'       ; RB2(TX)=1 others are 0
    movwf PORTB

    bsf STATUS,RP0          ; page 1

    movlw B'00100001'
    movwf PIE1                ;USART receive and TMR1 int enabled    

    movlw 0x00
    movwf TRISA             ; portA all pins output

    movlw b'11110010'       ; RB7-RB4 and RB1(RX)=input, others output
    movwf TRISB




    movlw 0x19                  ; 9600 baud, no Parity, 1 stop bit        
    movwf SPBRG
    movlw b'00100100'       
    movwf TXSTA  
    bcf STATUS,RP0
    movlw b'10010000'       
    movwf RCSTA
    clrf count
wait  
    decfsz count,F            ;pause just in case
    goto wait

  

    movlw b'11100000'        ;timer0, peripherals and global interrupts on
    movwf INTCON

    clrf setstate
    clrf usartdone
    clrf period
    clrf duty_H
    clrf duty_L
    clrf prescale
    incf prescale, F            ;prescale = 1
    movlw 0x04
    movwf iTMR0countH
    movlw 0xD1
    movwf iTMR0countM
    movlw 0x85
    movwf TMR0
    movlw d'64'
    movwf dutysamplecountH
    clrf dutysamplecountL
    movlw b'00001111'
    movwf T1CON
    bsf STATUS, RP0                    ;setup PWM
    clrf PR2
    bcf STATUS, RP0
    clrf CCPR1L
    movlw b'00001100'
    movwf CCP1CON
    bsf STATUS, RP0
    bcf TRISB, 3
    bcf STATUS, RP0
    movlw b'00000100'
    movwf T2CON

    bcf T1CON, TMR1ON            ;stop timer to safely write
    movlw 0xC5                :load with 0xC567 (=0xFFFF - decimal 15000)
    movwf TMR1H
    movlw 0x67
    movwf TMR1L
    bsf T1CON, TMR1ON            ;restart timer


loop

    ;optional code here


    goto loop



    END
 
Last edited:

eblc1388

Joined Nov 28, 2008
1,542
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.

 

Attachments

Last edited:
Top