scaling an encoder
I am trying to change my pause time with an encoder. I need to flash and LED with a variable pause time of 1 to 1000 ms. I think I need to use an interupt but I don't know how to scale the encoder to adjust the pause delay . In BS2 it uses */ and the off set but that was with RCTIME.· I am a total newbie to the sx . I looked at the best threads and examples but did not find or may have over looked the answer.
DO····
····· PAUSEUS 500
····· UpdateEncoders
····· delay = tmpw1
···········
·
· DO························ ' calculate on timing
???????·delay =· 10 */ 255··
· HIGH·led··········· ' LED on
····· pause delay····' pause 1 to 1000 ms
····· LOW·led······· ·' LED off
····· pause delay
··· HIGH·led2········· ·' LED on
····· pause delay····· ' pause 1 to 1000 ms
····· LOW·led2········ ·' LED off
····· pause delay
· LOOP
FUNC GetEncoder1
· tmpW1 = EncoderPort AND 3
· RETURN tmpw1
ENDFUNC
SUB UpdateEncoders
· encoder1 = GetEncoder1
· IF encoder1 <> encoder1Last THEN
··· IF encoder1 = 3 THEN
····· IF encoder1Last = 1 THEN
· delay = delay + 1
······· delay = delay MAX Highestdelay
····· ELSEIF encoder1Last = 2 THEN
········ delay = delay - 1
······· delay = delay MIN mindelay····
··· ENDIF
··· ENDIF
··· encoder1Last = encoder1
· ENDIF
''''''''''''''''''''''''''''''
·
DO····
····· PAUSEUS 500
····· UpdateEncoders
····· delay = tmpw1
···········
·
· DO························ ' calculate on timing
???????·delay =· 10 */ 255··
· HIGH·led··········· ' LED on
····· pause delay····' pause 1 to 1000 ms
····· LOW·led······· ·' LED off
····· pause delay
··· HIGH·led2········· ·' LED on
····· pause delay····· ' pause 1 to 1000 ms
····· LOW·led2········ ·' LED off
····· pause delay
· LOOP
FUNC GetEncoder1
· tmpW1 = EncoderPort AND 3
· RETURN tmpw1
ENDFUNC
SUB UpdateEncoders
· encoder1 = GetEncoder1
· IF encoder1 <> encoder1Last THEN
··· IF encoder1 = 3 THEN
····· IF encoder1Last = 1 THEN
· delay = delay + 1
······· delay = delay MAX Highestdelay
····· ELSEIF encoder1Last = 2 THEN
········ delay = delay - 1
······· delay = delay MIN mindelay····
··· ENDIF
··· ENDIF
··· encoder1Last = encoder1
· ENDIF
''''''''''''''''''''''''''''''
·
Comments
The easiest way to use interrupts with the encoder is this:
When you scale "delay" you'll have to put the result into another variable.
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
My goal is to live forever...Or die trying.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
www.hittconsulting.com
Post Edited (Bean (Hitt Consulting)) : 10/26/2007 2:50:12 AM GMT
INTR_FALL . The code below does not generate errors but I still can't get it to work I wanted to add the LCD to see the pause value.
' =========================================================================
'
' File...... TEMPLATE.SXB
' Purpose... SX/B Programming Template
' Author....
' E-mail....
' Started...
' Updated...
'
' =========================================================================
'
' Program Description
'
'adjust Pause with encoder and display value on LCD
'
' Device Settings
'
DEVICE SX28, OSC4MHZ, TURBO, STACKX, OPTIONX
FREQ 4_000_000
'
' Device Settings
'
'
' IO Pins
'
led VAR RB.5 ' LED pin
led2 VAR RB.6
EncoderPort PIN RC
Encoder1A PIN RC.0 INPUT PULLUP SCHMITT
Encoder1B PIN RC.1 INPUT PULLUP SCHMITT
LCD PIN RA.2 OUTPUT
'
' Constants
'
mindelay CON 10 ' Lowest allowable delay
maxdelay CON 1000 ' Highest allowable delay
LCDBaud CON "T19200" ' LCD Baud rate
ClearScreen CON 12 ' Clears LCD screen
NewLine CON 13 ' Put LCD cursor on the next line
Home CON 128 ' Move LCD cursor to upper left without clearing the screen
LcdBLon CON 17 'TURN ON LCD BACK LIGHT
DELAY2 con 2000
WAIT CON 100
'
' Variables
'
delay VAR WORD
tempW VAR WORD ' Used by Setdelay, LCDStr, LCDWord
temp VAR BYTE ' Used by Setdelay, LCDChar, LCDStr
tempW2 VAR WORD ' Used by Setdelay
encoder var word
encoder1 VAR word
encoder1Last VAR word
'
INTERRUPT ' Interrupt caused by falling edge of EncoderB input
WKPND_B = 0 ' Clear interrupt flag to enable further interrupts
IF Encoder1 = 0 THEN ' Change "0" to "1" if direction is backwards
DEC delay
delay = delay MIN MinDelay ' Min delay must be > 0
ELSE
INC delay
delay = delay MAX MaxDelay
ENDIF
RETURNINT
' =========================================================================
PROGRAM start
' =========================================================================
'
' Subroutine Declarations
'
'delay SUB 1,2 ' Pass delay wanted (0, 1 to 1000) (0 = OFF)
LCDChar SUB 1 ' Sends 1 character (byte) to the LCD
LCDStr SUB 2 ' Sends a string to the LCD
LCDWord SUB 2 ' Sends a value to the LCD as ASCII
GetEncoder1 FUNC 1
UpdateEncoders SUB 0
setdelay sub 1,2
'
' Program Code
'
Start:
DO
HIGH LCD ' For LCD High is idle state
PAUSE 10 ' Let LCD settle
LCDChar ClearScreen
PAUSE WAIT
LCDChar LcdBLon
LCDStr " delay test "
PAUSE delay2
LCDChar ClearScreen
PAUSE WAIT
LCDStr "< delay led test > "
LCDStr "<< pauseus >>"
PAUSE DELAY2
LCDChar ClearScreen
PAUSE WAIT
encoder1Last = GetEncoder1
do
tempW = delay */ 180 ' this is just a test value to test
PAUSE tempW
HIGH LED ' turn LED on
PAUSE Delay ' delay
LOW LED ' turn LED off
PAUSE Delay ' delay
HIGH LED2 ' turn LED on
PAUSE Delay ' delay
LOW LED2 ' turn LED off
PAUSE Delay
DO
IF delay <> tempW THEN
LCDChar Home
LCDStr " delay = "
LCDWord delay
tempW = delay
ENDIF
loop
'
' Subroutine Code
'
SUB Setdelay
IF __PARAMCNT = 1 THEN
delay = __PARAM1
ELSE
delay = __WPARAM12
ENDIF
IF delay < 1000 THEN
delay = 0
ENDIF
'
' LCD ROUTINE
'
SUB LCDChar
temp = __PARAM1
SEROUT LCD, LCDBaud, temp
UpdateEncoders
ENDSUB
SUB LCDStr
tempW = __WPARAM12
DO
READINC tempW, temp
IF temp = 0 THEN EXIT
LCDChar temp
LOOP
ENDSUB
SUB LCDWord
tempW = __WPARAM12
temp = "0"
DO
IF tempW < 1_000 THEN EXIT
INC temp
tempW = tempW - 1_000
LOOP
LCDChar temp
temp = "0"
DO
IF tempW < 1_000 THEN EXIT
INC temp
tempW = tempW - 1_000
LOOP
LCDChar temp
temp = "0"
DO
IF tempW < WAIT THEN EXIT
INC temp
tempW = tempW - WAIT
LOOP
LCDChar temp
temp = "0"
DO
IF tempW < 10 THEN EXIT
INC temp+
tempW = tempW - 10
LOOP
LCDChar temp
temp = "0" + tempW_LSB
LCDChar temp
ENDSUB
'
auto
FUNC GetEncoder1
temp = EncoderPort AND 3
RETURN temp
ENDFUNC
SUB UpdateEncoders
encoder1 = GetEncoder1
IF encoder1 <> encoder1Last THEN
IF encoder1 = 3 THEN
IF encoder1Last = 1 THEN
delay = delay + 1
delay = delay MAX maxdelay
ELSEIF encoder1Last = 2 THEN
delay = delay - 1
delay = delay MIN mindelay
ENDIF
ENDIF
encoder1Last = encoder1
ENDIF
Try...
For INTR_FALL make sure you are using the latest SX/B version 1.51.03 Dated 9/21/06. You can find it in a sticky at the top of the forum listing.
- Sparks
Sparks, thanks for catching that for me.
Dittos on the version too.
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
My goal is to live forever...Or die trying.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
www.hittconsulting.com
·
Exactly Sparks where do I check for the version 1.5.3 at. Sorry about the stupid questions....
' =========================================================================
'
'·· File...... delay2_0.SXB
'·· Compiler.. SX/B Version 1.51.03
'·· Purpose... Control an output delay encoders Digikey P10860-ND
'····
'·· '··
' =========================================================================
'
'·········· 220
' RC.0 ---/\/\/\
Encoder1 Phase A
'·········· 220······ GND --- Encoder1 Common···
connections)
' RC.1 ---/\/\/\
Encoder1 Phase B
'············
'············· 220
' RA.1
/\/\/\--- Serial To LCD
'
' Device Settings
'
DEVICE········· SX28, OSC4MHZ, TURBO, STACKX, OPTIONX
FREQ··········· 4_000_000
ID "delay2.0"
'
' IO Pins
'
led···· VAR RB.5···' LED pin
led2······· VAR RB.6··················· 'LED2 PIN
EncoderPort PIN RC
Encoder1A·· PIN RC.0 INPUT PULLUP
Encoder1B·· PIN RB.1 INPUT PULLUP INTR_FALL
LCD········ PIN RA.0 OUTPUT
'
' Constants
'
mindelay····· CON 4······· ' Lowest allowable delay
maxdelay····· CON 1000····· ' Highest allowable delay
LCDBaud······ CON "T2400"· ' LCD Baud rate
ClearScreen·· CON 12······· ' Clears LCD screen (Use PAUSE 5 after sending this command)
NewLine······ CON 13······· ' Put LCD cursor on the next line
Home········· CON 128······ ' Move LCD cursor to upper left without clearing the screen
LcdBLon······ CON 17······· 'TURN ON LCD BACK LIGHT
DELAY2······· con 2000
WAIT········· CON 100
'
' Variables
'
delay··········· VAR WORD
delayWANTED····· VAR WORD
tempW··········· VAR WORD ' Used by Setdelay, LCDStr, LCDWord
temp············ VAR BYTE ' Used by Setdelay, LCDChar, LCDStr
tempW2·········· VAR WORD ' Used by Setdelay
encoder········· var word
encoder1········ VAR word···
encoder1Last···· VAR word
'
INTERRUPT ' Interrupt caused by falling edge of EncoderB input
· WKPND_B = 0 ' Clear interrupt flag to enable further interrupts
· IF Encoder1 = 0 THEN ' Change "0" to "1" if direction is backwards
··· DEC delay
··· delay = delay MIN MinDelay ' Min delay must be > 0
· ELSE
··· INC delay
··· delay = delay MAX MaxDelay
· ENDIF
RETURNINT
' =========================================================================
PROGRAM start
' =========================================================================
'
' Subroutine Declarations
'
LCDChar······· SUB 1·· ' Sends 1 character (byte) to the LCD
LCDStr········ SUB 2·· ' Sends a string to the LCD
LCDWord······· SUB 2·· ' Sends a value to the LCD as ASCII
GetEncoder1··· FUNC 1
UpdateEncoders SUB 0
setdelay······ SUB 1,2
'
' Program Code
'
Start:
· HIGH LCD·· ' For LCD High is idle state
· PAUSE 10·· ' Let LCD settle
·· LCDChar ClearScreen
· PAUSE WAIT
· LCDChar LcdBLon
· LCDStr " delay test "
· PAUSE delay2
· LCDChar ClearScreen
· PAUSE WAIT
· LCDStr "< delay led test > "
· LCDStr "<< pauseus >>"
· PAUSE DELAY2
· LCDChar ClearScreen
· PAUSE WAIT
· encoder1Last = GetEncoder1
·
···
· PAUSEUS 100
····· UpdateEncoders
····· setdelay delay
······· IF delay <> tempW THEN
······· LCDChar Home
······· LCDStr "· delay = "
······· LCDWord delay
······· tempW = delay
····· ENDIF
·DO
··· tempW = delay */ 3
··· HIGH· LED·····' turn LED on
··· PAUSE Delay····' delay
··· LOW·· LED·····' turn LED off
··· PAUSE Delay····' delay
··· HIGH· LED2···' turn LED on
··· PAUSE Delay····' delay
··· LOW·· LED2·····' turn LED off
··· PAUSE Delay
···
···
loop
'
' Subroutine Code
'
·SUB Setdelay
·
· IF __PARAMCNT = 1 THEN
··· DELAYWANTED = __PARAM1
· ELSE
··· DELAYWANTED = __WPARAM12
· ENDIF
· IF DELAYWANTED < 1000 THEN
··· DELAY = 0
· ENDIF
'
'············ LCD ROUTINE
'
SUB LCDChar
· temp = __PARAM1
· SEROUT LCD, LCDBaud, temp
· UpdateEncoders
ENDSUB
SUB LCDStr
· tempW = __WPARAM12
· DO
··· READINC tempW, temp
··· IF temp = 0 THEN EXIT
··· LCDChar temp
· LOOP
ENDSUB
SUB LCDWord
· tempW = __WPARAM12
· temp = "0"
· DO
··· IF tempW < 1_000 THEN EXIT
··· INC temp
··· tempW = tempW - 1_000
· LOOP
· LCDChar temp
· temp = "0"
· DO
··· IF tempW < 1_000 THEN EXIT
··· INC temp
··· tempW = tempW - 1_000
· LOOP
· LCDChar temp
· temp = "0"
· DO
··· IF tempW < 10 THEN EXIT
··· INC temp
··· tempW = tempW - WAIT
· LOOP
· LCDChar temp
· temp = "0"
· DO
··· IF tempW < 10 THEN EXIT
··· INC temp
··· tempW = tempW - 10
· LOOP
· LCDChar temp
· temp = "0" + tempW_LSB
· LCDChar temp
ENDSUB
'
auto
·
·
FUNC GetEncoder1
· temp = EncoderPort AND 3
· RETURN temp
ENDFUNC
SUB UpdateEncoders
· encoder1 = GetEncoder1
· IF encoder1 <> encoder1Last THEN
··· IF encoder1 = 3 THEN
····· IF encoder1Last = 1 THEN
······· delay = delay + 1
······· delay = delay MAX maxdelay
····· ELSEIF encoder1Last = 2 THEN
······· delay = delay - 1
······· delay = delay MIN mindelay
····· ENDIF
··· ENDIF
··· encoder1Last = encoder1
· ENDIF
Does that help?
- Spark
This strikes me as being likely set your delay back to zero. Since maxdelay = 1000 it seems like 1000 is the only other valid state. However, you can not reach 1000 in a single pass through the program! So in reality setting a delay of 1000 can never be reached.
Of course, I may not properly understand your program, but that is the impression I developed. Make sure your delay is not being reset each time though the loop.
- Sparks
Spark I put my scope on the output and it's not pretty. I have to generate a better pulse or go into a freqout command to have better control.
I saw in another post how Bean set up and interupt to trigger a delay off the leading edge of a pulse out comand...????
SO maybe it would be better to send a freqout and on the leading edge trigger or shut off the other mosfet (LED)
I am starting to lean towards that approach. What do you think???
It looks like you are running the pulses from the main code and not a ISR. Can I change the ISR rate with an encoder to control my pulse out speed?????? Then I can use the other encoder to change the PWM (duty cycle). I would like to also set in the main code the way I need the pulse out.
example
LOW led2
HIGH LED1 ' turn LED on
PAUSE Delay
LOW LED1
HIGH led2 ' turn LED off
PAUSE Delay
LOW LED2
HIGH LED3 ' turn LED on
PAUSE Delay ' delay
LOW LED3
HIGH LED2
PAUSE Delay
Can I set my code up to turn on and off my mosfets and control the PWM and Freq with my encoders.I tried to do it with just the HIGH LOW and control the delay to change the PW but it is not a good way of doing it. I see in the example he looks like he is sending 4 square waves and you set it up to give (us) sec delay in between pulses and some overlap....ect... I need to be able to do that but I can't overlap. I can set up the pauseus delay inbetween the pulses Can an interuppt routine be added to that code to control the freq, he was trying to get 32 khz you sugested to go to 20Mhz clock. I am using a 50Mhz so I have plenty of speed I want to also show the settings on the LCD.
I was think of setting up the perfect pulses with a variable PWM control .. Encoder 1
Then Change the ISR rate to control the speed ... Encoder 2
Hard code the PAUSEUS delay inbetween pulses.
or like
Main:
FOR idx = 1 TO 10
PULSOUT RA.0, idx, 10 ' pulses from 100 to 1000 µs
PAUSE 1 ' delay 1 millisecond
NEXT
GOTO Main
What do you think.. is better... Thanks guys
BTW Sparks great thread on the UART.....
You want to accomplish a lot! As far as I can tell everything you want to accomplish with the SX should be within its capabilities.
I do not recall if you are using an SX48. If not, you might want to consider using one since it has two independently running hardware timers as well as twice the internal memory and more I/O pins than the SX28. However, I will assume for now that you are using an SX28 and will not discuss the use of the SX48 hardware timers.
First, as I noted in my opening comment, you are trying to accomplish a lot! It seems that you have already made a good deal of progress. However, since your delays are not working properly you will need to reduce your program down to its fundamental parts. I suggest that you begin verifying the operation of subsections whose functionality may be in question. For example, do you know for certain that you can change the value of a variable simply by rotating your encoder? If not, you might have a problem with your encoder logic. If you can verify that the encoder is altering the value of a variable in the desired way, then look elsewhere for a problem. Can you alter the pulse delays programmatically with hard-coded statements or a FOR…NEXT loop? If not, there may be a problem with how you are trying to process the delays. However, if you can change the delay programmatically and your encoder subroutine is actually changing the variable correctly you may need to look for other statements or subroutines that might alter or reset your delay value.
I think it will serve you well to separate each individual part of the program and verify its operation. Sometimes each part works separately but the system fails to function as a whole. When that happens you know you need to look at the interactions between various parts but at least you know that each part works.
The direct answer to that question is NO. I am not aware of any way to change the interrupt rate aside from reprogramming the device.
However, you can check a counter during each interrupt. If it is not time to do anything, simply update the counter and return. So you can achieve a very similar effect.
With all that you are trying to do, I am going to recommend that you consider a slightly different approach and do almost all of your signal processing inside the interrupt… but not yet. First verify that the separate parts of your program are operating properly.
When you are ready to restructure your program give careful consideration to how quickly you need your fastest signal response to be. That value or something a little faster will be the basis for your interrupt rate. In your case, 800Hz might be the fastest you will need to process signals to support a 400Hz motor especially since a hand-turned encoder probably will not alter its state very quickly. If you need a greater interrupt rate for PWM then use it as your base rate. The key is to handle your fastest signal changes and then relate all other time-based signal processing tasks to that fast rate.
Inside the ISR...
I think you will eventually want to handle three things within your interrupt service routine. You will want to check for a change in your encoder position and alter a variable accordingly. You will want to alter any output signals if it is time to do so. You will also want to keep track of how many interrupt time intervals have occurred. A typical way to do this is by adjusting one or more counter variables.
I suggest that you leave the main code to operate the LCD and perform other non-time-critical tasks such as reading from or writing to an EEPROM, etc.
The PAUSE command is useful but because of the number of things you are trying to have happen nearly simultaneously I think you need to abandon it and handle all of your signal timing directly in an ISR. Use interrupt-based counters and leave the PAUSE statements for things like the LCD that can run in the main program loop.
Obviously I did not solve your problem. You will need to narrow down your trouble location a little more or possibly repost your code. I recommend that you focus on getting the various parts working separately and then concentrate on combining everything together once the various subsections are known to work.
If I have not been very clear or you need more information, just let me know.
- Sparks
I know the LCD part is solid and I will leave it alone.. I will seperate the subs and work on it one at a time to get the LCD to show the Increments and the Decrements. I will work on that. You answered my question on the ISR.
1. I am going to work on the PWM and get the encoder to change the pulse width.
2. Then work on getting the LCD to display the value.
I will work on those things and the rest of the things you wrote about. Thanks for taking time to help me I really appreciate it.
Sparks, as you know, my approach to things is through assembler rather than SX/B, as it gives me the greatest flexibility, albeit at a considerable cost in time to write and debug the code as compared to SX/B.
That said, I would offer that the tasks datacps is attempting are easily within reach.... bordering on simple with my approach, especially if a co-operative RTOS is employed. I would bet not even 10% of the processor would be consumed by the application... seperate of the RTOS that is.
In that approach, I would want to disagree with you totally that (almost) everyting should be done in the ISR...... my belief is that almost nothing but tick counting should be done in the ISR.
But with SX/B things are a little different as currently it does not support multi-tasking, so to get around that, perhaps your suggestion has merit.
My point here is to broaden the readers' view to realize that there are more ways, perhaps many ways, to effect this project, each with their own advantages and disadvantages, and the statement about what to do in the ISR is a matter of approach, and does not hold for all cases.
Cheers,
Peter (pjv)
I want to set the delay for the pulse width..
I have everything working but I don't know where or how to put delay in another variable.
I am also having a problem scaling the encoder. The examples are for RC time.
All I need is to be able to change the pulsewith on the· PULSOUT RB.4, 600 to· PULSOUT RB.4, delay.
I want to be able then to change my pulsewidth with encoder 1. I can't figure out what I am doing wrong>>>>
Also on the scaling I need 1 to 1000·· us and I can't find any examples for encoders scales just RC time.
As for the ISR Peter all I need is to be able to control my Pulsewidth with 1 encoder and the frequency with the other.
I am working on a power invertor so I don't think I will need to go over 400 hz. SO my range will be 40 to 400 hz.
Any suggestions on how I can control the frequency range???????
I am going to turn on 2 mosfet a time so I won't need 4 outputs.· I can control my H drive with 2 only..
I am posting the code. Like I mentioned I have the circuit working but I can't change the pulseout width ( delay) and display the setting on my LCD.·
I am confused on temp , Tempw , ect and also I don't fully understand how the ISR inc and dec work with my encoder????
Bean.. how do I scale the encoder with· the */ . It looks simple enough but I can't get it to work.. What am I doing wrong....
'
' Device Settings
'
DEVICE SX28,TURBO,OPTIONX,STACKX,OSCHS3,BOR42
FREQ 50_000_000
ID "delay.1"
'
' IO Pins
'
·
led1·········· VAR RB.4
led2· VAR RB.5
led3· VAR RB.6··' LED pin
································
EncoderPort PIN RC
Encoder1A·· PIN RC.0 INPUT PULLUP
Encoder1B·· PIN RB.1 INPUT PULLUP INTR_FALL·
LCD··········· PIN RA.0 OUTPUT
'
' Constants
'
mindelay······ CON 1······· ' Lowest allowable delay
maxdelay····· CON 1000····· ' Highest allowable delay
LCDBaud······ CON "T19200"· ' LCD Baud rate
ClearScreen· CON 12······· ' Clears LCD screen (Use PAUSE 5 after sending this command)
NewLine······· CON 13······· ' Put LCD cursor on the next line
Home··········· CON 128······ ' Move LCD cursor to upper left without clearing the screen
LcdBLon······· CON 17······· 'TURN ON LCD BACK LIGHT
DELAY2········ CON 2000
WAIT··········· CON 100
'
' Variables
'
delay················· VAR WORD
delayWANTED····· VAR WORD
tempW··············· VAR WORD ' Used by Setdelay, LCDStr, LCDWord
temp·················· VAR BYTE ' Used by Setdelay, LCDChar, LCDStr
tempW2············· VAR WORD ' Used by Setdelay
encoder············· VAR WORD
encoder1··········· VAR WORD···
encoder1Last······ VAR WORD
'
INTERRUPT ' Interrupt caused by falling edge of EncoderB input
· WKPND_B = 0 ' Clear interrupt flag to enable further interrupts
· IF Encoder1 = 0 THEN ' Change "0" to "1" if direction is backwards
··· DEC delay
··· delay = delay MIN MinDelay ' Min delay must be > 0
· ELSE
··· INC delay
··· delay = delay MAX MaxDelay
· ENDIF
RETURNINT
' =========================================================================
PROGRAM start
' =========================================================================
'
' Subroutine Declarations
'
LCDChar·········· SUB 1·· ' Sends 1 character (byte) to the LCD
LCDStr············ SUB 2·· ' Sends a string to the LCD
LCDWord········· SUB 2·· ' Sends a value to the LCD as ASCII
GetEncoder1····· FUNC 1
UpdateEncoders SUB 0
setdelay············ SUB 1
'
' Program Code
'
Start:
· HIGH LCD·· ' For LCD High is idle state
· PAUSE 10·· ' Let LCD settle
·· LCDChar ClearScreen
· PAUSE WAIT
· LCDStr " delay test "
· PAUSE delay2
· LCDChar ClearScreen
· PAUSE WAIT
· LCDChar ClearScreen
· PAUSE WAIT
· encoder1Last = GetEncoder1
····
· PAUSEUS 100
····· UpdateEncoders
····
······· IF delay <> tempW THEN
······· LCDChar Home
······· LCDStr "· delay = "
······· LCDWord delay
·······
····· ENDIF
···
DO
····
····· PULSOUT·· RB.4, 600···················· ' pulses from 100 to 1000 µs
····· pauseus 2··
····· pulsout····· RB.5, 600
····· pauseus 2
··································
·
loop
··
····
'
' Subroutine Code
'
'
'''''''Problem Problem
''''Bean wrote ''
'When you scale "delay" you'll have to put the result into another variable.
''···· tempW = delay */ Scale
'''··· PAUSE tempW
''' I am having a problem here
'''''
··
·SUB Setdelay
·· IF __PARAMCNT = 1 THEN
··· DELAY = __PARAM1
· ELSE
··· DELAY = __WPARAM12
·ENDIF
· endsub
'
'············ LCD ROUTINE
'
SUB LCDChar
· temp = __PARAM1
· SEROUT LCD, LCDBaud, temp
· UpdateEncoders
ENDSUB
SUB LCDStr
· tempW = __WPARAM12
· DO
··· READINC tempW, temp
··· IF temp = 0 THEN EXIT
··· LCDChar temp
· LOOP
ENDSUB
SUB LCDWord
· tempW = __WPARAM12
· temp = "0"
· DO
··· IF tempW < 1 THEN EXIT
··· INC temp
··· tempW = tempW - 1
· LOOP
· LCDChar temp
· temp = "0"
· DO
··· IF tempW < 10 THEN EXIT
··· INC temp
··· tempW = tempW - 10
· LOOP
· LCDChar temp
· temp = "0"
· DO
··· IF tempW < 1 THEN EXIT
··· INC tempw
··· tempW = tempW - temp
· LOOP
· LCDChar temp
· temp = "0"
· DO
··· IF tempW < 1 THEN EXIT
··· INC temp
··· tempW = tempW - 1
· LOOP
· LCDChar temp
· temp = "0" + tempW_LSB
· LCDChar temp
ENDSUB
'
'···························· ---- encoders
·
FUNC GetEncoder1
· temp = EncoderPort AND 3
· RETURN temp
ENDFUNC
SUB UpdateEncoders
· encoder1 = GetEncoder1
· IF encoder1 <> encoder1Last THEN
··· IF encoder1 = 3 THEN
····· IF encoder1Last = 1 THEN
······· delay = delay + 1
······· delay = delay MAX maxdelay
····· ELSEIF encoder1Last = 2 THEN
······· delay = delay - 1
······· delay = delay MIN mindelay
····· ENDIF
··· ENDIF
··· encoder1Last = encoder1
· ENDIF
endsub
·
·
PAUSEUS 100
UpdateEncoders
IF delay <> tempW THEN
LCDChar Home
LCDStr " delay = "
LCDWord delay
ENDIF
DO
PULSOUT RB.4, 600 ' pulses from 100 to 1000 µs
pauseus 2
pulsout RB.5, 600
pauseus 2
PAUSEUS 100
UpdateEncoders
IF delay <> tempW THEN
LCDChar Home
LCDStr " delay = "
LCDWord delay
ENDIF
DO
PULSOUT RB.4, 600 ' pulses from 100 to 1000 µs
pauseus 2
pulsout RB.5, 600
pauseus 2
loop
do was after the LCD update and get delay value.
I fixed it by putting do before what i wanted to be my main loop.
do
UpdateEncoders
IF delay <> tempW THEN
LCDChar Home
LCDStr " delay = "
LCDWord delay
tempW2 = delay
ENDIF
PULSOUT RB.4, delay ' pulses from 100 to 1000 µs
pauseus 2
pulsout RB.5, delay
pauseus 2
LOOP
NOW when I touch my encoder the value increments by it self. I can see my pulse width increase but I can't control it. Now all I have to do is get the encoder to work and I need a way to be able to adjust the frequency.
It is fine that you disagree with me and fine for you to so state. That is one of the things that make these forums so helpful and great. People get to discuss and offer advice on different ways to do things. Sometimes differences are really only one opinion versus another. But sometimes someone really does have a better way of doing things.
I have learned a great deal from you in the past and respect your opinions and advice, as it seems your statements often come from much thought and experience. If you think it is better to do most of the signal processing outside the ISR, then I am sure that it is. However, at my present programming level (which uses SX/B almost exclusively) I am really only proficient with doing things either inside an ISR or inside a main program loop. Short of your task-switching model I do not know how to run more than two program loops. Within that context it seems better to me to handle time sensitive tasks with the ISR.
So yes, I will concede that a/your task-switching scheme might be a better approach than doing heavy processing with the ISR itself. I think either approach can work well if the timing is correct. I certainly think yours is a more adaptable method that once learned can be readily applied to a variety of programming tasks. I wish I had a better grasp of your concept!
I have examined your task switching method. I like the idea. If you can show datacps how to use your task-switching methods to accomplish his goals that would be great! I can probably only help with creating a single ISR that handles multiple tasks. This has much more to do with the way I am accustomed to thinking rather than a philosophical belief that it is the best way to accomplish this task. I can recall when a multi-function ISR was a great challenge for me. So I have grown and learned much both from you and many others in these forums.
I still struggle with wrapping my mind around the concepts required to enable multiple tasks to be running within different time frames and yet with all parts being short enough that none of them overrun their time allotment and thereby messing up the timing of other processes waiting for a chance to run. I think I understand the concepts in a vague intellectual yet distant way that is similar to studying the grammatical structure of a foreign language without the benefit of actually being able to read and write it. I do hope that some day I will be able to look at multiple tasks needing to run on the same CPU and think, “Ok. No sweat! I’ll just pass a few parameters to the cooperative RTOS when the task starts and I should be off and running.” I do wish that it seemed that simple to me. The problem I seem to have is that I do not know what thoughts to think in order for it to be that simple!
I appreciate your comments. I am sure others do as well. Please let us know what additional thoughts you have.
- Sparks
To address your scaling question: on the low frequency end at 40Hz you are going to need 40 * 2 = 80 signal transitions per second. If you are using a square-wave signal, that will require each transition to have a duration of 1 / 80 = 0.0125 seconds or 1.25ms. The time standard for the PULSEOUT command is in microseconds so your maximum delay value will be 1.25 * 100 = 125us. A high frequency of 400Hz requires 400 * 2 = 800 signal transitions per second. Assuming a square-wave signal, that will require each transition to have a duration of 1 / 800 = 0.00125 seconds or 0.125ms. This is equal to 0.125 * 100 = 12.5us. You will have to decide whether to round to 12 or 13us with this approach.
Now for the encoder handling… It looks to me like you have TWO places that are trying to adjust the value of Delay based upon the encoder movement! I think that surely you should only have one. Either remove the encoder handling in the interrupt (not my first choice) or else remove the “FUNC GetEncoder1” and “SUB UpdateEncoders” sections and their references. They seem to be trying to accomplish the same task and are likely conflicting with each other.
If you can get the encoder to alter the Delay value it should then be a fairly easy task to apply an appropriate scale factor to it.
Let me know if this helps get the encoder working.
- Sparks
Sorry to not have responded earlier; that is not my style, but I'm on a cruise ship in the middle of the Carribbean and the internet access from ship through satellite is just wretchedly slow, and at that its 75 cents per minute. So I'll only be very brief.
I'm also having the wonderful opportunity to do some SX assembler teaching while I'm at sea...... great fun.
I was not looking to say you were wrong with your "all in the ISR" statement, just that it did not fit the general case and folks might start using an inapprpriate method while not using SX/B.
Cheers,
Peter (pjv)