PDA

View Full Version : Help whit tmr1 on pic16f877a



DonLuis
- 2nd February 2013, 04:13
Hi:
After a long while being away, I finally have the time to continue learning about programming pics, I have started this project and again find myself stuck
I am trying to make a distance meter using tmr1 of a PIC16f877A using an incremental encoder which it has a circumference wheel of 200mm and 200 pulses/rev. as external clock source, the purpose of this is to measure pieces of tape of the same length, using a word size settable variable to load the tmr1 and on overflow create an interrupt.
So this is what I find out so far: tmr1 is composed of two 8 bit registers TMR1H and TMR1L and to load a value let´s say 10,000 (ten meters), I´ll have to do 65535-10000= 55535, which is the value I have to load tmr1 with, to cause an interrupt on overflow, but what is really confusing me, is that as I understand, I have to write to TMR1H and TMR1L separately breaking the value in two, and I don’t know how to approach this on the program.
May be I am getting it wrong, so I´ll greatly appreciate any guidance on this matter

prstein
- 2nd February 2013, 04:33
Is this what you're looking for?


wTimerVal var Word

wTimerVal = 55535
TMR0H = wTimerVal .highbyte
TMR0L = wTimerVal .lowbyte

Best Regards,
Paul

DonLuis
- 2nd February 2013, 11:19
Thanks prstein, yes I think that is it. I will try it and let you know

DonLuis
- 13th February 2013, 03:13
Hi there:
I apologize for taken so long to reply but in between attending a job and a family my time left to do other things is from very slim to none.
Anyways after messing around with the code I came out with something that works at least on the isis proteus simulator, one thing that I noticed is that when I press the encoder button the tmr1 value increment in more than one unit, but I think that’s because I didn’t put any debouncing time on the code I’ll check that out.
I going to leave de code and a snapshoot of the circuit for you to look at it and if you will comment about it, but please don´t be to rough on me, since this is my first code for something useful other than blinking leds.
About the code (this is just part of it) is to be used with an incremental encoder, I mean it only send pulses and not difference which way is turning, it is only to measure distance and to cause an interrupt whenever the set distance has been reached, ahhh and one other thing, does any body can tell me how to increase the count, because the tmr1 only counts up to little more than 65 meters before it overflows, providing than each pulse equals one millimeter

'************************************************* **************************
'Name : TAPE MEASURING
'Author : [Don Luis]
'Notice : Copyright (c) 2013 [select VIEW...EDITOR OPTIONS]
'All Rights Reserved
'Date : 02/02/2013
'Version : 1.0
'Notes : PROGRAM CODE TO TEST THE TMR1 OPERATION
'************************************************* *********************************

' FUSES DEFINE
DEFINE HS_OSC,WDT_OFF,PWRT_ON, BOD_OFF,LVP_OFF,CPD_OFF,WRT_HALF,DEBUG_OFF,PROTECT _OFF

' LCD INITIALIZING
DEFINE OSC 4
DEFINE LCD_DREG PORTB ' set portb for lcd
DEFINE LCD_DBIT 4 ' set data bit from 4 to seven
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 2 ' set bit 1 as RS bit
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 3 ' set bit 2 as enable bit
DEFINE LCD_BITS 4 ' define number of data bits
DEFINE LCD_LINES 2 ' define number of lines
DEFINE LCD_COMMANDUS 2000 ' set time for lcd to start
DEFINE LCD_DATAUS 50 ' set time for lcd data transfer
pause 2000

'INITIALIZING SFR'S
adcon1= %10001110
PIE1= %00000001 ' Periferal interrupt enable tmr1
INTCON= %11000000 ' TMR1 interrupt control off
on interrupt goto motstop ' Interrupt handdler

'SETTING TRIS
trisa= %11110011
trisb= %00000001
trisc= %11111111
trisd= %11110000
trise= %000

' PORT DEFINING
encoder var portc.0 ' variable for encoder signal input
motor var porta.3 ' variable for motor control
brake var porta.2 ' variable for brake control

' SETTING VARIABLES
t1val var word ' set variable to store tmr1 value
tempo var byte ' set variable for timing pause
medida var word ' set variable to store required travel distance
tctval var word ' set variable used to display the actual tmr1 value

'INITIALIZING VARIABLES
tempo= 50
t1val=0
medida= 10
tctval= 0

'INITIALIZING PORTS
low brake
low motor

lcdout $FE,$01 ' clear lcd display line 1
pause 20 ' small pause to give time to lcd
lcdout " SYSTEM READDY" ' display introduction message
pause 5000 ' during 5 seconds

main:
t1val=65535-medida ' load tmr1 whith FFFF- the value of medida
TMR1H = t1val.highbyte
TMR1L = t1val.lowbyte
T1CON=%00000111 ' enable tmr1
high motor ' turn motor on

rutpal:
tctval.highbyte= TMR1H
tctval.lowbyte= TMR1L ' load tctval variable with actual timer value
if TMR1H=0 & TMR1L=0 then ' this command is used to prevent the program from
goto main ' going into an endless loop after a return from
endif ' an interrupt routine
lcdout $FE,$01 ' clear display line 1
lcdout "TIMER VALUE" ' display message on line 1
pause 20 ' pause to give the lcd some time to execute
lcdout $FE,$C0 ' clear display line 2
lcdout dec tctval ' display decimal value of tctval on line 2
pause 100 ' small pause
goto rutpal ' loop untill a interrupt ocurrs

disable ' disable all interrupts
motstop: 'interrupt handler
low motor ' stop the motor
high brake ' turn brake on
pause 2000 ' pause just we can see de led on for a moment
low brake ' turn brake off
TMR1H=0 ' clear tmr1
TMR1L=0
T1CON=%00000110 ' disable tmr1
lcdout $FE,$01 ' clear lcd display line 1
lcdout " CYCLE" ' display message on line 1
pause 20 ' small pause to give time to the lcd to execute
lcdout $FE,$C0 ' clear line two of lcd
lcdout " CONCLUDED" ' display message on line two of lcd
PIR1.0=0 ' clear flag
pause 2000 ' two second pause
resume ' end interrupt routine
enable ' enable interrupts

6836

prstein
- 15th February 2013, 02:32
On a good day I am perhaps 10% as good as the regular and reliable people on this forum but I'll do my best...

A couple of things stand out to me as a little odd.


' FUSES DEFINE
DEFINE HS_OSC,WDT_OFF,PWRT_ON, BOD_OFF,LVP_OFF,CPD_OFF,WRT_HALF,DEBUG_OFF,PROTECT _OFF


Although this compiles I don't think it does anything. Presuming you're using PBP3, it would be something more like

#CONFIG
__config _CONFIG1, _HS_OSC & _WDT_ON & _LVP_OFF & _CP_OFF ;etc
#ENDCONFIG

See Chapter 4.9 of the PBP3 manual.

Regarding

if TMR1H=0 & TMR1L=0 then
When reading a 16-bit timer you should get in the habit of reading the low byte first. And when writing to the timer, write the high byte first. Check the datasheet for why this is so.

On your schematic, MCLR should be pulled high through a 4.7K (or so) resistor instead of being connected directly to power.

To increase the count from TMR1 I think you might be able to use a pre-scaler, although there would be a loss of resolution. You could also get clever and figure out how many times the TMR1 interrupt flag would occur.

Hope this helps...

Best Regards,
Paul

Acetronics2
- 15th February 2013, 07:20
+1 !

let's add ..



if TMR1H=0 & TMR1L=0 then


is automatically ( in this case ! ) "marked" by INTCON.2 flag ... ;) because of an interrupt generation.

but you have a very very very very ... high probability the "if TMR1H=0 & TMR1L=0" test result to be always false ... :D

Alain

DonLuis
- 17th February 2013, 22:32
Thank you all for your comments and taking the time, I’ll do the recommended corrections and keep working on the code and of course will read de manual.:smile:

DonLuis
- 21st July 2013, 18:02
Hello guys:
Continuing with my project, after completing my code which is rather long since include a longitude set up routine, a temperature set up, thermostat routine a 4x4 keyboard and a lcd display interface routine and other control goodies.

Even though almost everything works as planed I come up to a dead end, it so happens that using the tmr1 to measure the length of the expended foil I have a huge difference between the inputted measure and the one I get.

Between 2 and 3 times longer and never get the same, let me explain a little, let’s suppose the worst scenario
The expended roll measures 300mm in diameter (it’ll never get that big) so this is according to my math’s 300x3.1416= 942.48mm, and given that the shaft turns at 150 rpm then 150/60= 2.5 rps. Then 942.48x2.5= 2356mm per second and since every mm equals a pulse gives me a speed of 1/2356= 0.00043 us per mm and using a 4 Mhz xtal that is 1us, almost 400 times the foil speed, so I thought it wasn’t enough time for the pic to process the info, so I went o 8 Mhz, and then 16 Mhz xtal and all ways got the same.
So I decided to try counting by interrupts using Rb.0 and made a routine for that and I got the same results the only difference is that measures nearly equal, 1mean still 3 times more but with 5mm more or less, I did have a commercial incremental encoder but I don’t know what happen to it, can’t find it, so I make one and it looks like this (well they appear on the bottom)
I used a regular IR led and opt transistor, turning the roller by hand I can count the 149 pulses per revolution, the output (negative pulse) of the opt transistor is feed to a 74ls14 smith trigger and then (positive pulse) to the pic pin, so I have a doubt if the problem is in the code or in the hardware but I am missing pulses big time, any help on this mater like always be greatly appreciated, also I live some pieces of the code related.


‘THIS IS A CODE WITH THE TMR1 INTERRUPT

DEFINE INTRC_OSC_NOCLKOUT &_HS_OSC & _WDT_OFF & _PWRTE_ON & _BOREN_OFF & _LVP_OFF & _CPD_OFF &_WRT_HALF & _DEBUG_OFF & _CP_OFF

' LCD INITIALIZING
DEFINE OSC 16 ' define oscilator cristal 16 mhz
DEFINE LCD_DREG PORTB ' set portb for lcd
DEFINE LCD_DBIT 4 ' set data bit from 4 to seven
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 2 ' set bit 1 as RS bit
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 3 ' set bit 2 as enable bit
DEFINE LCD_BITS 4 ' define number of data bits
DEFINE LCD_LINES 2 ‘define number of lines
DEFINE LCD_COMMANDUS 2000 ' set time for lcd to start
DEFINE LCD_DATAUS 50 ' set time for lcd data transfer
DEFINE ADC_BITS 10 ' define analog register 10 bit word
DEFINE ADC_CLOCK 3 ' define clock source internal rc clock
DEFINE ADC_SAMPLEUS 50 ' define adc samplign every 50 ms
pause 3000 ' pause to initialize lcd

PIE1= %00000001 ' enable timer1
INTCON= %11000000 ' enable interrupts
on interrupt goto motstop ' interrupt handler

rutpal: ' main routine
LCDOUT $FE, $01
pause 20
lcdout "TEMP " ‘display TEMP suffix on line 1
LCDOUT $FE,$C0
LCDOUT "M.U." ‘ display M.U. suffix on line 2
low l4

rpal: ‘main loop
if alcal=0 then gosub nosensor ' check for temperature sensor condition
adcin 0, calsens ‘ sample sensor
calsens = 488 * calsens ; 1024*488=499712; ‘ convert to °C
calsens = DIV32 10
LCDOUT $FE, $80 +6 ‘ display temperature on line 1
pause 20
lcdout DEC calsens DIG 4, DEC calsens DIG 3,DEC calsens DIG 2, ".", DEC calsens DIG 1, $DF,"C", " rp"
LCDOUT $FE,$C0 +5 ' display used foil length on line 2
pause 20
LCDOUT dec contador
if calsens<= temperatura-200 then high calentador ' if temperature is lower than setting, turn heater on
if calsens=> temperatura then low calentador ' and if it's higher then turn it off
button porta.1,0,0,0,boton,1,b1 ' check activation sensor if pressed go to b1
if c1= 0 then gosub debo ' if the key * was pressed go to debounce routine
if c1=0 then ‘ if still pressed sound key and go to set temperature
sound porta.5,[fr,10]
high l4
gosub tempajust
if jo=1 then ‘ on return clear flag and go to main loop
jo=0
goto rutpal
endif
endif

if c2= 0 then ' if the key 0 was pressed go to jogging routine
if jo=1 then ‘ on return clear flag and go to main loop
jo=0
goto rutpal
endif
endif

if c3= 0 then gosub debo ' if the key # was pressed go to debounce routine
if c3=0 then
sound porta.5,[fr,10] ‘if still pressed sound key and go to set length
high l4 ‘ on return clear flag and go to main loop
gosub medajust
if jo=1 then
jo=0
goto rutpal
endif
endif

if c4= 0 then gosub debo ' if the if the key D was pressed go to debounce routine
if c4=0 then ‘if still pressed sound key and go to clear contador routine
sound porta.5,[fr,10] ‘ on return clear flag and go to main loop
high l4
gosub borrar
if jo=1 then
jo=0
goto rutpal
endif
endif
goto rpal ' loop untill a subroutine is called up


b1:
counter= 0 ' routine to prevent program from seizing if sensor is not released
if porta.1= 1 then
boton=0
goto avance
endif
if porta.1= 0 then counter= counter +1
pause 50
if counter= 50 then rutpal
goto b1

avance:
t1val= 65535 – medida ‘ load tmr1
TMR1H = t1val.highbyte
TMR1L = t1val.lowbyte
T1CON=%00000111 ‘ enable tmr1
high motor ‘ turn motor on
goto rutpal ‘ return to main loop

disable ‘ disable interrupts
motstop:
low motor ‘ stop motor
high brake ‘ turn brake on and wait 300ms
pause 300
low brake ‘ turn brake off
T1CON=%00000110 ‘ disable tmr1
PIR1.0=0 ‘ clear tmr1 overflow flag
contador= contador+medida ‘ add contador to previous count and return
resume
enable ‘ enable interrupts

‘THIS IS A CODE WITH THE RB.O INTERRUPT

DEFINE INTRC_OSC_NOCLKOUT &_HS_OSC & _WDT_OFF & _PWRTE_ON & _BOREN_OFF & _LVP_OFF & _CPD_OFF &_WRT_HALF & _DEBUG_OFF & _CP_OFF

' LCD INITIALIZING
DEFINE OSC 16 ' define oscilator cristal 16 mhz
DEFINE LCD_DREG PORTB ' set portb for lcd
DEFINE LCD_DBIT 4 ' set data bit from 4 to seven
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 2 ' set bit 1 as RS bit
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 3 ' set bit 2 as enable bit
DEFINE LCD_BITS 4 ' define number of data bits
DEFINE LCD_LINES 2 ‘define number of lines
DEFINE LCD_COMMANDUS 2000 ' set time for lcd to start
DEFINE LCD_DATAUS 50 ' set time for lcd data transfer
DEFINE ADC_BITS 10 ' define analog register 10 bit word
DEFINE ADC_CLOCK 3 ' define clock source internal rc clock
DEFINE ADC_SAMPLEUS 50 ' define adc samplign every 50 ms
pause 3000 ' pause to initialize lcd

INTCON= %10000000 ' enable interrupts
OPTION_REG.6=1 ‘ define interrupt edge (rising edge)
on interrupt goto motstop ' interrupt handler

rutpal: ' main routine
LCDOUT $FE, $01
pause 20
lcdout "TEMP " ‘display TEMP suffix on line 1
LCDOUT $FE,$C0
LCDOUT "M.U." ‘ display M.U. suffix on line 2
low l4

rpal: ‘main loop
if alcal=0 then gosub nosensor ' check for temperature sensor condition
adcin 0, calsens ‘ sample sensor
calsens = 488 * calsens ; 1024*488=499712; ‘ convert to °C
calsens = DIV32 10
LCDOUT $FE, $80 +6 ‘ display temperature on line 1
pause 20
lcdout DEC calsens DIG 4, DEC calsens DIG 3,DEC calsens DIG 2, ".", DEC calsens DIG 1, $DF,"C", " rp"
LCDOUT $FE,$C0 +5 ' display used foil length on line 2
pause 20
LCDOUT dec contador
if calsens<= temperatura-200 then high calentador ' if temperature is lower than setting, turn heater on
if calsens=> temperatura then low calentador ' and if it's higher then turn it off
button porta.1,0,0,0,boton,1,b1 ' check activation sensor if pressed go to b1
if c1= 0 then gosub debo ' if the key * was pressed go to debounce routine
if c1=0 then ‘ if still pressed sound key and go to set temperature
sound porta.5,[fr,10]
high l4
gosub tempajust
if jo=1 then ‘ on return clear flag and go to main loop
jo=0
goto rutpal
endif
endif

if c2= 0 then ' if the key 0 was pressed go to jogging routine
if jo=1 then ‘ on return clear flag and go to main loop
jo=0
goto rutpal
endif
endif

if c3= 0 then gosub debo ' if the key # was pressed go to debounce routine
if c3=0 then
sound porta.5,[fr,10] ‘if still pressed sound key and go to set length
high l4 ‘ on return clear flag and go to main loop
gosub medajust
if jo=1 then
jo=0
goto rutpal
endif
endif

if c4= 0 then gosub debo ' if the if the key D was pressed go to debounce routine
if c4=0 then ‘if still pressed sound key and go to clear contador routine
sound porta.5,[fr,10] ‘ on return clear flag and go to main loop
high l4
gosub borrar
if jo=1 then
jo=0
goto rutpal
endif
endif
goto rpal ' loop untill a subroutine is called up


b1:
counter= 0 ' routine to prevent program from seizing if sensor is not released
if porta.1= 1 then
boton=0
goto avance
endif
if porta.1= 0 then counter= counter +1
pause 50
if counter= 50 then rutpal
goto b1

avance:
INTCON=%10010000 ‘ enable RB.0 interrupts
high motor ‘start motor
goto rutpal ‘ return to main loop

disable ‘ interrupt handler routine, disable interrupts ' disable all interrupts
motstop:
counter= counter+1 ‘ increment count by one
if counter=> medida then ‘ if count matches setting turn motor off
low motor
high brake ‘ apply brake and pause 300 ms
pause 300
low brake ‘ turn brake off
contador= contador+ counter ‘ add count to previous count
counter=0 ‘ clear counter
INTCON=%10000000 ‘ disable RB.0 interrupts
else
INTCON=%10010000 ‘ if no match then enable rb.0 interrupts and return
endif
enable

70337034

DonLuis
- 22nd July 2013, 00:36
Hi, just an update:

today i tried a code using polling (i think that is called), and i got better results but still not what i need, these es the part of the code i tried:
avance:
ban= encoder
high motor
av:
if ban<>encoder then
ban=encoder
counter= counter+1
endif
if counter= medida then motstop
goto av

motstop:
low motor
high brake
pause 300
low brake
contador= contador+ counter
counter=0
goto rutpal

Archangel
- 22nd July 2013, 18:15
Hello Don Luis,
IMHO you need assy interrupts, and I recommend you use Darrel's Instant Interrupts. On Interrupt services the interrupt when it gets around to it, given all the things you have going on, you need interrupts that actually interrupt.

DonLuis
- 23rd July 2013, 02:53
Thanks for answering Archangel.

I don’t know the meaning of IMHO, but I appreciate your comment, now I am terrified to ask, do I have to do the hole code in assy?, I mean I been working on this project for over a year, you know, bumping my head around to get the hang of pbp, even blowing a couple pics and a few other components, I don’t main, there is no rush, just want to see it completed an working as I want to, I do not know anything about assembler, but yet I willing to learn if that is what it takes, on the meaning time I’ll take a look at Darrel’s interrupts.:frown:

Archangel
- 23rd July 2013, 09:50
IMHO = In My Humble Opinion, good luck. Funny I don't even use cell phone . . .



do I have to do the hole code in assy?
No ooooooo

Here is a timer1 demo I made tonight for 16F690


@ __CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOR_OFF & _FCMEN_OFF & _IESO_OFF
INCLUDE "DT_INTS-14.bas" ; Darrel Taylors instant interrupts
DEFINE OSC 4

; * * * * * * * * * * * * * Setup Darrel's Instant Interrupts * * * * * * * *

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _Flash, ASM, no
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

@ INT_ENABLE TMR1_INT ; enable external (INT) interrupts

; * * * * * * * * * * * * * Provide system variables to save return address' * * * *
;wsave VAR BYTE $20 SYSTEM ; location for W if in bank0
wsave VAR BYTE $70 SYSTEM ; alternate save location for W
; * * * * * * * * * * * * SETUP DEBUG Parameters * * * * * * * * * * * * *
DEFINE DEBUG_MODE 0 ' Debug sending True serial data
DEFINE DEBUG_REG_PORTA ' Debug Port = PortA as required by PICKIT2 serial Monitor
DEFINE DEBUG_BIT 0 ' Debug.bit = PortA.0
DEFINE DEBUG_BAUD 19200 ' Default baud rate = 9600
DEFINE DEBUGIN_REG PORTA' Debug Port = PortA as required by PICKIT2 serial Monitor
DEFINE DEBUGIN_BIT 1 ' Debugin bit PortA.1
DEFINE DEBUGIN_BAUD 19200' Default baud rate = 9600
DEFINE DEBUGIN_MODE 0 ' Debugin receiving data true = 0 inverted = 1

; * * * * * * * * * * * * Setup Timer 1 registers * * * * * * * * * * *

TMR1IF var PIR1.0 ' Explain to PBP which bit is the T1IF bit
INTCON = %11010000 ; GIE,PEIE,T0IE,INTE set RABIE,T0IF,INTF,RABIF cleared
PIR1 = %00000000
PIE1 = %00000001 ; -,ADIE ,RCIE ,TXIE ,SSPIE ,CCP1IE,TMR2IE,TMR1IE
T1CON = %01000101 ; T1GINV,TMR1GE,T1CKP,T1CKP,T1OSCEN,T1SYNC,TMR1CS,TM R1ON
CM2CON1 = %00000000


temp var word
overFlow var word
overFlow = 0
temp.highbyte = 0
temp.lowbyte = 0

main:
if temp.lowbyte >= 255 then
temp.highbyte = temp.highbyte +1
endif
if temp >= 65535 then
overFlow = overFlow + 1 ;track number of temp roll overs
endif
debug " Temp Var High = ",#temp.highbyte," Temp Var Low = ",#Temp.Lowbyte," ",10

debug "OverFlow = ",#overFlow," temp var ",#temp,10



goto main
; * * * * * * * * * * * * * End of Main Function * * * * * * * * * * * * *

@ INT_DISABLE TMR1_INT
Flash:
if TMR1IF then ; Flash is the ISR
temp = temp + 1 ; add 1 to timer roll over count
endif
TMR1L = 0 ; preload timer 0 with ? of 255 allows you to set counts until reset
TMR1H = 0
TMR1IF = 0 ; Clear T1 Interrupt flag bit

@ INT_ENABLE TMR1_INT
@ INT_RETURN


All this does is overflow the timer and display the results in PICKit2 USART display. It has Darrel's Instant Interrupts installed so you can pretty much copy paste, then use your registers as required

aratti
- 23rd July 2013, 10:35
Hi Don, here my suggestion. If your max encoder count is not bigger of 65535 then you can feed your encoder pulses directly to timer1 input (pin 15 of you 16f877). Timer1 has to be set as a counter using "T1CON = %00000111" and then you have two ways to control your motor.

1) You poll the timer1 register TMR1H and TMR1L to see when the count reaches the desired value to stop the motor.
Or
2) you use DT interrupt (as already suggested) and you just load the count in Timer1 register (you have to load the complement : 65535-desired count) and wait for the overflow. In other words when the count is reached the value of the timer1 counter will be 65535 and adding one pulses it will overflow invocking the interrupt. In this routine (called ISR) you will stop your motor.

If your needed count is greater then 2^16 it it still possibile to use timer1 as a counter but in this case interrupt is mandatory.

Cheers

Al.

DonLuis
- 25th July 2013, 02:44
Hi guys:

Aratti; I already tried tmr1 interrupt on overflow, as you are suggesting, I explained that, on my post on July 21st, it’s just that seem to take too long to stop the motor and I get much more than I am barging for, sort of speech, also tried external interrupts on RB.0, and lastly polling from what I got much better results if you like to take a look to that post, I even included the code I used for each attempt.

Archangel; thank you for that, I already took a look to Darrel’s page and downloaded his .bas files and included, them on the PBP folder, (I feel relief now), but I’ll to try this first, since I got everything setup, and due to that I have fairly good results on polling, using the same encoder disc it measures twice de input because it is counting up on every negative and positive pulse, so just finished while ago a disc with 75 slot’s about half the other one, if still no good output then I try Darrel’s code, I’ll let you all know as soon as I get around it.

aratti
- 25th July 2013, 15:29
I already tried tmr1 interrupt on overflow, as you are suggesting,

I suggested timer1 overflow with a true interrupt (Darrel Taylor interrupt) your code didn't use any interrupt.

You can try to use this simple snippet which uses the timer1 as a counter, without interrupt and works pretty well.



False con 0
True con 1
Z0 Var Byte
Cnts var word
Tape_Len Var Word

Logic_1 var portXx ' any available free input

Motor = False
Brake = False
TMR1H = 0
TMR1L = 0

Main_Loop:
If ????? goto Load_Tape
If ????? goto Set_Tape_L
goto Main_loop

Set_tape_L:
Tape_Len = XXXXX ' encoder pulses derived from the tape lenght desired
return

Start_Motor:
Brake = False
Motor = True
Return

Stop_Motor:
Motor = false
Brake = True
Pause 200
Brake = False
T1CON.0 = False
Return


Load_Tape:
Cnts = 0
TMR1H = 0
TMR1L = 0
T1CON.0 = true
Resume_Halt:
Lcdout $FE, 1, " Press Yy to stop "
Lcdout $FE, $C0, "--------------------"
Lcdout $FE, $94, "Now Loading Tape ..."
Lcdout $FE, $D4, "Loaded: ",dec Cnts

Gosub Start_Motor

For Z0 = 0 To 100 ' 100 millisecs delay
pause 1
if Logic_1 = True then Hw_Halt ' check if emergency stop is activated
Next Z0

Winding: ' loading start here
Cnts.highbyte = TMR1H
Cnts.lowbyte = TMR1L
If Cnts => Tape_Len then
gosub Stop_Motor ' if count = lenght desired stop motor
goto Main_Loop
End If
if Logic_1 = True then Hw_Halt ' If emergency stop key pressed stop motor

Lcdout $FE, $D4, "Loaded: ",dec Cnts ' display updated count
goto Winding

Hw_Halt:
gosub Stop_Motor
Emergency_menu:
1) if ????? then goto Resume_Halt
2) if ????? then goto Main_Loop
goto Hw_Halt

End


Naturally you need to complete the code replacing the parts with ?????? and Xx with reference to your hardware setup.

Cheers

Al.

DonLuis
- 26th July 2013, 21:55
Hi guys:

Well finally SUCCES, with the new encoder disc and using the polling routine that I have, which is similar to the one Aratti suggested (thank you for that).

I all ways get the inputted length + 18mm exactly and I figured that it is due to the inertia of the motor before the brake applies and doesn’t matter which method I use still have to deal with it, so I made a compensation routine modifiable by the user that it is subtracted to the inputted length before the motor is started and then added to de counter before its value is displayed on the lcd and orale!!! It works like a charm, never de less I started to study assembly language and to begin with I found an eBook named Designing Embedded Systems with Pic Microcontrollers Principles and Applications by Tim Wilmshurst, so I thank you all for your help with this project and hope count with you on the next one.
;)