Simulating a Camshaft Encoder signal

Discussion in 'Embedded Systems and Microcontrollers' started by Kefka, Aug 1, 2011.

  1. Kefka

    Thread Starter New Member

    Aug 1, 2011
    2
    0
    Hey guys, i need some advice, i have to simulate a Camshaft encoder signal which is 24 pulses plus 1 whit the 16f876, heres the signal on the scope:

    [​IMG]

    I thought of using TMR0 interrupt and then in the ISR Change the conf. of PWM then going back to the main and so on, but I'm having all sort of problems whit the timing, like this:

    [​IMG]
    I was wondering if you have any tips or ideas as to how to simulate this signal.

    Thanks in advance.​
     
  2. kavli

    New Member

    Aug 1, 2011
    23
    2
    Have you disabled interrupts when you're modifying the PWM register?
    Apart from that, I think I'd have solved it by just using one timer and a counter for locating the marker.
    When hitting the marker, skip two toggles of the output.

    -- K
     
  3. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    I don't know if this is happening here but if the pulse is shorter than one instruction cycle then MPLAB SIM won't show it, but it will happen in real life.
     
  4. Kefka

    Thread Starter New Member

    Aug 1, 2011
    2
    0
    ok guys i manage to get rid of the blank spaces but still dont know how to make it count 23 pulses the double pulse, heres the code thus far:


    INT_VAR UDATA_SHR
    w_temp RES 1 ; variable used for context saving
    status_temp RES 1 ; variable used for context saving

    UDATA_SHR

    ;****************************************************

    RESET CODE 0x0101
    pagesel MAIN
    goto MAIN

    ;****************************************************
    INT_VECTOR CODE 0x0004 ; interrupt vector location

    INTERRUPT
    ORG 0X04

    movwf w_temp ; save off current W register contents
    movf STATUS,w ; move status register into W register
    movwf status_temp ; save off contents of STATUS register
    bcf INTCON,T0IF

    movlw B'01111100' ; period
    movwf PR2
    bcf STATUS,RP0
    movlw B'00111110' ; setting the duty cycle time to 50%
    movwf CCPR1L
    bsf CCP1CON,5
    bcf CCP1CON,4
    bsf STATUS,RP0
    bcf TRISC,2 ; pin 2 of port c is an output
    bcf STATUS,RP0
    movlw B'00000101'
    movwf T2CON
    bsf CCP1CON,3
    bsf CCP1CON,2


    movf status_temp,w ; retrieve copy of STATUS register
    movwf STATUS ; restore pre-isr STATUS register contents
    swapf w_temp,f
    swapf w_temp,w ; restore pre-isr W register contents
    movlw 1<<GIE|1<<T0IE
    movwf INTCON

    retfie ; return from interrupt

    ;****************************************************
    __config 0x393A
    ORG 0X00
    GOTO MAIN

    code
    MAIN


    bcf STATUS,RP0
    movlw b'110000100'
    banksel OPTION_REG
    movwf OPTION_REG
    clrf PORTA ;clear content of port A
    clrf PORTB ;clear content of port B
    clrf PORTC ;clear content of port C
    bsf STATUS,RP0 ;change to bank 1
    movlw B'11111111'
    movwf TRISA ;set port A as input
    clrf TRISB ;set port B as output
    clrf TRISC
    movlw 1<<GIE|1<<T0IE
    movwf INTCON



    movlw B'11111001' ; period
    movwf PR2
    bcf STATUS,RP0
    movlw B'00111110' ; setting the duty cycle time to 25%
    movwf CCPR1L
    bsf CCP1CON,5
    bcf CCP1CON,4
    bsf STATUS,RP0
    bcf TRISC,2 ; pin 2 of port c is an output
    bcf STATUS,RP0
    movlw b'01001101'
    movwf 12h
    bsf CCP1CON,3 ;configuring CCP1 module for PWM operation
    bsf CCP1CON,2

    goto MAIN

    END
     
  5. kavli

    New Member

    Aug 1, 2011
    23
    2
    Ok. I still see you're using the PWM path. I don't think it's a totally wrong path, but I don't think it's the easiest and most straight forward solution.

    Here is some pseudocode for a state-machine driven approach, using only timer0.
    Not tested, but should generally work.

    The reason the counter is counting from 46 instead of 23 is that the state-machine is clocked in half-phase increments.

    -- K

    Code ( (Unknown Language)):
    1.  
    2. # states:
    3. # 1 - notch high
    4. # 2 - notch low
    5. # 3 - double notch
    6.  
    7. init:
    8.   mask interrupts
    9.   set counter = 46
    10.   set state = 1
    11.   set nextstate = 1
    12.   setup timer0
    13.   enable interrupts
    14.  
    15. on_timer_interrupt:
    16.   mask interrupts
    17.   if state == 1:
    18.     set output = 1
    19.     counter--
    20.     if counter == 0:
    21.       nextstate = 3
    22.     else
    23.       nextstate = 2
    24.   elif state == 2:
    25.     set output = 0
    26.     counter--
    27.   elif state == 3:
    28.     counter = 46
    29.     nextstate = 1
    30.   else:
    31.     # Not reached
    32.  
    33.   state = nextstate
    34.  
    35.   reset timer0
    36.   reenable interrupts
    37.  
    38. main:
    39.   init()
    40.  
     
  6. kavli

    New Member

    Aug 1, 2011
    23
    2
    ...there should, of course be a:
    Code ( (Unknown Language)):
    1.  
    2.    elif state == 2:
    3.      set output = 0
    4.      counter--
    5. +    nextstate = 1
    6.  
    -- K
     
Loading...