Shop OBEX P1 Docs P2 Docs Learn Events
scaling an encoder — Parallax Forums

scaling an encoder

datacpsdatacps Posts: 139
edited 2007-11-09 18:14 in General Discussion
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
''''''''''''''''''''''''''''''


·

Comments

  • BeanBean Posts: 8,129
    edited 2007-10-24 11:33
    SX/B does have the */ operator. It only works with WORD variables though.

    The easiest way to use interrupts with the encoder is this:

    EncoderA PIN RB.0 INPUT PULLUP 
    EncoderB PIN RB.1 INPUT PULLUP INTR_FALL ' Interrupt on falling edge (RB ONLY) 
    
    
    MinDelay CON 100
    MaxDelay CON 1000
     
    delay    VAR WORD
     
    INTERRUPT ' Interrupt caused by falling edge of EncoderB input 
      WKPND_B = 0 ' Clear interrupt flag to enable further interrupts 
      IF EncoderA = 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
    


    When you scale "delay" you'll have to put the result into another variable.

    tempW = delay */ Scale 
    PAUSE tempW
    


    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
  • datacpsdatacps Posts: 139
    edited 2007-10-26 01:06
    Bean I tried using the code I get an error on mindelay and maxdelay var 100 and VAR 1000 also it flags me
    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
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2007-10-26 02:25
    I suspect Bean meant to use constants for MinDelay and MaxDelay.
    Try...
    MinDelay CON 100
    MaxDelay CON 1000
    


    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
  • BeanBean Posts: 8,129
    edited 2007-10-26 02:49
    Yes, I meant to use CON instead of VAR.
    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
    ·
  • datacpsdatacps Posts: 139
    edited 2007-10-26 12:01
    Thanks guys. I did spot the error with min and max and corected it. I am using sx key 3.2.3 is there another update???? .
    Exactly Sparks where do I check for the version 1.5.3 at. Sorry about the stupid questions....
  • datacpsdatacps Posts: 139
    edited 2007-10-26 16:58
    Ok I got it not to error now . INTR_FALL I had the interupt in the wrong place. OOOPPPs . I will test my code again. and see what happens with the LCD.
  • datacpsdatacps Posts: 139
    edited 2007-10-27 05:15
    I thought I had it figured out. But I can't figure out where my mistake is. I put the delay into delaywanted and set up the interupt the way you explained. Now I can't even turn on the LCD or the LED. What am I doing wrong..
    ' =========================================================================
    '
    '·· 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
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2007-10-29 16:38
    A quick glance reveals that SUB Setdelay and SUB UpdateEncoders do not have associated ENDSUB statements.

    Does that help?

    - Spark
  • datacpsdatacps Posts: 139
    edited 2007-10-30 01:57
    I made the Corrections .. Thanks for pointing that out. I changed the device setting to 50Mhz. I am going over the code . I had a problem with the LCD so I changed the LCD and it works..???? Now I get the splash screen going into the delay code .. Now all I have to do is scale it correctly and set the delay.
  • datacpsdatacps Posts: 139
    edited 2007-10-30 03:24
    AFter testing further, I get 00000 across the LCD Display, When I turn the encoder. the light starts to blink with long pauses and the encoder only seems like it decrements 10 at a time. I see the LED change blinking rate . I don't see the LCD change or it does not increment. I am confused on the scale. I thought that the scale I am using is for RCTIME. I am a little confused as to exactly how if I am not using RCTIME...
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2007-10-30 17:34
    I do not understand the purpose of the following statements in SUB Setdelay
    IF DELAYWANTED < 1000 THEN
        DELAY = 0
      ENDIF
    


    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
  • datacpsdatacps Posts: 139
    edited 2007-10-31 01:50
    Thanks Sparks those are some safty code bits from the last code I had done. I took it out and it goes to 10000 now . I still can't change the delay with the encoder. I am just trying to put together code to make this program work. I am trying to make the code for my invertor project on another thread. I may just send a freqout comand if I can get the mosfet driver to turn two mosfet on at the same time. I saw another thread· how bean put a counter on or a inpin to watch for the pulse to set a delay. Can this chip look at other pins and send out lets say 4 different outputs. I got to turn on 2 mosfets at the same time or with a few usec delay between the sets of mosfets. I am trying to come up with an H drive. I want to use the encoders to change delays and freqout so I can control speed and also be able to use the circuit to drive a transformer to make AC to power ac motors ect...I am a newbie so I still have a lot to learn but I am trying simple things first one step at a time...My next step here is to get the encoder to control the delay and display the delay on the LCD, I only get delay = 10000·and the delay does not change. I am trying a few different things . I think I will eliminate the scale and let the delay start at 100 and go up and down from there???? The interupt has the delay inc and dec but I don't think I am setting up the delay in the sub corectly... . the range for AC motors are 45 to 60 hz and 400 for Mil, If I can control all those aspects of the signal to the mosfets than I can do motors and transformers and control speed on DC motors too. Once I get it working I can add the other encoders for the other controls... Setting high and low and changing the delay is the simplest way for me to start. I am sure there are other ways to do it better.. I may try a inpin and when I send lets say a freqout of 60 hz I can turn on the other 2 mosfet everytim the frequency is low I can fire the other two mosfets. That is basically what I am trying to do. I am just not as good as most of the guys on this site but I love the SX CHip and I am still learning and enjoying working on these projects. Thanks for your help.....
  • datacpsdatacps Posts: 139
    edited 2007-10-31 10:23
    Sorry about the last entry. I had a few seconds to post before my Wife got mad..

    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???
  • datacpsdatacps Posts: 139
    edited 2007-11-02 03:06
    Spark or Bean. I have been looking at all the PWM and interupt examples. I have a question Can the chip do the timed pulses like the http://forums.parallax.com/forums/default.aspx?f=7&m=125729
    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.....
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2007-11-02 19:58
    datacps,

    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.

    datacps said...
    Can I change the ISR rate with an encoder to control my pulse out speed??????
    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
  • datacpsdatacps Posts: 139
    edited 2007-11-02 20:55
    Thanks Sparks. You are right .
    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.
  • pjvpjv Posts: 1,903
    edited 2007-11-02 22:00
    Hi All;

    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)
  • datacpsdatacps Posts: 139
    edited 2007-11-04 05:40
    Ok guys I changed from high low to pulseout. The output looks a lot better on my scope.
    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
    ·

    ·
  • datacpsdatacps Posts: 139
    edited 2007-11-05 04:16
    Ok sorry about that guys.. I found my mistake..

    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.
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2007-11-06 20:01
    pjv,

    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
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2007-11-06 20:50
    datacps,

    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
  • pjvpjv Posts: 1,903
    edited 2007-11-09 18:14
    Hi 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)
Sign In or Register to comment.