Læse RC-signal med PIC16F628 (Læst 2926x)

Offline Leonard

  • Spændingsdeler
  • ****
  • Indlæg: 67
  • Antal brugbare Indlæg: 2
    • Vis profil
    • RC Trucks
Læse RC-signal med PIC16F628
« Dato: Marts 24, 2014, 08:15:30 »
Jeg har nu søgt og gennemlæst utallige tråde og manualer på engelsk og troede faktisk jeg havde fattet det.
Men det har jeg så ikke.
Jeg har Microchips MP Lab IDE at programmere i og Pic Kit 2 til at få koden ud i pic-kredsen. Det virker fint.
Jeg troede at jeg kunne bruge PulsIn instruksen til at læse pulsens længde fra en servo-kanal fra en rc-modtager. Denne instruks findes så tilsyneladende ikke i PIC16F628.
Jeg er helt blank nu.

Pulsen varierer fra 1 mS til 2 mS og jeg vil gerne kunne aflæse om pulsen er i den ene ende, i midten eller i den anden ende og ud fra det, så gå til en subrutine.

Nogen der kan hjælpe med et kode forslag ?
Thomas Leonard

 

Offline gerd

  • µProcessoren
  • *
  • Indlæg: 898
  • Antal brugbare Indlæg: 95
    • Vis profil
    • Hjemmeside med nogle af mine projekter
Sv: Læse RC-signal med PIC16F628
« Svar #1 Dato: Marts 24, 2014, 20:06:42 »
Hej Thomas,

en PIC16F628 har en Input Capture Module. Det er perfekt til det.

- Konfigurer Timer 1 med f. eks. 10µs tælle frekvens.
- Konfigurer Input Capture så at du har en capture event med interrupt ved næste positive kant.
- I interrupt gemme capture værdien A og skifte til negative kant.
- I næste interrupt gemme capture værdien B og B-A er impulsvarigheden



Kode:
void init() 
{
    initTimer1For10usClock();
    initInputCaptureForRisingEdge();
    initInputCaptureInterrupt();
}

void IRQ (void)
{
    //It was an input capture interrupt
    if (PIR1bits.CCP1IF == 1)
    {
        // Reset the input capture flag
        PIR1bits.CCP1IF=0;
  
        if (CCP1M0 == 1)  //was it a rising edge ? 
        {
            posEdgeTimestamp = CCPR1L; // use only the low byte.
            CCP1M0 = 0; // switch to falling edge
        }
        else
        {
            negEdgeTimestamp = CCPR1L; // use only the low byte.
            CCP1M0 = 1; // switch to rising edge
            pulseDuration = negEdgeTimestamp - posEdgeTimestamp; // Calculate the pulse duration
        }
}


gerd
« Senest Redigeret: Marts 25, 2014, 10:14:45 af gerd »

 

Offline Leonard

  • Spændingsdeler
  • ****
  • Indlæg: 67
  • Antal brugbare Indlæg: 2
    • Vis profil
    • RC Trucks
Sv: Læse RC-signal med PIC16F628
« Svar #2 Dato: Marts 24, 2014, 20:19:48 »
Det lyder jo meget godt, men den kode ligner ikke noget pic-assembler ...
Thomas Leonard

 

Offline gerd

  • µProcessoren
  • *
  • Indlæg: 898
  • Antal brugbare Indlæg: 95
    • Vis profil
    • Hjemmeside med nogle af mine projekter
Sv: Læse RC-signal med PIC16F628
« Svar #3 Dato: Marts 24, 2014, 20:53:34 »
Hej,
nej det er C. Microchip har en gratis C-compiler. http://www.microchip.com/pagehandler/en_us/devtools/mplabxc/

Men du kan også laver det i assembler. Jeg kan skrive i morgen en assembler eksempel. Men jeg kan ikke teste det.

gerd

 

Offline gerd

  • µProcessoren
  • *
  • Indlæg: 898
  • Antal brugbare Indlæg: 95
    • Vis profil
    • Hjemmeside med nogle af mine projekter
Sv: Læse RC-signal med PIC16F628
« Svar #4 Dato: Marts 25, 2014, 12:26:30 »
3 variabler:
Kode:
TIMESTAMP_A        equ    0x20
TIMESTAMP_B        equ    0x21
TIME_BETWEEN_AB    equ    0x22

Reset og interrupt vector:
Kode:
;***********************************************
; Reset vector
;***********************************************
    org     0x0000
    goto    RESET

;***********************************************
; IRQ vector
;***********************************************
    org     0x0004
    goto    IRQ

Initialisering:
Kode:
;***********************************************
; Reset and initialization
;***********************************************
    org     0x0005
RESET
    bsf     STATUS,RP0       ; change to bank 1
    bsf     TRISB,3          ; Input capture is PORT RB3, so set RB3 as input
    bcf     STATUS,RP0       ; change to bank 0

    movlw   B'00000001'      ; Enable Timer1 with 1:1 prescaler
    movwf   T1CON            ; so it counts every 400ns, at fosc = 10MHz
    
    movlw   B'00000101'      ; input capture every every rising edge
    movwf   CCP1CON
    
    movlw   B'11000000'      ; Enable all un-masked (Peripheral)-interupts
    movwf   INTCON
    bsf     STATUS,RP0
    movlw   B'00000100'      ; Enable CCP1-Interupt
    movwf   PIE1
    bcf     STATUS,RP0
    
    clrf    TIME_BETWEEN_AB ;

Din main loop:   
Kode:
    
;***********************************************
; Main loop
;***********************************************    
MAIN

; The result (pulse duration) is in TIME_BETWEEN_AB.
; TIME_BETWEEN_AB is the difference between the HIGH bytes of the timer.
; So if it counts with 2.5MHz or 400ns (10MHz system clock) the count value after
; 1.5ms is 3750. And the high byte of 3750 is round about 15.
; 
; 1.0ms: TIME_BETWEEN_AB is 10
; 1.5ms: TIME_BETWEEN_AB is 15
; 2.0ms: TIME_BETWEEN_AB is 20

    goto MAIN

Interrupt:
Kode:
;***********************************************
; Input capture interrupt to detect RC signals
;***********************************************    
IRQ
    movwf   W_TEMP          ;copy W to temp register, could be in either bank
    swapf   STATUS,W        ;swap status to be saved into W
    bcf     STATUS,RP0      ;change to bank 0 regardless of current bank
    movwf   STATUS_TEMP     ;save status to bank 0 register
    
    
    btfsc   CCP1CON,0       ; was it a positive or negative edge ?
    goto    INCAP_RISING    ; CCP1CON.0 = 1 <==> rising edge
    goto    INCAP_FALLING   ; CCP1CON.0 = 0 <==> falling edge    
    
    
INCAP_RISING
    movf    CCPR1H,W        ; save the CCPR1H register 
    movwf   TIMESTAMP_A     ; into the variable TIMESTAMP_A
    bcf     CCP1CON,0       ; switch to falling edge
    goto    IRQ_END
    
INCAP_FALLING
    movf    CCPR1H,W        ; save the CCPR1H register 
    movwf   TIMESTAMP_B     ; into the variable TIMESTAMP_B
    
    movf    TIMESTAMP_A,W   ; subtract B-A
    subwf   TIMESTAMP_B,W   ; subtract B-A     
    movwf   TIME_BETWEEN_AB ; TIME_BETWEEN_AB = TIMESTAMP_B-TIMESTAMP_A
    bsf     CCP1CON,0       ; switch to rising edge
    goto    IRQ_END

IRQ_END    
    movwf   W_TEMP          ;copy W to temp register, could be in either bank
    swapf   STATUS,W        ;swap status to be saved into W
    bcf     STATUS,RP0      ;change to bank 0 regardless of current bank
    movwf   STATUS_TEMP     ;save status to bank 0 register    

    retfie

 

Offline Leonard

  • Spændingsdeler
  • ****
  • Indlæg: 67
  • Antal brugbare Indlæg: 2
    • Vis profil
    • RC Trucks
Sv: Læse RC-signal med PIC16F628
« Svar #5 Dato: Marts 27, 2014, 15:12:03 »
Tak for svarene og eksemplerne, jeg roder lidt videre med det.
Thomas Leonard

 

Offline Leonard

  • Spændingsdeler
  • ****
  • Indlæg: 67
  • Antal brugbare Indlæg: 2
    • Vis profil
    • RC Trucks
Sv: Læse RC-signal med PIC16F628
« Svar #6 Dato: April 15, 2014, 10:18:19 »
Når jeg søger på Google efter noget med Pickredse og RC-signaler, så dukker der hele tiden en kommando op, der hedder PulsIn.
Jeg kan dog ikke lure om det er afhængigt af hvilken kreds der bruges eller om det er det værktøj, der bruges til at programmere med.

Jeg har Microchips MPLab og en PicKit2, men der synes jeg ikke jeg kan finde PulsIn.

Det virker bare en hel del enklere at bruge en enkelt kommando end de lange script som Gerd har skrevet herover.
Thomas Leonard

 

Offline gerd

  • µProcessoren
  • *
  • Indlæg: 898
  • Antal brugbare Indlæg: 95
    • Vis profil
    • Hjemmeside med nogle af mine projekter
Sv: Læse RC-signal med PIC16F628
« Svar #7 Dato: April 15, 2014, 12:19:35 »
Hej Thomas,

>der hedder PulsIn.
Det er en PicBasic Pro kommando.

 

Offline Leonard

  • Spændingsdeler
  • ****
  • Indlæg: 67
  • Antal brugbare Indlæg: 2
    • Vis profil
    • RC Trucks
Sv: Læse RC-signal med PIC16F628
« Svar #8 Dato: April 15, 2014, 14:58:25 »
Tak for det hint, det er jo genialt, basic lærte jeg i 1981 på ZX81 og det har jeg meget nemmere ved at programmere i end C+ eller assembler.
Det vil jeg kigge på og afprøve.
Thomas Leonard