Vai al contenuto
PLC Forum


Misurare lunghezza impulsi con PICBasic


battlechess

Messaggi consigliati

Salve a tutti.

Sto cercando di relizzare un programma in pibasic per pic16f87x 20Mhz allo scopo di ricavare

alcuni tempi all'interno di un segnale. Nello specifico:

rilevare la durata di uno stato low sul pin RB0 (1=>0=>1) della durata di 24µs.

rilevare la durata di uno stato high (0=>1=>0), sempre sullo stesso pin, la cui durata

può variare da 512 a 1536µs.

tra uno stato high ed il successivo lo stato low ha una durata di 48µs

gli stati high sono in totale 60

memorizzare i tempi degli stati high ricavati nell'eeprom del pic.

Ho provato molti metodi tra cui rctime e pulsein ma il problema che ho riscontrato è

il timer che conta fino a 255 quindi, non riesco a risalire al valore esatto della durata

dell'impulso.

Cortesemente, potreste aiutarmi?

grazie a tutti

Link al commento
Condividi su altri siti


Questo è un classico problema da risolvere in Assembler. Devi gestire l'nterrupt sulla transizione 0==>1 di RB0 (INTCON <6> = 1). Nella gestione dell'interrupt fai partire TMR0, p.e., setti per la transizione 1==>0 (INTCON <6> = 0). Sul nuovo interrupt blocchi e leggi TMR0. Con questo rilevi il tempo di "high". Ripeti con fronti invertiti per misurare la durata di "low"

Link al commento
Condividi su altri siti

Se hai bisogno di piu' risoluzione , puoi usare il modulo comparatore CCP che sfrutta registri da 16bit e il timer 1 sempre a 16 bit.

Il problema e' che non so' se ci sono istruzioni gia' in basic ... non lo conosco.

Altro consiglio , cambia il titolo del 3d , perche " non ci riesco" non aiuta a capire di che cosa hai bisogno.

Modificato: da dlgcom
Link al commento
Condividi su altri siti

Salve a tutti!

Anche io dovrei fare la medesima cosa, ossia calcolare il tempo trascorso fra due impulsi provenienti da un encoder per poi calcolare il numero di giri del motore.

Io avevo pensato di programmare il pin RB0 come ingresso ad interrupt e programmare il TMR0 in modo che giri in Background ad una cadenza di circa 64uS. A questo punto TMR0 incrementerà un registro (Reg1)appunto ogni 64uS, su RB0 arriverà un interrupt dall'encoder che alzerà ad 1 e poi a 0 un flag.

Sul TRUE di questo flag memorizzo il valore di Reg1 su Reg2; sul FALSE del flag eseguo la differenza tra il valore corrente di Reg1 e Reg2.

A questo punto andrei ad eseguire i calcoli dovuti. Potrebbe andare bene secondo voi? Uso il linguaggio C.

Avrei un'altra domandina....

Perchè se programmo TMR0 per contare 2uS (che credo sia la min. temp.)mi manda in palla tutto?

Ciao Grazie!

Link al commento
Condividi su altri siti

Forse ti stai complicando la vita. Basta far partire TMR0 su un fronte e bloccarlo sull'altro. Con questa metodologia di fai un periodimtro con risoluzione eccellente.

Tieni presente che il periodimetro è ottimo per basse velocità, poi perde in precisione. L'algoritmo ideale prevede l'uso contemporaneo del periodimetro e del frequenzimetro, con scelta istantanea della misura più precisa.

Link al commento
Condividi su altri siti

Ho provato a mettere in pratica i vostri consigli ma almeno sul simulatore MPLab non funziona.

Potete cortesemente darmi una dritta dove è il baco? Ho rivisto il programma più volte ma non sono riuscito a trovare l'inghippo.

Grazie

T1CON=%00000000 'Timer1 reset

CCP1CON=%00000000

CCPR1L=0

CCPR1H=0

Speed var word

state var bit

TMR1L=0 ' Reset Timer

TMR1H=0 ' Remember Timer is OFF

pir1.2=0 ' Reset Capture Flag

pir1.0=0

CCP1CON = %00000101 'Trigger on Rising edge

' Interrupt

INTCON = %11000000 'General Interrupt Enable -

PIE1=%00101111

ON INTERRUPT GoTo interr

mainloop:

GoTo mainloop

'Gestione di Interrupt

interr:

'************************************

'Interrupt Speed High Pulse

If pir1.2=1 then

If state=0 then

T1CON.0=1 ' Enable Timer

CCP1CON = %00000101 ' Next trigger on Rising edge

pir1.2=0 ' Reset Capture Flag

state =1

else

Speed.lowbyte = CCPR1L

Speed.highbyte = CCPR1H

' Store the captured value in period variable

T1CON.0=0 ' Timer is OFF

CCP1CON=0 ' Capture is OFF

TMR1L=0 ' Reset Timer

TMR1H=0 ' Remember Timer is OFF

pir1.2=0 ' Reset Capture Flag

CCP1CON = %00000100 ' Next trigger is Falling edge

state=0

goto scrivi

endif

endif

gosub scrivi

Resume

scrivi:

disable interrupt

write 1,Speed.highbyte

write 2,Speed.Lowbyte

enable interrupt

resume

Link al commento
Condividi su altri siti

Il baco probabilmente sta nel picbasic. Prova a scrivere in assembler od in "C".

Potresti essere piu' chiaro riguardo al punto sopra?

Comunque anche se la cosa è del tutto sperimentale (sto facendo della gran didattica a casa)per informazione la frequenza degli impulsi non dovrebbe essere superiore ai 2Khz.

Link al commento
Condividi su altri siti

Ciao a Tutti,

non essendo un esperto di assembler per pic, di seguito allego il listato asm del programma convertito dal compilatore picbasic. Potreste gentilmente darci uno sguardo per verificare la correttezza?

Grazie anticipatamente

==============================================================

; PicBasic Pro Compiler 2.46, © 1998, 2005 microEngineering Labs, Inc. All Rights Reserved.

_USED EQU 1

INCLUDE "C:\PROGRA~1\MECANI~1\PBP246\16F877A.INC"

; Define statements.

#define CODE_SIZE 8

#define osc 20

RAM_START EQU 00020h

RAM_END EQU 001EFh

RAM_BANKS EQU 00004h

BANK0_START EQU 00020h

BANK0_END EQU 0007Fh

BANK1_START EQU 000A0h

BANK1_END EQU 000EFh

BANK2_START EQU 00110h

BANK2_END EQU 0016Fh

BANK3_START EQU 00190h

BANK3_END EQU 001EFh

EEPROM_START EQU 02100h

EEPROM_END EQU 021FFh

R0 EQU RAM_START + 000h

R1 EQU RAM_START + 002h

R2 EQU RAM_START + 004h

R3 EQU RAM_START + 006h

R4 EQU RAM_START + 008h

R5 EQU RAM_START + 00Ah

R6 EQU RAM_START + 00Ch

R7 EQU RAM_START + 00Eh

R8 EQU RAM_START + 010h

FLAGS EQU RAM_START + 012h

GOP EQU RAM_START + 013h

RM1 EQU RAM_START + 014h

RM2 EQU RAM_START + 015h

RR1 EQU RAM_START + 016h

RR2 EQU RAM_START + 017h

_Speed EQU RAM_START + 018h

PB01 EQU RAM_START + 01Ah

_PORTL EQU PORTB

_PORTH EQU PORTC

_TRISL EQU TRISB

_TRISH EQU TRISC

_Speed_LOWBYTE EQU _Speed

_Speed_HIGHBYTE EQU _Speed + 001h

#define _state PB01, 000h

#define _PIR1_2 PIR1, 002h

#define _PIR1_0 PIR1, 000h

#define _T1CON_0 T1CON, 000h

INCLUDE "INTHAND.MAC"

INCLUDE "C:\PROGRA~1\MECANI~1\PBP246\PBPPIC14.LIB"

MOVE?CB 000h, T1CON

MOVE?CB 000h, CCP1CON

MOVE?CB 000h, CCPR1L

MOVE?CB 000h, CCPR1H

MOVE?CB 000h, TMR1L

MOVE?CB 000h, TMR1H

MOVE?CT 000h, _PIR1_2

MOVE?CT 000h, _PIR1_0

MOVE?CB 005h, CCP1CON

MOVE?CB 0C0h, INTCON

MOVE?CB 02Fh, PIE1

ONINT?LL _interr, L00001

LABEL?L _mainloop

ICALL?L L00001

GOTO?L _mainloop

LABEL?L _interr

ICALL?L L00001

CMPNE?TCL _PIR1_2, 001h, L00002

ICALL?L L00001

CMPNE?TCL _state, 000h, L00004

ICALL?L L00001

MOVE?CT 001h, _T1CON_0

ICALL?L L00001

MOVE?CB 005h, CCP1CON

ICALL?L L00001

MOVE?CT 000h, _PIR1_2

ICALL?L L00001

MOVE?CT 001h, _state

ICALL?L L00001

GOTO?L L00005

LABEL?L L00004

ICALL?L L00001

MOVE?BB CCPR1L, _Speed_LOWBYTE

ICALL?L L00001

MOVE?BB CCPR1H, _Speed_HIGHBYTE

ICALL?L L00001

MOVE?CT 000h, _T1CON_0

ICALL?L L00001

MOVE?CB 000h, CCP1CON

ICALL?L L00001

MOVE?CB 000h, TMR1L

ICALL?L L00001

MOVE?CB 000h, TMR1H

ICALL?L L00001

MOVE?CT 000h, _PIR1_2

ICALL?L L00001

MOVE?CB 004h, CCP1CON

ICALL?L L00001

MOVE?CT 000h, _state

ICALL?L L00001

GOTO?L _scrivi

ICALL?L L00001

LABEL?L L00005

ICALL?L L00001

LABEL?L L00002

ICALL?L L00001

GOSUB?L _scrivi

ICALL?L L00001

RESUME?

LABEL?L _scrivi

IDISABLE?

WRITE?CC 001h, 0ABh

WRITE?CB 001h, _Speed_HIGHBYTE

WRITE?CB 002h, _Speed_LOWBYTE

IENABLE?

ICALL?L L00001

RESUME?

END

================================================================

Listato INTHAND.MAC

....................................

NOLIST

; PicBasic Pro Compiler 2.46, © 1998, 2005 microEngineering Labs, Inc. All Rights Reserved.

LABEL?L macro Label

RST?RP

ifdef PM_USED

LALL

Label

XALL

else

Label

endif

endm

CMPNE?TCL macro Regin, Bitin, Cin, Label

if (Cin == 0)

CLRWDT?

BIT?GOTO 1, Regin, Bitin, Label

else

if (Cin == 1)

CLRWDT?

BIT?GOTO 0, Regin, Bitin, Label

else

L?GOTO Label

endif

endif

endm

GOSUB?L macro Label

local dlabel

ifdef DEBUG_STACK

CHK?RP DEBUG_STACK

ifdef DEBUG_STACK_ADDR

bcf STATUS, C

rlf DEBUG_STACK, W

addlw DEBUG_STACK_ADDR

movwf FSR

movlw low (dlabel)

movwf INDF

incf FSR, F

movlw (dlabel) >> 8

movwf INDF

endif

incf DEBUG_STACK, F

endif

L?CALL Label

dlabel

endm

GOTO?L macro Label

L?GOTO Label

endm

ICALL?L macro Label

L?CALL Label

endm

IDISABLE? macro

endm

IENABLE? macro

endm

ONINT?LL macro Inthand, Intchk

local label

bsf INTCON, GIE

L?GOTO label

Intchk btfsc INTCON, GIE

return

L?GOTO Inthand

label

endm

ONINT_USED = 1

RESUME? macro

RST?RP

retfie

endm

WRITE?CB macro Cin, Bin

MOVE?CB Cin, EEADR

MOVE?BA Bin

L?CALL WRITE

endm

WRITE_USED = 1

WRITE?CC macro Cin1, Cin2

MOVE?CB Cin1, EEADR

MOVE?CA Cin2

L?CALL WRITE

endm

WRITE_USED = 1

LIST

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...