Shop OBEX P1 Docs P2 Docs Learn Events
Learning SX/B - Page 2 — Parallax Forums

Learning SX/B

24

Comments

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2009-02-03 23:13
    Ugha said...

    That's great! I'll check it out, thanks!
    Do you know if its complete? As in I can do everything with it that I can do with SX/B?
    Yes, it is complete. You can compile for all sx devices. You have all the possibilities
    that sxb 2.0 offers, except for large arrays on sx18/20/28 (limited to 16 bytes).
    But there are libraries written (by me and others), particularly the Task library
    that offers the same as sxb tasks.
    At the moment I favor sxb over c4sx because I don't like the way cc1b handles
    local variables. It uses staticly assigned variables (not a real stack) so you
    will frequently use #pragma to set a bank for new locals (this is not automated).
    Also, in the libraries I wrote you will see lots of assembly too.
    One big advantage of C4SX is that it·natively supports libraries.
    Edit:
    C4SX does not offer all the commands that are builtin into sxb, like pulseIn, rcTime etc.
    You will have to write libraries for those commands.

    regards peter

    Post Edited (Peter Verkaik) : 2/3/2009 11:27:00 PM GMT
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-02-03 23:46
    1) The internal clock is just not accurate enough for reliable serial comms.

    2) You can count cycles or use Guenther's SX/Sim. If you're using buffered serial it's mostly a "don't care" as it's happening in the background (unless you have a full buffer). When using straight SEROUT it takes 10xbit_time to send a byte. Bit time is 1/Baud. At 2400, for example, the bit time is 416 microseconds and a full byte takes 4.16 milliseconds.

    3) True, but you'll find a balance. 20MHz seems to be good for battery-run apps (all BS2 Stamps run 20MHz or faster).

    4) There's www.sxlist.com, but you'll have to do a bit of touch up to incorporate the code found there into your SX/B programs. I really don't think there's any true "plug and play" solution, though Peter Verkaik's very advanced approach to programming may come the closest.
  • UghaUgha Posts: 543
    edited 2009-02-04 00:28
    Quick question... are 2d arrays allowed?
    If so how are they declared and accessed?
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-02-04 01:03
    Not in SX/B. SX/B 2.0 allows arrays of any size (up to the memory limits) so you could synthesize a 2D array with SUBs and FUNCS..
  • RobotWorkshopRobotWorkshop Posts: 2,307
    edited 2009-02-04 02:24
    Ugha said...
    The encoders are single channel encoders. I'm going to use them to keep track of the tracks on my robot and use the information for a crude form of PID.

    The two motors with encoders are for my tracks, the other two will be much more rarely used and control the robot's forearms.

    If you are going to keep track of the main drive motors then I would seriously consider using a full quadrature encoder on each motor. It gives you speed and direction. That will give you much better control since the micro can get you right on target. With only one channel you only can tell if it rotates and just hope that it goes the right way. A good source for encoders are the non-optical Microsoft and Logitech mice. Also HP printers have some nice encoders. Just find a matching pair of old inkjet printers. I used them in my encoder article.

    For the arms I would probably add the full encoders as well and at least one limit switch for the home position.
    Ugha said...
    I have a pair of encoders on each arm of the robot that I will be monitoring with a BS2, two IR transmitters/receivers for forward ranging and crude motion tracking and I'll also end up with two IR transmitters/receivers (Either a slot interrupt or maybe a homemade one using the IR pair that comes in the boebot kit) for the encoders mentioned above. I'm also toying with the idea of using a super-bright LED and CDS cell instead of IR encoders for the tracks (which will, of course, require RCTIME to monitor the resistance)

    You'll want to watch the resolution of the encoders to ensure it doesn't exceed the polling interval you use on the stamp. Otherwise you will lose count since some may be missed. That was the whole point of the July article on encoder scaling. An SX28 sits in the middle to watch the encoders and adjusts the count so nothing is lost.
    Ugha said...
    The PWM control is duty cycle for the motors. I have the four motors connected to two SN754410 H-bridges and I intend to PWM the enable pins on the two chips to control the speed of the motors.

    Using the SX chips you have some options. You can simulate PWm within the ISR routine. This would be fine for the SX28 or SX48 chips. When using the SX48 it has a pair of 16-bit timers that can generate the PWM signals so that the ISR can do even more things without worrying about PWM too. Any other I/O pins can be used for direction. I was using an L298 which I made to use a SN754410 footprint so I've already written SX48 code that can look at encoders and leverage the hardware to generate PWM. It hasn't been converted to SX/B 2.0 yet but it could be.
    Ugha said...
    At this time I'm planning on connecting two BS2s with the SX. One BS2 will handle all the I/O that I can't place on the SX, the other will be the "brain" and will contain the scripts and limited AI actions for the robot.

    So I'll need the SX to buffer data from and to two sources.

    I'm not quite sure what other sensors I may end up adding. A PIR is possible but I haven't decided for sure what I'll end up doing.

    The IR devices and sensors are pretty dumb, excluding the Ping of course. (which does require some math on behalf of the SX).

    I've already a couple of SX28s and I'd like to try to use them. Do you think my application is too intensive for anything but a SX48?

    The main reasons for using the SX48 over the SX28 are:

    - The SX48 has more Program space/RAM (only important if you are running out on the SX28)
    - The SX48 has more I/O (useful if you are running low on pins)
    - The SX48 has two 16-bit timers vs a single 8-bit timer.

    I use both!
    Ugha said...
    Unfortunately I've never subscribed to Servo although I may eventually. Your applications sound great, I'd love to check them out. If I do sign up for Servo, I'll see what the back issues cost.

    You don't have to subscribe to get their back issues. You can either buy the single issue or a CD by year with electronic versions. Just checkout their website.
    Ugha said...
    Some notes, I don't mind if there are some brief sub-second delays between serial transmission. In fact, besides the PWM speed control and syncing with the encoders to keep the path straight, nothing requires exact timing. This is just for fun, not a professional job.

    I am willing to offload some more work from the SX to one of the two BS2s if needed, what time each job (PWM, serial buffer, ect) takes, which one is better suited to which processor, is something I have no clue about and one of the things I need help with.

    From what you describe it may be easier to spread out the functions across a couple processors. I tend to use the SX chips as intelligent peripherals or for controlling the whole show on small projects.

    It's good to think about the whole picture and how you want it to fit together but you may want to start prototyping each section, get that working, and then see how you want to combine them.

    Robert
  • UghaUgha Posts: 543
    edited 2009-02-04 03:39
    I don't understand why I'd need speed and direction.
    If I'm signalling my H-bridge to go forward, why do I need to know that its going forward? I can imagine if it were coasting or something of the like, but I don't understand it on a smallscale
    robot on which I will know the direction I command it to go.
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2009-02-04 05:12
    Ugha--

    These guys know far more than I ever will. HOWEVER, whenever Ugly Buster's motor controller's received a command to instruct a motor to turn in this direction or that direction, it ALWAYS did. Having a quadrature encoder report that fact would have been a huge waste of time.

    A quadrature encoder would be just the ticket to DISCOVER which way a motor was turning. But, as far as I have ever been able to figure out, in the machines I have built, anyway, direction feedback is totally useless in the drive mechanism.

    All of my gear motors have quadrature encoders. I only use a single channel. A single channel provides data that may be accumulated thereby yielding position information assuming no wheel slippage. An appropriate motor controller, operating under nominal circumstances, sets the speed.

    --Bill

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    You are what you write.
  • RobotWorkshopRobotWorkshop Posts: 2,307
    edited 2009-02-04 05:26
    You should get both because without it you don't really KNOW which way it it moving. You just see pulses and ASSUME it may happen to be going the direction you want/expect.

    The other reason is accuracy. Even if you are going to control the speed how are you going to determine how far you've gone? By factoring in the direction you can get a much better idea on how far each wheel turned. Besides it seems to make all the calculations easier.

    If you are just putting a low resolution encoder disk directly on a slow moving wheel then you can probably get by with just using a single channel for regulating speed.

    There should be a quadrature example in the SX/B help file which can give you an idea how they are to work with.

    Robert
  • pjvpjv Posts: 1,903
    edited 2009-02-04 07:22
    Hi Bill;

    In regard to using just a single channel of a quadrature setup, this can easily pick up extra pulses on the edge transitions. Just park a unit at the critical switch point and watch the counts accumulate due to noise or vibration. To ensure accuracy on the counts, you must take care of that in software or schmidt triggers, and this my be easy or more difficult, depending on speed of the pulses. Alternately this can be more easily and totally reliably handled in quadrature. That's why those encoders were invented. And inherently they give direction to boot.

    If you don't care about inaccuracy, then a single channel will do. Only you can decide what is good enough.

    Cheers,

    Peter (pjv)
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2009-02-04 14:59
    robert and pjv--

    You have certainly given me something to contemplate and, just as certainly, I appreciate it. It is, perhaps, that my machines are designed to operate indoors and, hence, ARE slow moving. Therefore, I "get" away with it.

    I still don't understand how one might instruct an HB-25 to move in one direction and it MIGHT move in the opposite, though. Is it because of false inputs on floating pins which may be caused by real inputs on adjacent pins?

    Thanks!

    --Bill

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    You are what you write.
  • ZootZoot Posts: 2,227
    edited 2009-02-04 15:06
    That's not what PJV means -- especially at "slow" speeds, the transition from 1->0 or 0->1 on an encoder will "jitter" -- I am having this exact issue with a single (rather than quadrature) encoder on a big 'bot. The quadrature encoding means that *always* when one encoder is crossing an edge, the other is in the middle of a stripe, so even if the edge is bouncing "back and forth" the "click" count is maintained -- basically the count will jiggle up and down during transitions, and remain accurate. With a single encoder, you accumulate counts without knowing direction (i.e. that wheel is jittering at the edge). Regardless, if it works, it's good!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2009-02-04 17:49
    Zoot--

    My robots have experienced jitter just as you described. This did not happen often, but I could not account for it until now.·Thanks!

    I all my gear motors have quadrature encoders of which I use a single channel. Is it also possible to double the resolution by using both channels?

    --Bill

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    You are what you write.
  • ZootZoot Posts: 2,227
    edited 2009-02-04 18:11
    Bill -- Whether or not you get better resolution depends on how you've been treating the single encoder click counts. Regardless, you will certainly get more stable and accurate counts. If you are taking full advantage of *every* edge with single encoder, that's where you get the errors (when the wheel is physically jittering there is no way to know if the edge is moving past or moving back and forth).

    The solution, at trade off of halving your resolution, is that you only count the "click" you get two white-to-black edge changes in a row (or the opposite). A white to black edge change followed by a black to white edge change would be jitter (unless it is followed by a another "perfect" black to white edge change, in which case it's a direction change -- and as you point out, on a heavy 'bot you would theoretically "know" that you changed direction because you told your motors to do it. But it's still not very stable and kinda "hacky".

    In any case, that was my thinking when I was lazy and didn't build quadrature encoders. Now I wish I had - the firmware of counting quadrature is much simpler, actually, and in the long run I'd have probably saved a lot of time and hassle.

    To come full circle, there is already a quadrature encoder example in the SX/B documentation (help file). It's a perfect project to get going with an SX -- making a simple peripheral that counts your encoders, maybe does some light pre-processing on them (i.e. "pre-chew" numbers for direction, distance, total distance, etc, so your Stamp(s) don't have to do the work) and deliver it ready-to-go to your host. I do recommend serial tx/rx (SERIN/SEROUT) for communication. It's (relatively) easy and there are a wealth of examples for both the Stamp and the SX. This way your host can send a string using SEROUT like "!GENC" (get encoders) and expect, say 9 bytes back with current distance and speed (as words) for each motor, plus a byte of bit "flags", motor moving/not-moving, motor direction, for each motor.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php


    Post Edited (Zoot) : 2/4/2009 6:35:06 PM GMT
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2009-02-04 18:21
    Zoot--

    Thank you for the detailed reply. I will definitely check out the SX/B help file. For some reason, when I wrote the program that blinked the LED, I did not get very deeply into the help file. [noparse]:)[/noparse]

    Ugly Buster weighs just south of 26 pounds.

    --Bill

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    You are what you write.
  • pjvpjv Posts: 1,903
    edited 2009-02-04 20:08
    Hi Bill;

    Actually quadrature operation gives double the resolution of a single channel.

    At any instant, with quadrature there is one of 4 possible states.... lo/lo· hi/lo· lo/hi· hi/hi. And the encoder moves through all four of them in one physical cog, and each of them can be detected by the micro. The "forward" sequence is· lo/lo· to· lo/hi· to· hi/hi· to· hi/lo· to lo/lo· and the "reverse" sequence is (not surprisingly)· lo/lo· to· hi/lo· to· hi/hi· to· lo/hi· to· lo/lo.
    Four phase states per cog. And the "direction" is determined at any point by comparing the current state to the previous state.

    Attached is a state machine implementation of a quadrature encoder for you to peruse. Assemble it and single step through it with the debugger or SXSim to see how easily it works.
    The state lookup table is made up of all the possibilities of the previous state combined with the current state.


     
     
    Assume RA.1 and RA.0 are inputs and connected to the two quadrature channels
    Assume varable Prev holds the state of the previous sample.
     
    Loop         rl   Prev
                 rl   Prev                ;make room for the new sample coming in
                 and  Prev,#%0000_1100    ;get rid of any carry-ins and older samples
    Sample       mov  w,RA                ;get new sample to w
                 and  w,#%0000_0011       ;disregard all except the two state bits
                 or   Prev,w              ;merge new sample in with previous sample
                 mov  w,Prev              ;get old/new state pairs
                 call Lookup              ;lookup same/forward/reverse in Prev/New state table
                 add  Position,w          ;update position by one... positive or negative
     
         (delay here to set he speed you want to sample at)
     
                 jmp  Loop                ;get next sample
     
     
    Lookup       add  pc,w                ;jump into table and return with +1 for forward, -1 for reverse, and 0 for no change
     
    P00N00       retw 0                   ;no change
    P00N01       retw 1                   ;forward
    P00N10       retw -1                  ;reverse
    
    P00N11       retw 0                   ;impossible
    
    P01N00       retw -1                  ;reverse
    
    P01N01       retw 0                   ;no change
    
    P01N10       retw 0                   ;impossible
    
    P01N11       retw 1                   ;forward
    
    P10N00       retw 1                   ;forward
    P10N01       retw 0                   ;impossible
    
    P10N10       retw 0                   ;no change
    
    P10N11       retw -1                  ;reverse
    P11N00       retw 0                   ;impossible
    
    
    P11N01       retw -1                  ;reverse
    
    P11N10       retw 1                   ;forward
    
    P11N11       retw 0                   ;no change
    
    
     
     
    
    
    

    Cheers,

    Peter (pjv)
  • UghaUgha Posts: 543
    edited 2009-02-04 20:57
    I've attached my first SX/B program.

    It compiles fine and I think I've got the logic right, but at this time I haven't tested it (I'd have to wait til tomorrow or the next day for various reasons).
    I tried to figure out SXSim but its all greek to me.

    Consider it a rough draft or outline. I have attempted no speed management and all issues of speed (Duration on PWMs, serial timeouts, ect) are random placeholders
    because I've got to gather a great deal more information (How fast can a BS2 go from reading an input to receiving/sending serial, ect... and how long it takes an SX
    to do various tasks).

    I've attempted to create my own crude task engine to split up the various jobs the SX will have to do.

    I may even end up rewriting it without using the ACK1 and ACK2 lines, just a single serial line to all three chips.

    What I'd like is suggestions on how to include interrupts to prevent the SX from having to wait on the BS2s all the time, as well as advice on better methods to
    accomplish this without use of assembly.

    I understand I'll eventually have to learn assembly, but for now I'd like to stick with SX/B... even if it is slow or takes a lot of work-arounds.
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2009-02-04 22:02
    Peter--

    Thank you very much for the detailed explanation and the code!

    --Bill

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    You are what you write.
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-02-04 22:49
    I posted a framework earlier that will handle the serial IO and motor PWMs for you, all you have to do is add in your foreground logic. When you use inline SERIN and SEROUT you're consuming a lot of time and this will create problems for your application, especially since you want to have speed control over motors. On that... the PWM command is great from charging RC circuits (analog output) and dimming LEDs, but not so great with motors; the reason is that it only run while the instruction is active so your program will just be sending PWM bursts to the motors; probably not what you want.

    I've attached an encoder demo that is from an old Parallax AppNote for the PIC -- I just coded it to my particular style. Since you want two encoders I wrote the program with two and have tested them using a parallel LCD. Works just hunky-dorey.

    Notes:

    * You can use INC x instead of x = x + 1 (same for DEC)

    * When multiplying or dividing by powers of two (2, 4, 8, 16, ...) shift operators are more efficient
    -- use x = x >> 1 instead of x = x / 2

    * TASK is a keyword in SX/B 2.0 so you shouldn't use this as a variable name

    * Even though the compiler is forgiving you should enclose subroutines in SUB/ENDSUB blocks and functions in FUNC/ENDFUNC blocks
  • UghaUgha Posts: 543
    edited 2009-02-04 23:43
    JonnyMac:
    Thanks for the input... the reason why I didn't use anything from your previous code samples is because I wanted to learn the actual SX/B language somewhat before I did the whole
    copy and paste thing.

    I will, of course, examine your samples closely and will most likely use elements from all of them.

    I also appreciate the tips. I wasn't aware of SUB/ENDSUB and the like beforehand (I checked, the helpfile doesn't mention them).

    Question... do you think I'm trying to do too much with the SX at my beginner stage? Should I offload the PWM of the four motors to one of the stamps?

    Finally, I hope your not getting annoyed with me...
    Most people would be quite happy just using your code and moving on to something else. I'm a little different, I want to UNDERSTAND every aspect of my project.
    Including the code you've provided. So I guess you could say I'm doing it the hard way.

    I guess what I'm saying is, I'll just have to crack down and learn a little assembly... if you and the others don't mind me annoying you with questions [noparse]:)[/noparse]
  • UghaUgha Posts: 543
    edited 2009-02-05 00:26
    Time for my first annoying questions...

    I can't seem to get one of the example programs you've provided to compile.

    First, the Ugha_Robot.SXB you made for me has 27 errors... To start with is:
    speed VAR pwmCtrl(0) ' 0 (stop) to 255 (full)
    Is giving the error INVALID PARAMETER "("
    Each line that has pwmCtrl(0) in it is also producing the same error. There are several other errors after it but I'm assuming it all has to do with the same thing.
    At first I assumed my compiler was outdated, so I upgraded from v1.50.1 to v1.51.03 with no difference in the errors.
    I honestly don't see what's wrong with that or the surrounding lines... therefore the problem must be something on my end.

    Any idea what it might be?

    Also related to the same area... I'm confused.
    acc1 VAR pwmCtrl(9)

    This aliases acc1 as the ninth element of pwmCtrl if I understand it correctly... but you only have pwmCtrl defined with 8 elements.
    Am I missing something?

    I'm very confused [noparse]:([/noparse]
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-02-05 01:39
    "Too much" is in the eye of the beholder -- you'll decide that. With the programming experience you have there's no reason you can build your project, just do it a step at a time. You may have noticed that my code samples are somewhat modular. They're not exactly plug-and-play but they're close enough that I can integrate a module into a new program, do the necessary tweaks for the project at hand, then move forward. No matter how many samples you get from me or others your involvement will be required.

    Like you, I used code from others but spend time learning it, understanding it, then making it my own. The PWM code, for example. Guenther's original version presets the output then turns it right back off if it is not supposed to be on. I decided to add a few cycles to the routine to give absolutely clean output. Of course, I could only do this after understanding how the original version worked.

    If you're in the gift-giving mood give yourself a Parallax Professional Development board and Guenther's book -- you'll be repaid in spades with the hours of fun you'll have and the ability to quickly develop a new project.
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-02-05 02:07
    I use the 2.0 beta -- download it from the sticky post at the top of the SX forum.

    http://forums.parallax.com/showthread.php?p=780347

    Whoops, there is an error; but I got away with something. In the original program I declared pwmCntrl as eight bytes but then defined 12 elements. Here's the rub: in the SX28 SX/B puts arrays of less than 16 elements into one contiguous bank, so the rxSerial array (defined after pwmCntrl) was set to the next physical bank in memory and didn't clobber the end of my pwm aliases.

    Here's the compiler (2.00.08) output -- note how the aliases are correct despite my size error:
    pwmCtrl          EQU  $30        ;pwmCtrl               VAR     Byte(8) BANK
    speed            EQU  pwmCtrl+0  ; speed                VAR     pwmCtrl(0)
    speed0           EQU  pwmCtrl+0  ; speed0               VAR     pwmCtrl(0)
    speed1           EQU  pwmCtrl+1  ; speed1               VAR     pwmCtrl(1)
    speed2           EQU  pwmCtrl+2  ; speed2               VAR     pwmCtrl(2)
    speed3           EQU  pwmCtrl+3  ; speed3               VAR     pwmCtrl(3)
    acc0             EQU  pwmCtrl+8  ; acc0                 VAR     pwmCtrl(8)
    acc1             EQU  pwmCtrl+9  ; acc1                 VAR     pwmCtrl(9)
    acc2             EQU  pwmCtrl+10 ; acc2                 VAR     pwmCtrl(10)
    acc3             EQU  pwmCtrl+11 ; acc3                 VAR     pwmCtrl(11)
    
    rxSerial         EQU  $50        ;rxSerial              VAR     Byte (14) BANK  <-- note in next bank
    


    I fixed the program (with encoders folded in). Note that the speed is 50MHz. According to SX/Sim the ISR takes about 130 cycles (max) -- at 50MHz there 325 cycles between interrupts so there's plenty of time left for the foreground to do its thing.

    Rip, tear, dissect, toss what doesn't work -- I offer this stuff only as help as you may choose to use it.

    Post Edited (JonnyMac) : 2/5/2009 2:46:55 AM GMT
  • PJMontyPJMonty Posts: 983
    edited 2009-02-05 03:20
    Just a note regarding the quadrature decoder code that Peter (PJV) posted. The function he wrote needs to be called at a rate that is higher than the fastest possible frequency the quadrature encoder will ever generate. For example, if you have a 256 pulse per revolution encoder running at 1 revolution per second, it will generate a pulse train of 256 Hz. Unless you have a very high resolution encoder, it's not hard to sample at a rate higher than the encoder will generate. However, it's also important that the function be called on a regular and consistent basis. If there is even a single gap between calls to the encoder function that is too long and you miss an encoder state change, then you'll end up missing a creating errors in the encoder count.

    Other than these simple caveats, the technique Peter (PJV) showed is the best way to decode an encoder, and never worry about jitter screwing up the count. It's especially nice for mechanical encoders as they also have switch bounce which is automatically taken care of by this technique.

    Thanks,
    PeterM
  • pjvpjv Posts: 1,903
    edited 2009-02-05 08:37
    Hi PJ;

    I'm glad you brought that up.... you are abolutely correct.

    As many on the forums here know, I generally run all my code in a multi-tasking manner under a very tight interrupt 1 to 10 uSec regime. I would therefore arrange to call this routine very cosistently at the appropriate speed, and never miss a pulse.

    Given those real time techniques, I'm sure the things Ugha wants to do could all be readily handled by a single SX, and simultaneously to boot. Unfortunately (or, depending how you look at it, fortunately) he would have to learn assembler.

    It's all a matter of learning, and to squeeze the most out of an SX, assembler is an absolute must...... but all in due time.

    Cheers,

    Peter (pjv)
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2009-02-05 15:11
    PeterM and pjv--

    Couldn't pjv's code be made into an interrupt service routine which would make itself known as often as necessary?

    The use of the phrase "to call this routine very cosistently" is what confused me. It SEEMS to this newbie that you would not have to call it at all if it called you.

    --Bill

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    You are what you write.
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-02-05 16:28
    PJV uses a really interesting scheduling structure which means that the interrupt does one thing: it sets a marker that the interrupt has occurred; this is the base timing in the system and everything cascades from there.

    I've been experimenting with this style folded into SX/B -- not there yet but having fun. For grins I wrote an SX/B program that uses a modified version of PJVs encoder routine and a simplistic version of his scheduler. Note that I'm not good enough with Assembly to know if RETW will work across page boundaries and as that could happen with the placement of the ENCODER subroutine I changed the table call to the READ+offset (I used the code generated by SX/B and tweaked it).

    The attached program scans an encoder every 10us, updates eight LEDs with the position every 100us, and toggles and LED every 250ms. It's happily running on my PDB so while perhaps not a perfect implementation of PJV's scheduling strategy, it is working.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2009-02-05 17:19
    Jonnymac,

    retw tables must be in the lower half of codepages.
    Good place is directly after interrupt routine, or after
    initial jump to interrupt routine.
    See attachement. This version should work.

    regards peter
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-02-05 18:06
    Thanks, Peter, it does work. Since the program is so small I added a line to force the ENCODER subroutine into another page -- still works.

    Post Edited (JonnyMac) : 2/5/2009 6:49:52 PM GMT
  • pjvpjv Posts: 1,903
    edited 2009-02-05 20:30
    Hi All;

    Peter Verkaik... you are absolutely correct. Please do understand in my small example I was not trying to be perfect and deal with all issues and caveats, just the basic concepts for others to understand.

    Jonny... nice going.·However, nowadays I prefer to use a counter in the interrupt that I empty in the base of the scheduler. Reason is that running multiple fast tasks, on occasion one could (but should not) overrun the base counter, and hence loose a tick. Obviously this would cause jitter, and loss of total tick counts. With a counter in the interrupt, such cannot happen as all ticks are accounted for, albeit a bit skewed in time but·a better solution because·long term timing stays perfect.


    
    
    IntValue       equ    -100             ;2 uSec interrupt at 5o MHz .... use -50 for 1 uSec or -250 for 5 uSec
     
     
    Interrupt
                   bank   IntCtr           ;not required if you park the counter in global memory
                   inc    IntCtr           ;increment each time we have an interrupt tick
                 (some code)               ;some VERY short time critical code (such as ADC code) is permitted here, depending on the size of your base tick
                   mov    w,#IntValue      ;reload interrupt with negative number
                   retiw                   ;return to scheduler (or app)
     
    Scheduler1   
                   bank   IntCtr           ;not required if you park the counter in global memory
    Scheduler2     test   IntCtr           ;test for non-zero
                   snz                     ;
                   jmp    Scheduler2       ;wait here until counter is non-zero. ie at least one iterrupt has occurred
     
                   dec    IntCtr           ;
                   bank   Timers           ;
                   decsz  Timer10uSec      ;
                   jmp    Scheduler2       ;wait for 10 uSec tick
                   mov    Timer10uSec,#5   ;reload 10 uSec timer with 5 2uSec interrupts. This value must be adusted for other interrupt values
     
                 (your 10 uSec code -if any)
                   decsz  Timer100uSec     ;
                   jmp    Scheduler2       ;wait for 100 uSec tick
                   mov    Timer100uSec,#10 ;reload 100 uSec timer with 10 10 uSec ticks
     
                 (your 100 uSec code -if any)
                   decsz  Timer1mSec       ;
                   jmp    Scheduler2       ;wait for 1 mSec tick
                   mov    Timer1mSec,#10   ;reload 1mSec timer with 10 100 uSec ticks
     
                 (your 1 mSec code -if any)
     
    
    
     
                 (rest of scheduler counters in the same manner)  
     
                   jmp    Scheduler1       ;
     
     
    

    Please realize this snippet is not complete... counter definitions, initialization etc. are required. But it should show the intended operating concept. I have not tested it, but I believe it is correct.

    Actually, I find that serial routines work·just fine·using a 20 uSec (5x oversampling at 9600) sample clock, and I can ·run multiple receivers and transmitters at the same time (something of apparent interest to some posters here). Of course those MUST be non-blocking. IE do a little bit of work in each as required, and return to the scheduler.

    If enough others are interested I'd be happy to spend some time developing those and posting them here.

    Cheers,

    Peter (pjv)
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-02-05 21:52
    Peter,

    I'm trying to hybridize your scheduler strategy with the way I've done things in the past, that is, UARTS in the interrupt. I study your state-driven UART and found that it uses fewer cycles per call (by design, of course) so I modified it a bit and stuck it back into the ISR. So far, so good. Working on the TX side now. My intent is to use the scheduler to handle the enqueuing and enqueuing of serial bytes.

    I've tested the attached program at 38.4k serial RX which is the design max.
Sign In or Register to comment.